2. MCU 中断系统概述:中断向量表、中断优先级、中断嵌套、中断使能与屏蔽机制

中断系统是 MCU 实时响应外部或内部事件的硬件核心。在 UART 中断模式驱动开发中,理解中断系统的底层机制是配置可靠通信的基础。本节将系统梳理中断向量表、优先级、嵌套、使能与屏蔽四大核心概念,并给出它们在 Cortex-M 系列 MCU(如 STM32)中的典型实现。

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

中断向量表是一张存储在 MCU 起始地址(通常为 0x0000 0000 或 0x0800 0000)的地址映射表。每个中断源对应表中的一个表项,表项内容为该中断服务函数(ISR)的入口地址。当 MCU 响应中断时,硬件自动从向量表中取出对应地址并跳转执行。

关键点: 向量表在系统启动时由链接脚本定位,复位后 MCU 从向量表首地址(__initial_sp)加载栈指针,从第二个字(Reset_Handler)加载复位入口。UART 中断的向量表项通常位于外部中断区域(如 IRQ 37~52 取决于具体 MCU)。
中断向量表结构(Cortex-M 系列) 向量表基地址(0x0000 0000 / 0x0800 0000) 偏移 0x00 初始栈指针(__initial_sp) 偏移 0x04 复位中断(Reset_Handler) 偏移 0x08 NMI(不可屏蔽中断) 偏移 0x0C ~ 0x2C 系统异常(HardFault、SVCall、PendSV、SysTick) 偏移 0x30 ~ 0x3FF 外部中断(UART、TIM、GPIO、DMA 等) 4 字节/表项 UARTx_IRQHandler 的入口地址由启动文件中的 .isr_vector 段定义

2.2 中断优先级(Interrupt Priority)

中断优先级决定了当多个中断同时触发时,MCU 优先响应哪一个。Cortex-M 内核支持可编程优先级,通常分为抢占优先级(Preemption Priority)和子优先级(Subpriority)。

优先级类型 作用 典型位数(STM32) 数值与优先级关系
抢占优先级 决定是否打断正在执行的低优先级中断 4 位(0~15) 数值越小,优先级越高
子优先级 当抢占优先级相同时,决定响应顺序 4 位(0~15) 数值越小,优先级越高
配置建议: 在 UART 驱动中,通常将 UART 中断的抢占优先级设为中等(如 5~7),避免被 SysTick(通常为最低优先级)以外的低优先级中断干扰,同时不阻塞高实时性中断(如 TIM 定时器)。

2.3 中断嵌套(Interrupt Nesting)

中断嵌套是指一个中断服务函数正在执行时,被另一个更高优先级的中断打断的现象。Cortex-M 内核通过硬件自动压栈(Push)和出栈(Pop)现场来支持嵌套,无需软件干预。

中断嵌套执行流程 主程序(Main) 低优先级 ISR(UART) 高优先级 ISR(TIM) 时间 → 硬件自动压栈 R0-R3、R12、LR、PC、xPSR;出栈时自动恢复 嵌套深度受限于栈空间,典型 MCU 支持无限嵌套(仅受 RAM 限制)

2.4 中断使能与屏蔽机制

中断使能(Enable)与屏蔽(Mask)是控制中断是否被响应的两种手段。使能是允许特定中断源触发,屏蔽则是全局或局部地禁止中断响应。

2.4.1 中断使能

  • 外设级使能: 在 UART 控制寄存器(如 USART_CR1)中设置 RXNEIE(接收中断使能)或 TCIE(发送完成中断使能)位。
  • 内核级使能: 在 NVIC(嵌套向量中断控制器)中使能对应中断通道,调用 NVIC_EnableIRQ(USARTx_IRQn)。

2.4.2 中断屏蔽

  • 全局屏蔽: 使用 __disable_irq()(CPSID I)关闭所有可屏蔽中断;使用 __enable_irq()(CPSIE I)恢复。
  • 优先级屏蔽: 设置 BASEPRI 寄存器,屏蔽所有优先级低于或等于该值的中断。例如 __set_BASEPRI(0x50) 屏蔽优先级 >= 5 的中断。
  • 局部屏蔽: 在 NVIC 中调用 NVIC_DisableIRQ(USARTx_IRQn) 关闭特定中断。
常见陷阱: 在 ISR 内部使用 __disable_irq() 会导致所有中断被关闭,包括 SysTick,可能造成系统时钟失准。推荐使用 __set_BASEPRI() 进行优先级屏蔽,或使用临界区保护宏(如 __disable_irq() / __enable_irq() 对)仅保护关键代码段。

2.5 中断使能与屏蔽机制对比

机制 作用范围 实现方式 典型场景
全局使能/屏蔽 所有可屏蔽中断 __enable_irq() / __disable_irq() 系统初始化、临界区保护
优先级屏蔽 低于设定优先级的中断 __set_BASEPRI(priority) ISR 内保护共享数据
外设级使能 单个外设中断源 设置外设控制寄存器位 UART 接收/发送中断开关
NVIC 通道使能 单个中断通道 NVIC_EnableIRQ() / NVIC_DisableIRQ() 动态控制 UART 中断响应

2.6 中断配置代码示例(STM32 UART)

/* 1. 设置中断优先级分组(抢占优先级 4 位,子优先级 0 位) */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);

/* 2. 配置 UART 中断优先级 */
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 5;  /* 抢占优先级 */
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;         /* 子优先级 */
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

/* 3. 使能 UART 外设级接收中断 */
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);

/* 4. 全局中断使能(通常在系统初始化时已调用) */
__enable_irq();

/* 5. 在 ISR 中使用优先级屏蔽保护临界区 */
void USART1_IRQHandler(void)
{
    if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
    {
        /* 进入临界区:屏蔽优先级 <= 10 的中断 */
        __set_BASEPRI(0xA0);

        /* 读取接收数据寄存器 */
        uint8_t data = USART_ReceiveData(USART1);

        /* 退出临界区:恢复 BASEPRI */
        __set_BASEPRI(0);

        /* 处理接收数据(如放入环形缓冲区) */
        // ...
    }
}
总结: 中断向量表提供 ISR 入口映射,优先级决定响应顺序,嵌套实现高优先级打断低优先级,使能与屏蔽机制提供灵活的中断控制粒度。在 UART 驱动开发中,合理配置这四层机制是保证数据不丢失、系统不卡死的核心前提。