基于Cortex-M4内核的寄存器要点总结

Cortex-M4的寄存器

        ARM架构中,处理器不能直接操作内存(存储器)中数据,必须先把内存中的数据加载到寄存器组中的寄存器里,处理完后,若有必要,再写回内存。这种方式一般被称作“加载-存储架构”。如果core的寄存器数量充足的话,在进行数据处理时,寄存器组中可以临时存储一些数据变量,而无需每次更新到系统内存及在使用时将它们读回,从而可以有效的提高系统的工作效率。

1.Register Bank

        Cortex-M4有16个用于数据处理和程序控制的寄存器,称为Register Bank,依次被标记为R0~R15。

        R0~R12是32位通用寄存器(general purpose register)。其中前8个寄存器R0~R7被称为low register,因为访问空间的限制,大多数16位指令只能够访问low registers。而high register(R8~R12)则能被32位和几个特殊的16位指令(如MOV(move))访问, R0~R12的初始值是未定义的。

R13,栈指针SP(stack pointer,堆栈指针) 32

  1. 通过PUSH和POP指令访问栈空间内存(即系统的RAM区)。物理上存在两个栈空间指针:主栈指针Main Stack Pointer(MSP, 或SP_main)和进程栈指针Process Stack Pointer(PSP, 或SP_process)。其中MSP是默认的栈指针,系统复位或运行在处理(Handler)模式下时,通过R13访问的是MSP, 而PSP只能在线程(Thread)模式下使用。
  2. 至于使用的是哪个栈指针由CONTROL寄存器控制/配置(仅在Thread Mode下才可设置CONTORL寄存器),但在同一时间只有一个栈指针工作。 MSP和PSP都是32位的寄存器,但它们的低两位总是0,对这两个bit位的写操作不起作用。对于ARM Cortex-M处理器,PUSH和POP指令总是32位的,栈操作的地址也必须对齐到32位的字边界上。
  3. 一般用到嵌入式OS时才会使用PSP(用于thread级app的SP),此时OS内核同应用任务的栈是相互独立的。PSP得初始值未定义,而MSP(用于OS内核的SP)的初始值则需要在复位流程中从存储器的第一个字中取出。
  4. 在编译器中,可以通过r13(R13)或sp(SP)来访问堆栈(具体是MSP和PSP由当时环境决定);也可以通过指定的MRS、MSR指令来访问MSP和PSP。
  5. 注:

    Cortex-M0中堆栈方向是向低地址方向增长,为满堆栈机制。堆栈操作是通过PUSH和POP来完成操作的。(压栈:栈顶地址减小;出栈:栈顶地址增大)

    栈一般放在ARM的 RAM高位区,如某MCU中RAM地址为0x20000000-0x20007fff,共32KByte。栈大小设为4KByte的话,其地址一般就放在0x20007000-0x20007fff,其中0x20007000为绝对栈顶,0x20007ffc为绝对栈底,sp总是指向相对栈顶。第一个PUSH数据被存在绝对栈底(此时绝对栈底也是相对栈顶)。实际上,除了POP指令可以从栈顶中取数据外;MOV指令也可从任意位置取数据,但不会影响栈结构(即不影响其sp)。

    由于ARM寄存器均是32bit,故PUSH和POP指令均是32bit访问,故sp指针总是至少4Byte对齐(低2bit永远为0)。有时编译器也会分配8Byte对齐的栈,这是由于double浮点类型需要占用8Byte,为了处理方便,故将栈设为8Byte对齐。

    在一般函数(无参无局部变量无返回值)嵌套调用时,关于sp的操作。在执行BL FunctionA指令时,LR记录的是BL FunctionA的下一条顺序指令,在进入FunctionA后执行的第一条操作便是PUSH {LR}即将下一条顺序指令压入栈中,然后才开始执行FunctionA函数体。函数体执行结束之后,使用POP {PC}指令将栈顶数据弹到PC中,即可返回继续执行BL FunctionA的下一条顺序指令。函数嵌套调用与函数返回关系如下图:

 

R14,链接寄存器LR (Link Register)

  1. 它被用于在调用函数或者执行子程序时,记录返回地址,在函数或子程序结束时,程序控制可以通过将LR的数值加载到程序计数器(PC)中,从而返回到调用程序处并继续执行。
  2. 在发生函数或子程序调用时,LR的值会被自动更新,如果被调用的函数在执行过程中仍需要调用其他函数, 则需要先把LR的值压栈,保存,否则返回地址将丢失。
  3. 异常处理(中断也是一种异常)期间,LR会被写入一个特别的值EXC_RETURN(异常返回),之后该数值会在异常处理结束时触发异常返回。
  4. 虽然在Cortex-M处理器中,任何函数的返回地址都一定是偶数(由于指令会对齐到半字地址上,因此第0位为0),但LR的第0位仍然是可读可写的,有些跳转/调用操作需要将LR(或正在使用的任何寄存器)的第0位,置1以表示Tbumb状态。

