Cortex-M3的低层编程

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

Cortex-M3的低层编程􀁺概览􀁺汇编与C的接口􀁺典型的开发流程􀁺第一步工作􀁺与外界互动􀁺使用数据存储器􀁺使用互斥访问实现互斥锁操作􀁺使用位带实现互斥锁操作􀁺使用位段提取与查表跳转概览在CM3上编程,既可以使用C也可以使用汇编。可能还有其它语言的编译器,但是大多数人还是会在C与汇编的世界里游弋。C与汇编都有尺短寸长,不能互相取代。使用C能开发大型程序,而汇编则用于执行特种任务。在使用不同的工具链和芯片时,有大量的用法和用量都随之不同。因此,本书不会深入讲解怎样精通一个具体的工具链,也不会大谈如何把程序烧到板子上。在第19章和第20章会提到一些入门知识,具体内容还需查阅相关的文献和在线帮助文档。使用汇编如果工程比较小,使用纯汇编常常是可行的,而且你能随心欲地优化和控制程序。不过,你的开发周期会变长。尤其是当工程变大,需要处理比较复杂的数据结构,以及要管理函数库时,你将发现汇编会使工作量激增。各种地址和间接引用千头万绪;bug劈头盖脸;甚至好几天都改不完,简直就是自虐。当然,如果你想成为系统开发的大虾,就必须以“我不下地狱谁下地狱”的决心,去勇敢面对,后天下乐而乐。不论如何,时间宝贵。我们应该以C来实现程序的大框架,而本着好钢用在刀刃上的原则来使用汇编,因为只有在不多的特殊场合是非使用汇编语言不可的,它们是:•􀁺无法用C写成的函数,如操作特殊功能寄存器,以及实施互斥访问。•􀁺在危急关头执行处理的子程(如,NMI服务例程)。•􀁺存储器极度受限,只有使用汇编才可能把程序或数据挤进去。•􀁺执行频率非常高的子程,如操作系统的调度程序。•􀁺与处理器体系结构相关的子程,如上下文切换。•􀁺对性能要求极高的应用,如防空炮的火控系统。使用C用C写的程序可以移植,并且操作复杂数据结构时远远比汇编方便。但因为C是一种通用语言——至少是低等高级语言,它并不指定如何初始化具体的处理器(用于在main执行前准备好执行环境)。在解决这个问题时,不同的工具链都有自己的一套,因此最聪明的办法就是看一看工具链附带的示例程序。如果使用RealView开发套件(RVDS)或者KEIL的RealView微控制器开发套件(RVMDK),则编译器和汇编器是ARM提供的,而且它们中都附带了很多示例。如果使用了GNU的工具链,则第19章以CodeSourceryGNU工具链为例,给出一个简单的示例(其它示例可以网上找)。尽管在使用了C后,大大加速了开发,但是底层的系统控制往往还需要汇编代码。很多编译器都允许你直接在C代码中插汇编,称为“内联汇编”;另外还允许你写独立的汇编模块,与编译后的C模块一起连接。以往,使用内联汇编的作法比较多,但是在ARM编译器中,不支持对Thumb‐2指令的内联汇编。取而代之的,是从RealViewC编译器的3.0版开始,新增了所谓“嵌入式汇编”的功能,它支持Thumb‐2指令。它让你可以在C程序中插入使用汇编语言编写的函数,例如:__asmvoidSetFaultMask(unsignedintnew_value){//在这里使用汇编代码实现本函数MSRFAULTMASK,new_value//把new_value写入FAULTMASK中BXLR//返回主程序(不可省略)}RealViewC编译器对嵌入式汇编的详细论述,在《RVCT3.0CompilerandLibraryGuide(Ref6)》中给出。在CM3中,嵌入式汇编还是比较需要的,因为常常会有访问特殊功能寄存器的时候。比如,在设置堆栈时,就要使用MRS/MSR指令。对于其它不能由编译器产生的指令,比如WFI/WFE、互斥访问、存储器隔离等指令,也必须用汇编显式给出。在以前的ARM处理器中,因为支持ARM/Thumb双重状态,往往需要所谓的“interworking”,且不同的源文件可能需要编译成不同状态下的代码。在CM3中不再有此需求,因为只使用了Thumb状态,从而工程管理清爽多了。当使用C开发程序时,推荐你开启CM3的双字对齐管理机制(在NVIC配置与控制寄存器中,把STKALIGN置位),代码形如:#defineNVIC_CCR((volatileunsignedlong*)(0xE000ED14))*NVIC_CCR=*NVIC_CCR|0x200;//设置STKALIGN位这是用于确保系统能严格遵守AAPCS过程调用标准,个中细节请参阅第12章。汇编与C的接口在很多情况下,都需要让C程序模块与汇编程序模块互相交互,它们包括:•在C代码中使用了嵌入式汇编(或者是在GNU工具下,使用了内联汇编)•C程序呼叫了汇编程序,这些汇编程序是在独立的汇编源文件中实现的•汇编程序调用了C程序在这些情况下,必须知晓参数是如何传递的,以及值是如何返回的,才能在主调函数与子程序之间协同工作。这些交互的机制在ARM中有明确的规定,由文档《ARMArchitectureProcedureCallStandard(AAPCS,Ref5)》给出。不过,在大多数场合下的情况都比较简单:当主调函数需要传递参数(实参)时,它们使用R0‐R3。其中R0传递第一个,R1传递第2个……在返回时,把返回值写到R0中。在子程序中,可以随心所欲地使用R0‐R3,以及R12(回顾第9章,想想为什么会PUSH它们)。但若使用R4‐R11,则必须在使用之前先PUSH它们,使用后POP回来。可见,汇编程序使用R0‐R3,R12时会很舒服。但是如果换个立场——汇编要呼叫C函数,则考虑问题的方式就有所不同:必须意识到子程序可以随心所欲地改写R0‐R3,R12,却决不会改变R4‐R11。因此,如果在调用后还需要使用R0‐R3,R12,则在调用之前,必须先PUSH,从C函数返回后再POP它们,对R4‐R11则不用操心。在本章的示例程序中,绝大多数只是调用汇编子程序,它们只影响少量寄存器,或者会在返回前恢复寄存器的内容,所以往往没有严格遵守AAPCS。这主要是为了突出其它重点,简化程序,请读者不要钻牛角尖。典型的开发流程在开发基于CM3的应用程序时,常常有多种源程序和库,有些是自己写的,有些是别人已经写好的(尤其是底层的软件)。上述这些开发工具,在代码生成的流程都差不离。对于最基本的应用,也至少需要C编译器,连接器以及二进制文件处理工具。如果使用的是ARM的工具,如RVDS或RealView编译器工具(RVCT),则它们的流程如图10.1所示。其中的“分散加载脚本”是可选的,但是当存储器映射变得比较复杂时,则需要它。图10.1使用ARM工具链时的典型开发流程在上述基本工具之外,RVDS还提供了大量的其它实用程序,比如一个集成开发环境(IDE)以及调试器。欲知详情,可登录ARM网站()第一步工作本章为提供了若干汇编写的例子,在实际应用中,这些程序都会用C写。但是以汇编的方式呈现,有助于让读者更深更好地理解CM3的工作内幕,以便在以后用C开发时心里更有底。这里给的程序都用ARM的汇编器(armasm)来汇编,其它工具可能对语法格式有些不同的要求。而且实际上,开发工具几乎都会把启动工作为你做好,让你根本不用去想还有启动代码的事(不过,这也妨碍了我们学习得更深入)。下面,就隆重请出本书第一个完整的示例程序(请参考向量表来阅读)STACK_TOPEQU0x20002000;SP初始值,常数AREA|HeaderCode|,CODEDCDSTACK_TOP;栈顶(MSP的)DCDStart;复位向量ENTRY;指示程序从这里开始执行Start;主程序开始;初始化寄存器MOVr0,#10;加载循环变量的初值MOVr1,#0;初始化运算结果的值;计算10+9+8+...+1loopADDr1,r0;R1+=R0SUBSr0,#1;R0自减,并且根据结果更新标志(有”S”后缀)BNEloop;if(R0!=0)gotoloop;;现在,运算结果在R1中deadloopBdeadloop;工作完成后,进入无穷循环END;标记文件结束这个例子非常简单,它只初始化了SP以及PC,以及初始化了需要使用的寄存器,然后就执行连加循环中。使用ARM工具来汇编该程序,命令为:$armasm--cpucortex-m3-otest1.otest1.s命令行中的“‐o”指示后面的是输出文件名——也就是test1.o,它也就是目标文件。接下来,我们就要使用连接器,连接各目标文件(本例中只有一个)并创建出一个可执行的映像(ELF),命令为:$armlink--rw_base0x20000000--ro_base0x0--map-otest1.elftest1.o这里,“‐‐ro_base0x0”的意思是说,把只读区(也就是程序ROM)的起始地址设为0;而“‐‐rw_base0x20000000”则指定读写区(数据存储器)从0x20000000开始(在本例中,我们没有定义任何RAM数据)。“‐‐map”选项则要求连接器给出存储器分配映射表,通过它,可以查看编译后的映像中内存的布局。最后,我们要生成二进制烧写文件,命令行为:$fromelf--bin--outputtest1.bintest1.elf如果想要看看生成的映像是否确实是我们想要的,还可以像这样对它做反汇编:$fromelf-c--outputtest1.listtest1.elf(其实基本上很少会做上步——译者注)如果一切都好,就可以把ELF映像或者二进制代码烧写到器件中了,也可使用模拟器来测试。与外界互动

1 / 22
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功