1. 中断向量表基础概念
1.1 中断向量表的定义
中断向量表(Interrupt Vector Table,IVT)是一张存储在固定内存区域的地址映射表,表中每一项存放着对应中断服务程序(Interrupt Service Routine,ISR)或异常处理程序的入口地址。当处理器检测到异常或中断事件时,硬件自动从向量表中取出对应地址,并跳转执行该地址处的代码。
核心要点:中断向量表本质上是“异常编号 → 处理函数地址”的查找表,由硬件直接使用,无需软件干预。
1.2 中断向量表的作用
- 异常分发:将不同异常源(复位、NMI、硬故障、SVC、PendSV、SysTick 等)映射到对应的处理函数。
- 系统启动引导:复位后处理器从向量表首地址加载主栈指针(MSP)和复位向量,完成初始化。
- 实时响应:硬件级查表跳转,延迟极低,满足嵌入式实时性要求。
- 可配置性:通过修改向量表内容或重定位向量表基址,实现灵活的中断管理。
1.3 在 ARM Cortex-M 系列处理器中的位置
ARM Cortex-M 系列处理器(M0/M0+/M3/M4/M7/M33 等)采用统一中断向量表设计,向量表固定在地址 0x00000000 起始处(默认),或通过 VTOR(Vector Table Offset Register)寄存器重定位到其他地址。
| 异常编号 | 向量表偏移 | 异常类型 | 优先级 | 说明 |
|---|---|---|---|---|
| 0 | 0x00 | MSP 初始值 | — | 主栈指针初始值,复位后加载到 SP |
| 1 | 0x04 | Reset | -3(最高) | 复位异常,系统启动入口 |
| 2 | 0x08 | NMI | -2 | 不可屏蔽中断 |
| 3 | 0x0C | HardFault | -1 | 硬故障,所有故障的默认处理 |
| 4 | 0x10 | MemManage | 可编程 | 存储器管理故障(M3/M4/M7) |
| 5 | 0x14 | BusFault | 可编程 | 总线故障(M3/M4/M7) |
| 6 | 0x18 | UsageFault | 可编程 | 用法故障(M3/M4/M7) |
| 7–10 | 0x1C–0x28 | 保留 | — | ARM 保留 |
| 11 | 0x2C | SVC | 可编程 | 系统服务调用(Supervisor Call) |
| 12 | 0x30 | DebugMon | 可编程 | 调试监视器 |
| 13 | 0x34 | 保留 | — | ARM 保留 |
| 14 | 0x38 | PendSV | 可编程 | 可挂起系统服务请求 |
| 15 | 0x3C | SysTick | 可编程 | 系统滴答定时器 |
| 16+ | 0x40+ | 外部中断 | 可编程 | 芯片厂商定义的外设中断 |
注意:Cortex-M0/M0+ 只支持 NMI、HardFault、SVC、PendSV、SysTick 和最多 32 个外部中断;M3/M4/M7 支持完整的 MemManage、BusFault、UsageFault 以及最多 240 个外部中断。
1.4 向量表布局与内存映射
下图展示了 ARM Cortex-M 处理器默认中断向量表在内存中的布局结构:
1.5 向量表在启动文件中的体现
在 ARM Cortex-M 工程中,中断向量表通常由启动文件(startup_xxx.s)定义。以下是一个典型的 Cortex-M4 启动文件片段:
; 中断向量表定义(startup_stm32f407xx.s)
__Vectors DCD __initial_sp ; 0x00: MSP 初始值
DCD Reset_Handler ; 0x04: 复位向量
DCD NMI_Handler ; 0x08: NMI
DCD HardFault_Handler ; 0x0C: 硬故障
DCD MemManage_Handler ; 0x10: 存储器管理故障
DCD BusFault_Handler ; 0x14: 总线故障
DCD UsageFault_Handler ; 0x18: 用法故障
DCD 0 ; 0x1C: 保留
DCD 0 ; 0x20: 保留
DCD 0 ; 0x24: 保留
DCD 0 ; 0x28: 保留
DCD SVC_Handler ; 0x2C: SVC
DCD DebugMon_Handler ; 0x30: 调试监视器
DCD 0 ; 0x34: 保留
DCD PendSV_Handler ; 0x38: PendSV
DCD SysTick_Handler ; 0x3C: SysTick
; 外部中断从 0x40 开始
DCD WWDG_IRQHandler ; 0x40: 窗口看门狗
DCD PVD_IRQHandler ; 0x44: PVD
; ... 后续中断向量
常见错误:向量表第一项必须是有效的栈指针值,第二项必须是复位处理函数地址。如果这两个值错误,芯片上电后将无法正常启动,直接进入 HardFault 或死机。
1.6 向量表重定位(VTOR 寄存器)
Cortex-M3/M4/M7/M33 等处理器提供了 VTOR(Vector Table Offset Register) 寄存器,允许将向量表从默认的 0x00000000 重定位到其他地址(如 SRAM 或 Flash 的偏移位置)。这在以下场景中非常有用:
- Bootloader + 应用程序:Bootloader 位于 Flash 起始地址,应用程序位于偏移地址,需重定位向量表。
- 运行时动态更新:将向量表复制到 SRAM 中,运行时修改中断处理函数。
- 多核系统:每个核使用独立的向量表。
VTOR 寄存器位于系统控制块(SCB)中,地址为 0xE000ED08,其格式如下:
| 位段 | 名称 | 描述 |
|---|---|---|
| [31:7] | TBLBASE | 向量表基址的高 25 位,要求 128 字节对齐 |
| [6:0] | 保留 | 必须写 0 |
设置 VTOR 的示例代码:
/* 将向量表重定位到 0x08010000(应用程序起始地址) */
#define SCB_VTOR (*(volatile uint32_t *)0xE000ED08)
SCB_VTOR = 0x08010000;
对齐要求:VTOR 的值必须按 128 字节对齐(即低 7 位为 0),否则处理器行为不可预测。向量表大小至少为 16 个异常向量(64 字节),加上外部中断后总大小需对齐到 128 字节的整数倍。
1.7 异常优先级与向量表的关系
ARM Cortex-M 使用抢占优先级模型,异常编号越小,优先级越高(复位为 -3,NMI 为 -2,HardFault 为 -1)。向量表本身不存储优先级信息,优先级由系统优先级寄存器(如 SHPR1–SHPR3)和NVIC 优先级寄存器单独配置。向量表只负责提供处理函数的入口地址。
1.8 本章小结
- 中断向量表是异常编号到处理函数地址的映射表,由硬件直接使用。
- 在 ARM Cortex-M 中,向量表默认位于 0x00000000,通过 VTOR 可重定位。
- 向量表第一项为 MSP 初始值,第二项为 Reset_Handler,这是系统启动的关键。
- 异常优先级由独立的寄存器控制,与向量表内容无关。
- 启动文件中的
__Vectors段是向量表的具体实现,必须保证正确性。