【第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. 工程开始时选定一个优先级分组,然后别动它。

相关推荐
bjxiaxueliang2 小时前
一文详解Cpp多线程编程:从传统pthread到现代thread实践指南
java·开发语言·jvm
QQ_4376643142 小时前
C++11并发编程
开发语言·c++
贪玩成性2 小时前
LED5050驱动程序,高效率
单片机·mcu
leiming62 小时前
c++ 容器 queue
开发语言·c++
CSDN_RTKLIB2 小时前
【类定义系列三】内联函数进阶
开发语言·c++
d111111111d2 小时前
STM32 电源管理模式全解析:低功耗场景该如何选型?
笔记·stm32·单片机·嵌入式硬件·学习
北京流年3 小时前
执行clang --version报错说由于找不到 libgcc_s_seh-1.dll和 找不到 libstdc++-6.dll 这两个文件
开发语言·c++
M158227690553 小时前
串口设备联网利器!SG-TCP232-110 单通道串口服务器,让老旧设备秒变智能终端
运维·服务器·单片机
weixin_440730503 小时前
Java基础学习day01
java·开发语言·学习