中断与NVIC问答合集
由本目录 15 篇中断主题问答的答案精华按知识点重组而成,原帖全部保留,每节末尾标注出处。
1. 什么是中断延时:上半部与下半部
中断延时的定义:中断请求发生到进入 ISR 之前的那段时间。处理中断时的经典分法:
- 上半部:ISR 内必须立刻做的部分,最重要的是清除对应的中断标志位;
- 下半部:标志位改变后与中断相关的事务处理,这些事务合理安排在 ISR 之外执行,可以有效减少中断服务时间,从而降低系统的中断延时。
— 中断延时是中断请求到进入ISR之前的时间,上半部是ISR内必须要做的部分(Jack)
注:什么是中断延时: 中断延时是 与上篇为同文异发(正文逐字相同,仅多一个 #知识总结 标签),2025-03-13 与 03-19 先后发布,属于近似重复,保留待人工合并。
2. 如何减少中断延迟处理时间
四条实操路径:
- 提高中断优先级;
- 减少更高优先级服务函数的执行时间——例如通过全局标志位实现中断服务函数"快进快出";
- 减少临界区;
- 把中断服务函数分散加载到 RAM 区域执行,减少流水线取指令时间。
(中断资源与实时性上限的系统级讨论见 关于中断优化: 中断在系统是一)
— 老师,中断的延迟处理时间要怎么(Jack)
3. 系统级视角:单个中断快慢不重要,中断偏移才重要
单一中断耗时久不久不重要,重要的是所有中断延时加起来是否构成整个系统的中断偏移。如果产生了偏移,说明系统的中断资源已经溢出,在中断任务上已经不具备实时性。
— 单一中断久不久不重要,重要的是所有中断延时加起来是不是构成了整个系统的中断偏移(Jack)
4. NVIC 仲裁规则:同优先级同时触发怎么办
两个定时器中断优先级设置相同时同时触发:IRQ 号小的先执行。NVIC 手册原文:If multiple interrupts are pending for the same priority level, the interrupt with the lowest IRQ number is processed first.
— 老师,如果这两个定时器的中断优先级设置的一样,如果同时触发是定时器6会先执行(Jack)
5. 如何实验观察中断嵌套
在两个中断函数中分别设断点做对照实验:
void EXTI0_IRQHandler(void)
{
EXTI->PR = EXTI_PR_PR0;
NVIC_SetPendingIRQ(USART1_IRQn); // 人为触发 USART1
while (1); // 看是否会被 USART1 抢占
}
void USART1_IRQHandler(void)
{
// 设置断点在这里
}
若能执行到 USART1_IRQHandler,说明嵌套发生了(优先级更高);若卡死在 EXTI0 的 while(1),说明没有嵌套(优先级不够或被屏蔽)。
— 怎么看中断有没有嵌套? 观察(Jack)
6. 中断屏蔽的语义:悬起但不响应
使用中断屏蔽寄存器组屏蔽掉的中断:可以悬起,但不能响应——屏蔽解除后仍会补上处理,事件不会丢。
— 使用中断屏蔽寄存器组屏蔽的中断是可以悬起不能响应,还是连悬起都没有(Jack)
7. 中断与 RTOS:高优先级任务被唤醒后怎么办
- 在 ISR 中调用队列发送等 OS API 时,若有高优先级任务因此被唤醒,并不会立即切换:只置位 PendSV 悬起,等退出所有中断后再响应 PendSV 完成任务切换。这类似于"中断下半部"的优化思路,因此不会如直觉般破坏实时性。
- 若不主动让出 CPU,ISR 结束后会继续执行被打断的低优先级任务,直到其用完时间片或主动阻塞,高优先级任务的实时性就没了保障;标准做法正是依赖上述 PendSV 机制,让 ISR 结束后立刻切换到被唤醒的高优先级任务。
— 在0-4的中断里面调用os的api函数,也算是执行了这个中断的ISR(Jack)
— 在中断服务程序中向队列中发送数据时,可能会有更高优先级的任务会因此被唤醒,这里的更高(Jack)
软件中断在业务开发中用得不多,但线程间通信(IPC)内部到处在用:FreeRTOS 消息队列发送完成后,若发现有更高优先级任务因该消息被唤醒,就会触发 PendSV 软件中断执行上下文切换,保证及时响应。
— 老师,请问在开发中,软件中断是(Jack)
8. ISR 编写守则:不改共享全局变量
中断里面不建议修改被(中断与线程)共享的全局变量;中断内只置位一个标志位,或发信号量,让外面的线程有秩序地去修改。
— 中断里面不建议修改被共享的全局变量,中断里面可以置位一个标志位,或者发信号量(Jack)
9. HardFault 定位:LR = 0xFFFFFFF1 的含义
在 HardFault 中看到 LR 为 0xFFFFFFF1,说明进入 HardFault 之前已经处于中断之中——即产生错误时的调用路径是:线程 → 中断 → HardFault。这为栈回溯定位提供了关键线索。
— 当你在错误中断(Hardfault)中看到LR是0xFFFFFFF1时(Jack)
10. 重定位与中断向量表
重定位的两个用处中与中断直接相关的一条:进入用户空间前把中断向量表搬到 RAM,可减少中断延时,在 ADC 这类高速应用中能提升整体性能(另一条是进入用户程序前做前置校验与配置,例如跳过部分区域初始化加快启动)。
— 重定位的用处: 1.进入用户空(Jack)
11. 更多相关问答(答案在原帖截图中)
- 任何中断都可以打断正在执行的任务是吗 可屏蔽的中断起作用是任务重添加tasKDISA(Jack)——任务级开关中断(DISABLE/ENABLE_INTERRUPTS)与可屏蔽中断的关系
- 中断中发送消息通知后,如果有高优先级线程被唤醒该怎么办(Jack)——ISR 发消息唤醒高优线程的处理
- 关于中断向量表的疑问:如果BOOT和APP的中断服务函数源代码都相同(橙子,未答)——BOOT 与 APP 能否共用中断向量表的实践困惑
来源笔记
- 中断延时是中断请求到进入ISR之前的时间,上半部是ISR内必须要做的部分(Jack)
- 什么是中断延时: 中断延时是(Jack,近重复篇)
- 老师,中断的延迟处理时间要怎么(Jack)
- 单一中断久不久不重要,重要的是所有中断延时加起来是不是构成了整个系统的中断偏移(Jack)
- 老师,如果这两个定时器的中断优先级设置的一样,如果同时触发是定时器6会先执行(Jack)
- 怎么看中断有没有嵌套? 观察(Jack)
- 使用中断屏蔽寄存器组屏蔽的中断是可以悬起不能响应,还是连悬起都没有(Jack)
- 在0-4的中断里面调用os的api函数,也算是执行了这个中断的ISR(Jack)
- 在中断服务程序中向队列中发送数据时,可能会有更高优先级的任务会因此被唤醒,这里的更高(Jack)
- 老师,请问在开发中,软件中断是(Jack)
- 中断里面不建议修改被共享的全局变量,中断里面可以置位一个标志位,或者发信号量(Jack)
- 当你在错误中断(Hardfault)中看到LR是0xFFFFFFF1时(Jack)
- 重定位的用处: 1.进入用户空(Jack)
- 任何中断都可以打断正在执行的任务是吗 可屏蔽的中断起作用是任务重添加tasKDISA(Jack)
- 中断中发送消息通知后,如果有高优先级线程被唤醒该怎么办(Jack)
- 关于中断向量表的疑问:如果BOOT和APP的中断服务函数源代码都相同(橙子)