《ARM Cortex-M0 权威指南》笔记(2)—体系结构
1. 操作模式和状态
Cortex-M0 处理器包含两种操作模式和两种状态。
处理器在运行程序时处于Thumb状态(Thumb state),在这种状态下,处理器可以处在线程模式(Thread mode),也可以处在处理模式(Handler mode)。
2. 寄存器和特殊寄存器
Cortex-M0 寄存器组中,包含13个32位的通用目的寄存器,以及多个特殊寄存器。
2.1 基本寄存器
在使用 ARM 汇编器之类的 ARM 开发工具操作这些寄存器时,寄存器的写法可以用大写(如:R0),也可以用小写(如:r0)。R0~R12 寄存器的初始值未定义。
R13,栈指针(SP)
用于对栈空间的存取操作(通过PUSH和POP指令)。Cortex-M0在不同物理位置上存在两个栈指针,主栈指针(MSP)为上电后默认指针,用于异常处理;进程栈指针(PSP),只能用在线程模式(Thread mode)。可以通过配置 CONTROL 寄存器,选择使用哪个栈指针。
使用 ARM 开发工具编写程序代码时,程序员可以使用 “R13” 或 “SP” 来操作栈指针。在 ARM 处理器中,由于寄存器是 32 位,故 PUSH 和 POP 指令永远是32位操作,而且存取的地址必须是 32 位字对齐的。在处理器上电流程中,中断向量表的头4字节被取出,然后填充到 MSP ,作为 MSP 的初始值。
在许多应用中,系统完全依赖 MSP,PSP一般没有必要使用。使用操作系统的设计通常会用到PSP,因为操作系统内核的栈空间和线程级的应用程序的栈空间是相互独立的。PSP 的初始值未定义。
R14,链接寄存器(LR)
用于存储子程序或函数调用的返回地址。子程序或函数执行完毕,存储在LR中的返回地址将被装载到程序计数器(PC)中,以便调用程序可以继续执行。当发生异常中断时,LR会提供一个特定值,用于中断返回。
在使用 ARM 开发工具编程时,通常会通过 R14 或 LR 访问链接寄存器,而且不区分大小写。
尽管 Cortex-M0 处理器的函数返回地址始终是偶数(最低位为 0,因为最小的指令都是16位,也就是半字对齐),LR的第 0 位却是可读可写的。对于 ARMv6-M 体系结构,为了指明当前处于 Thumb 状态,一些指令需要函数地址的最低位为 1 。
R15,程序计数器(PC)
在使用 ARM 开发工具编程时,可以使用 R15 或 PC 来操作程序计数器,大小写均可。
Cortex-M0 处理器的指令地址必须是半字,也就意味这 PC 寄存器的最低位必须始终为 0。不过,在使用跳转指令(BX 或 BLX)执行程序跳转时,PC 的最低位应该被置为1,以表明目标分支处于 Thumb 程序区域。
xPSR,组合程序状态寄存器
应用程序状态寄存器(APSR)
APSR包含了ALU标志:N(负号标志)、Z(零标志)、C(进位或借位标志)和V(溢出标志)。它们位于APSR的最高4位,一般用于控制条件跳转。
ALU标志描述,如下图:
ALU标志示例,如下图:
程序状态寄存器(IPSR)
IPSR包含当前正在执行的中断服务程序(ISR)编号,Cortex-M0的每个异常中断都会有一个特定的中断编号(表示中断类型)。
执行程序状态寄存器(EPSR)
EPSR包含T位,改位用以指示当前是否处于Thumb状态。由于Cortex-M0处理器只支持Thumb状态,故T位一般为1。清除该位后,执行下一条指令会触发硬件异常中断。
2.2 PRIMASK 寄存器
中断屏蔽特殊寄存器(PRIMASK)仅有一位宽,被称作中断屏蔽寄存器,置位后,除了不可屏蔽中断(NMI)和硬件错误异常外的其他中断都会被屏蔽掉。
2.3 CONTROL 寄存器
特殊寄存器(CONTROL),处理器模式决定使用的栈指针,而处理器模式依赖于CONTROL寄存器的配置。
复位以后,系统默认使用主栈指针(MSP),在线程模式下,通过将CONTROL寄存器的第一位置1,处理器也可以切换至使用进程帧指针(PSP)(前提是当前不处在异常中断处理处)。
栈指针选择:
3. 异常和中断
异常会引起程序控制的变化。在异常发生时,处理器停止当前的任务,转而执行被称作异常处理的程序;异常处理完成后,还会继续执行刚才暂停的正常程序流程。异常分为很多种,中断只是其中的一种。
异常类型:
4. 系统控制块
除了NVIC,系统控制空间(SCS)中也包含了许多系统管理的寄存器,这些寄存器被称为系统控制块(SCB)。
尽管已经是ARM系统最小的处理器,Cortex-M0仍然具有多种调试特性。处理器内核实现的功能包括停止模式调试、单步、寄存器访问,另外还有单独的调试模式提供了断点单元(BPU)和数据监视点(DWT)单元。
支持JTAG和SWD两种协议,进行调试。
5. 程序映像和启动流程
通常,Cortex-M0处理器的程序映像从地址0x00000000开始。
程序映像的开始为向量表,其中包含了异常的起始地址(向量),每个中断向量的地址都等于“异常号 x4”。例如,外部IRQ#0 的异常类型为16,因此IRQ#0 的向量地址为 16x4=0x40。
复位时,处理器首先读取向量表前两个字,第一个字为MSP初始值;第二个字为复位向量,标识程序执行的起始地址(复位处理)。
例如:
如果启动代码位于地址0x000000C0,就需要在复位向量处写入这个地址,并且将地址的最低位置为1,以表明当前为Thumb代码;因此,地址0x00000004处的值被置为0x000000C1。
在取得复位向量值以后,处理器将开始从这个地址处执行程序代码。
传统的ARM处理器(如:ARM7TDMI)在这个方面的处理不同,它们往往从地址0x00000000处开始执行程序;而且向量表中为跳转指令,Cortex-M0处理器则为地址值。
在复位流程中,处理器会取出MSP的初始值和复位向量,然后开始执行复位处理,这些所需信息都放在一个叫做启动代码的程序文件中。启动代码中的复位处理可能还会履行系统初始化的职责,有些情况下,系统初始化在C程序main()中开始。