2. 中断控制器基础:中断的概念、中断向量、中断优先级与中断嵌套

在嵌入式实时系统(RTOS)中,中断是处理器响应外部或内部异步事件的核心机制。对于 VxWorks BSP 开发而言,中断控制器(Interrupt Controller)是连接硬件外设与内核调度器的关键桥梁。本章将系统性地梳理中断的基本概念、向量表结构、优先级仲裁逻辑以及嵌套处理流程,为后续深入分析具体中断控制器(如 GIC、IOAPIC)的 BSP 适配打下坚实基础。

2.1 中断的基本概念

中断(Interrupt)是一种硬件机制,允许外设或软件通过向处理器发送电信号,暂停当前正在执行的程序流,并跳转到一个预先定义的服务例程(ISR)去处理该事件。处理完成后,处理器恢复被中断的上下文,继续执行原程序。

关键术语速查表
术语 英文 说明
中断请求 IRQ 外设向中断控制器发出的硬件信号
中断服务例程 ISR 响应中断时执行的函数,要求短小、无阻塞
中断向量 Vector 标识中断源的唯一编号,用于索引中断向量表
中断控制器 PIC / GIC / IOAPIC 集中管理多个中断源,负责优先级裁决与分发
中断上下文 Interrupt Context ISR 执行时的 CPU 状态,与任务上下文隔离
VxWorks 实践提示: 在 BSP 中注册 ISR 时,必须使用 intConnect() 或 intVecSet() 函数,并确保 ISR 中不调用可能引起阻塞的 API(如 semTake() 带超时、malloc() 等)。

2.2 中断向量与向量表

中断向量(Interrupt Vector)是一个整数编号,每个中断源对应一个唯一的向量号。处理器在响应中断时,通过向量号在中断向量表(IVT)中查找对应的 ISR 入口地址。向量表通常位于内存的固定基地址,由 BSP 在启动阶段初始化。

中断向量表结构(IVT) 中断向量表基地址 (VBR / VBAR) 向量 0:复位 向量 1:机器错误 向量 2:NMI 向量 3:外部 IRQ0 … ISR_Reset ISR_MachineErr ISR_NMI ISR_UART_Rx … 说明: • 每个向量表条目占用 4 字节(32位)或 8 字节(64位),存放 ISR 入口地址。 • VxWorks BSP 在 sysALib.s 中通过 .word 伪指令构建向量表,并在 sysHwInit() 中设置向量基址寄存器。
BSP 开发注意: 不同架构的向量表布局差异很大。ARM Cortex-A 使用 VBAR 寄存器指向向量表,且支持中断向量偏移;x86 架构在实模式下使用 IVT(0x0000~0x03FF),保护模式下使用 IDT。BSP 必须根据 CPU 类型正确初始化向量表基址。

2.3 中断优先级

中断优先级(Priority)用于决定当多个中断同时发生时,处理器优先响应哪一个。中断控制器通常支持可编程优先级,允许软件为每个中断源分配 0~255 级优先级(数值越小优先级越高,或反之,取决于具体硬件)。

优先级仲裁的基本规则如下:

  1. 抢占规则: 高优先级中断可以抢占正在执行的低优先级 ISR。
  2. 同优先级轮询: 相同优先级的中断按硬件连接顺序或 Round-Robin 方式响应。
  3. 屏蔽规则: 当前 ISR 执行期间,中断控制器可自动屏蔽同级或更低优先级的中断。
优先级配置示例(GIC-400)
/* VxWorks BSP 中设置中断优先级示例 */
#include <vxWorks.h>
#include <intLib.h>
#include <hwif/vxBus.h>

STATUS sysIntPrioritySet(
    UINT32  vector,      /* 中断向量号 */
    UINT32  priority     /* 优先级值,0~255,0 为最高 */
    )
{
    VXB_DEVICE_ID pDev;
    UINT32        regBase;

    /* 通过 vxBus 获取中断控制器寄存器基址 */
    pDev = vxbDevFindByClass("arm_gic", 0);
    if (pDev == NULL)
        return ERROR;

    regBase = vxbDevRegBaseGet(pDev, 0);
    if (regBase == 0)
        return ERROR;

    /* 写入 GICD_IPRIORITYR 寄存器 */
    *(volatile UINT32 *)(regBase + 0x400 + (vector >> 2)) =
        (priority & 0xFF) << ((vector & 3) << 3);

    return OK;
}

