一、定义
(1)针对SoC来说,发生复位、软中断、中断、快速中断、取指令异常、数据异常等,我们都统一叫异常。所以说:中断其实是异常的一种。
(2)异常的定义就是突发事件,打断了CPU的正常常规业务,CPU不得不跳转到异常向量表中去执行异常处理程序;中断是异常的一种,一般特指SoC内的内部外设产生的打断SoC常规业务,或者外部中断(SoC的GPIO引脚传回来的中断)。
理解函数调用与异常的区别
二、异常处理流程
核心内容参考:ARMv7-M Architecture Reference Manual
的 B1.5 Armv7-M exception model章节
在发生中断时先保存现场,再去处理中断,最后恢复现场。
1、保存现场(硬件自动完成):
当发生中断的瞬间,栈会自动保存相关寄存器,如图:
C函数遵循Arm Architecture Procedure Calling Standard (AAPCS),编译器编译出来的汇编代码保证不会破坏 R4 至 R11,而LR (R14), R12, R3, R2, R1, and R0 都是被调用者保护寄存器,在函数内部可能会用到且被改变,因此,中断发生的之后,一定要先保存这些都寄存器。
并不是把R15直接stacking,而是只把r15的 return address 入栈。
注意:上图中“LR”保存的是正常函数调用的返回地址,“返回地址”保存的是中断处理完成后的返回地址。
2、取中断向量:
Armv7-M定义好了异常向量表,定义了各种异常发送时跳转的函数。数组总线把相关内容入栈的同时,地址总线也从中断向量表中取指址,调用中断服务程序
3、更新一系列的寄存器:
在入栈和取向量的工作都完毕之后,执行服务例程之前,还要更新一系列的寄存器:
- SP:在入栈中会把堆栈指针(PSP或MSP)更新到新的位置。在执行服务例程后,将由MSP负责对堆栈的访问。
- PSR:IPSR位段(地处PSR的最低部分)会被更新为新响应的异常编号。
- PC:在向量取出完毕后,PC将指向服务例程的入口地址,
- LR:其值被更新成一种特殊的值,称为“EXC_RETURN”,并且在异常返回时使用。EXC_RETURN的二进制值这是一个高28位全为1的值,只有[3:0]的值有特殊含义
实际上合法的值如下:
另一方面,在NVIC中,也伴随着更新了与之相关的若干寄存器。例如,新响应异常的悬起位将被清除,同时其活动位将被置位。
4、触发中断返回:
通过把EXC_RETURN往PC里写来识别返回动作,在启动了中断返回序列后,下述的处理就将进行:
- 出栈:先前压入栈中的寄存器在这里恢复。内部的出栈顺序与入栈时的相对应,堆栈指针的值也改回去。
- 更新NVIC寄存器:伴随着异常的返回,它的活动位也被硬件清除。对于外部中断,倘若中断输入再次被置为有效,悬起位也将再次置位,新一次的中断响应序列也可随之再次开始。
ref:
《The Definitive Guide to the ARM Cortex-M3》
Cortex-M4异常&中断处理流程_cortex m 中断栈帧-CSDN博客
[012] [ARM-Cortex-M3/4] 异常与中断处理流程_cortex-m3异常中断的入栈与出栈流程-CSDN博客
深入理解异常和中断(Cortex-M3) - _huaj - 博客园
【嵌入式系统放牛班】Cortex-M Interrupt Handler_哔哩哔哩_bilibili