STM32L432KC特定条件下EXTI中断服务程序执行两次问题求助
作为计算机工程课程项目,我正在开发一款秒表,通过连接到微控制器GPIO端口的按键触发上升沿中断(按键按下时触发)。中断服务程序(ISR)仅通过切换SysTick控制寄存器中的使能位来启停SysTick定时器。
表面上该中断无任何作用,经GDB调试发现中断被执行了两次:第一次中断处理关闭SysTick定时器,第二次立即将其重新开启。此问题仅在同时满足以下两个特定条件时出现:
- 中断服务程序生成的汇编代码使用
bx LR指令退出中断; - 中断挂起寄存器中对应的中断挂起位(Interrupt Pending bit)在异常返回前被立即清除。
两位同学测试我的代码后也出现相同问题,我多次检查软件未发现异常,相关资料也未提及此类现象。
几乎可以排除按键抖动问题:在使用push {LR}后立即pop {PC}的情况下中断正常,且按键并联了去抖电容,在其他测试中均有效。
为定位问题,我将LED连接到另一个GPIO引脚,以切换SysTick使能位的方式切换对应输出数据寄存器位,结果出现相同问题,LED会短暂闪烁,可见中断服务程序被执行了两次。
尚未验证中断挂起位是否会单独触发中断服务程序。若属实,则异常返回序列与中断挂起位清除之间可能存在竞争条件,导致中断连续触发两次。发布此问询后2-3小时我将进行测试。一个指向竞争条件的线索是:用GDB单步执行处理程序可“解决”问题,但在函数头部设置断点后连续运行两次则无法解决。
目前最佳临时解决方法是在异常进入时立即清除中断挂起位,或强制汇编代码使用push {LR}和pop {PC}指令,但第二种方法存在风险,栈中可能残留额外LR值,破坏处理器状态恢复。
若有人愿意复现问题,我已将精简版代码上传至GitHub,该代码专为STM32-L423KC编写,未使用HAL库(符合课程要求)。
内容的提问来源于stack exchange,提问作者Keheck

