ARM Cortex-M 中的 异常和中断
ARM Cortex-M 中的异常和中断是一个非常核心且基础的概念,对于理解 Cortex-M 内核的工作原理至关重要。
我将围绕以下四个核心部分展开:
1. 什么是异常?
在 ARM Cortex-M 的语境下,异常 是一个广义的总称,指任何需要处理器暂停当前正在执行的指令 ,转而去执行一段特殊代码(称为异常处理程序 或异常服务例程)的事件。
中断 是 异常 的一个子集。具体来说:
-
异常 :包括所有由内部或外部事件触发的处理流程转移。Cortex-M 内核预定义了一系列异常类型 ,每个类型有一个固定的编号,称为 异常号。
-
中断 :特指由外部外设 (如定时器、UART、GPIO)通过中断请求信号触发的异常。它们的异常号是 可配置的,由芯片厂商在设计外设时分配。

Cortex-M 异常的分类表(按异常号排序)
| 异常号 | 类型 | 优先级(默认) | 简称 | 触发源 |
|---|---|---|---|---|
| 1 | 复位 | -3(最高) | Reset | 上电、复位引脚 |
| 2 | 不可屏蔽中断 | -2 | NMI | 不可屏蔽的中断源(如看门狗) |
| 3 | 硬错误 | -1 | HardFault | 所有无法被正确处理的严重错误 |
| 4 | 存储管理错误 | 可配置 | MemManage | MPU权限违规、访问非法地址 |
| 5 | 总线错误 | 可配置 | BusFault | 总线传输错误(如访问不存在设备) |
| 6 | 使用错误 | 可配置 | UsageFault | 未定义指令、非法状态转换(如从ARM态进入) |
| 7-10 | 保留 | - | - | - |
| 11 | SVCall | 可配置 | SVC | 由 SVC 指令触发的系统服务调用 |
| 12 | 调试监控 | 可配置 | DebugMon | 调试事件 |
| 13 | 保留 | - | - | - |
| 14 | PendSV | 可配置 | PendSV | 由软件挂起的系统服务请求,常用于RTOS上下文切换 |
| 15 | SysTick | 可配置 | SysTick | 系统滴答定时器中断 |
| 16及以上 | 外部中断 | 可配置 | IRQ0, IRQ1, ... | 芯片上的外设(如UART、TIMER、GPIO) |
关键点总结:
- 中断 = 外部中断(IRQ)。
- 其他异常(1-15)由内核内部机制或指令触发,各有特定用途。
Reset、NMI、HardFault的优先级是固定的负值,高于所有可配置优先级的中断,这意味着它们不能被屏蔽,且能抢占任何其他处理。
2. 嵌套向量中断控制器NVIC
NVIC 是 Cortex-M 内核内部一个极其重要的集成模块,它负责管理所有的可配置优先级异常(即异常号4-6,11-15,以及所有外部中断IRQ)。
你可以把 NVIC 想象成一个高度智能的交通管制中心。
NVIC 的核心功能:
-
优先级管理:
- 每个异常(除复位、NMI、硬错误外)都有一个可编程的优先级(优先级数值越小,优先级越高)。
- NVIC 支持优先级分组 ,允许你将优先级数值进一步划分为抢占优先级 和子优先级 。抢占优先级 高的异常可以打断正在执行的抢占优先级 低的异常(嵌套)。子优先级 仅在多个待处理异常具有相同抢占优先级时,决定谁先执行。
-
中断的使能与屏蔽:
- 全局开关 : 通过
CPSID I/CPSIE I指令或访问PRIMASK寄存器,可以全局禁用/启用所有可屏蔽异常(主要是IRQ和SysTick等)。 - 个体开关 : NVIC 提供了
ISER(中断使能)和ICER(中断除能)寄存器,可以独立地控制每个外部中断的开关。
- 全局开关 : 通过
-
中断挂起与状态:
- 当外设发出中断请求,但处理器因优先级或其他原因未能立即响应时,NVIC 的
ISPR(中断挂起)寄存器会记录这个"待处理"的状态。 - 一旦条件允许(如更高优先级中断处理完毕),NVIC 会根据挂起状态和优先级,决定下一个响应的异常。
- 当外设发出中断请求,但处理器因优先级或其他原因未能立即响应时,NVIC 的
-
自动的嵌套与返回:
- NVIC 与内核硬件紧密协作,在进入和退出异常时,自动 完成一系列关键操作:
- 入栈: 将当前执行环境的寄存器(如PC, LR, PSR, R0-R3, R12)压入堆栈。
- 取向量 : 从向量表中取出对应异常处理程序的入口地址。
- 更新寄存器 : 更新LR为特殊值(
EXC_RETURN),PSR等。 - 出栈与返回 : 处理程序结束时,通过
BX LR指令(其中LR是EXC_RETURN)触发硬件自动从堆栈恢复寄存器,并返回到被中断的程序。
- NVIC 与内核硬件紧密协作,在进入和退出异常时,自动 完成一系列关键操作:
简单流程: 外设触发中断 -> NVIC 接收、根据优先级裁决 -> 若允许响应,NVIC 通知内核 -> 内核硬件自动保存现场、跳转到处理函数 -> 处理函数执行完毕返回 -> 内核硬件自动恢复现场。
3. 向量表
向量表 本质上是一个地址查询表 ,它存储在内存的特定位置(默认在 0x00000000)。表中的每一项都是一个 4 字节的地址 (在32位系统中),指向对应异常或中断的处理函数。
向量表的结构:
- 第0项 : 初始主堆栈指针 的值。这是处理器启动后第一个加载到MSP寄存器的值。
- 第1项 : 复位异常处理函数 的地址。处理器上电后执行的第一条指令就从这里取得。
- 第2项 : NMI处理函数 的地址。
- 第3项 : 硬错误处理函数 的地址。
- ... 以此类推,按照异常号顺序排列。
向量表重定位:
-
在大多数实际应用中,向量表会被复制并重定位到RAM 或特定的Flash区域 (如
0x08000000,这是STM32 Flash的起始地址)。这通过设置 Cortex-M 的VTOR寄存器实现。 -
为什么? 因为RAM中的向量表可以被运行时修改,这对于实现动态改变中断服务函数 (如通过函数指针)、Bootloader跳转到应用程序等场景至关重要。

