2. 中断系统概述:中断向量表、中断优先级、中断嵌套与响应流程

在嵌入式系统中,中断是CPU处理异步事件的核心机制。对于GPIO中断驱动开发而言,理解中断系统的底层运作——从硬件信号触发到CPU执行中断服务函数(ISR)的完整路径——是编写可靠、低延迟驱动的先决条件。本节将围绕中断向量表、中断优先级、中断嵌套与响应流程四个核心概念展开,并结合ARM Cortex-M系列与Linux通用中断子系统进行对比说明。

2.1 中断向量表(Interrupt Vector Table, IVT)

中断向量表是一张存储在固定内存地址的表,表中每一项存放着对应中断源的中断服务函数入口地址。当CPU检测到中断请求时,硬件自动根据中断号从向量表中取出地址并跳转执行。

关键点: 向量表基地址在Cortex-M中由VTOR寄存器控制,支持运行时重定位;在Linux设备树中,中断控制器通过interrupt-cells属性描述中断号与触发类型。
GPIO驱动视角: 每个GPIO引脚可映射到一个或多个中断号。在STM32中,EXTI线0~15对应中断向量EXTI0_IRQn ~ EXTI15_10_IRQn;在Linux中,GPIO中断通过gpio_to_irq()获取虚拟IRQ号。
中断向量表结构(ARM Cortex-M) 中断向量表(IVT) 偏移地址 中断号 中断服务函数入口 优先级 0x0000_0000 0 (Reset) Reset_Handler -3 (最高) 0x0000_0004 1 (NMI) NMI_Handler -2 0x0000_0008 2 (HardFault) HardFault_Handler -1 0x0000_0040 16 (EXTI0) EXTI0_IRQHandler 可配置 0x0000_0044 17 (EXTI1) EXTI1_IRQHandler 可配置 ...... 注:Cortex-M 向量表前16个为系统异常,从第16号开始为外部中断(包括GPIO EXTI中断)。 每个向量表项占4字节,基地址由VTOR寄存器设定,支持运行时重定位。

2.2 中断优先级(Interrupt Priority)

中断优先级决定了当多个中断同时发生时CPU优先响应哪一个,以及一个中断是否可以被另一个更高优先级的中断抢占。不同架构的优先级管理方式存在差异:

架构/子系统 优先级位数 数值与优先级关系 分组方式 GPIO中断示例
ARM Cortex-M3/M4 8位(实际使用高4位) 数值越小,优先级越高 抢占优先级 + 子优先级(NVIC) EXTI0_IRQn 可设为 0x10
ARM Cortex-M7 8位(实际使用高4~8位) 数值越小,优先级越高 抢占优先级 + 子优先级(NVIC) EXTI9_5_IRQn 可设为 0x30
RISC-V (PLIC) 可配置(常见3位) 数值越大,优先级越高 单一优先级域 GPIO中断号0~31
Linux IRQ子系统 由中断控制器驱动定义 依赖底层硬件 通过irq_set_priority()设置 gpio_to_irq() 返回虚拟IRQ
常见陷阱: 在Cortex-M中,如果两个中断具有相同的抢占优先级,则不会发生嵌套——CPU会等待当前ISR执行完毕后再响应另一个中断。GPIO中断驱动中,务必为不同实时性要求的GPIO线分配不同的抢占优先级。

2.3 中断嵌套(Interrupt Nesting)

中断嵌套是指一个中断服务函数正在执行时,另一个更高优先级的中断到达,CPU暂停当前ISR,转而执行更高优先级的ISR,待其完成后返回被暂停的ISR继续执行。中断嵌套是提高系统实时性的关键机制。

GPIO驱动中的嵌套场景: 一个高优先级定时器中断可以抢占正在执行的GPIO按键中断ISR,确保时间关键任务(如PWM波形更新)不被GPIO抖动处理阻塞。
中断嵌套执行流程 时间 → 主程序(Main) GPIO_ISR (低) 高优先级ISR 恢复 抢占 返回 中断嵌套执行步骤: 1. CPU正在执行主程序(绿色)。 2. 低优先级GPIO中断到达,CPU保存现场,跳转到GPIO_ISR(蓝色)。 3. 高优先级中断到达,CPU再次保存现场,抢占执行高优先级ISR(红色)。 4. 高优先级ISR执行完毕,恢复GPIO_ISR现场,继续执行。 5. GPIO_ISR执行完毕,恢复主程序现场。

2.4 中断响应流程(Interrupt Response Flow)

