1. 中断基础概念
中断是嵌入式系统与 Linux 内核中处理异步事件的硬件-软件协作机制。当外设或 CPU 内部需要立即处理的事件发生时,中断信号打断当前执行流,跳转到预先注册的处理函数,完成后再恢复原执行流。理解中断的定义、向量表、优先级与嵌套是后续框架注册与性能验证的基石。
1.1 中断定义
中断(Interrupt)是一种由硬件或软件触发的信号,通知处理器暂停当前任务,转而执行一个特定的中断服务程序(ISR, Interrupt Service Routine)。中断的核心目的是提高系统实时性与资源利用率,避免 CPU 轮询等待。
| 特性 | 中断驱动 | 轮询方式 |
|---|---|---|
| CPU 利用率 | 高,无事时休眠或执行其他任务 | 低,持续占用 CPU 检查状态 |
| 响应延迟 | 微秒级,事件触发即响应 | 取决于轮询周期,通常毫秒级 |
| 功耗 | 低,可进入低功耗模式 | 高,CPU 持续活跃 |
| 实现复杂度 | 较高,需配置中断控制器与向量表 | 简单,仅需循环读取寄存器 |
| 适用场景 | 实时性要求高、事件稀疏 | 事件频繁、延迟容忍度高 |
1.2 中断向量表
中断向量表(Interrupt Vector Table, IVT)是一张存储在固定内存地址的跳转表,每个表项对应一个中断号,存放该中断对应的 ISR 入口地址。当 CPU 响应中断时,硬件自动根据中断号从向量表中取出地址并跳转执行。
在 ARM Cortex-M 系列中,向量表起始地址通常为 0x00000000(或通过 VTOR 寄存器重定位),前 16 个为系统异常,之后为外设中断。x86 架构使用 IDT(Interrupt Descriptor Table),每个表项 8 字节,包含段选择子与偏移量。
setup_idt() 初始化 IDT,中断门使用 DPL=0(内核态)或 DPL=3(用户态)。ARM 平台通过设备树或 request_irq() 动态注册中断处理函数,内核维护 irq_desc 数组管理每个中断号的状态与回调。
1.3 中断优先级
中断优先级决定了当多个中断同时发生时,CPU 优先响应哪一个。优先级通常由中断控制器(如 ARM GIC、x86 APIC、NVIC)的寄存器配置,数值越小优先级越高(ARM Cortex-M 采用 0 为最高优先级)。
优先级分组(Priority Grouping)允许将优先级位拆分为抢占优先级(Preempt Priority)和子优先级(Subpriority),实现更灵活的嵌套控制。
| 优先级值(8 位) | 抢占优先级(3 位) | 子优先级(1 位) | 实际抢占行为 |
|---|---|---|---|
| 0x00 (0) | 000 | 0 | 最高抢占,可打断所有 |
| 0x10 (16) | 001 | 0 | 可打断优先级 2~7 的中断 |
| 0x20 (32) | 010 | 0 | 中等优先级 |
| 0x30 (48) | 011 | 0 | 较低优先级 |
| 0xE0 (224) | 111 | 0 | 最低优先级,不可打断任何中断 |
irq_chip 和 irq_domain 映射,优先级配置属于板级 BSP 代码。
1.4 中断嵌套
中断嵌套(Interrupt Nesting)是指一个中断服务程序正在执行时,另一个更高优先级的中断到达,CPU 暂停当前 ISR,转而执行更高优先级的 ISR,完成后返回被暂停的 ISR 继续执行。嵌套深度受硬件栈空间和中断控制器支持的限制。
中断嵌套的流程如下:
- 低优先级中断触发:CPU 保存现场(PC、PSR、寄存器),跳转到对应 ISR。
- 高优先级中断到达:中断控制器向 CPU 发出更高优先级的请求。
- 硬件判断:若新中断优先级高于当前 ISR 的优先级(且中断使能),CPU 再次保存当前 ISR 的上下文。
- 执行高优先级 ISR:完成后执行中断返回指令(如
ERET或BX LR)。 - 恢复低优先级 ISR:CPU 恢复之前保存的上下文,继续执行。
local_irq_disable() 和 spin_lock_irqsave() 在临界区屏蔽中断,防止嵌套导致的数据竞争。
1.5 中断处理流程总结
一个完整的中断生命周期包含以下阶段:
- 触发:外设或软件设置中断挂起位。
- 仲裁:中断控制器根据优先级选择最高优先级中断。
- 响应:CPU 保存现场,查找向量表,跳转 ISR。
- 执行:ISR 执行必要操作(通常为读取数据、清除中断标志)。
- 返回:执行中断返回指令,恢复现场,继续原执行流。
mutex_lock()、kmalloc(GFP_KERNEL))会触发内核调度,导致系统死锁或崩溃。ISR 中应仅使用原子操作或 GFP_ATOMIC 标志。Linux 内核提供 in_interrupt() 宏检查当前是否在中断上下文中。