目录
- 1.系统模型
- 操作模式和状态
- 寄存器和特殊寄存器
- 2.存储器系统
- 3.栈空间操作
- 4.异常和中断
- 5.嵌套向量中断控制器(NVIC)
1.系统模型
操作模式和状态
Cortex-M0处理器包含两种操作模式和两种状态。
- 处理器在运行程序时处于Thumb状态,在这种状态下,处理器可以处在线程模式(Thread mode),也可以处在处理模式(Handler mode)。在ARMv6-M的体系结构里,线程模式和处理模式的系统模型几乎完全一样,不同之处在于,线程模式通过配置CONTROL特殊寄存器,可以使用影子栈指针。
- 调试状态仅用于调试操作,暂停处理器内核后,指令将不再执行,这时也就进入了调试状态。在这种状态下,调试器可以读取甚至改变内核寄存器的值。在Thumb状态或是调试状态下,调试器都可以访问系统存储器空间。
- 处理器上电以后,默认处在Thumb状态和线程模式。
寄存器和特殊寄存器
数据解析和控制处理的过程中,需要处理器内核的多个寄存器参与。如果需要处理存储器中的数据,这些数据就需要首先被加载到处理器内核的寄存器(寄存器组中的某个),处理完后,如有必要,它们还会被送到存储器中,这种方式被称为“加载—存储架构”。
Cortex-M0的寄存器组中,包含了13个32位的通用目的寄存器,以及多个特殊寄存器。
寄存器细节如下所述:
- R0~R12:R0 ~ R12为通用寄存器由于16位的Thumb指令集在空间上的限制,许多Thumb指令只能操作R0到R7,它们也被称为低寄存器,而像MOV之类的一些指令则可以使用全部的寄存器。此外,R0 ~ R12的初始值未定义。
- R13,栈指针(SP):R13为栈指针,用于对栈空间的存取操作(通过PUSH和POP指令),Cortex-M0在不同的物理位置上存在两个栈指针。主栈指针(MSP,在ARM文档中被称为SP_main)为上电后的默认指针,用于异常处理。另外一个称作进程栈指针(PSP,在ARM文档也被称为SP_process),只能用在线程模式。可以通过配置CONTROL寄存器,选择使用哪个栈指针。
在ARM处理器中,由于寄存器是32位的,故PUSH和POP指令永远是32位操作,而且存取的地址须是32位字对齐的。在处理器上电流程中,中断向量表的头4字节会被取出,然后填充到MSP,作为MSP的初始值。PSP的初始值未定义。 - R14,链接寄存器(LR):R14为链接寄存器,用于存储子程序或者函数调用的返回地址。子程序或函数执行完毕,存储在LR中的返回地址将被装到程序计数器(PC),以便调用程序可以继续执行。当发生异常中断时,LR会提供一个特定值,用于中断返回机制。
尽管Cortex-M0处理器的函数返回地址始终是偶数(最低位是0,因为最小的指令都是16位半字对齐的),LR的0位却是可读可写的。对于ARMv6-M体系结构,为了指明当前处于Thumb状态,一些指令需要函数地址的最低位为1。 - R15,程序计数器(PC):R15为程序计数器,并且可读可写。读操作返回当前正在执行的指令地址加上4(这是由流水线的特性决定的),而写入R15会导致程序跳转执行(和函数调用不同,链接寄存器不会更新)。
在ARM汇编器中,可以用R15或PC来操作程序计数器,大小写均可。Cortex-M0处理器的指令地址须是半字16位对齐的,这也就意味着PC寄存器的最低位必须始终为0。不过,在使用跳转指令(BX或BLX)执行程序跳转时,PC的最低位应该被置为1,以表明目标分支处于Thumb程序区域。如果试图切换至Cortex-M0未知的ARM状态,错误异常中断就会被触发。 - xPSR,组合程序状态寄存器: 组合程序状态寄存器提供了程序执行信息和ALU(算术逻辑单元)标志,该寄存器由三个程序状态寄存器(PSR)组成:应用程序状态寄存器(APSR)、中断程序状态寄存器(IPSR)、执行程序状态寄存器(EPSR)。
APSR包含了ALU标志:N(负号标志)、Z(零标志)、C(进位或借位标志)和V(溢出标志)。它们位于APSR的最高4位,一般用于控制条件跳转。在Cortex-M0中,几乎所有的数据处理指令都会更改APSR。具体的ALU标志描述如下:
IPSR中包含了当前正在执行的中断服务程序(ISR)编号,Cortex-M0的每个异常中断都会有一个特定的中断编号(表示中断类型)。这对调试时识别当前中断非常有用,而且在多个中断共用一个中断处理的情况下可以看出发生的是哪个中断。
EPSR包含了T位,该位用以指示当前是否处于Thumb状态。由于Cortex-M0处理器只支持Thumb状态,故T位一般为1。消除该位后,执行下一条指令会触发硬件异常中断。
这三个寄存器可以作为一个寄存器xPSR来访问(如下图)。
- PRIMASK(中断屏蔽特殊寄存器):PRIMASK仅有一位宽,被称作中断屏蔽寄存器,置位后,除了不可屏蔽中断(NMI)和硬件错误异常外的其他中断都会被屏蔽掉。此时当前中断优先级被置为了0,这也是可以配置的最高等级。
要访问PRIMASK寄存器,可以通过特殊寄存器操作指令(MSR和MRS),也可以使用“改变处理器状态”指令(CPS)。在处理对时间敏感的应用时,需要操作PRIMASK寄存器。 - CONTROL(特殊寄存器):Cortex-M0处理器具有两个栈指针,处理器模式决定了使用的栈指针,而处理器模式依赖于CONTROL寄存器的配置。
复位以后,系统默认使用主栈指针(MSP),在线程模式下,通过将CONTROL寄存器的第一位置1,处理器也可以切换至使用进程栈指针(PSP)(前提是当前不是处在异常中断处理中)。在处理异常中断时(运行在处理模式下),系统只使用MSP,CONTROL寄存器读出值为0。要改变CONTROL寄存器的值,应该在线程模式下操作,或者借助异常中断进入和返回机制。
2.存储器系统
Cortex-M0处理器具有4GB的存储器地址空间。在体系结构上,存储器空间被分作一系列的区域,每个区域都有推荐的用途,以提高不同设备间的可移植性。
大多数情况下,连接到Cortex-M0的存储器都是32位的。其支持各种大小的数据传输,包括字节(8位)、半字(16位)和字(32位)。Cortex-M0支持大端和小端操作,使用相应的配置即可选择,但已成型的设计不能在两者之间切换。
3.栈空间操作
- 栈空间是一种先入先出的结构,在系统空间中用作临时数据存储。栈空间操作的关键点之一为栈指针寄存器,每次执行栈操作时,栈指针的内容自动调整。在Cortex-M0中存在着两个栈指针,但每次只会使用一个,这是由CONTROL寄存器以及处理器的状态决定的。
- 根据所用架构的不同,有些处理器在向栈存入数据时地址会自动增加,而有些则会减小。Cortex-M0处理器的栈操作基于“满递减”的栈模型,这就意味着栈指针始终指向栈空间的最后一个数据,在执行数据存储前PUSH,栈指针会首先减小。操作流程如下:
- 每次出栈以及压栈操作的最小单位是4字节(32位),还可以使用一条指令实现对多个寄存器的压栈和出栈操作。Cortex-M0的栈空间被设计为字对齐的(地址值必须是4的倍数,比如0x0、0x4、0x8等),由于这个原因,栈指针的最低两位(BITS[1:0])在硬件上被置为0,因此读出固定为0。栈指针用法如下:
- 在一个具有操作系统的典型嵌入式应用中,操作系统内核使用MSP,而应用程序进程则使用PSP。这样就使得内核的栈空间与应用程序进程的栈空间相互独立,而操作系统的上下文切换也会非常迅速(在应用程序进程间相互切换)。
- 由于栈是向下生长的(满递减),内存的上边界通常会被用作栈指针的初始值。
4.异常和中断
- 异常会引起程序控制的变化。在异常发生时,处理器停止当前的任务,转而执行被称作异常处理的程序;异常处理完成后,还会继续执行刚才暂停的正常程序流程。
- 异常分为很多种,中断只是其中的一种。Cortex-M0处理器最多支持32个外部中断(通常称为IRQ)和一个被称为不可屏蔽中断(NMI)的特殊中断,中断事件的异常处理通常被称作中断服务程序(ISR),终端一般由片上外设或IO口的外部输入产生。
除了NMI和IRQ,一些用于操作系统和错误处理的常见系统异常如下:
每一个异常都对应一个异常编号,异常编号还指明了异常向量的地址。需要注意的是,在设备驱动库中,异常编号和中断编号是相互独立的。系统异常使用负数定义,而中断则是使用从0 ~ 31的正数定义。
复位是一类特殊的异常。如果发生复位的话,Cortex-M0处理器将会退出主程序,并且在线程模式中执行复位处理(不必从处理模式返回到线程模式)。另外,数值为1的异常号在IPSR中是不可见的。
5.嵌套向量中断控制器(NVIC)
为了管理中断请求的优先级并且处理其他异常,Cortex-M0处理器内置了嵌套向量中断控制器(NVIC),其具有以下特性:
- 灵活的中断管理:Cortex-M0处理器中,每一个外部中断都可以被使能或禁止,并且可以被设置为挂起状态或者清除状态。处理器的中断可以是信号级的(在中断服务程序清除中断请求以前,外设的请求会一直保持),也可以是脉冲形式的(最小一个时钟周期),这样中断控制器可以处理任何中断源。
- 支持嵌套中断:Cortex-M0处理器的任何中断都有一个固定或者可编程的中断优先级。当外部中断之类的异常发生时,NVIC将该异常的优先级与当前级别相比较。如果新的优先级更高,当前任务就会被暂停,一些寄存器将会被压栈处理,然后处理器开始执行新异常的处理程序。高优先级的中断完成后,异常返回就会执行,处理器随后将自动进行出栈操作来恢复寄存器的值,并且继续运行之前的任务。这种机制在允许中断服务嵌套的同时,并没有带来软件开销。
- 向量化的异常入口:异常发生时,处理器需要定位对应异常处理程序的入口。按照传统的处理方式,就像ARM7TDMI等处理器那样,这个过程需要软件来实现。而Cortex-M0则会从存储器的向量表中,自动定位异常处理的入口。这样一来,从异常产生到异常处理执行的时间就缩短了。
- 中断屏蔽:Cortex-M0中的NVIC通过PRIMASK特殊寄存器提供了一种中断屏蔽特性,NVIC可以屏蔽掉除了硬件错误和NMI之外的所有异常。