R15,程序计数器PC (Program Counter),可读可写。

  1. 读操作返回当前指令地址+4(由于流水线特性的设计以及对ARM7TDMI的兼容设计)。 写操作(例如,使用数据传输/处理指令)将导致程序执行地址的跳转。
  2. 因为指令必须半字或者整字对齐,所以PC的最低位(LSB)总为0。 但是通过跳转等语句更新PC时,需要将PC的最低位置1,以标识Thumb状态,否则会由于使用不支持的ARM指令(如ARM7TDMI中的32位ARM指令)而触发错误异常。对于C语言编程,不需要考虑这一点,因为编译器已经帮我们完成了这一操作。(对于高级编程语言,包括C和C++编译器会自动将跳转目标的LSB置位)
  3. 多数情况下,跳转和调用由专门的指令实现,利用数据处理指令更新PC的情况较少。不过,在访问位于程序存储器中的字符数据时,PC数值非常有用,因此会经常发现存储器读操作将PC作为基地址寄存器,而地址偏移则由指令中的立即数生成。

2.特殊寄存器

除了上述Register Bank中涉及到的16个寄存器外,Cortex-M4还有一些反应系统状态、控制内核工作模式、异常中断屏蔽掩码等特殊功能的寄存器。 这些特殊的寄存器并没有分配地址映射,可以通过MSR或者MRS读写这些寄存器。

2.1.状态寄存器PSR(Program Status Register)

APSR(Application PSR)、EPSR(Execution PSR)和Interrupt PSR(IPSR)。另外这三个寄存器可以组合为一个寄存器一起访问,标记为xPSR。

注:GE只有基于ARMv7E-M架构的处理器才有,例如Cortex-M4

在ARM的汇编器中,用PSR标识三个状态寄存器的组合。 我们可以单独的访问每个状态寄存器,也可以通过PSR访问他们的组合,参考如下的代码。 但是,需要注意的是,EPSR是不能够直接通过MRSMSR读写的,而IPSR则是一个只读的寄存器

MRS r0, PSR  ; 读组合寄存器的值到r0中

MSR PSR, r0  ; 写r0的值到组合寄存器中

        MRS r0, APSR ; 读应用寄存器的值到r0中

        MSR APSR, r0 ; 写r0的值到应用寄存器中

状态寄存器的位定义如下:

N: 负数标识位(Negative flag)

Z: 零标识位(Zero flag)

C: 进位或者无借位标识位(Carry or NOT borrow flag)

V: 溢出标识位(Overflow flag)

Q: Sticky saturation flag

GE: 大于等于标识位(Greater-Than or Equal flags for each byte lane)

ICT/IT: Interrupt-Continuable Instruction(ICT)bits, IF-THEN instruction status bit for conditional execution.

T: Thumb状态标识位,始终为1;尝试清除该位将触发一个错误异常。

Exception Number: 异常代号,标志着正在处理的异常。

