最近调一个 STM32 项目时遇到个怪现象:UART 接收中断偶尔丢数据,定时器中断偶尔晚到几十微秒,逻辑分析仪抓下来看,低优先级中断被高优先级中断“插队”还算正常,但有两次高优先级中断也被延迟了。查了一圈,问题出在 NVIC 优先级分组上,分享一下排查过程。
1. 先确认优先级分组到底设成了什么
很多人用 HAL 库默认的 NVIC_PRIORITYGROUP_4(4 位全是抢占优先级,没有子优先级),也有人图省事在 CubeMX 里改成 GROUP_2 而没改代码里的优先级数值。第一步永远是读回 AIRCR 寄存器确认实际分组,再对照代码里的数值算一遍抢占关系,不要凭印象。
2. 同抢占优先级下,子优先级≠执行顺序保证
在 GROUP_2 这类带子优先级的分组里,同抢占优先级的中断按子优先级排队,但同抢占+同子优先级的中断,响应顺序取决于中断号,这个顺序在手册里是固定的,代码里写反了也没用。我的项目里两个外设中断就撞在这个坑上。
3. 临界区关中断的范围要收敛
排查时发现一段旧代码用 __disable_irq() 包住了整个数据处理函数,最长关中断 80 微秒。高优先级中断在这段时间里只能 pending,表现为“偶尔晚到”。改成只保护真正需要原子的几行,或者用 BASEPRI 只屏蔽低优先级中断,延迟立刻消失。
4. 用 DWT 周期计数器量化,别凭感觉
在中断入口和出口各读一次 DWT_CYCCNT,连续跑一万次取最大延迟,改动前后对比才有说服力。我这次改动后最大延迟从 80 微秒降到 3 微秒以内。
总结:中断丢事件先别怀疑硬件,先把分组、数值、临界区三样东西对齐,再用计数器量化。你们在 STM32 上遇到过最难查的中断问题是什么?