5.2 中断优先级与嵌套:多中断共存的秩序


5.2 中断优先级与嵌套:多中断共存的秩序

本节摘要:真实系统里十几个中断源并存,谁先谁后、谁能打断谁,由优先级与嵌套规则裁定。本节讲清 Cortex-M 两级优先级(抢占与子优先级)的分工逻辑、嵌套发生与被禁止的条件,给出一套多中断系统的优先级分配方法论,并讨论优先级反转这一经典陷阱在裸机下的变体。读完你能为一个多中断系统排出既满足实时性又避免饥饿的秩序。

会议室的比喻用坏了,换一个调度模型

讲中断优先级的文章爱用"领导插话"之类的会议比喻,但比喻解释不了"为什么同级不能互相打断"。更贴切的模型是医院的分诊台:病人(中断事件)到达后按病情分级,危重(高抢占优先级)可以打断正在进行的普通处理;同级病人之间按挂号顺序(硬件编号)就诊;而"子优先级"决定同级病人里的排队顺序,但同级之间永远不打断——正在缝合的医生不会被另一个同级病人叫停。带着这个模型读规则,每一条都有画面。

两级优先级:抢占级定谁打断谁,子级定排队序

Cortex-M 的每个中断配一个 8 位优先级寄存器(多数芯片只实现高 4 位,即 16 级),并由一个全局"优先级分组"设置把它切成两段:

抢占优先级(主优先级)裁决打断权:数值越小越紧急。运行中若来了抢占级更高的中断,当前执行立即暂停、转去服务新中断——这就是嵌套。抢占级相同或更低,则只能挂起等待。

子优先级只在"同时挂起的同级中断之间"排顺序:硬件按子级数值加中断编号决定先服务谁,但绝不打断正在执行的同级 ISR。

分组设置(如 4 位全给抢占、或 2 位抢占 2 位子级)决定了两级各有多少档位。设置一次,全系统生效,一般在启动时配好不再动。

/* NVIC 优先级设置:分组后两级各司其职 */ NVIC_SetPriorityGrouping(3); /* 4 位抢占 0 位子级(16 级抢占) */ NVIC_SetPriority(TIM2_IRQn, 8); /* 定时器:中等紧急 */ NVIC_SetPriority(USART1_IRQn, 10); /* 串口:较低紧急 */ NVIC_SetPriority(EXTI0_IRQn, 2); /* 外部按键:高紧急 */ NVIC_EnableIRQ(TIM2_IRQn); /* 三处使能缺一不可 */

嵌套规则与深度控制

嵌套是双刃剑。正向价值明显:紧急事件不等闲事——电机过流保护(最高级)可以随时打断显示刷新(最低级),响应时间有保障。代价是栈消耗叠加分析复杂度:每层嵌套在栈上压一份现场(硬件八个寄存器加软件保存的部分),嵌套深度乘以单层开销就是栈预算;而低优先级 ISR 被任意高优先级打断后,其执行时间变得不可预测——所有时序分析都要按"最坏嵌套"做。

两条工程纪律控制嵌套风险。第一,层级要少:实际项目里把优先级归并为三到四档(紧急保护、实时通信、一般事件、后台批量)远比十六级各用各的清晰——档位越少,越坏情况越可分析。第二,同级互斥要靠软件:同级不互相打断意味着两个同级 ISR 若共享数据,硬件不会替你挡住——5.4 节的竞态案例正是栽在这里。

分配方法论:四档模型的实战推演

给一个真实场景排优先级:一台工业数据采集器,中断源有五类——电机过流保护信号、CAN 总线接收、1ms 系统节拍、串口调试打印的发送空中断、按键检测。

推演过程:电机过流威胁硬件安全,必须在微秒级响应,抢最高档(抢占 0);CAN 接收有硬件 FIFO 缓冲两三帧,容忍几十微秒延迟,排第二档(抢占 1);系统节拍驱动所有时间任务,晚一拍全体时基后移,排第三档(抢占 2);按键与串口发送都是毫秒级容忍度的闲事,合并最低档(抢占 3)。子优先级仅在第三档内部区分节拍与 ADC 采完的先后。

从推演里提炼三条分配原则。原则一,按"能容忍的最大延迟"排,不按"感觉重要"排——串口打印很重要,但它能等;系统节拍不起眼,但它拖累全局。原则二,同档合并:容忍度相近的中断共享一档,减少层级、简化最坏情况分析。原则三,最高档留给保护性事件:过流、过压、硬件看门狗喂狗窗口这类"晚了就出事故"的中断独占最高档,且 ISR 压到最短。

档位 抢占级 中断源 容忍延迟 ISR 预算
紧急保护 0(最高) 过流过压保护 10µs 几微秒,只置标志或直接关驱动
实时通信 1 CAN 接收 50µs 取数据入队列,几微秒
系统时基 2 1ms 节拍、ADC 完成 200µs 置标志、累加计数,极短
后台事件 3(最低) 按键、串口发送空 10ms 置标志即可

优先级反转:裸机也有它的变体

教科书里的优先级反转(高优先级任务被低优先级任务间接阻塞)发生在 RTOS 环境,第 6 章详述。裸机下的变体同样致命:低优先级 ISR 关中断太久,或低优先级 ISR 执行过长,高优先级事件被变相阻塞。比如最低档的串口中断里直接调用 printf(它内部自旋等待发送完成),高优先级的过流保护虽然能打断它——但若串口 ISR 已在临界区里关了全局中断,保护中断就被硬生生挡在门外。所以"ISR 不做重活、不开长临界区"不只是风格问题,而是保全整个优先级体系的前提。优先级体系的价值建立在每一档都守纪律的基础上——一处耍赖,全局失守。

中断进不来的六个时刻:响应承诺的例外清单

优先级体系承诺"高优先级随叫随到",但有六个时刻例外,排查"中断怎么不响应"时应逐条对照。一,同级或同源占用:同抢占级的中断正在执行,新事件只能排队(同级永不互断)。二,关中断窗口:任何软件关中断的临界区里,除不可屏蔽的少数异常外全部拦在门外。三,挂起已被置位:同源事件已挂起时,重复触发不重复登记(5.1 的合并丢失)。四,硬件屏蔽寄存器:某些外设(如 CAN 的错误中断)有独立屏蔽位,一处没开整链不通——对照 5.1 的使能三要素逐站查。五,故障处理程序跑飞:HardFault 这类异常若在处理中再出故障,系统可能锁死在故障循环里,表现为"所有中断都死了"。六,动态优先级配置错误:运行中被改错的优先级分组会让两级解释错位,现象是"中断能进但次序全乱"。把这六条印在排错手册第一页,多数"中断失踪案"能在十分钟内收案。

本节要点回顾

  • 两级分工:抢占级定打断权(数值小者胜),子级只排同级队列序,同级永不互断。
  • 嵌套是双刃剑:保障紧急响应,代价是栈叠加与时序分析复杂化;层级归并为三四档最可分析。
  • 按容忍延迟排优先级:能等的靠后、拖累全局的居中、晚了出事故的独占最高档。
  • 同档合并:容忍度相近的中断共享档位,是控制嵌套深度的第一杠杆。
  • 优先级体系靠纪律维生:任一 ISR 耍赖(重活、长临界区),整个体系的响应承诺随之作废。
  • 体系位置:优先级是硬件给的秩序,下一节轮到人的一方——ISR 该怎么写才算守纪律。

作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U