1. 基础知识
Fault 类异常
有若干个系统异常专用于 fault 处理。 CM3 中的 Faults 可分为以下几类:
- 总线 faults
- 存储器管理 faults
- 用法 faults
- 硬 fault
表 7.8 总线 fault 状态寄存器(BFSR), 地址:0xE000_ED29
表 7.9 存储器管理 fault 状态寄存器(MFSR),地址:0xE000_ED28
表 7.10 用法 fault 状态寄存器(UFSR), 地址:0xE000_ED2A
表 7.11 硬 fault 状态寄存器 地址:0xE000_ED2C
1.1 总线 Faults
当 AHB 接口上正在传送数据时,如果回复了一个错误信号(error response),则会产生总线 faults,产生的场合可以是:
- z 取指,通常被称作“预取流产”(prefetch abort)
- z 数据读/写,通常被称作“数据流产”(data abort)
在 CM3 中执行如下动作可以触发总线异常:
- 中断处理起始阶段的堆栈 PUSH 动作。 称为“入栈错误”
- 中断处理收尾阶段的堆栈 POP 动作。 称为“出栈错误”
- 在处理器启动中断处理序列(sequence)后的向量读取时。这是一种罕见的特殊情况,被归类为硬 fault。
1.3存储器管理 faults
存储器管理faults多与MPU有关,其诱因常常是某次访问触犯了MPU设置的保护策略。另外,某些非法访问,例如,在不可执行的存储器区域试图取指,也会触发一个 MemManagefault,而且即使没有 MPU 也会触发。MemManage faults 的常见诱因如下所示:
- 访问了 MPU 设置区域覆盖范围之外的地址
- 往只读 region 写数据
- 用户级下访问了只允许在特权级下访问的地址
1.4 用法 faults
用法 faults 发生的场合可以是:
- 执行了未定义的指令
- 执行了协处理器指令(Cortex‐M3 不支持协处理器,但是可以通过 fault 异常机制来使用软件模拟协处理器的功能,从而可以方便地在其它 Cortex 处理器间移植)
- 尝试进入 ARM 状态(因为 CM3 不支持 ARM 状态,所以用法 fault 会在切换时产生。软件可以利用此机制来测试某处理器是否支持 ARM 状态)
- 无效的中断返回(LR 中包含了无效/错误的值)
- 使用多重加载/存储指令时,地址没有对齐。另外,通过设置 NVIC 的对应控制位,可以在下列场合下也产生用法 fault:
- 除数为零
- 任何未对齐的访问
1.5硬 fault
硬 fault 是上文讨论的总线 fault、存储器管理 fault 以及用法 fault 上访的结果。如果这些 fault 的服务例程无法执行,它们就会成为“硬伤”——上访(escalation)成硬 fault。另外,在取向量(异常处理是对异常向量表的读取)时产生的总线 fault 也按硬 fault 处理。
在NVIC 中有一个硬 fault 状态寄存器(HFSR),它指出产生硬 fault 的原因。如果不是由于取向量造成的,则硬 fault 服务例程必须检查其它的 fault 状态寄存器,以最终决定是谁上访的。
2. 经典案例
STM32F103项目中使用了uCOS-II,出现一个致命问题:当只跑uCOS-II时,程序运行正常,一旦开启USB功能(或任何其它带高优先级中断的程序),程序运行一段时间后就会死掉,时间是随机的。
通过keil启动程序,死机时停下来,看到死在HardFault_Handler中:
HardFault_Handler\
PROC
EXPORT HardFault_Handler [WEAK]
B .
ENDP
提示出现了硬件错误。
看下这时的寄存器: