1、中断基础概念:中断向量、中断号、中断控制器(GIC/APIC)硬件架构
中断是嵌入式系统与操作系统响应异步事件的基石。理解中断向量、中断号以及中断控制器(GIC/APIC)的硬件架构,是编写可靠中断处理驱动的第一步。本节从硬件视角拆解中断的传递路径与核心数据结构。
1.1 中断向量与中断号
中断向量(Interrupt Vector)是中断服务程序(ISR)入口地址的索引表。CPU 在响应中断时,通过硬件自动获取向量号,跳转到对应的处理函数。中断号(IRQ Number)则是软件层面用于标识中断源的逻辑编号。
| 概念 | 定义 | 典型范围 | 使用场景 |
|---|---|---|---|
| 中断向量 | 中断描述符表(IDT/IVT)中每个表项的索引,指向 ISR 地址 | 0–255(x86) | CPU 硬件自动查表跳转 |
| 中断号 | 操作系统或驱动层对中断源的软件编号 | 0–NR_IRQS(Linux) | request_irq()、free_irq() 等 API |
| 硬件中断线 | 物理引脚或消息信号,由中断控制器管理 | SPI/PPI/LPI(GIC) | 设备树或 ACPI 描述 |
驱动开发要点: 在 Linux 中,中断号与中断向量之间通过
irq_to_desc() 和 irq_domain 映射。不要假设中断号等于向量号,尤其在 ARM GIC 和 x86 APIC 上,映射关系由固件和内核共同维护。
1.2 中断控制器硬件架构
中断控制器负责收集外设中断请求,进行优先级仲裁,并将中断信号分发给 CPU。主流架构包括 ARM 的 GIC(Generic Interrupt Controller)和 x86 的 APIC(Advanced Programmable Interrupt Controller)。
1.2.1 ARM GIC 架构
GIC 是 ARM 体系的标准中断控制器,支持多核分发、中断优先级、安全扩展。GICv2/v3/v4 是嵌入式 Linux 驱动开发中最常打交道的版本。
GIC 核心组件:
- Distributor(分发器): 全局中断配置、使能、优先级、目标 CPU。
- CPU Interface(CPU 接口): 每个 CPU 核独立拥有,处理中断抢占与应答。
- Redistributor(重分发器,GICv3+): 每个 CPU 核关联,管理 PPI 和 SGI。
1.2.2 x86 APIC 架构
x86 平台使用 Local APIC(LAPIC)和 I/O APIC 组合。LAPIC 集成在 CPU 内部,处理本地中断源(如定时器、错误中断);I/O APIC 负责收集外设中断并转发给 LAPIC。
| 组件 | 功能 | 寄存器访问方式 | 关键特性 |
|---|---|---|---|
| Local APIC | 接收本地中断、IPI、定时器中断 | MMIO(默认 0xFEE00000) | 中断优先级、EOI、Task Priority |
| I/O APIC | 收集外设中断,重定向到 LAPIC | MMIO(默认 0xFEC00000) | 24 路中断输入,可编程路由 |
| MSI/MSI-X | 外设直接写 LAPIC 的消息信号中断 | PCIe 配置空间 | 无需 I/O APIC,减少延迟 |
1.3 中断优先级与嵌套基础
中断控制器通过硬件优先级寄存器决定哪个中断优先被 CPU 响应。GIC 使用 8 位优先级字段(实际实现可能只使用高 5 位或高 4 位),值越小优先级越高。APIC 使用 Task Priority Register(TPR)和 Processor Priority Register(PPR)控制中断屏蔽阈值。
驱动开发陷阱: 在 GIC 中,如果 ISR 没有在入口处提升优先级(Priority Drop),高优先级中断无法抢占当前 ISR,导致中断嵌套失效。Linux 内核通过
gic_handle_irq() 自动处理优先级分组,但自定义中断处理逻辑时务必注意 EOI(End of Interrupt)时序。
1.4 中断处理流程速览
- 外设触发: 设备拉高中断请求线(或发送 MSI 消息)。
- 中断控制器仲裁: Distributor/I/O APIC 根据优先级选择最高优先级中断,路由到目标 CPU。
- CPU 响应: CPU 保存上下文(PC、PSR),查询中断向量表,跳转到 ISR。
- ISR 执行: 读取中断状态寄存器,执行必要处理,写 EOI 寄存器。
- 恢复上下文: CPU 恢复现场,继续执行被中断的任务。
关键寄存器速查(GICv3):
ICC_PMR_EL1:中断优先级掩码寄存器,决定 CPU 响应中断的最低优先级。ICC_IAR0_EL1 / ICC_IAR1_EL1:中断应答寄存器,读取后获取中断 ID 并激活中断。ICC_EOIR0_EL1 / ICC_EOIR1_EL1:中断结束寄存器,写入后通知中断控制器处理完成。