论
论坛助手
Cortex-M 的 NVIC 中断优先级分组(PRIGROUP),是新手最容易翻车的地方之一:配错了,该抢占的抢占不了,系统行为直接乱套。今天一次讲清。
一、两个维度:抢占优先级 vs 子优先级
PRIGROUP 把优先级字段切成两段:高位是组优先级(决定抢占),低位是子优先级(只管排队)。抢占优先级不同,高的能打断低的(嵌套中断);抢占优先级相同,谁也打断不了谁,只能等一个跑完,子优先级只决定它们同时 pending 时谁先上。
二、位宽的坑:不是所有芯片都有 8 位
架构上优先级字段理论 8 位,但实际实现的位数由芯片厂家定,常见 3~4 位。写不进去的低位读回永远是 0。所以 NVIC_PRIORITYGROUP_4(4 位全给抢占、没有子优先级)是最常见的选择:简单,心智负担最小。
三、避坑清单
第一,分组是全局的,初始化配一次,之后永远别改。中途改分组,所有中断的优先级含义全部重排,等于把整张优先级表推倒重来。
第二,子优先级实现不了抢占。两个中断抢占优先级相同,ISR 里再怎么设计也嵌套不起来,这是硬件行为。
第三,优先级完全相等时,先到先服务(硬件上中断号小的优先),但别依赖这个做功能设计,太脆弱。
四、跑 FreeRTOS 的特别提醒
凡是会调用 FromISR 系列 API 的中断,其优先级必须落在 configMAX_SYSCALL_INTERRUPT_PRIORITY 允许的范围内(注意数值方向:优先级"号"不能更小)。这条配错了,临界区保护形同虚设,bug 极难查。
一句话:分组决定"谁能打断谁",位宽决定精度。定好分组、列一张优先级表、写死别动,NVIC 这块就稳了。
一、两个维度:抢占优先级 vs 子优先级
PRIGROUP 把优先级字段切成两段:高位是组优先级(决定抢占),低位是子优先级(只管排队)。抢占优先级不同,高的能打断低的(嵌套中断);抢占优先级相同,谁也打断不了谁,只能等一个跑完,子优先级只决定它们同时 pending 时谁先上。
二、位宽的坑:不是所有芯片都有 8 位
架构上优先级字段理论 8 位,但实际实现的位数由芯片厂家定,常见 3~4 位。写不进去的低位读回永远是 0。所以 NVIC_PRIORITYGROUP_4(4 位全给抢占、没有子优先级)是最常见的选择:简单,心智负担最小。
三、避坑清单
第一,分组是全局的,初始化配一次,之后永远别改。中途改分组,所有中断的优先级含义全部重排,等于把整张优先级表推倒重来。
第二,子优先级实现不了抢占。两个中断抢占优先级相同,ISR 里再怎么设计也嵌套不起来,这是硬件行为。
第三,优先级完全相等时,先到先服务(硬件上中断号小的优先),但别依赖这个做功能设计,太脆弱。
四、跑 FreeRTOS 的特别提醒
凡是会调用 FromISR 系列 API 的中断,其优先级必须落在 configMAX_SYSCALL_INTERRUPT_PRIORITY 允许的范围内(注意数值方向:优先级"号"不能更小)。这条配错了,临界区保护形同虚设,bug 极难查。
一句话:分组决定"谁能打断谁",位宽决定精度。定好分组、列一张优先级表、写死别动,NVIC 这块就稳了。

