1. 中断基础概念

中断(Interrupt)是嵌入式系统中处理器与外部设备交互的核心机制。它允许外设或软件在需要时“打断”CPU当前正在执行的程序流,转而执行一个预先定义好的中断服务程序(ISR, Interrupt Service Routine),处理完成后自动返回被中断的断点继续执行。这一机制避免了CPU轮询外设状态带来的性能浪费,是实现高效驱动响应的基石。

核心理解:中断的本质是“事件驱动的异步通知”。CPU无需主动查询外设状态,外设通过中断线主动告知CPU“我有事需要处理”,从而大幅提升系统实时性与吞吐量。

1.1 中断定义与分类

中断根据触发源和触发方式可分为以下几类:

分类维度 类型 说明 典型示例
触发源 硬件中断 由外部设备(如GPIO、定时器、UART)通过中断控制器向CPU发送的电平或边沿信号触发 按键按下、DMA传输完成
软件中断 由CPU执行特定指令(如ARM的SWI、x86的INT n)主动触发,常用于系统调用 Linux系统调用、任务切换
触发方式 电平触发 中断信号保持有效电平(高或低)直到CPU响应并清除 传统PCI设备中断
边沿触发 中断信号在电平跳变(上升沿或下降沿)时触发,脉冲宽度极短 GPIO按键中断
可屏蔽性 可屏蔽中断 CPU可通过中断屏蔽寄存器(IMR)暂时忽略该中断请求 大部分外设中断
不可屏蔽中断 CPU必须立即响应,无法通过软件屏蔽,用于紧急事件 看门狗超时、电源故障
驱动开发要点:在Linux内核中,硬件中断对应的处理函数注册在request_irq()中,软件中断则通过trigger_softirq()或tasklet机制实现。理解中断分类有助于选择正确的注册方式和处理策略。

1.2 中断向量表

中断向量表(Interrupt Vector Table, IVT)是存储在固定内存地址的一张表格,表中每一项存放着对应中断号的中断服务程序入口地址。当CPU接收到中断请求时,硬件自动根据中断号查表,跳转到对应的ISR执行。

中断向量表的结构与寻址方式因架构而异:

  • x86架构:IVT位于内存地址0x0000~0x03FF(实模式),共256个中断向量,每个向量4字节(段地址+偏移地址)。保护模式下使用中断描述符表(IDT)。
  • ARM Cortex-M:中断向量表位于Flash起始地址(0x00000000),前16个为系统异常向量,后续为外设中断向量,每个向量4字节(函数地址)。
  • RISC-V:使用mtvec/stvec寄存器指向中断向量表基址,支持直接模式和向量模式。
中断向量表结构示意图(ARM Cortex-M 架构) 中断向量表(基址 0x00000000) 偏移地址 中断向量内容 说明 0x0000 初始栈指针 (MSP) 复位后栈顶地址 0x0004 复位向量 系统上电后第一条指令地址 0x0008 ~ 0x003C 系统异常向量 (14项) NMI、HardFault、MemManage等 0x0040 外设中断向量 #0 TIMER0_IRQHandler 0x0044 外设中断向量 #1 UART0_IRQHandler 0x0048 外设中断向量 #2 GPIOA_IRQHandler ... ... ... 中断请求 → 硬件查表
常见陷阱:在ARM Cortex-M上,向量表第0项必须是有效的栈指针,否则复位后CPU无法正确初始化栈空间。驱动开发中若需重定位向量表(如使用RTOS),必须确保新向量表对齐到512字节或1024字节边界(具体见芯片手册)。

1.3 中断优先级

中断优先级决定了当多个中断同时发生时,CPU优先响应哪一个。优先级管理是中断控制器(如ARM GIC、NVIC、x86 APIC)的核心功能。不同架构的优先级实现方式有所差异:

架构/控制器 优先级位数 优先级值含义 分组方式
ARM Cortex-M NVIC 8位(实际使用3~8位) 数值越小,优先级越高 支持抢占优先级与子优先级分组(PRIGROUP)
ARM GICv2/v3 8位 数值越小,优先级越高 支持安全/非安全世界独立优先级配置
x86 APIC 8位 数值越大,优先级越高 固定优先级与轮转优先级模式
RISC-V PLIC 可配置(通常3~7位) 数值越大,优先级越高 支持阈值中断,低于阈值的中断被屏蔽
驱动开发关键:在Linux内核中,中断优先级通常在硬件初始化阶段由板级代码或设备树配置。驱动开发者一般通过irq_set_priority()(RTOS环境)或设备树interrupts属性中的优先级字段进行设置。高优先级中断应分配给时间敏感的外设(如定时器、DMA),低优先级中断分配给非实时外设(如按键、LED)。

1.4 中断嵌套

中断嵌套(Interrupt Nesting)是指CPU在处理一个中断服务程序(ISR)的过程中,又被另一个更高优先级的中断打断,转而执行更高优先级的ISR,处理完成后再返回被中断的低优先级ISR继续执行。中断嵌套是提升系统实时响应能力的重要机制。

中断嵌套的实现依赖以下硬件与软件条件:

  • 硬件支持:中断控制器必须支持优先级仲裁,且CPU在ISR执行期间能够重新使能中断(通常通过自动或手动清除中断屏蔽位实现)。
  • 栈管理:每次中断嵌套都需要保存当前ISR的上下文(寄存器、返回地址),嵌套深度受限于栈空间大小。
  • 可重入性:ISR必须可重入(reentrant),即不能使用全局静态变量而不加保护,否则嵌套可能导致数据竞争。
中断嵌套执行时序图 t 主程序(Main) 低优先级 ISR 高优先级 ISR ... 低优先级中断触发 高优先级中断触发(嵌套) 返回低优先级ISR 嵌套过程中的栈状态 栈帧:主程序上下文 R0-R12, LR, PC, xPSR 返回地址:主程序断点 栈帧:低优先级ISR上下文 R0-R12, LR, PC, xPSR 返回地址:低优先级ISR断点 栈帧:高优先级ISR上下文 R0-R12, LR, PC, xPSR 返回地址:低优先级ISR断点 栈增长方向(向低地址) 嵌套深度 = 3(主程序 + 低优先级ISR + 高优先级ISR)
嵌套风险提示:中断嵌套深度过大会导致栈溢出,尤其在资源受限的MCU上(如STM32F103默认栈大小仅1KB)。驱动开发中应遵循以下原则:
1. ISR尽量短小精悍,避免在ISR中执行耗时操作。
2. 合理分配中断优先级,避免高优先级ISR频繁打断低优先级ISR导致“优先级反转”。
3. 在RTOS环境下,ISR中禁止调用可能引起任务阻塞的API(如vTaskDelay())。

1.5 中断处理流程总结

一个完整的中断处理流程包含以下关键步骤,驱动开发者需要深刻理解每个环节的硬件与软件行为:

  1. 中断请求(IRQ):外设检测到事件(如数据到达、传输完成),通过中断线向中断控制器发送请求信号。
  2. 中断仲裁:中断控制器根据优先级规则,选择当前最高优先级的中断请求,向CPU发送中断信号。
  3. CPU响应:CPU完成当前指令后,保存现场(压栈PC、xPSR、LR、R0-R3、R12),查询中断向量表获取ISR入口地址。
  4. ISR执行:CPU跳转到ISR执行。在ISR中,驱动开发者需要完成:清除中断标志、读取/写入数据、通知内核或应用层。
  5. 中断返回:ISR执行完毕后,执行中断返回指令(如ARM的BX LR),CPU从栈中恢复现场,继续执行被中断的程序。
Linux内核视角:在Linux中,中断处理被分为上半部(Top Half)和下半部(Bottom Half)。上半部在ISR中执行,要求快速完成(通常只做寄存器操作和标志清除);下半部通过tasklet、工作队列或软中断延后执行耗时操作。这正是本课程后续章节的核心内容——tasklet机制正是下半部的一种高效实现。