2.2.异常/中断掩码寄存器(PRIMASK, FAULTMASK, 和BASEPRI

  1. 仅在privileged的情况下访问。每个异常/中断都有一个优先级,取值越小优先级越高。默认情况下,这些寄存器的值都为0,所有的中断都是关闭的。
  2. PRIMASK只有最低位有定义,用于打开或屏蔽除复位、NMI(Non-Maskable Interrupt, 不可屏蔽中断)以及硬件错误异常(HardFault Exception)外的所有异常和中断。 同时会把当前正在处理的中断或者异常的优先级提升到level 0,可屏蔽中断的最高优先级。
  3. PRIMASK通常用于执行一些对时序要求严格的任务时,暂时关闭所有中断,实时程序处理完毕后清除PRIMASK,重新开启中断。
  4. FAULTMASK与PRIMADSK类似,并且它可以关闭硬件异常(HardFault Exception),同时把当前异常的优先级提升至level -1。 和PRIMASK不同的是,当中断服务程序返回后FAULTMASK将会自动清除。
  5. 为了提供灵活的中断屏蔽机制,ARMv7-M架构提供了BASEPRI寄存器,可以根据优先级屏蔽中断或者异常。 BASEPRI寄存器的可用位长由具体的CPU厂商实现,Cortex-M4通常有8个或者16个优先级,因此通常为3位或者4位。 BASEPRI中的值为0时,没有作用。BASEPRI非零时,将屏蔽具有相同和更低优先级的中断。(中断优先级号低于阈值不屏蔽,等于或高于阈值屏蔽)
  6. CMSIS-Core定义了一系列的C语言函数用来访问这三个中断屏蔽寄存器:

        x = __get_BASEPRI();

        x = __get_PRIMASK();

        x = __get_FAULTMASK();

        __set_BASEPRI(x);

        __set_PRIMASK(x);

        __set_FAULTMASK(x);

        __disable_irq();    // 置位PRIMASK,关闭中断

        __enable_irq();     // 清除PRIMASK,开启中断

也可以通过汇编语句访问这些寄存器:

MRS r0, BASEPRI  ; 读BASEPRI值到r0

MRS r0, PRIMASK   ; 读PRIMASK的值到r0

MRS r0, FAULTMASK ; 读FAULTMASK的值到r0

MSR BASEPRI, r0   ; 写r0的值到BASEPRI

MSR PRIMASK, r0   ; 写r0的值到PRIMASK

MSR FAULTMASK, r0 ; 写r0的值到FAULTMASK

另外,更改处理器状态(Change Processor State)指令提供了用于修改

PRIMASK和FAULTMASK的简单指令:

CPSIE i ; 清除PRIMASK,使能中断

CPSID i ; 置位PRIMASK,关闭中断

CPSIE f ; 清除FAULTMASK,使能中断

CPSID f ; 置位FAULTMASK,关闭中断

2.3.控制寄存器(CONTROL

  1. CONTROL寄存器主要用来选择栈空间指针寄存器。
  2. CONTROL寄存器只能够在系统具有privileged级权限下被修改,它可以在任何情况下被读取。

      系统复位后,CONTROL的值为0,标识着系统以MSP作为栈空间指针寄存器,而且具有privileged级的访问权限。priveleged的应用程序可以通过写CONTROL寄存器,切换栈空间指针和系统的访问权限。

     但是一旦nPRIV置位后,系统将不能对CONTROL寄存器进行写访问。也就是说,在unpriveleged级权限下的系统不能自由地变更系统的访问权限和栈空间指针。这对于系统的安全性而言是有必要的。

       如果必须切换回privileged的权限,则需要借助中断机制。在中断服务程序中清除nPRIV位,中断服务程序返回后系统就具有了privileged的权限。

       对于使用CMSIS接口的处理器,我们可以通过如下的C语言代码访问CONTROL寄存器:

        x = __get_CONTROL();

        __set_CONTROL(x);

       或者汇编的形式:

        MRS r0, CONTROL ; 读CONTROL中的数据到r0中

        MSR CONTROL, r0 ; 写r0的数据到CONTROL中

在对CONTROL寄存器进行写操作时,有两点需要注意:

  1. 对于有FPU的Cortex-M4处理器,执行浮点数指令时,FPCA位会被自动置位。 如果写操作清除了该位,紧接着产生了中断的话,浮点运算单元中的数据将不会被保存,在中断处理过程中可能修改相关的寄存器,导致中断返回时数据不能正常恢复。
  2. 修改了CONTROL寄存器后,需要执行一个Instruction Synchronization Barrier(ISB)指令, 以保证修改能够应用到以后需要执行的代码中。 而Cortex-M4做了简化,不执行这一操作也没有影响。

3.常用汇编指令

ldr:通常都是作加载指令的,但是它也可以作伪指令,通常有两种不同的表示:

1)ldr pc, =MyHandleIRQ 表示将MyHandleIRQ地址放入pc寄存器中,相当于PC=MyHandleIRQ 。

例如:

ldr r0,=label

//用于加载立即数或一个地址值到指定寄存器中

//如果label是立即数: ldr r0,=0x123 ;将0x123存入r0中

//如果label是个标识符: ldr r0,=label_1 ;将label_1所指向的地址值存入r0中

2)ldr pc,MyHandleIRQ 表示将 MyHandleIRQ地址中的值放入pc寄存器中,相当于PC=*(MyHandleIRQ )。

例如:

ldr r0,[r1] //将r1中的值存到r0中

ldr r1,[r2,#16] //将(r2+16)地址中的内容存到r1中

ldr r1,[r2],#4 //将r2地址中的内容存到r1中,同时r2=r2+4

3)LDMIA R1!,{R0,R4-R12}

LDMIA 中的 IA表示每次访问后递增地址,LD表示加载(load)

R1后面的感叹号“!”表示会自动调节 R1里面存的指针

该代码段表示:任务栈R1的存储地址由低到高,将R1存储地址里面的内容手动加载到 CPU 寄存器 R0,R4-R12里面;

4)STMDB R1!, {R0,R4-R12}

与3)指令相反,ST表示存储(store),D表示decrease,B表示before,

