中断具体行为一般包括中断响应、异常返回、中断嵌套、咬尾中断、晚到中断、异常返回值、中断延迟以及异常响应期间的faults等。
中断响应
当外设产生一个中断请求时,系统首先要做的就是保存好当前的现场,也就是自动压栈,M3的硬件压栈跟M0基本一样,依次把xPSR、PC、LR、R12以及R3 – R0入栈。这里有个疑问,M3是双堆栈的,硬件怎么知道要往哪个堆栈里面压?Control[1]能判断当前处在哪种模式(不同模式有对应堆栈),如果异常时刻当前的代码正在使用PSP(进程堆栈)则压入PSP,否则就压入主堆栈MSP。压栈的顺序和地址如下表所示:
| 栈内地址 | 寄存器 | 保存顺序 | 说明 |
| 旧SP(N-0) | 上一次入栈 | – | 1. 压栈地址与压栈顺序需要注意区分,保存顺序不是按连续地址进行的 2. 在程序过程调用规范中有约定,优先使用R0 – R3、R12用来传参或保存临时结果,所以硬件压栈也选择这5个寄存器3. 如果程序临时结果或者传参很多,入栈时也要按需将R4-R11入栈,但是硬件不会自动压,当然软件也不需要参与,外包给第三方编译器了。 |
| (N-4) | xPSR | 2 | |
| (N-8) | PC | 1 | |
| (N-12) | LR | 8 | |
| (N-16) | R12 | 7 | |
| (N-20) | R3 | 6 | |
| (N-24) | R2 | 5 | |
| (N-28) | R1 | 4 | |
| (N-32) | R0 | 3 |
取向量
系统响应中断需要从中断向量表中找到请求的中断,每个外设中断都被分配了特定的中断向量号,当中断发生时,处理器根据中断向量号跳到对应的中断服务函数入口,这个由指令总线完成,这里也能体现双总线的哈佛总线结构的优势,入栈和取指能同时进行。
更新寄存器
在入栈和取向量操作完成之后,执行服务函数之前还需要更新一系列寄存器,前面压栈完成后栈地址有了变化,需要把栈指针SP更新到新的位置;PSR更新当前正在响应的中断编号;PC指要指向中断向量表中中断号对应的服务函数入口地址;LR在出入中断服务函数时不仅仅是一个返回地址了,展开来说:
进入中断服务函数前,Cortex-M3的LR(链接寄存器)会保存返回地址的特殊值,这个值不是直接的返回地址,而是经过编码的一个数值,用来指示处理器在中断返回时需要执行的一些特定操作。对于中断,LR被设置为一个特定格式的数值,该数值包含有关如何恢复程序状态的信息。
从中断服务函数中返回时,通过执行BX LR指令,处理器使用LR寄存器中的值来决定返回的位置以及是否需要恢复某些处理器状态。具体来说,在中断处理例程结束时,LR通常指向紧接在中断发生点之后的指令地址,但其最低位会被设置以表示要切换回线程模式,并且可能会根据之前的状态恢复浮点上下文等信息。
中断返回值
在进入异常服务程序后,将自动更新LR的值为特殊的EXC_RETURN,仅bit[3:0]有效,保留位默认1,当中断服务程序把这个值送到PC时,就会启动处理起的中断返回序列。因为LR的值时CM3内核自动设置的,没什么特使需求就不要取改动它。
| 位域 | 含义 |
| bit[31:4] | 必须全为1,可能是内部设计用来区分中断返回还是连接地址的 |
| bit[3] | 0:返回后进入Handler模式,可能是还有其他中断;1:返回后进入线程模式 |
| bit[2] | 0:从主堆栈中做出栈操作,返回使用MSP1:从进程堆栈中做出栈操作,返回后使用PSP |
| bit[1] | 必须为0 |
| bit[0] | 0:返回ARM状态1:返回Thumb状态,在M3中必须要为1 |
三种中断优先级的场景
1.嵌套中断
嵌套中断没什么意思,老生常谈了,一个中断服务程序(ISR)执行过程中,如果有更高优先级的中断发生,处理器暂停当前ISR的执行转而去处理更高优先级的中断。中断嵌套的设计初衷应该是允许更紧急的事件能够被更迅速地响应,从而提高系统的响应速度和实时性能。
2.咬尾中断
咬尾中断有点意思,设计初衷还是为了缩短中断的延迟。它针对的是一种高优先级中断执行过程中有低优先级的中断发生的场景。按照前面的理解,肯定是要等高优先级处理完了再处理低优先级的,高优先级处理完要出栈,即把之前的现场A还原,然后处理低优先级的入栈,即把现场A再保存,也就是A现场被还原又没保存,属于无用功啊,于是咬尾中断被设计,高优先级处理完直接处理低优先级,现场A就不用还原了。就好像小明刚上完厕所,小明的爸粑也想上,于是进来说算了小明你出去吧不要浪费水和时间了晚点我一起冲。
3.晚到中断
晚到中断有点意思,设计初衷是为了增强优先级,它针对的是一个中断服务函数处理的早期阶段,还没跳转进中断服务函数时,更高优先级的来了,那么前面的压栈操作就相当于给高优先级的做了,直接跳高优先级中断的服务函数,就好像小明的后妈买了一个雪糕给小明,小明正要伸手接过来时她发现亲儿子小强来了,于是雪糕就直接到了亲儿子小强的手里。