ARM Cortex-M 中的 异常和中断

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)由内核内部机制或指令触发,各有特定用途。
  • ResetNMIHardFault 的优先级是固定的负值,高于所有可配置优先级的中断,这意味着它们不能被屏蔽,且能抢占任何其他处理。

2. 嵌套向量中断控制器NVIC

NVIC 是 Cortex-M 内核内部一个极其重要的集成模块,它负责管理所有的可配置优先级异常(即异常号4-6,11-15,以及所有外部中断IRQ)。

你可以把 NVIC 想象成一个高度智能的交通管制中心

NVIC 的核心功能:

  1. 优先级管理

    • 每个异常(除复位、NMI、硬错误外)都有一个可编程的优先级(优先级数值越小,优先级越高)。
    • NVIC 支持优先级分组 ,允许你将优先级数值进一步划分为抢占优先级子优先级抢占优先级 高的异常可以打断正在执行的抢占优先级 低的异常(嵌套)。子优先级 仅在多个待处理异常具有相同抢占优先级时,决定谁先执行。
  2. 中断的使能与屏蔽

    • 全局开关 : 通过 CPSID I / CPSIE I 指令或访问 PRIMASK 寄存器,可以全局禁用/启用所有可屏蔽异常(主要是IRQ和SysTick等)。
    • 个体开关 : NVIC 提供了 ISER(中断使能)和 ICER(中断除能)寄存器,可以独立地控制每个外部中断的开关。
  3. 中断挂起与状态

    • 当外设发出中断请求,但处理器因优先级或其他原因未能立即响应时,NVIC 的 ISPR(中断挂起)寄存器会记录这个"待处理"的状态。
    • 一旦条件允许(如更高优先级中断处理完毕),NVIC 会根据挂起状态和优先级,决定下一个响应的异常。
  4. 自动的嵌套与返回

    • NVIC 与内核硬件紧密协作,在进入和退出异常时,自动 完成一系列关键操作:
      • 入栈: 将当前执行环境的寄存器(如PC, LR, PSR, R0-R3, R12)压入堆栈。
      • 取向量 : 从向量表中取出对应异常处理程序的入口地址。
      • 更新寄存器 : 更新LR为特殊值(EXC_RETURN),PSR等。
      • 出栈与返回 : 处理程序结束时,通过 BX LR 指令(其中LR是 EXC_RETURN)触发硬件自动从堆栈恢复寄存器,并返回到被中断的程序。

简单流程: 外设触发中断 -> 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 提供了强大的错误检测和上报机制。当发生非法操作时,会触发相应的错误异常

主要错误异常类型:

  1. HardFault(硬错误)

    • 最高优先级的错误异常,是"最后的安全网"。
    • 当其他可配置的错误异常(如MemManage、BusFault、UsageFault)被禁用 ,或者它们本身在处理过程中再次出错 时,错误就会升级为HardFault。
    • 常见原因: 访问非法内存地址(空指针)、堆栈溢出、跳转到非法代码区、中断服务函数缺失(向量表项为空)等。
  2. MemManage Fault(内存管理错误)

    • 通常由 MPU触发。
    • 常见原因: 向只读区域写入数据、从非执行区域取指、以特权模式访问用户模式专属区域等违反MPU配置规则的行为。
  3. BusFault(总线错误)

    • 在指令加载、数据读写时,由总线系统报告的错误。
    • 常见原因: 访问一个物理上不存在的存储设备地址、设备未准备好、违反AHB总线协议等。
  4. UsageFault(使用错误)

    • 指令执行相关的问题触发。
    • 常见原因: 执行未定义的指令(如ARM指令)、尝试切换到非法状态(在Cortex-M上执行切换到ARM状态的指令)、非对齐的内存访问(如果已被使能检测)、除零错误(某些Cortex-M型号支持)等。

错误发生后的处理流程:

  1. 错误条件被检测到。
  2. 触发对应的错误异常。如果该异常被使能,则进入其处理函数;如果被禁用,则立即升级为HardFault
  3. 在错误异常的处理函数中,程序员可以:
    • 读取一系列配置和控制寄存器 来诊断错误原因。最重要的是 CFSR(可配置故障状态寄存器),它的各个位精确指出了是哪种具体错误(如 IMPRECISERR, PRECISERR, IBUSERR 等)。
    • 读取 BFAR(总线故障地址寄存器)或 MMFAR(内存管理故障地址寄存器)来获取导致错误的地址
    • 读取 HFSR(硬错误状态寄存器)了解HardFault的起因。
    • 读取 LR 和堆栈中自动保存的上下文(PC, PSR等),回溯到错误发生时的代码位置。
  4. 根据错误类型,处理函数可以尝试恢复,或进行系统复位、进入安全模式、记录错误日志等操作。

调试技巧

  • 在开发中,最常遇到的是 HardFault
  • 当程序"死机"时,首先检查是否进入了 HardFault 处理函数。
  • 通过查看 CFSR 的值、分析堆栈中保存的PC和LR值,可以精确定位到导致崩溃的源代码行。

总结图景

  1. 事件发生: 外部设备发出中断请求(IRQ),或内核内部发生错误/执行特定指令。
  2. NVIC裁决: NVIC 接收请求,根据优先级、使能状态和当前执行环境,决定是否响应以及响应哪个异常。
  3. 硬件自动响应 : 若响应,内核硬件自动保存现场,并通过向量表查找跳转地址。
  4. 执行处理程序: 跳转到对应的异常/中断服务函数执行用户代码。
  5. 自动返回: 函数通过返回特殊值,触发硬件自动恢复现场,程序继续执行。

理解这四部分及其相互作用,是掌握 Cortex-M 实时性和可靠性的基石。

相关推荐
麒qiqi1 小时前
从像素点亮到时序控制:i.MX6U 驱动 LCD 的完整流程
单片机·嵌入式硬件
济6172 小时前
linux 系统移植(第二十期)---- BusyBox构建根文件系统---- Ubuntu20.04
linux·嵌入式硬件
西城微科方案开发2 小时前
汽车打气泵方案
单片机·汽车·方案公司推荐
三佛科技-187366133972 小时前
FT32F072RBAT7/CBAT7/KBBT7/KBBU7/KBCW7 32位MCU单片机解析
单片机·嵌入式硬件
wypywyp2 小时前
5.stm32 江协科技笔记1
stm32·单片机·嵌入式硬件
小慧10242 小时前
STM32多串口应用
stm32·单片机·嵌入式硬件
小龙报3 小时前
【SOLIDWORKS 练习题】草图专题:3.机械臂
笔记·单片机·嵌入式硬件·物联网·开源·硬件工程·材料工程
Moonquakes5403 小时前
嵌入式开发基础学习笔记(RGB LCD 驱动开发)
arm开发·驱动开发·嵌入式硬件
LaoZhangGong1234 小时前
学习TCP/IP的第8步:紧急数据
网络·stm32·单片机·学习·tcp/ip·以太网