版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、基于Cortex-M3内核的嵌入式软件开发 (AN179) 马 雷 译应用笔记179基于cortex-m3内核的嵌入式软件开发2007年版,所有版权保留。版本发布信息表1.版本更新历史记录日期版本更新的内容2007年1月A第一版发布(内部)2007年3月B第二版发布2009年5月1翻译英文第二版文档AN179关于所有权的说明 带有或者的字符和图标是ARM有限公司在欧盟和其它国家的注册商标。除非另有说明,在文中提到其它的商标和名字的所有权分别归他们的所有者拥有。在没有得到作者的书面许可之前,这份应用文档或其中的一部分都不得任何形式复制。这份文档描述的产品信息是不断更新和发展的。用户可以诚意地从A
2、RM公司得到关于这份文档的使用和更详细的产品信息。无论如何,这份应用文档意在帮助读者更好的使用这些产品;拒绝用于商业目的。由于用户使用这份文档造成的损失和伤害,ARM有限公司不承担任何责任。ARM公司这些条款的意思是这份应用文档作为一份软件开发的辅助资料,不作为标准使用。关于机密性的说明 这份文档是一份非机密文件。在得到ARM公司的授权许可后,用户有使用、复制,以及传播这份文件的权利。对于产品开发,这个文档描述的信息是最终版的。网址特此声明 本译文仅作为学习交流使用,不得用于任何商业目的。由此引起的版权纠纷,本人概不负责。译文中难免有一些不当之处,请指正。也可
3、邮箱联系,我的邮箱是。目 录第一章 Cortex-M3内核41.1 嵌套向量中断控制器(NVIC)41.2 存储器保护单元(MPU)41.3 调试端口(DAP)41.4 存储器映射4第二章 基于Cortex-M3内核的软件开发62.1 异常处理(Exception handling)6写一个异常表6写一个异常处理过程7放一张异常表7系统控制空间(SCS)寄存器的配置7设置一个中断请求9中断的优先级92.2 存储器保护单元(MPU)9MPU寄存器的地址9储器保护单元(MPU)的配置10存储器区域的大小和属性寄存器(存储器存取的类型和许可)10子区域(Sub-re
4、gions)112.3 栈和堆的配置11配置栈和堆11一个区域模型11两个区域模型12八字节栈队列122.4支持的指令集13访问存储器指令13屏蔽指令13条件执行指令142.5位别名区(Bit-banding)15地址变换(Address translation)15位别名区的读写(Reading and writing to the bit-banding region)15使用别名区的C语言代码(Using bit-banding from C code)152.6执行状态(Execution Modes)16工作方式(Operating Modes)16主堆栈和进程堆栈(Main and
5、 Process Stacks)162.7管理程序调用(Supervisor Calls(SVC)162.8 系统定时器(SysTick)18系统定时器18系统定时器的配置182.9 RVCT3.0的设置19编译器和汇编器的设置19链接器的设置19第一章 Cortex-M3内核这份应用文档介绍了Cortex-M3内核的ARM处理器的主要性能特点,及其相关的开发工具。这份应用文档还介绍了现有的ARM工程如何移植到Cortex-M3内核的ARM处理器上。 Cortex-M3内核的ARM处理器是一款高性能、低成本,以及其低功耗的32位精简指令处理器。这种内核的处理器仅仅支持Thumb-2指令,不支持
6、ARM指令系统。Cortex-M3内核是基于ARMv7-M架构设计的,是一种高性能ARMv7架构的三种内核之一;这种内核也有低的中断响应时间和划分硬件的特性。Cortex-M3内核也是CPU的内核,这种内核包括很多外设(一个嵌套向量中断控制器、一个可选择的存储器保护单元、定时器、调试端口、一个可选择的嵌入跟踪宏单元)。Cortex-M3内核的存储器内存映射是固定的。1.1 嵌套向量中断控制器(NVIC)这一标准依赖于半导体厂商的落实执行,嵌套向量中断控制器支持多达240个外部中断、这些多达256个不同的中断优先级来区分不同的中断。嵌套向量中断控制器支持电平触发和脉冲触发。当处理器响应中断时由硬
7、件自动保存处理器状态;当处理器退出中断时复位处理器状态。嵌套向量中断控制器还支持中断嵌套。Cortex-M3内核不同以前的ARM内核,通过嵌套向量控制器得到一张向量表。这张Cortex-M3的向量表包含异常处理和中断服务程序的地址,和其它大多数ARM核不同是非指令的。最初的堆栈指针和复位的地址必须分别为0x0和0x4;这些值在处理器复位时装入合适的处理器的寄存器。1.2 存储器保护单元(MPU)这个存储器保护单元是Cortex-M3内核可选择的外设。如果内核集成了存储器保护单元;这个外设提供一个强制的存储器保护区,以及在这个区域的存取规则。这个存储器保护单元支持多达八个不同的区域,并且每个区域
8、又分成八个大小相同的子区域。1.3 调试端口(DAP)调试端口使用AHB-AP总线接口连接处理器和其他外设。这种内核支持两种不同的调试接口分别是JTAG调试接口(SWJ-DP)和两线串行调试接口(SW-DP)。你使用这两种接口的任意一种就可以调试Cortex-M3内核的处理器,这些依赖于半导体厂商的落实执行。1.4 存储器映射不同于以前的ARM内核,Cortex-M3内核的器件的存储器映射是固定的。这一特性,在基于Cortex-M3内核的处理器不同的系统中用户很容易地使用软件的接口。这些地址空间分成很多不同的段,如图片1和表2所示。图片1 Cortex-M3存储器映射表2 详细描述了Corte
9、x-M3存储器映射存储器描述存取总线code代码段存储器 (flash, ROM, 或者重映射的RAM)指令总线和数据总线 SRAM带有位操作特性的片上SRAM系统总线peripheral带有位操作特性的普通外设系统总线external RAM外部存储器系统总线external device外设的存储器空间或者共享存储器系统总线Private peripheral为系统器件(MPU、NVIC、DAP,和其它的内核器件)提供的地址空间系统总线vendor specific附加厂商说明信息-第二章 基于Cortex-M3内核的软件开发这一章从多种不同的角度描述了基于Cortex-M3内核的软件开发
10、;如何为配置文件写代码以及这种内核的主要特性。这一章的例程是用RealView编辑工具(RVCT)3.0或者3.0以上的版本设计的。2.1 异常处理(Exception handling)写一个异常表要得到一个异常向量表的最简单的办法就是在存储器地址0x0的位置上放一个C函数指针指向分散加载描述文件;用这个C函数指针初始化堆栈指针,映像的入口指针和异常处理的地址。例1 为异常处理用C语言写的结构/* Filename: exceptions.c */typedef void(* const ExecFuncPtr)(void) _irq;/* Place table in separate s
11、ection */#pragma arm section rodata=exceptions_areaExecFuncPtr exception_table = (ExecFuncPtr)&Image$ARM_LIB_STACKHEAP$ZI$Limit,(ExecFuncPtr)_main, /* Initial PC, set to entry point */NMIException,HardFaultException,MemManageException,BusFaultException,UsageFaultException,0, 0, 0, 0, /* Reserved */S
12、VCHandler,DebugMonitor,0, /* Reserved */PendSVC,SysTickHandler,/* Configurable interrupts start here.*/InterruptHandler0,InterruptHandler1,InterruptHandler2/*/;#pragma arm section注释:在这个结构里完成两项工作:第一,初始化堆栈指针;第二,映像的入口指针。用连接器定义的符号产生一个初始化堆栈指针,关于堆和栈的详细配置说明请参阅11页。这个C库的入口指针就是映像的入口指针,如例1所示。也用宏指令(#pragma arm
13、section rodata=exceptions_area)将异常向量表放在它自己的那个段,在宏指令#pragma arm section rodata=exceptions_area和#pragma arm sectionin之间那个段称为异常区域,编译器遇到这个指令将数据放到R0里。在映像文件里会提到这个区域。然后,把异常向量表放在存储器映射地址0x0的正确位置上。写一个异常处理过程当一个异常发生或者恢复时,这个内核保存系统的状态。因此,这个异常处理过程不需要保存或者恢复系统状态;被写成一个普通的应用程序接口函数。尽管如此,我们推荐你使用限定词“_irq”;这个限定词使代码更清晰、明确。
14、编译器使用这个关键字堆栈需要的地方八字节对齐,八字节堆栈对齐更详细的信息请参阅13页。例2 简单的C语言异常处理过程_irq void SysTickHandler(void)printf(- SysTick Interrupt -);注释:执行中断服务程序后清楚相应的中断源。在Cortex-M3内核里,高性能内核完全地处理有优先次序的、可以嵌套的以及挂起的异常。这就意味着在每个异常处理过程的入口内核的中断都是使能的。放一张异常表在这个目标里,因为异常表已经放在了它的异常区域内,所以用这个映像文件很容易地将异常表放在0x0的地址上如例3所示。例3 在映像文件里放一张异常表LOAD_REGION
15、 0x 0x; Maximum of 256 exceptions (256*4 bytes = 0x400)VECTORS 0x0 0x400exceptions.o (exceptions_area, +FIRST)注释:首先确保这个绝对初始区域是异常区域;防止链接器不用段排除机制删除向量表。系统控制空间(SCS)寄存器的配置这个系统控制空间寄存器的地址是0xE000E000。因为系统控制空间寄存器里有很多单独的寄存器,所以最好用一个结构来声明它们。用放置异常表相似的方法,通过在映像文件里增加结构来设置系统控制空间寄存器在存储器的正确位置。系统控制空间寄存器的结构如例4所示。例4 SCS寄
16、存器结构typedef volatile struct int MasterCtrl;int IntCtrlType;int zReserved008_00c2;/* Reserved space */struct int Ctrl;int Reload;int Value;int Calibration; SysTick;int zReserved020_0fc(0x100-0x20)/4;/* Reserved space */* Offset 0x0100 */struct int Enable32;int Disable32;int Set32;int Clear32;int Acti
17、ve64;int Priority64; NVIC;int zReserved0x500_0xcfc(0xd00-0x500)/4;/* Reserved space */* Offset 0x0d00 */int CPUID;int IRQcontrolState;int ExceptionTableOffset;int AIRC;int SysCtrl;int ConfigCtrl;int SystemPriority3;int SystemHandlerCtrlAndState;int ConfigurableFaultStatus;int HardFaultStatus;int Deb
18、ugFaultStatus;int MemManageAddress;int BusFaultAddress;int AuxFaultStatus;int zReserved0xd40_0xd90(0xd90-0xd40)/4;/* Reserved space */* Offset 0x0d90 */struct int Type;int Ctrl;int RegionNumber;int RegionBaseAddr;int RegionAttrSize; MPU; SCS_t;注释:这个系统控制空间(SCS)寄存器结构不包含你的器件里的所有SCS寄存器;详细情况请参考芯片制造商的参考手册
19、。设置一个中断请求每一个中断请求对应嵌套向量中断控制器的中断使能寄存器的一个单独的位。为了使一个中断请求有效,你必须置位中断使能寄存器相应的位;关于中断使能寄存器的详细信息,用户请参考芯片制造商的数据手册。为第7页的例4所示的系统控制空间寄存器结构写的一个在中断使能代码如例5所示。例5 一个中断请求使能函数void NVIC_enableISR(unsigned isr)/* The isr argument is the number of the interrupt to enable. */SCS.NVIC.Enable (isr/32) = 1(isr % 32);注释:在系统控制空间
20、区域内,有一些寄存器只能在特权模式下访问。用户置位中断清除使能寄存器相应的位即可清除相应的中断。中断的优先级用户通过设置中断优先级寄存器来配置每一个中断的优先级。每一个中断有多达256不同的优先级;这些中断的优先级占用了8个位,存储器的每个字存储四个中断优先级在一起的组。优先级数低的为高优先级中断。因此,0是最高优先级;255是最低优先级。2.2 存储器保护单元(MPU)Cortex-M3内核有一个可选择的存储器保护单元(MPU)。如果你确定自己使用的芯片内部含有存储器保护单元,请参考数据手册或者从你的芯片制造商那里索取其它的信息。MPU寄存器的地址存储器保护单元(MPU)寄存器的地址是0xE
21、000ED90。存储器保护单元有5个基本的寄存器;每个寄存器有许多别名寄存器。存储器保护单元(MPU)寄存器的简要说明如表3所示,详见Cortex-M3技术参考手册。表3 MPU寄存器名称(name)地(Address)描述(Description)MPU类型寄存器0xE000ED90包括此寄存器的15-8位;无此寄存器默认为0。MPU控制寄存器0xE000ED94使能MPU;在特权模式下使用默认的存储器映射;在处理硬故障、非屏蔽中断,故障屏蔽时使能MPU。MPU区号寄存器0xE000ED98用于选择进行访问的保护区。0xE000ED9C用于写或读MPU区域的基地址。MPU区域属性与大小寄存器
22、0xE000EDA0用于写或读MPU区域的大小和控制权限。存储器保护单元(MPU)的每一个区域(MPU区域基地址寄存器、MPU区域属性与大小寄存器)都有一个别名区;用户操作这些别名区就可以直接操作MPU区域属性和大小寄存器。它们的地址是从存储器地址0xE000EDA4开始的。STM这些用法说明对用户快速的配置MPU很有帮助,用这些信息可以写别名区的地址。储器保护单元(MPU)的配置为了配置存储器保护单元的一个区域,首先你必须选择一个你想配置的区域。你有两种方法选择你想配置的区域:第一种方法,你可以写一个确定的值到MPU区号寄存器来选择你想要配置的区域;第二种方法,你可以写MPU区域基地址寄存器
23、的0到3位(VALID)来选择你想要配置的区域。同时,你也可以用第二种方法编程MPU区域基地址来编程MPU区域基地址寄存器。当你已经选择了一个区域时,你必须编程这个区域的基地址。按照这些区域的大小来排列基地址的值,因此一个64KB区域必须以许多64KB的大小排列(例如0x, 0x等等)。最后,你必须配置MPU区域属性与大小寄存器来设置这个区域的大小、许可,以及使能这个区域。关于这些寄存器的更详细的信息请参考Cortex-M3技术参考手册。注释:用户激活一些区域以前,用户可以写MPU控制寄存器的第0位来使能存储器保护单元(MPU)。存储器区域的大小和属性寄存器(存储器存取的类型和许可)这块存储器
24、保护单元(MPU)支持很多不同的存储类型、扩展,以及存储属性。你设置MPU区域属性与大小寄存器来配置MPU的每一个区域,MPU区域属性与大小寄存器的详细信息如表4所示。表4.MPU区域属性与大小寄存器位置(field)名称(name)功能描述(Description)28XN禁止指令存取位,该位为1时禁止指令存取。26:24AP数据存取位,在特权模式和用户模式允许你配置数据存取位来读写数据。21:19TEX扩展类型,允许你配置存储器存取类型。例如一些外设和指令。18S共享使能位。17C高速缓存使能位。16B缓冲器使能位。15:8SRD禁止子区域位(查看子区域Sub-region)。5:1REG
25、ION SIZE配置这个区域的大小,例如4K或者8K。0SZENABLE这个区域的使能位。关于这个区域的详细配置信息请参考Cortex-M3技术参考手册。子区域(Sub-regions)每一个存储区域都分成8个子区域,这些子区域是独立的不受其他的区域影响。每一个子存储区域的大小是整个存储区域大小的八分之一,用户通过修改在这个存储器区域的大小和属性寄存器里的禁止子区域位(SRD)来禁止子区域的操作;SRD的最低位可以屏蔽子区域的最低地址。子区域主要用于存储器区域的搭接或重叠。例如,如果你有一个很大的存储器区域,你仅仅想要其中的一小部分的属性不同;此时你就可以用子区域来选择这个很大的存储器区域的一
26、部分。在一个大的存储器区域里的一个子区域被禁用了,此时第二个MPU区域为这个子区域提供必要的属性。注释:子区域不能用在32字节、64字节,以及128字节大小的存储器区域。2.3 栈和堆的配置配置栈和堆RealView编译工具(RVCT)提供很多方法配置栈和堆在存储器的位置。其中有两种主要的方法:第一种,重新执行用户初始化堆和栈函数(_user_initial_stackheap());第二种,用确定的区域名将堆和栈放到映射文件里。这个编译工具也支持堆和栈的两种类型的执行,也即是一个区域模型和两个区域模型。在一个区域模型里,堆和栈共享一个单一的存储器区域。当栈从顶部向下生长时,堆是从存储器区域的
27、底部向上生长。在两个区域模型里,堆和栈分别有自己的存储器区域。堆从存储器的从头到尾一直向上生长;栈是从它自己的存储器的顶部一直向下生长。更进一步的信息,请查阅RVCT开发向导、RVCT编译器以及库参考向导。注释:你应该可以用MPU将侦查到的溢出放到一个存储区域内。一个区域模型如果你用一个区域模型,在存储器里放置堆和栈的最简单方式是放在映射文件里。在映射文件里,你需要用确定的区域名(ARM_LIB_STACKHEAP)来设置堆和栈区域的大小和地址。如例6所示。例6.摘录映射文件里一个区域模型的例子; Heap and stack share 1MBARM_LIB_STACKHEAP 0x EMP
28、TY 0x注释:EMPTY用于告诉编译器在连接时不增加这个区域的大小。你能使用链接器定义标识符(Image$ARM_LIB_STACK$ZI$Limit)在你的向量表里在最先入口处(at 0x0)放置栈的初始值。你能用重新执行这个函数(_user_initial_stackheap())代替用确定的区域名来设置堆和栈的大小和地址。尽管如此,你仍然必须确定在向量表里正确指定了SP的初值。关于这个函数(_user_initial_stackheap())的详细信息请参考RVCT开发向导和库使用向导。两个区域模型为了使用两个区域模型,在映射文件里你必须指定两个区域;其中一个区域为堆,另一个区域为栈;
29、它们有自己特殊的区域名分别是ARM_LIB_HEAP和ARM_LIB_STACK。你也必须增加一条汇编语言形式的输入语句(_use_two_region_memory)或者一条C语言形式的输入语句(_use_two_region_memory)。你这样声明以后就可以使用两个区域模型而非(默认)一个区域模型。如例7所示。例7.摘录映射文件里两个区域模型的例子; Heap starts at 1MB and grows upwardsARM_LIB_HEAP 0x EMPTY 0x-0x8000; Stack space starts at the end of the 2MB of RAM; a
30、nd grows downwards for 32KB (indicated by the negative length)ARM_LIB_STACK 0x EMPTY -0x8000你能使用链接器定义标识符(Image$ARM_LIB_STACK$ZI$Limit)在你的向量表里在最先入口处(at 0x0)放置栈的初始值。另一种方法,你能用重新执行这个函数(_user_initial_stackheap())代替用确定的区域名来放置堆和栈。尽管如此,如前所述你必须添加指向向量表的初始化栈指针。八字节栈队列ARM结构要求在所有的外部接口上栈必须八字节对齐,即双重的应用接口。例如在不同的源文件函
31、数之间的调用。尽管如此,内部编码不需要支持八字节栈对齐例如一个函数的子函数。这就意味着当中断或者异常发生时,这个栈不能八字节对齐。当一个异常发生时,Cortex-M3的第一版和以后的版本内核能自动的对齐栈指针。你可以配置地址(0xE000ED14)处的配置寄存器里的STKALIGN (bit9)寄存器的第九位来使能这个功能。如果你用Cortex-M3版本0的话,硬件上不支持这种栈的调整。编译器会在你的中断请求处理操作时生成正确的对齐栈代码。为了这样操作你必须在你的中断请求处理函数名前使用前缀(_irq);这个前缀(_irq)是处理器为Cortex-M3的零版本内核(cpu=Cortex-M3-
32、rev0)的编译开关,而不是所有Cortex-M3内核处理器(-cpu=Cortex-M3)的编译开关。注释:处理器为Cortex-M3的零版本内核(cpu=Cortex-M3-rev0)的编译开关(_irq)只有在RVCT 3.0 SP1或者其以上的版本才支持。2.4支持的指令集因为通常会有一些特殊的用法不容易用C语言表达的功能,Cortex-M3这种内核支持很多编译器不能自己生成的指令。尽管如此,用户仍然通过汇编程序或者嵌入汇编的方式一直使用着这些指令。注释:你可以在RVCT汇编程序向导和ARM架构参考手册找到关于下面的指令更多的详细信息和完整的指令集。访问存储器指令编译器不能用C语言直接
33、生成的主存储器指令是用于装载和存储的专用指令(LDREX和STREX)。这些指令常常专用于存储器的存取操作,例如在不同的线程之间提供人工干预操作。屏蔽指令Cortex-M3,这种内核支持许多屏蔽指令。在下一个指令或者事件开始执行以前,这些屏蔽指令常常用于确保必然事件执行完成。在处理器内部,指令同步屏蔽(ISB)刷新流水线;以致于这个指令执行完以后,紧接着从缓存或者存储器取出指令表。这个表会改变这个系统,例如MPU立即生效。数据同步屏蔽(DSB)指令作为一种特殊的存储器屏蔽指令。访问外部存储器操作完成之前,执行完成数据同步屏蔽指令(DSB)。执行数据同步屏蔽指令,在该指令没有完成以前不再执行任何
34、指令换句话说,执行完成所有的挂起操作。数据存储屏蔽(DMB)指令作为一种存储器屏蔽指令。数据存储屏蔽(DMB)指令和数据同步屏蔽(DSB)指令有微小的差别。数据存储屏蔽(DMB)指令确保:数据同步屏蔽(DSB)指令执行完成之前,访问任意存储器;执行数据同步屏蔽(DSB)指令后,紧接着执行访问任意存储器操作。如例8所示,典型MPU代码的一部分显示如何这些屏蔽指令。用嵌入汇编完成一个小的功能,每个功能都含有一条屏蔽指令。编译时链接器将连接这些功能。例8 用预处理指令使用屏蔽指令的范例/* pseudo_intrinsics.c */* Small embedded assembly functio
35、ns for barrier instructions*/* Link with armlink -inline . */_asm void _ISB(void)ISBBX lr_asm void _DSB(void)DSBBX lr/* scs.c - Initialize System Control Space registers */void SCS_init(void)/* Code to configure the MPU regions inserted here*/* Enable the MPU */SCS.MPU.Ctrl |= 1;/* Force Memory Writ
36、es before continuing */_DSB();/* Flush and refill pipline with updated permissions */_ISB();条件执行指令不同ARM指令,大部分的精简指令(Thumb)不受限制可以执行。除了精简指令集1提供的16位条件转移外,精简指令集2增加了3个条件指令。它们分别是:(1) 一个改进的32位条件转移指令,这条指令可以向前或者向后的范围是 一兆字节(1MB)。(2) 16位与0比较转移转移指令(CBZ)和16位与非0比较转移指令(CBNZ), 跳转的范围是从4字节到130字节。例如当向下计数到0时,这条指令能生成从一个循
37、环跳出的C语言代码。(3)16位的if-then指令(IT),这条指令(IT)常常用于补偿下面的4个条件指令。这是一个大多数用于代替条件执行的指令,例如在简短的if结构里。汇编程序能自动生成适合16位的if-then指令(IT)代替有条件的执行指令。当其它的ARM程序代码移植到Cortex-M3内核的处理器时,这条指令特别有用。 系统“提示”(hints)如果你的工具支持的话,这里有很多直接对内核操作的指令。对内核而言,这些指令只提供一种指示;不强制内核去做这种操作。如果你的器件不支持那指令,那么指示指令的一部分或者全部作为一个空操作执行(“NOP”)。表5列出了指示指令指令功能描述WFE等待
38、事件唤醒以前用于指示处理器在低功耗模式或者等待事件。当唤醒时不需要软件干涉。WFI等待中断唤醒以前用于指示处理器在低功耗模式或者等待中断。当唤醒时不需要软件干涉。SEV发送一个事件在多核系统中发送一个事件到所有的处理器。2.5位别名区(Bit-banding)位别名区(Bit-banding)的一个字映射到位段区(Bit-band)的一个比特位。例如,写别名区的一个字将置位或者清除位段区相应的一个位。这允许用一个简单的装入寄存器指令(LDR)存取操作一个字别名地址来直接对别名区每个独立的位存取操作;同样也允许对C语言来说,触发每个独立的比特位不需要执行一个读-改-写的指令序列。地址变换(Add
39、ress translation)这种Cortex-M3内核有两个32MB的别名区映射到两个1MB位段区。这两个别名区是独立分开的,一个在SRAM区;另一个在外设区。在位段区的每个位对应32MB位别名区连续的地址。例如,对位段区的第八个位存取操作只需操作32MB的别名区相应的一个字。位别名区的读写(Reading and writing to the bit-banding region)当写别名区一个32位字的第0位(bit0)时,常常在别名区(bit-banding)置一个值。当从别名地址读时,将从位段区第0位返回一个值;其它的位将清0。你也可以用正常的存取(字、半字以及字节)的方式在位段
40、区访问基本的位段区。使用别名区的C语言代码(Using bit-banding from C code)对C语言来说,用宏预处理指令来执行访问别名区(bit-banding)。你如何使用别名区如例9所示。例9用宏预处理指令使用别名区的C语言代码#define BITBAND_SRAM_REF 0x#define BITBAND_SRAM_BASE 0x#define BITBAND_SRAM(a,b) (BITBAND_SRAM_BASE + (a-BITBAND_SRAM_REF)*32 + (b*4) / Convert SRAM address#define BITBAND_PERI_R
41、EF 0x#define BITBAND_PERI_BASE 0x#define BITBAND_PERI(a,b) (BITBAND_PERI_BASE + (a-BITBAND_PERI_REF)*32 + (b*4) / Convert PERI address#define MAILBOX 0x#define TIMER 0x/ Mailbox bit 0#define MBX_B0 *(volatile unsigned int *)(BITBAND_SRAM(MAILBOX,0)/ Mailbox bit 7#define MBX_B7 *(volatile unsigned in
42、t *)(BITBAND_SRAM(MAILBOX,7)/ Timer bit 0#define TIMER_B0 *(volatile unsigned char *)(BITBAND_PERI(TIMER,0)/ Timer bit 7#define TIMER_B7 *(volatile unsigned char *)(BITBAND_PERI(TIMER,7)int main(void)unsigned int temp = 0;MBX_B0 = 1; / Word writetemp = MBX_B7; / Word readTIMER_B0 = temp; / Byte writ
43、ereturn TIMER_B7; / Byte read2.6执行状态(Execution Modes)工作方式(Operating Modes)Cortex-M3支持特权模式和用户模式(非特权模式)下执行。在特权模式,代码的执行不受任何限制;相反的在用户模式下,代码的执行受到一定的限制。这些限制包括指令用法的限制(例如MSR的作用域),基于系统设计限制访问存储器和外设;通过配置MPU可以设置限制操作。处理器支持两种工作方式,即线程模式和处理程序模式。正常情况下从一个异常返回或者复位后处理器进入线程模式。当在线程模式下,代码可以在特权模式下执行;也可以在非特权模式下执行。由于一个异常发生,处
44、理器进入处理程序模式。在处理程序模式下,代码总是以特权模式执行;因此当一个异常发生时,内核自动切换到特权模式执行。在链接寄存器(R14)里,当你调整变量(EXC_RETURN)的值而从一个异常返回时;你能在特权线程模式和用户线程模式之间切换。你也可以用MSR指令清除CONTROL0第0位来从特权线程模式切换到用户线程模式。尽管如此整个过程没有任何异常的情况下,你不能直接从非特权模式切换到特权模式。例如一个管理程序调用(SVC)。主堆栈和进程堆栈(Main and Process Stacks)Cortex-M3支持两种不同的堆栈,一个是主堆栈和另一个进程堆栈。为了支持这两个堆栈,Cortex-
45、M3有两个堆栈指针(R13)。在使用中用哪种堆栈指针取决于堆栈。对于R13而言,每次只使用一个堆栈指针。尽管如此,你也能使用指令MSR和MRS来访问这两个堆栈指针。复位后使用主堆栈;在处理程序模式(当进入一个异常处理程序时)总是使用主堆栈。当在线程模式时,进程堆栈指针仅仅作为当前的堆栈指针有效。在线程模式下你有两种方法去选择是使用主堆栈指针还是使用进程堆栈指针。当退出处理程序模式时,你可以用变量EXC_RETURN的值来选择是使用主堆栈指针还是使用进程堆栈指针;当在线程模式时,你可以用指令MSR来写CONTROL1第1位来选择是使用主堆栈指针还是使用进程堆栈指针。注意:你必须用上下文切换程序或
46、者初始化程序初始化进程堆栈指针。2.7管理程序调用(Supervisor Calls(SVC)与以前的ARM内核一样,Cortex-M3有一条生成管理程序调用请求的指令SVC(以前称为SWI)。管理程序调用指令常常用于请求特权操作或者来自操作系统的访问系统资源的请求。一个数嵌入到管理程序调用指令里,这个数常被称为是管理程序调用序号。这个管理程调用序号有时用来指示是什么调用请求。对于以前的ARM核来说,你必须在链接寄存器里用返回地址从这条指令中提取管理程调用序号;而其它的管理程调用的自变量早在从R0到R3的时候有效。在开始进入异常时,Cortex-M3内核自动将管理程序调用的自变量寄存器保存在堆
47、栈中。管理程序调用指令(SVC)的处理程序的第一条指令执行以前,一个迟到的异常发生可能会破坏这个自变量的副本与R0到R3保持的同步。这就意味着,管理程序调用指令(SVC)的处理程序使用堆栈里这个自变量的副本。调整堆栈寄存器的值必须将任意的返回值传递给调用函数;为了这样做,当开始执行管理程序调用指令(SVC)的处理程序时必须执行一段简短的汇编代码。从堆栈寄存器保存的标识符指令中提取的管理程序调用指令(SVC)序号、传递次数,以及一个指向用C语言写的处理程序结构的自变量的指针。如例10所示是一个管理程序调用指令(SVC)处理程序的例子。当调用SVC指令时,处理器设置代码测试值EXC_RETURN来
48、确定使用的栈指针。对大多数系统而言SVC指令不需要这样做,因为在一个典型的系统设计里管理程序调用(SVC)只有使用进程堆栈的用户代码组成。既然这样,汇编代码是有一些简单的MSR指令组成;后面紧接着是处理程序C结构的分支(B instruction变址指令)。例10 SVC处理程序_asm void SVCHandler(void)IMPORT SVCHandler_mainTST lr, #4MRSEQ r0, MSPMRSNE r0, PSPB SVCHandler_mainvoid SVCHandler_main(unsigned int * svc_args)unsigned int s
49、vc_number;/* Stack contains:* r0, r1, r2, r3, r12, r14, the return address and xPSR* First argument (r0) is svc_args0*/svc_number = (char *)svc_args6)-2;switch(svc_number)case SVC_00:/* Handle SVC 00 */break;case SVC_01:/* Handle SVC 01 */break;default:/* Unknown SVC */break;你能声明许多不同的管理程序调用指令(SVC)序号,如例11所示。_ _svc是一个编译器的关键字,用来替代用一个包含特定数字的SVC指令调用一个函数。例11 C语言的形式调用SVC的例子#define SVC_00 0x00#define SVC_01 0x01void _svc(SVC_00) svc_zero(const char *string);void _svc(SVC_01) svc_one(const char *string);int call_system_func(void)svc_zero(Strin
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025LED显示屏租赁合同范本
- 2025年短视频内容分发渠道合同协议(流量合作)
- 2025花卉买卖合同范本
- 保密协议书 著作
- 私募基金合伙人协议书
- 美容合资协议合同范本
- 承继协议书与补充协议书区别
- 2025年标准劳动合同范本下载
- 社区医疗合作协议书
- 物流分包协议书
- 《零售药店实务》期末考试复习题库(含答案)
- 人教版(2019)选择性必修第二册Unit 1 Science and Scientists Workbook Expanding Your World 课件
- 前置胎盘临床诊断与处理指南
- 市值管理定制服务协议
- 如何做好转介绍
- 汉语拼音音节全表优质资料
- 支局长培训测试题附答案(商客)
- 2022福建泉州市丰泽区市场监督管理局公开招聘人员3人模拟试卷【共500题附答案解析】
- 幼儿园绘本故事:《我不知道我是谁》
- 船舶结构与设备课件——船体结构
- A Brief Introduction to the United Kingdom
评论
0/150
提交评论