2.4 中断嵌套

中断嵌套(Interrupt Nesting)是指在一个 ISR 执行过程中,允许更高优先级的中断打断当前 ISR,先执行高优先级 ISR,完成后返回被中断的 ISR 继续执行。嵌套深度受限于中断控制器的硬件设计以及操作系统的中断栈大小。

中断嵌套执行时序图 时间→ 主程序(任务上下文) 低优先级 ISR (Prio=5) 高优先级 ISR (Prio=1) 恢复低优先级 IRQ_Low IRQ_High 嵌套执行流程说明: 1. 主程序执行时,低优先级中断 IRQ_Low 到达,CPU 跳转到低优先级 ISR。 2. 低优先级 ISR 执行过程中,高优先级中断 IRQ_High 到达。 3. 中断控制器仲裁后,向 CPU 发出高优先级中断请求。 4. CPU 保存低优先级 ISR 的上下文,跳转到高优先级 ISR 执行。 5. 高优先级 ISR 执行完毕,执行中断返回指令(如 ERET / IRET)。 6. CPU 恢复低优先级 ISR 的上下文,继续执行直到完成。 7. 最终返回主程序。
VxWorks 嵌套配置: 在 BSP 的 config.h 中,宏 INCLUDE_INT_LIB 和 INCLUDE_VXEVENTS 控制中断嵌套支持。中断栈大小由 ISR_STACK_SIZE 定义,默认通常为 4096 字节。如果嵌套深度过大,可能导致栈溢出,系统崩溃。

2.5 中断优先级与嵌套的硬件依赖

不同中断控制器的优先级模型和嵌套机制存在显著差异。下表对比了三种常见中断控制器的关键特性:

特性 ARM GIC-400 x86 IOAPIC + LAPIC NXP (Freescale) MPIC
优先级范围 0~255(0 最高) 0~15(0 最低) 0~15(0 最高)
嵌套支持 硬件自动支持,通过 GICC_PMR 寄存器控制 需软件操作 LAPIC TPR 寄存器实现 硬件自动支持,通过 MI_PRI_MASK 寄存器控制
向量表位置 由 VBAR 寄存器指定 IDT 由 IDTR 寄存器指定 由 IVOR 寄存器指定(e500 核)
BSP 初始化关键函数 sysGicInit() sysIoApicInit() sysMpicInit()
常见 BSP 陷阱: 在移植 BSP 时,如果中断控制器不支持硬件嵌套,而 VxWorks 配置了嵌套使能,会导致 ISR 重入时寄存器保存不完整,出现“中断丢失”或“栈损坏”现象。务必查阅芯片参考手册,确认硬件是否支持自动中断屏蔽。

2.6 中断延迟与实时性考量

中断延迟(Interrupt Latency)是指从中断信号到达处理器引脚,到 ISR 第一条指令开始执行的时间间隔。在 VxWorks 实时系统中,中断延迟是衡量 BSP 性能的核心指标之一。

影响中断延迟的主要因素包括:

  • 中断屏蔽时间: 内核或高优先级 ISR 执行期间关闭中断的时间窗口。
  • 中断控制器仲裁时间: 硬件优先级比较和向量生成时间。
  • 上下文保存开销: CPU 自动压栈(PC、SR、通用寄存器)的时钟周期数。
  • Cache 与 TLB 缺失: 向量表和 ISR 代码不在 Cache 中时,需要从主存加载。
VxWorks 中断延迟测量方法
/* 使用 sysTimestamp 测量中断延迟 */
#include <vxWorks.h>
#include <sysTimestamp.h>
#include <intLib.h>

UINT64 tStart, tEnd;
UINT32 latencyMax = 0;

void myIsr(void)
{
    tEnd = sysTimestamp();
    UINT64 latency = tEnd - tStart;
    if (latency > latencyMax)
        latencyMax = (UINT32)latency;

    /* ISR 处理逻辑 */
}

void triggerInterrupt(void)
{
    tStart = sysTimestamp();
    /* 触发硬件中断,例如写 GPIO 寄存器 */
    *(volatile UINT32 *)GPIO_SET_REG = 1 << 5;
}

通过上述方法,BSP 开发者可以量化中断延迟,并针对性地优化中断屏蔽区间、调整优先级分配或使用中断绑定(Interrupt Affinity)将关键中断绑定到特定 CPU 核。

2.7 小结