1. 中断基础概念

1.1 中断的定义

中断(Interrupt)是一种硬件或软件触发的机制,用于通知处理器发生了需要立即关注的事件。当中断发生时,处理器会暂停当前正在执行的程序,保存现场,然后跳转到一个预先定义好的地址去执行中断服务程序(ISR),处理完后再返回被中断的程序继续执行。

核心特征:中断是异步事件驱动的,处理器不需要主动查询事件是否发生,而是由外设或软件主动通知处理器。

1.2 中断与轮询的对比

轮询(Polling)是另一种处理外设事件的方式,处理器周期性地检查外设的状态寄存器,判断是否有事件需要处理。中断与轮询在实时性、CPU利用率、系统复杂度等方面存在显著差异。

对比维度 中断(Interrupt) 轮询(Polling)
触发方式 事件发生时由外设主动通知 处理器主动查询状态
CPU利用率 高,无事时CPU可执行其他任务 低,即使无事件也消耗CPU周期
实时性 高,事件发生后立即响应 低,响应延迟取决于轮询间隔
系统复杂度 较高,需要中断控制器、向量表等 较低,只需读取状态寄存器
适用场景 低频或突发性事件(按键、网络包) 高频且可预测的事件(ADC采样)
功耗 低,CPU可进入休眠模式 高,CPU持续运行
设计建议:在嵌入式系统中,通常将中断用于处理不可预测的异步事件,而将轮询用于处理周期性的、延迟容忍度较高的任务。混合使用两种方式往往能获得最佳效果。
中断 vs 轮询 工作流程对比 中断模式 CPU 执行主程序 外设产生中断信号 CPU 保存现场并跳转 ISR ISR 执行 → 恢复现场 轮询模式 CPU 执行主程序 CPU 查询外设状态寄存器 判断事件标志位是否置位 有事件则处理,无则继续轮询

1.3 中断向量表

中断向量表(Interrupt Vector Table, IVT)是存储在内存中的一张表格,每个表项对应一个中断源,存放着该中断对应的中断服务程序(ISR)的入口地址。当处理器接收到中断信号时,通过中断号在向量表中查找对应的ISR地址,然后跳转执行。

ARM架构中的向量表:在ARM Cortex-A系列处理器中,向量表基地址由VBAR(Vector Base Address Register)寄存器控制。每个向量表项占用4字节(32位)或8字节(64位),存放跳转指令或ISR地址。
中断号 向量表偏移 中断类型 描述
0 0x0000 复位(Reset) 系统上电或复位后执行
1 0x0004 未定义指令(Undefined Instruction) 执行未定义的指令码
2 0x0008 软件中断(SVC) 通过SVC指令触发
3 0x000C 预取中止(Prefetch Abort) 指令预取时发生错误
4 0x0010 数据中止(Data Abort) 数据访问时发生错误
5 0x0014 超中断(Hypervisor) 虚拟化相关
6 0x0018 IRQ(普通中断) 外设中断请求
7 0x001C FIQ(快速中断) 高优先级快速中断
ARM Cortex-A 中断向量表结构 中断向量表(基地址由 VBAR 寄存器指定) 偏移 0x00 复位 跳转到 Reset_Handler 偏移 0x04 未定义指令 跳转到 Undef_Handler 偏移 0x08 软件中断 (SVC) 跳转到 SVC_Handler 偏移 0x18 IRQ(普通中断) 跳转到 IRQ_Handler 偏移 0x1C FIQ(快速中断) 跳转到 FIQ_Handler

1.4 中断服务程序(ISR)基本流程

中断服务程序(Interrupt Service Routine, ISR)是响应中断事件时执行的专用函数。ISR的执行流程必须遵循严格的规范,以确保系统稳定性和数据一致性。

ISR 执行的标准步骤

  1. 保存现场:将当前CPU寄存器(R0-R12、LR、SPSR等)压入栈中保存。
  2. 识别中断源:读取中断控制器(如GIC)的中断状态寄存器,确定具体是哪个外设触发了中断。
  3. 清除中断标志:在中断控制器和外设中清除对应的中断挂起位,防止重复触发。
  4. 执行中断处理:根据中断类型执行对应的处理逻辑(如读取数据、设置状态等)。
  5. 恢复现场:从栈中恢复之前保存的寄存器值。
  6. 返回中断:执行中断返回指令(如ARM的MOVS PC, LR),恢复被中断程序的执行。
关键注意事项:
  • ISR应尽量短小精悍,避免执行耗时操作(如打印、复杂计算)。
  • ISR中禁止调用可能导致阻塞的函数(如信号量等待、内存分配)。
  • ISR中访问的共享数据必须使用原子操作或关中断保护。
  • 在ARM架构中,ISR入口和出口必须使用特定的指令序列来切换处理器模式。
/* ARM Cortex-A 中断服务程序入口汇编示例 */
IRQ_Handler:
    /* 1. 保存现场 */
    SUB     lr, lr, #4          /* 修正返回地址 */
    SRSDB   sp!, #0x13          /* 保存SPSR和LR到SVC模式栈 */
    CPS     #0x13               /* 切换到SVC模式 */
    PUSH    {r0-r12, lr}        /* 保存通用寄存器 */
    
    /* 2. 识别中断源 - 读取GIC中断号 */
    MOV     r4, #0xFFFFFF00     /* GIC基地址(示例) */
    LDR     r0, [r4, #0x0C]     /* 读取GICC_IAR获取中断ID */
    
    /* 3. 清除中断标志 */
    STR     r0, [r4, #0x10]     /* 写入GICC_EOIR确认中断结束 */
    
    /* 4. 调用C语言ISR处理函数 */
    BL      C_IRQ_Handler
    
    /* 5. 恢复现场 */
    POP     {r0-r12, lr}        /* 恢复通用寄存器 */
    RFEIA   sp!                 /* 恢复SPSR和PC,返回被中断程序 */
中断服务程序(ISR)完整执行流程 中断触发 ① 保存现场(压栈) ② 识别中断源 ③ 清除中断标志 ④ 执行中断处理逻辑 ⑤ 恢复现场 → 返回
ARM架构特殊说明:在ARM Cortex-A系列处理器中,中断响应过程涉及处理器模式的自动切换。当IRQ中断发生时,处理器自动切换到IRQ模式,并保存返回地址到LR_irq、保存CPSR到SPSR_irq。ISR编写者需要特别注意模式切换时的寄存器使用规则。