Cortex-M7/M4中高优先级ISR调用SVCall触发HardFault是否符合预期?
我正在开发一款RTOS,已实现调度器、上下文切换器等可用模块,当前正在开发SVCall功能。测试平台以STM32F746-Disco(Cortex-M7)为主,同时兼容STM32F469-Disco(Cortex-M4)。
我的需求是将SVCall设置为挂起状态,等当前中断处理完成后,通过尾链方式进入SVC处理程序。这种“中断级联”的方式在其他场景是可行的——比如裸中断处理程序保存线程寄存器后,通过软件触发另一个ISR来执行复杂的C代码。
测试结果如下:
- 从线程中执行
__asm volatile("SVC 0");,功能正常; - 从优先级低于SVCall的ISR中执行该指令,功能正常;
- 从优先级高于SVCall的ISR中执行该指令时,SVC指令直接触发HardFault,既无法进入SVC处理程序,也无法完成当前高优先级中断的处理。
其他中断的级联方式是有效的:从高优先级ISR激活低优先级中断,完成高优先级中断后会进入低优先级中断处理程序,但SVCall不支持这种方式——只有当SVCall优先级高于调用源优先级时才能正常工作。
请问这是SVCall的预期行为吗?
这是SVCall的预期行为,核心原因来自Cortex-M内核对SVC指令的设计规则:
SVC的优先级约束:SVC是内核提供的系统调用触发机制,仅允许在优先级低于自身的上下文中执行。如果在优先级高于或等于SVC的上下文(比如高优先级ISR)中执行
SVC指令,内核会直接判定为非法操作,触发HardFault——这和普通中断“挂起等待后续响应”的逻辑完全不同。与普通中断的本质差异:普通中断属于外设触发的异步事件,可通过挂起位延迟响应;但SVCall是同步的特权请求指令,设计初衷是让低特权级代码(线程、低优先级ISR)向高特权级上下文请求服务,不支持高优先级上下文反向触发低优先级的SVC。
替代实现方案:如果需要在高优先级ISR中触发后续特权级操作,可采用以下方式:
- 设置全局标志位,在高优先级ISR中置位,后续由空闲任务或专门的后台处理任务检查标志并执行对应逻辑;
- 调整SVCall的优先级使其高于目标ISR(需评估对系统调度逻辑的影响);
- 触发一个优先级适配的普通外设中断来承载后续操作。
内容的提问来源于stack exchange,提问作者Ilya