从GPIO引脚电平变化到CPU执行对应的ISR,完整的硬件与软件协同流程可分为以下阶段:

  1. 中断源触发: GPIO引脚检测到设定的边沿(上升沿/下降沿/双边沿)或电平。
  2. 中断挂起: 外部中断控制器(如STM32的EXTI)将对应中断挂起寄存器位置1。
  3. 中断屏蔽检查: 检查中断屏蔽寄存器(IMR)对应位是否使能。
  4. 中断信号传递: 中断控制器向CPU核(如Cortex-M的NVIC)发送中断请求信号。
  5. 优先级裁决: NVIC比较当前中断优先级与正在执行的中断优先级,决定是否抢占。
  6. 硬件自动压栈: CPU自动将xPSR、PC、LR、R0~R3、R12压入当前栈。
  7. 向量表查找: CPU根据中断号从向量表中取出ISR入口地址。
  8. ISR执行: CPU跳转到ISR,执行用户编写的处理代码。
  9. 中断返回: ISR执行完毕,执行异常返回指令(如BX LR),CPU自动出栈恢复现场。
驱动开发优化点: 在ISR中应尽快完成必要操作(如读取GPIO数据寄存器、清除中断标志位),将耗时任务(如消息处理、协议解析)推迟到中断底半部(Bottom Half)或工作队列(Workqueue)中执行。
GPIO中断响应完整流程 GPIO引脚电平变化 EXTI检测边沿/电平 挂起寄存器置位 (PR) IMR使能? 中断被屏蔽 NVIC优先级裁决 硬件自动压栈 + 取向量 执行ISR → 中断返回 硬件自动完成(约12个周期): • 压栈:xPSR, PC, LR, R0~R3, R12 • 从向量表加载PC • 更新LR为EXC_RETURN • 更新IPSR为中断号

2.5 中断响应时间关键指标

指标 定义 典型值(Cortex-M4 @168MHz) GPIO驱动影响
中断延迟 从中断请求到ISR第一条指令执行 12~16个CPU周期(约70~95ns) 决定GPIO事件响应速度
中断响应时间 中断延迟 + ISR执行时间 取决于ISR长度 影响系统实时性上限
中断恢复时间 从ISR返回指令到主程序恢复 12个CPU周期 影响中断嵌套深度
最差情况中断延迟 考虑最高优先级中断屏蔽 + 最长指令执行 通常 < 1μs 必须满足GPIO应用时序要求
驱动开发避坑: 在ISR中调用可能导致睡眠的函数(如mutex_lock()、kmalloc(GFP_KERNEL))会触发内核调度,导致中断延迟急剧增大。GPIO中断ISR中应仅使用原子操作或spin_lock()。

2.6 中断标志位清除机制

中断服务函数执行完毕后,必须清除中断挂起标志位,否则中断控制器会持续向CPU发送中断请求,导致系统陷入死循环。不同硬件平台的清除方式不同:

  • STM32 EXTI: 向EXTI_PR寄存器对应位写1清除。
  • Linux GPIO中断: 由中断控制器驱动自动处理,用户ISR中通常不需要手动清除。
  • Zynq GIC: 读取IAR寄存器自动清除中断标志。
/* STM32 GPIO中断ISR示例 - 手动清除中断标志 */
void EXTI0_IRQHandler(void)
{
    /* 检查中断源 */
    if (EXTI->PR & EXTI_PR_PR0) {
        /* 执行GPIO中断处理逻辑 */
        uint8_t pin_state = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0);
        
        /* 清除中断挂起标志位(写1清除) */
        EXTI->PR = EXTI_PR_PR0;
    }
}

/* Linux GPIO中断ISR示例 - 无需手动清除 */
static irqreturn_t gpio_irq_handler(int irq, void *dev_id)
{
    struct gpio_device *dev = (struct gpio_device *)dev_id;
    
    /* 读取GPIO电平 */
    int val = gpiod_get_value(dev->desc);
    
    /* 调度工作队列处理耗时任务 */
    schedule_work(&dev->work);
    
    /* 返回IRQ_HANDLED,中断控制器驱动负责清除标志 */
    return IRQ_HANDLED;
}

2.7 中断系统对比总结

概念 裸机/RTOS环境 Linux内核环境 GPIO驱动关注点
中断向量表 由链接脚本定义,固定或VTOR重定位 由中断控制器驱动管理,动态注册 确保GPIO中断号映射正确
中断优先级 NVIC寄存器直接配置 通过irq_set_priority()或设备树 GPIO中断优先级需低于定时器中断
中断嵌套 硬件自动支持,需配置抢占优先级 支持,但需考虑中断上下文限制 避免在GPIO_ISR中调用睡眠函数
中断响应流程 硬件自动压栈 + 向量跳转 硬件流程 + 内核irq_enter/irq_exit ISR应短小精悍,使用底半部机制
中断标志清除 手动写寄存器清除 由中断控制器驱动自动处理 裸机开发中极易遗漏,需格外注意
本节要点: 中断向量表是中断响应的入口映射表;中断优先级决定中断的抢占行为;中断嵌套提高了系统的实时响应能力;完整的中断响应流程涉及硬件自动压栈、向量查找、ISR执行和现场恢复。GPIO驱动开发者必须深刻理解这些机制,才能编写出高效、稳定的中断处理代码。