该代码段表示:R1的存储地址由高到低递减,将R0,R4-R12里的内容存储到R1任务栈里面。

  • 31
    点赞
  • 64
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
STM32F407ZGT6GK原理图 STM32F407ZGT6 :ARM Cortex-M4 32位 MCU+FPU,210DMIPS,高达1 MB Flash/192 + 4KB RAM,USB OTG HS/FS,以太网,17 个TIM,3个ADC,15 个通信接口、摄像头。 特性: 1、内核:带有 FPU 的 ARM® 32 位 Cortex®-M4CPU、在 Flash 存储器中实现零等待状态运行性能的自适应实时加速器 (ART 加速器 ™)、主频高达 168MHz, MPU,能够实现高达210 DMIPS/1.25DMIPS/MHz (Dhrystone 2.1)的性能,具有 DSP 指令集。 2、存储器 – 高达1 MB Flash – 高达 192+4 KB的SRAM, 包括64-KB的CCM(内核耦合存储器)数据 RAM – 具有高达 32 位数据总线的灵活外部存储控制器: SRAM、 PSRAM、 NOR/NAND存储器 3、 LCD 并行接口,兼容 8080/6800 模式 4、 时钟、复位和电源管理 – 1.8 V 到 3.6 V 供电和 I/O – POR、 PDR、 PVD 和 BOR – 4 至 26 MHz 晶振 – 内置经工厂调校的 16 MHz RC 振荡器( 1% 精度) – 带校准功能的 32 kHz RTC 振荡器 – 内置带校准功能的 32 kHz RC 振荡器 5、低功耗 – 睡眠、停机和待机模式 – VBAT 可为 RTC、 20×32 位备份寄存器 + 可选的 4 KB 备份 SRAM 供电 6、3 个 12 位、 2.4 MSPS ADC:多达 24 通道,三重交叉模式下的性能高达 7.2 MSPS 7、2 个 12 位 D/A 转换器 8、通用DMA:具有FIFO和突发支持的16路DMA控制器 9、多达17个定时器: 12个16位定时器,和2个频率高达 168 MHz 的 32 位定时器,每个定时器都带有 4 个输入捕获 / 输出比较 /PWM,或脉冲计数器与正交 ( 增量 ) 编码器输入 10、调试模式 – SWD & JTAG 接口 – Cortex-M4 跟踪宏单元 ™ 11、多达 140 个具有中断功能的 I/O 端口 –高达 136 个快速 I/O,最高 84 MHz – 高达 138 个可耐 5 V 的 I/O 12、多达 15 个通信接口 – 多达 3 个 I2C 接口 (SMBus/PMBus) – 高达 4 个 USART/4 个 UART( 10.5 Mbit/s、ISO7816接口、 LIN、 IrDA、 调制解调器控制) – 高达 3 个 SPI ( 42 Mbits/s), 2 个具有复用的全双工 I2S, 通过内部音频 PLL 或外部时钟达到 音频级精度 – 2 个 CAN ( 2.0B 主动)以及 SDIO 接口
Cortex-M4是一种32位内核的微控制器处理器,由ARM公司推出。技术参考手册是为了帮助开发人员更好地了解和使用Cortex-M4处理器。 Cortex-M4技术参考手册详细介绍了Cortex-M4的体系结构、寄存器、指令集、中断控制和外设等方面的内容。通过阅读这本手册,开发人员可以深入了解Cortex-M4的各种功能和特性,从而更好地进行软件开发和系统设计。 首先,手册介绍了Cortex-M4的体系结构,包括处理器核心、存储器系统和总线接口等。开发人员可以了解到Cortex-M4的组成部分和各个模块的功能,从而能够更好地利用这些功能进行软件编程。 其次,手册提供了Cortex-M4的寄存器信息,包括通用寄存器、特权寄存器和系统控制寄存器等。开发人员可以通过查阅这些寄存器的描述和操作指南,实现对Cortex-M4内部状态的控制和管理。 指令集是处理器的核心部分,Cortex-M4的技术参考手册提供了详细的指令描述和执行规则。开发人员可以了解到Cortex-M4支持的指令类型和格式,以及各种运算和控制指令的具体作用和使用方法。 此外,手册介绍了Cortex-M4的中断控制系统和外设接口。开发人员可以学习如何配置和操作中断控制器,实现对外部事件的响应和处理。同时,手册还介绍了Cortex-M4支持的各种外设接口,如GPIO、UART、SPI等,开发人员可以根据手册提供的信息,进行外设的使用和配置。 总而言之,Cortex-M4技术参考手册是一本必要的参考资料,对于希望了解和使用Cortex-M4处理器的开发人员来说,具有重要的指导作用。通过阅读手册,开发人员可以全面了解Cortex-M4的体系结构和功能特性,从而能够更好地进行软件开发和系统设计。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ChenK21_idea

看后有收获,请赐些奶粉钱,谢谢

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值