Tianya
发布于 2026-07-15 / 17 阅读
0

ARMv7-M异常分析

1. 异常分析流程

1.1. 流程说明

1.1.1. 确定异常之前的状态

进入异常时,处理器会拦截写入LR寄存器的值,把PC值替换为EXC_RETURN,EXC_RETURN各位段定义如下:

  1. Bit[31:28]:固定为0xF
  2. Bit[27:5]:保留位,软件必须置 1(SBOP:Software Bit One Policy,软件置 1 规则)。若向该区域任意位写入 0 以外的值,行为不可预测(UNPREDICTABLE)。
  3. Bit[4:4]:处理器无浮点扩展单元 FP 时,软件必须置 1。若向该位写入 0 以外的值,行为不可预测。处理器无浮点扩展单元 FP 时,用于标识本次异常的栈帧是否分配了浮点状态存储空间:0,栈帧分配了浮点上下文存储空间。
  4. Bit[3:0]:定义异常返回所需执行的硬件行为,对应表格:
    • 表1,无浮点单元的内核

    • 表2,带浮点单元的内核
      两张表格统一遵守以下规则:

    1. 表格未列出的 EXC_RETURN 数值均为保留值,对应内核不可使用;
    2. 表格中「Return stack(返回堆栈)」列代表:异常返回流程中,处理器用于恢复现场上下文的堆栈;同时也是异常退出后程序运行所使用的堆栈。

表1:无浮点扩展内核的异常返回行为 EXC_RETURN 定义

EXC_RETURN返回到返回的栈
0xFFFFFFF1Handler Mode(异常处理模式)Main(主堆栈 MSP)
0xFFFFFFF9Thread Mode(线程模式)Main(主堆栈 MSP)
0xFFFFFFFDThread Mode(线程模式)Process(进程堆栈 PSP)

表2:带浮点扩展内核的 EXC_RETURN 异常返回行为定义

EXC_RETURN返回到返回的栈栈帧类型
0xFFFFFFE1Handler Mode(异常处理模式)Main(主堆栈 MSP)扩展栈帧 Extended
0xFFFFFFE9Thread Mode(线程模式)Main(主堆栈 MSP)扩展栈帧 Extended
0xFFFFFFEDThread Mode(线程模式)Process(进程堆栈 PSP)扩展栈帧 Extended
0xFFFFFFF1Handler Mode(异常处理模式)Main(主堆栈 MSP)基础栈帧 Basic
0xFFFFFFF9Thread Mode(线程模式)Main(主堆栈 MSP)基础栈帧 Basic
0xFFFFFFFDThread Mode(线程模式)Process(进程堆栈 PSP)基础栈帧 Basic

1.1.2. 分析异常现场

处理进入异常时,会进行一次压栈操作。根据EXC_RETURN的值的不同,会压入不同的栈帧。如果处理器有FPU,有可能压入扩展帧,如果没有FPU,只会压入标准帧,参考表1表2。从栈帧中的RetuenAddress(就是进入异常之前的PC),再结合MAP文件(如果有条件可以使用反汇编文件),基本可以确定异常发生的位置。

图1:标准帧图2:扩展帧
image-nOUY.pngimage-fmkr.png

1.2. 异常分析流程图

进入 Fault Handler
读取 LR 获取 EXC_RETURN 值
LR.bit2 == 1?
异常前使用 PSP
异常前使用 MSP
读取 PSP 值
读取 MSP 值
LR.bit4 == 1?
扩展栈帧
(浮点上下文)
栈指针需额外偏移
标准栈帧
(8字自动压栈)
SP 直接指向栈帧基址
按顺序提取栈帧内容
R0,R1,R2,R3,R12,LR,PC,xPSR
解析关键字段
xPSR.IPSR:判断异常前是否在中断中
IPSR != 0?
异常发生在中断服务程序中检查对应 ISR 代码
异常发生在中断服务程序中检查对应 ISR 代码
PC:定位触发异常的指令
结合反汇编 / Map 文件定位源码
栈帧 LR:获取异常前调用返回地址
回溯调用链辅助定位错误传递路径
可选:读取 SCB->CFSR
细分 MemManage/BusFault/UsageFault
综合 PC、xPSR、CFSR 等信息确定异常根本原因