1. 中断基础概念:什么是中断、中断向量表、中断优先级、中断嵌套
各位同学,咱们今天聊聊中断。说实话,中断是RTOS的命根子,搞不懂中断,车载系统就别想稳定。我做了十几年嵌入式,见过太多因为中断处理不当导致车机死机的案例。嗯,咱们从最基础的说起。
1.1 什么是中断?
中断,说白了就是CPU正在干一件事,突然被一个紧急事件打断,转去处理这个紧急事件,处理完再回来接着干原来的事。
你想想看,你正在写代码,突然电话响了。你放下键盘接电话,接完继续写。这就是中断。CPU也是这样——它正在执行主程序,外设(比如CAN控制器、定时器)发来一个信号,CPU就暂停当前任务,跳去执行中断服务程序(ISR),执行完再回来。
关键点:中断是异步事件。CPU不知道它什么时候来,但必须能随时响应。
我在项目中遇到过一个问题:某个传感器中断来得太频繁,CPU几乎一直在处理中断,主任务根本跑不动。后来我调整了中断触发阈值,才解决问题。所以,中断虽好,但不能滥用。
1.2 中断向量表
中断向量表,就是一张“地址表”。每个中断源对应一个表项,表项里存放的是该中断的ISR入口地址。
CPU收到中断信号后,硬件会自动查这张表,找到对应的ISR地址,然后跳过去执行。整个过程是硬件完成的,不需要软件干预,速度极快。
举个例子,ARM Cortex-M系列的中断向量表通常放在Flash的起始地址。第0项是栈顶指针,第1项是复位向量,从第16项开始是外部中断。
; 典型的ARM Cortex-M中断向量表布局
; 地址偏移 内容
; 0x00000000 栈顶指针
; 0x00000004 复位向量
; 0x00000008 NMI
; 0x0000000C HardFault
; ...
; 0x00000040 SysTick
; 0x00000044 IRQ0 (外部中断0)
; 0x00000048 IRQ1 (外部中断1)
; ...
个人经验:我建议你在项目初期就把中断向量表规划好。我曾经见过一个团队,中途加中断导致向量表溢出,整个系统启动就崩。嗯,这种事一次就够了。
1.3 中断优先级
多个中断同时发生怎么办?谁先处理?这就靠中断优先级了。
每个中断都有一个优先级。优先级高的中断先执行,优先级低的后执行。如果高优先级中断正在处理,低优先级中断来了,那就等着。
车载系统中,优先级分配特别重要。比如:
| 中断源 | 优先级 | 说明 |
|---|---|---|
| 安全气囊触发 | 最高(0) | 人命关天,必须立即响应 |
| CAN总线错误 | 高(1) | 通信故障需快速处理 |
| 定时器 | 中(2) | 周期性任务,可稍等 |
| UART接收 | 低(3) | 数据接收,延迟一点没关系 |
避坑指南:我曾经把一个低优先级中断的ISR写得特别长,结果高优先级中断来了只能干等。后来我养成了习惯:ISR里只做最必要的事,耗时操作一律丢到任务里做。
1.4 中断嵌套
中断嵌套,就是中断里还能再进中断。高优先级中断可以打断低优先级中断的执行。
举个例子:CPU正在处理UART中断(优先级3),突然来了一个CAN错误中断(优先级1)。CPU会暂停UART中断,转去处理CAN错误中断。处理完CAN错误,再回来继续处理UART中断。
中断嵌套的好处是:紧急事件不会被次要事件阻塞。但坏处也很明显——嵌套层数太多,栈空间容易爆。而且嵌套越深,系统行为越难预测。
// 中断嵌套示例(伪代码)
void UART_ISR(void) {
// 正在处理UART数据
// 突然CAN错误中断来了
// CPU自动保存当前上下文,跳转到CAN_ISR
// CAN_ISR执行完毕,返回UART_ISR
// 继续处理UART数据
}
void CAN_ISR(void) {
// 高优先级中断处理
// 处理完返回
}
我的建议:车载系统中,我一般限制中断嵌套不超过2层。超过这个深度,栈空间和实时性都难以保证。你想想看,嵌套5层的中断,一旦出问题,调试起来简直要命。
1.5 总结
中断是RTOS的基石。理解中断、中断向量表、优先级和嵌套,是写好车载软件的第一步。我个人习惯在项目初期就画好中断优先级分配表,明确每个中断的职责和优先级。这样后期出问题的概率会小很多。
下一章咱们聊聊中断延迟和抖动,这两个指标直接决定了你的系统能不能满足实时性要求。嗯,到时候我会分享一个我在ADAS项目中踩过的坑,保证让你印象深刻。