2. 中断机制入门:CPU中断控制器(GIC)工作原理、中断向量表、中断优先级与嵌套
中断是嵌入式系统响应外部或内部异步事件的硬件机制。在UART驱动中,每当接收FIFO达到触发阈值或发送完成时,硬件会向CPU发送中断信号,驱动的中断处理函数(ISR)随即被调用。理解中断控制器的底层工作原理,是优化中断响应延迟、避免数据丢失的前提。
2.1 中断控制器(GIC)工作原理
ARM Cortex-A系列处理器通常使用通用中断控制器(Generic Interrupt Controller, GIC)。GIC负责接收来自外设(如UART、定时器、GPIO)的中断请求,进行优先级仲裁,并将最高优先级的中断分发给指定的CPU核心。
GIC核心组件:
- 分发器(Distributor):集中管理所有中断源的使能、优先级、触发方式(电平/边沿)和目标CPU列表。
- CPU接口(CPU Interface):每个CPU核心拥有独立的CPU接口,负责向核心发送IRQ/FIQ信号,并处理中断确认(ACK)和结束中断(EOI)操作。
GIC中断类型:
- SPI(Shared Peripheral Interrupt):共享外设中断,可路由到任意CPU,UART通常使用SPI。
- PPI(Private Peripheral Interrupt):私有外设中断,绑定到特定CPU,如本地定时器。
- SGI(Software Generated Interrupt):软件触发中断,用于核间通信(IPI)。
2.2 中断向量表
中断向量表是CPU在响应中断时,用于查找对应中断服务程序入口地址的跳转表。ARM Cortex-A处理器在中断异常发生时,硬件自动从向量表加载PC值,跳转到对应的异常处理入口。
| 向量偏移 | 异常类型 | 工作模式 | 说明 |
|---|---|---|---|
| 0x00 | Reset | SVC | 系统上电复位入口 |
| 0x04 | Undefined Instruction | UND | 未定义指令异常 |
| 0x08 | Supervisor Call (SVC) | SVC | 系统调用异常 |
| 0x0C | Prefetch Abort | ABT | 指令预取中止 |
| 0x10 | Data Abort | ABT | 数据访问中止 |
| 0x14 | Hypervisor Call | HYP | 虚拟化异常 |
| 0x18 | IRQ | IRQ | 普通中断(外设中断入口) |
| 0x1C | FIQ | FIQ | 快速中断(高优先级) |
UART中断响应路径:
- UART外设产生中断信号 → GIC分发器仲裁 → CPU接口断言IRQ。
- CPU硬件自动完成:保存CPSR到SPSR_irq,切换到IRQ模式,跳转到0x18向量地址。
- 向量表0x18处存放跳转指令(如
ldr pc, [pc, #offset]),跳转到内核的asm_do_IRQ汇编入口。 - 汇编入口保存现场,调用C函数
handle_arch_irq,读取GICC_IAR寄存器获取中断号。 - 根据中断号查找
irq_desc数组,调用注册的UART中断处理函数。
2.3 中断优先级与嵌套
GIC支持多达256级中断优先级(0~255,数值越小优先级越高)。当多个中断同时到达时,分发器选择优先级最高的中断发送给CPU。中断嵌套是指高优先级中断可以抢占正在执行的低优先级中断处理过程。
中断嵌套风险: 在UART驱动中,如果接收中断被更高优先级的中断(如定时器)长时间抢占,可能导致UART FIFO溢出,造成数据丢失。因此,UART中断通常设置为中等偏上优先级,且ISR应尽量短小,或采用顶半部/底半部(Threaded IRQ)机制。
2.3.1 优先级配置与分组
GIC支持优先级分组,将优先级位域划分为组优先级(Group Priority)和子优先级(Sub-priority)。组优先级用于决定中断抢占关系,子优先级仅用于同组中断同时到达时的选择。
| 分组模式 | 组优先级位数 | 子优先级位数 | 抢占粒度 |
|---|---|---|---|
| Group 0 | 5 | 0 | 32级抢占 |
| Group 1 | 4 | 1 | 16级抢占,每级2个子优先级 |
| Group 2 | 3 | 2 | 8级抢占,每级4个子优先级 |
| Group 3 | 2 | 3 | 4级抢占,每级8个子优先级 |
| Group 4 | 1 | 4 | 2级抢占,每级16个子优先级 |
2.3.2 中断嵌套流程
中断嵌套的硬件行为如下:
- CPU正在执行低优先级中断ISR(优先级150)。
- 高优先级中断(优先级50)到达GIC,分发器判断优先级更高,向CPU发送IRQ。
- CPU硬件再次保存当前ISR的现场(返回地址和CPSR),切换到IRQ模式,跳转到向量表。
- 高优先级ISR执行完成后,执行
EOI(End of Interrupt)写操作,通知GIC中断处理完毕。 - CPU恢复低优先级ISR的现场,继续执行。
2.4 中断响应延迟关键指标
中断响应延迟是衡量系统实时性的核心指标,直接影响UART数据接收的可靠性。延迟由硬件和软件两部分组成:
| 延迟阶段 | 典型耗时 | 说明 |
|---|---|---|
| 硬件延迟 | 10~50 ns | GIC仲裁、CPU异常响应、向量表跳转 |
| 现场保存 | 50~200 ns | 保存寄存器、切换栈指针 |
| 中断号查询 | 20~100 ns | 读取GICC_IAR、查找irq_desc |
| ISR执行 | 取决于实现 | UART数据读取、FIFO处理 |
| 现场恢复+EOI | 30~100 ns | 写GICC_EOI、恢复寄存器 |
优化方向:
- 将UART中断优先级设置为较高等级,减少被其他中断嵌套的概率。
- ISR中只做必要的数据读取和FIFO清空操作,耗时任务交给工作队列(Workqueue)或Tasklet。
- 使用FIQ代替IRQ可获得更低的延迟(ARM FIQ有独立的寄存器组,无需保存所有寄存器)。
- 在GIC层面启用中断分组,将关键中断分配到高优先级组。