中断向量表
- VTOR寄存器:中断向量地址Vn = VTOR + 中断号N * 4
- 每个中断向量的大小=4B,所以是N*4
- 由于实际有256个中断向量,所以中断向量表大小为1024B,因此该表必须以1024对齐,即链接脚本中使用ALIGN(1024)
- 所以VTOR也必须以1024对齐,即VTOR低10位必须为0
CM3编程模型
- 两种模式:thread模式(特权/用户级)、handler模式(特权级)
- 堆栈指针
- MSP(特权级):中断服务程序(ISR)、RTOS的特权级任务使用
-
PSP(特权/用户级):用户程序、RTOS的用户任务使用
-
特殊寄存器CONTROL
- CONTROL[1]决定使用哪一个SP,只有在特权的thread模式中可写(handler只能选MSP所以不可写)
- CONTROL[0]决定特权级/用户级,只有特权中可写
- 执行ISR的开头会修改CONTROL,将用户态切换到特权态
中断/异常模型
- 抢占优先级(preemptive)与次优先级:实现优先级分组
- 可抢占=>中断嵌套,不可抢占=>单中断;默认可抢占。
- 抢占优先级:决定了谁先抢占
- 次优先级:在挂起队列中,决定谁先
- 注意:中断A(抢占=1,次=5)正在运行,此时来了中断B(抢占=1,次=1),中断B不能抢占,因为次优先级只决定挂起队列的优先级
- 尾链特性(Tail-chain):如果执行完中断A后,需要连续执行中断B,此时会省略出入栈过程,直接ISRA->ISRB
-
迟来特性(Late Arrival):若中断A正在软件保存环境时,此时来了更高的中断B,会暂停保存,立刻转去服务中断B
-
中断发生到ISR执行的流程
-
硬件保存断点:PSRx、PC、LR、r12、r3-r0(8*32b=32B)
-
读中断向量表,找到新的SP和跳转的PC
-
加载流水线:跳转到PC并更新LR,执行指令
-
软件保存环境:保存剩下的寄存器(8*32b=32B)
-
中断发生到ISR执行的时间(中断延迟计算)
-
NVIC识别延迟+流水线延迟(执行指令+取下一个指令)+NVIC处理延迟+硬件保存断点延迟 = 12CLK
- 使用尾链和迟来特性优化
中断行为分析(重点)
-
单次中断(正常)
-
过程:中断请求->挂起位置位->经过一个中断延迟后才响应->执行ISR->挂起位清0

- 单次中断(挂起时取消中断)

-
持续中断
-
再次进入ISR时,由于Tail-chain机制,会产生一个尖刺

-
多次脉冲中断(挂起中出现第2~n个)
-
原因:挂起中出现的多个脉冲被识别为了一个中断

-
多次脉冲中断(解挂后出现第2~n个)
-
原因:挂起中出现的第二个脉冲被识别为了新的中断
- 中断结束又重新进入中断时,会被咬尾优化:
- 正常情况:中断1->主程序->中断2
- 咬尾优化:中断1->中断2(将两次上下文切换变为了一次)

丢中断原因分析
- 多个中断产生太快
- 原因:中断1挂起时,又来了多个同类型中断,由于使用的是同一个pending寄存器,所以导致后面的中断没有被记录上
- ISR过程太长
-
原因:中断1执行ISR时,中断2触发并挂起,但当ISR执行结束时将挂起标志也清除了,导致中断2没有被识别
-
解决方案
-
异步解决方案:设置一个队列,ISR中只入队中断信息,在主循环中while查询队列并执行程序
-
关中断解决方案:进入中断后立刻关闭中断