参考arm_cortexm3_processor_trm,ARM cortex M3权威指南以及其他网络上的资料整理
文章目录
前言
异常是打断程序正常执行流程的一种事件。异常发生时,处理器会暂停当前程序并保存现场,然后去执行异常处理例程,异常事件处理完成之后再回到之前被打断的地方并恢复现场,继续执行程序。
一、ARMv7-M异常模型
1.异常类型和优先级
前三个异常的优先级是固定的,后面的异常优先级是可编程的。
优先级编号越小,优先级越高。
1.1 Reset
M3复位时进入该异常。
1.2 NMI
NMI(不可屏蔽中断)是除重置之外的优先级最高的异常。固定的优先级为-2。
1.3 HardFault
1.4 MemManage
MemManage fault与MPU或固定内存保护策略违例相关。软件可以禁用此故障。如果在软件禁用此故障,上述的违例情况会产生HardFault。MemManage fault的优先级可配置。
1.5 BusFault
BusFault故障处理memory相关的故障。通常这些故障是由在总线上检测到的错误引起的。
该异常可能是同步的,也可能是异步的,因为M3支持写缓冲,当总线异常发生时,处理器可能已经执行了多条指令,这种情况下就是异步异常。
软件可以禁用此故障,如果在软件禁用此故障,上述的违例情况会产生HardFault。BusFault的优先级可配置。
1.6 UsageFault
UsageFault与指令执行相关,包括下面的情况:
•执行未定义的指令
•在无效状态下执行指令
•异常返回时出错
•试图访问已禁用或不可用的协处理器
除此之外,可以设置控制寄存器来产生以下情况下的UsageFault
•非对齐访问
•除以零操作
软件可以禁用此故障,如果在软件禁用此故障,上述的违例情况会产生HardFault。UsageFault的优先级可配置。
1.7 Debug Monitor
DebugMonitor是一种同步异常。Debug monitor发生在禁用调试功能
1.8 SVCall
调用SVC指令引起该异常。在应用上,用户代码使用SVC指令来调用底层操作系统,从用户级切换到特权级。
programs can execute in a privileged or unprivileged manner. System level support requires privileged access, giving system software the access permissions required to configure and control the resources. Typically, an operating system provides this control, providing system services to the applications, either transparently, or through application initiated Supervisor Calls. The operating system is also responsible for servicing interrupts and other system events, making exceptions a key component of the system level programmers’ model.
In deeply embedded systems, particularly at low cost or performance points, there might be no clear distinction between an operating system and the applications, and software might be developed as a homogeneous codebase.
1.9 Interrupts
1.10 向量表
当处理器接受到异常后,需要从向量表找到异常处理函数的入口地址。
向量表默认从0地址开始,每个函数入口地址占用4字节。
0地址为SP_main的初始值。
向量表支持重定位,使用Vector Table Offset Register, VTOR设置向量表起始地址。使用前先将向量表搬移到该地址,再使用数据屏障指令确保搬移操作完成,最后配置VTOR。
2.异常执行流程
2.1 异常请求
处理器在接受到异常请求时,会根据如下条件判断是否进入异常:
1)处理器处于运行的状态,未被halt
2)异常处于使能状态的
3)如果程序已经处于异常中,则异常要高于当前当前异常的优先级才会马上执行
4)异常没有被异常屏蔽寄存器(如PRIMASK)屏蔽
若SVC指令被用在某异常处理过程中,而且该异常的优先级小于SVC,会引起HardFault异常。
2.2 异常进入
进入异常的具体流程如下:
1)当处理器决定执行中断,首先会把多个通用寄存器和返回地址压栈,如果处理器处于handle模式且正在使用SP_process,那么压栈就会选择SP_process,否则就选SP_main。
2)从向量表中取出异常向量,通常获取地址的操作和压栈的操作是同时进行的。
3)开始执行异常处理函数。
4)更新多个NVIC寄存器和内核寄存器,包括挂起状态寄存器(这个需要软件来清掉)和异常的活跃状态,处理器内核寄存器中的寄存器包括程序状态寄存器(PSR),链接寄存器(LR),程序计数器(PC)以及栈指针(SP)。
5)链接寄存器LR会被更新为EXC_RETURN的特殊值。该数值为32为,且高27位为1。低5位中有些部分用于保存异常流程的状态信息(如压栈时使用哪个栈),用于异常退出时的数据恢复。
2.3 异常处理
执行函数期间处理器就会处于handle模式,使用主栈指针(MSP),同时处理器运行在特权访问等级。
处理异常的过程中如果又来了一个异常,如果这个异常的优先级比当前的中断更高,那么就去执行更高优先级的中断,这就叫中断嵌套,如果来的中断优先级和现在的中断优先级一样或者是更低,那么新来的这个中断就会被pending住,直到当前的中断执行完再去相应这个新来的中断。
在异常处理的结尾,程序代码执行的返回会引起EXC_RETURN数值被加载到程序计数器(PC),并触发异常返回机制。