通用目的寄存器
1. 寄存器组。Cortex-M4有16个用于数据处理和程序控制的寄存器,称为寄存器组,依次被标记为R0~R15。R0~R12是32位通用寄存器(general purpose register)。其中前8个寄存器R0~R7被称为低寄存器,因为访问空间的限制,大多数16位指令只能够访问low registers。而R8 ~R12称为高寄存器,能被32位和几个特殊的16位指令访问,R0~ R12的初始值是未定义的。
2. R13为栈指针SP(stack pointer) 。通过PUSH和POP指令访问栈空间内存(即系统的SRAM区)。物理上存在两个栈空间指针:主栈指针(Main Stack Pointer,MSP)和进程栈指针(Process Stack Pointer,PSP)。其中MSP是默认的栈指针,系统复位或运行在处理(Handler)模式下时,通过R13访问的是MSP, 而PSP只能在线程(Thread)模式下使用。至于使用的是哪个栈指针由CONTROL寄存器控制/配置(仅在Thread Mode下才可设置CONTORL寄存器),但在同一时间只有一个栈指针工作。 MSP和PSP都是32位的寄存器,它们的低两位总是0,对这两个位的写操作不起作用。对于Cortex-M3/4处理器,PUSH和POP指令总是32位的,栈操作的地址也必须对齐到32位的字边界上。 一般用到RTOS时才会使用PSP,此时RTOS内核与应用任务的栈是相互独立的。PSP得初始值未定义,而MSP(用于OS内核的SP)的初始值则需要在复位流程中从存储器的第一个字中取出。 在编译器中,可以通过R13或SP来访问堆栈,具体访问的是MSP和PSP由当时环境决定。
3. R14为链接寄存器LR (Link Register)。它被用于在调用函数或者执行子程序时,记录返回地址,在函数或子程序结束时,程序控制可以通过将LR的数值加载到程序计数器PC中,从而返回到调用程序的调用点处,并继续执行。在发生函数或子程序调用时,LR的值会被自动更新,如果被调用的函数在执行过程中仍需要调用其他函数, 则需要先把LR的值压栈保存,否则前一次调用函数的返回地址将丢失。在异常或中断服务函数执行时,LR中写入一个EXC_RETURN,表示异常返回,之后该数值会在异常或中断处理结束时触发异常或中断返回。
4. R15为程序计数器PC (Program Counter),可读可写。取指令操作后,返回PC的值为当前指令地址加4。 通过写操作修改PC的值或者跳转指令,将导致程序执行地址的跳转。因为指令必须半字或者整字对齐,所以PC的最低位(LSB)总为0。 但是通过跳转等语句更新PC时,需要将PC的最低位置1,以标识Thumb状态,否则会由于使用不支持的ARM指令而触发错误异常。对于C语言编程,不需要考虑这一点,因为编译器已经帮我们完成了这一操作。对于高级编程语言,包括C和C++编译器会自动将C/C++代表转为32位的Thumb2代码。