layout: post
title: “中断的具体行为”
date: 2024-1-17 15:39:08 +0800
tags: Cotex-M3 Cotex-M3权威指南
自动保存现场的必要部分:依次把xPSR, PC, LR, R12以及R3-R0由硬件自动压入适当的堆栈中
如果当响应异常时,当前的代码正在使用PSP,则压入PSP,也就是使用进程堆栈;否则就压入MSP,使用主堆栈。一旦进入了服务例程,就将一直使用主堆栈。
先把PC与xPSR的值保存,就可以更早地启动服务例程指令的预取——因为这需要修改PC;同时,也做到了在早期就可以更新xPSR中IPSR位段的值
优先入栈这几个寄存器的原因是使得中断控制函数可以使用C语言进行编写, 编译器优先使用入栈了的寄存器来保存中间结果当然,如果程序过大也可能要用到R4-R11,此时编译器负责生成代码来push它们。
数据总线在忙的时候指令总线会获取到程序的入口
在CM3中,是通过把EXC_RETURN往PC里写来识别返回动作的。
以上的行为是自动的
NVIC和CM3处理器会根据优先级的设置来控制抢占与嵌套行为。因此,在某个异常正在响应时,所有优先级不高于它的异常都不能抢占之,而且它自己也不能抢占自己。
有了自动入栈和出栈,就不用担心在中断发生嵌套时,会使寄存器的数据损毁,从而可以放心地执行服务例程。
有一件事情却必须更加一丝不苟地处理了,否则有功能紊乱甚至死机的危险。这就是计算主堆栈容量的最小安全值。
相同的异常是不允许重入的。因为每个异常都有自己的优先级,并且在异常处理期间,同级或低优先级的异常是要阻塞的。因此对于同一个异常,只有在上次实例的服务例程执行完毕后,方可继续响应新的请求。由此可知,在SVC服务例程中,就不得再使用SVC指令,否则将fault伺候。
当处理器在响应某异常时,如果又发生其它异常,但它们优先级不够高,则被阻塞
在中断退出又进入的过程中, 不需要在进行一次出站入栈的过程
如果是在低优先级中断入栈的时候产生的高优先级中断, 会在入栈结束之后进入高优先级的处理函数, 之后使用咬尾中断处理
在进入异常处理函数的时候, LR寄存器保存的值是EXC_RETURN
高28位全为1的值,只有[3:0]的值有特殊含义
进入之前的LR会被自动入栈
EXC_RETURN的格式可见,我们不能把0xFFFF_FFF0-0xFFFF_FFFF中的地址作为任何返回地址。其实也并不用担心会弄错,因为CM3已经把这个范围标记成“取指不可区”
中断延迟的定义是:从检测到某中断请求,到执行了其服务例程的第一条指令时,已经流逝了的时间。
在CM3中,若存储器系统够快,且总线系统允许入栈与取指同时进行,同时该中断可以立即响应,则中断延迟是雷打不动的12周期(满足硬实时所要求的确定性)。
进行了入栈、取向量、更新寄存器以及服务例程取指的一系列操作。
处理咬尾中断时,省去了堆栈操作,因此切入新异常服务例程的耗时可以短至6周期。
入栈期间引起了总线fault,则本次入栈操作将被强行中止,并且把总线异常悬起或者在允许时立即响应。若除能了总线fault,则此次故障将成为“硬伤”——上访至硬fault。在总线fault被使能的情况下,如果它的优先级比正在响应的异常高,则抢占之,否则将悬起直到引起fault的异常执行完毕。
入栈操作引起MPU访问违例,则产生存储管理fault,并且必须能立即执行MemFault服务例程,否则将无条件上访成硬fault。
中断返回时的出栈期间引起了总线fault,则本次出栈操作将被强行中止,并且把总线异常悬起或立即响应。若除能了总线fault,则此次故障将成为“硬伤”——上访至硬fault。其它情况下,只要总线fault的优先级比当前的高(也包括比当前最深嵌套的优先级高),则可以立即响应。这种情况称为“出栈错误”
直接上硬fault, MPU的限制则管不着取向量操作
LR中的EXC_RETURN不是合法的值(合法值见表9.4,包括企图返回ARM状态),则引起用法fault。如果用法fault被除能,也上访成硬fault。