【第14期】裸机中断优先级:抢占与嵌套的逻辑

核心概念:当多个中断同时发生,或者一个中断正在处理时又来了一个新中断,CPU 该听谁的?

在 ARM Cortex-M 内核中,管理这一切的大管家叫 NVIC (Nested Vectored Interrupt Controller) ,中文直译为"嵌套向量中断控制器"。它的逻辑非常像医院的急诊室分诊台

1. 法则:抢占 vs 响应

这是新手最容易晕的地方。STM32/Cortex-M 把优先级分成了两个维度:抢占优先级 (Preemption Priority)响应优先级 (Sub Priority)

我们要死死记住这两条法则:

  • 法则一(抢占):只有"抢占优先级"高的人,才能打断正在干活的人。

    • 比喻 :医生正在给普通病人(抢占低)包扎,突然送来一个心脏停跳的病人(抢占高)。医生必须立马停下手中的活,先救心脏停跳的。这就叫中断嵌套
  • 法则二(响应):如果"抢占优先级"相同,不管后面那个多急,都不能打断。

    • 比喻 :医生正在抢救一个心脏停跳的(抢占高),这时候送来一个大出血的(抢占也高,且相等)。虽然大出血也很急,但既然已经在救心脏了,大出血的只能在门口排队,等医生救完心脏这个再进来。

    • 那"响应优先级"有啥用? 它只决定排队的顺序。如果门口同时送来了两个病人,医生做完手头的事出门一看,谁的"响应优先级"高,就先救谁。

2. 这里的"高"其实是"低"

这是一个反直觉的设定:数字越小,优先级越高

  • 0 是最高优先级(皇上)。

  • 15 是低优先级(平民)。

新手大坑 :很多开发者忘记配置优先级,默认全是 0。这意味着所有中断都是最高级,且谁也打断不了谁(因为级别一样),完全退化成了单任务排队系统。

3. 优先级分组 (Priority Grouping)

CPU 里的优先级寄存器通常只有 4 个 bit (不同型号略有差异)。我们需要把这 4 个 bit 切分成两部分,一部分给"抢占",一部分给"响应"。

这就是 NVIC_PriorityGroupConfig 的作用。常见的 5 种分组(以 STM32 为例):

分组 (Group) 抢占位 (Preemption) 响应位 (Sub) 描述 适用场景
NVIC_PriorityGroup_0 0 bit (0级) 4 bit (16级) 无嵌套。所有中断按顺序排队。 简单逻辑,不想处理复杂的嵌套并发问题。
NVIC_PriorityGroup_1 1 bit (2级) 3 bit (8级) 只有 2 层嵌套关系。
NVIC_PriorityGroup_2 2 bit (4级) 2 bit (4级) 推荐平衡配置。4 层嵌套,同级内 4 个排队位。 大多数通用工程。
NVIC_PriorityGroup_3 3 bit (8级) 1 bit (2级)
NVIC_PriorityGroup_4 4 bit (16级) 0 bit (0级) 全抢占。只要级别高 1 级就能打断。 实时性要求极高的系统 (如电机控制)。

工程建议 :在一个项目中,只在初始化时设定一次分组,千万不要在程序运行中途改来改去,否则整个中断逻辑会瞬间崩塌。

4. 真实场景推演

假设我们将系统配置为 Group 2(2位抢占,2位响应)。

  • 中断 A:抢占 2,响应 0

  • 中断 B:抢占 2,响应 1

  • 中断 C:抢占 1,响应 0 (它是最急的,数字最小)

场景一:B 正在运行,A 来了。

  • 结果:B 继续运行,A 等待。

  • 原因 :虽然 A 的响应优先级 (0) 比 B (1) 高,但通过法则二 ,他们的抢占优先级都是 2。平级不可打断。

场景二:B 正在运行,C 来了。

  • 结果:B 暂停(压栈保护现场),C 立即执行。C 执行完后,B 恢复运行。

  • 原因 :C 的抢占优先级 (1) 小于 B (2),也就是 C 级别更高。符合法则一,发生嵌套。

场景三:A 和 B 同时到来。

  • 结果:CPU 先执行 A。

  • 原因:抢占一样,这时看响应优先级。A (0) < B (1),A 胜出。

5. 为什么要尽量避免复杂的嵌套?

初学者可能会觉得:"嵌套好啊,反应快!"

但老手都知道,中断嵌套是 Bug 的温床。

  1. 堆栈溢出 (Stack Overflow):每嵌套一层,就要多压一次栈(32字节以上)。如果嵌套层数太多,MSP 堆栈可能瞬间被打爆,导致程序跑飞。

  2. 临界区竞争:如果低优先级中断正在改一个全局变量,高优先级中断插进来也改这个变量,数据就坏了。(这就是下一期的主题)。


总结下关键点:

  1. 抢占 (Preemption) 决定能不能打断别人。

  2. 响应 (Sub) 决定能不能插队

  3. 数字越 ,优先级越

  4. 工程开始时选定一个优先级分组,然后别动它。

相关推荐
1+α几秒前
汽车里的“神经网络”——CAN总线科普
c语言·stm32·嵌入式硬件·信息与通信
爱编码的小八嘎1 分钟前
C语言对话-19.新的起点,第一部分
c语言
时艰.2 分钟前
Java 线程池 — ThreadPoolExecutor
java·开发语言·python
暖馒4 分钟前
深度剖析串口通讯(232/485)
开发语言·c#·wpf·智能硬件
新新学长搞科研8 分钟前
【CCF主办 | 高认可度会议】第六届人工智能、大数据与算法国际学术会议(CAIBDA 2026)
大数据·开发语言·网络·人工智能·算法·r语言·中国计算机学会
珠海西格电力科技1 小时前
微电网控制策略基础:集中式、分布式与混合式控制逻辑
网络·人工智能·分布式·物联网·智慧城市·能源
草莓熊Lotso2 小时前
Linux 基础 IO 初步解析:从 C 库函数到系统调用,理解文件操作本质
linux·运维·服务器·c语言·数据库·c++·人工智能
梵刹古音2 小时前
【C语言】 字符数组相关库函数
c语言·开发语言·算法
微风中的麦穗8 小时前
【MATLAB】MATLAB R2025a 详细下载安装图文指南:下一代科学计算与工程仿真平台
开发语言·matlab·开发工具·工程仿真·matlab r2025a·matlab r2025·科学计算与工程仿真
2601_949146538 小时前
C语言语音通知API示例代码:基于标准C的语音接口开发与底层调用实践
c语言·开发语言