与NVIC的关系:
- NVIC 不存储向量表,它负责管理异常的触发、优先级和状态。
- 当 NVIC 通知内核需要响应某个异常(比如IRQ#5)时,内核硬件会根据
VTOR寄存器的值找到向量表基址,然后根据异常号(例如 16+5=21)计算出偏移量,取出第21项的地址,并跳转到那个地址执行。
4. 错误处理
Cortex-M 提供了强大的错误检测和上报机制。当发生非法操作时,会触发相应的错误异常。
主要错误异常类型:
-
HardFault(硬错误):
- 最高优先级的错误异常,是"最后的安全网"。
- 当其他可配置的错误异常(如MemManage、BusFault、UsageFault)被禁用 ,或者它们本身在处理过程中再次出错 时,错误就会升级为HardFault。
- 常见原因: 访问非法内存地址(空指针)、堆栈溢出、跳转到非法代码区、中断服务函数缺失(向量表项为空)等。
-
MemManage Fault(内存管理错误):
- 通常由 MPU触发。
- 常见原因: 向只读区域写入数据、从非执行区域取指、以特权模式访问用户模式专属区域等违反MPU配置规则的行为。
-
BusFault(总线错误):
- 在指令加载、数据读写时,由总线系统报告的错误。
- 常见原因: 访问一个物理上不存在的存储设备地址、设备未准备好、违反AHB总线协议等。
-
UsageFault(使用错误):
- 由指令执行相关的问题触发。
- 常见原因: 执行未定义的指令(如ARM指令)、尝试切换到非法状态(在Cortex-M上执行切换到ARM状态的指令)、非对齐的内存访问(如果已被使能检测)、除零错误(某些Cortex-M型号支持)等。

错误发生后的处理流程:
- 错误条件被检测到。
- 触发对应的错误异常。如果该异常被使能,则进入其处理函数;如果被禁用,则立即升级为HardFault。
- 在错误异常的处理函数中,程序员可以:
- 读取一系列配置和控制寄存器 来诊断错误原因。最重要的是
CFSR(可配置故障状态寄存器),它的各个位精确指出了是哪种具体错误(如IMPRECISERR,PRECISERR,IBUSERR等)。 - 读取
BFAR(总线故障地址寄存器)或MMFAR(内存管理故障地址寄存器)来获取导致错误的地址。 - 读取
HFSR(硬错误状态寄存器)了解HardFault的起因。 - 读取
LR和堆栈中自动保存的上下文(PC, PSR等),回溯到错误发生时的代码位置。
- 读取一系列配置和控制寄存器 来诊断错误原因。最重要的是
- 根据错误类型,处理函数可以尝试恢复,或进行系统复位、进入安全模式、记录错误日志等操作。
调试技巧:
- 在开发中,最常遇到的是 HardFault。
- 当程序"死机"时,首先检查是否进入了 HardFault 处理函数。
- 通过查看
CFSR的值、分析堆栈中保存的PC和LR值,可以精确定位到导致崩溃的源代码行。
总结图景
- 事件发生: 外部设备发出中断请求(IRQ),或内核内部发生错误/执行特定指令。
- NVIC裁决: NVIC 接收请求,根据优先级、使能状态和当前执行环境,决定是否响应以及响应哪个异常。
- 硬件自动响应 : 若响应,内核硬件自动保存现场,并通过向量表查找跳转地址。
- 执行处理程序: 跳转到对应的异常/中断服务函数执行用户代码。
- 自动返回: 函数通过返回特殊值,触发硬件自动恢复现场,程序继续执行。
理解这四部分及其相互作用,是掌握 Cortex-M 实时性和可靠性的基石。