MS-RTOS 程序崩溃分析方法
本章将介绍 MS-RTOS 的程序崩溃分析方法。
程序崩溃分析方法
程序崩溃后,MS-RTOS 会通过 ms_printk
函数输出类似如下的信息:
----------------------MS-RTOS crash info begin----------------------
#MemManage
R0: 20010000 R1: 20021ca4 R2: 00000000 R3: 20010000
R4: 20020754 R5: 00000000 R6: 00000000 R7: 20021c80
R8: 00000000 R9: 20020148 R10: 00000000 R11: 00000000
R12: 2002017c SP: 20021c60 LR: 08080217 PC: 080801fc
EXC_RETURN: fffffffd
MMFSR=00000082
MMFAR=20010000
MMFSR=MMARVALID DACCVIOL
The fault occurred in thread "process" pid 2.
Call stack analysis:
APP: 0x80801fc, ELF: 0xbcc
APP: 0x8080217, ELF: 0xbe7
APP: 0x808022d, ELF: 0xbfd
APP: 0x8080243, ELF: 0xc13
APP: 0x8080283, ELF: 0xc53
APP: 0x8081275, ELF: 0x1c45
APP: 0x80801d5, ELF: 0xba5
APP: 0x808253b, ELF: 0x2f0b
----------------------MS-RTOS crash info end------------------------
将其复制并保存为一个文本文件(如 crash.log),并放置到应用程序工程编译的输出目录(应用程序工程目录下的 Debug 或 Release 子目录),然后执行 MS-RTOS 崩溃分析脚本(在 Windows 系统上要用“命令提示符”程序,不能用 PowerShell 程序)。
- 如果崩溃是由于应用程序的问题而造成的,执行类似如下的命令(xxx 为应用程序工程编译生成的应用程序 ELF 文件):
arm-msrtos-crash-analysis.py --app xxx crash.log
- 如果崩溃是由于 BSP 或驱动的问题而造成的,执行类似如下的命令(xxx 为 BSP 工程编译生成的 BSP ELF 文件):
arm-msrtos-crash-analysis.py --kernel xxx crash.log
MS-RTOS 崩溃分析脚本将输出更详尽的崩溃原因和调用栈,开发者可以根据调用栈定位到出错的文件和函数位置。
Cortex-M 相关寄存器解析中文解释
内存管理 fault 状态寄存器(MFSR)提供的讯息
-------------------------------------------------------------------------------
位 | 可能的原因
-------------------------------------------------------------------------------
STKERR | 入栈时发生错误(异常响应开始时)
| 1) 堆栈指针的值被破坏
| 2) 堆栈容易过大,已经超出 MPU 允许的 region 范围
-------------------------------------------------------------------------------
USTKERR | 出栈时发生错误(异常响应终止时)
| 1) 异常服务例程破坏了堆栈指针
| 2) 异常服务例程更改了 MPU 配置
-------------------------------------------------------------------------------
DACCVIOL | 内存访问违例,常常是用户程序企图访问特权级 region 所致
-------------------------------------------------------------------------------
IACCVIOL | 内存访问违例,常常是用户程序企图访问特权级 region 所致
| 1) 跳转到不可执行指令的 regions
| 2) 异常返回时,使用了无效的 EXC_RETURN 值
| 3) 中断向量表中有无效的向量,如异常在向量建立之前就发生
| 4) 在异常处理期间,入栈的 PC 值被破坏
-------------------------------------------------------------------------------
LSPERR | 浮点错误,只在带有 FPU 的 Cortex-M4 上存在
-------------------------------------------------------------------------------
总线 fault 状态寄存器(BFSR)提供的讯息
-------------------------------------------------------------------------------
位 | 可能的原因
-------------------------------------------------------------------------------
STKERR | (自动)入栈期间出错
| 1) 堆栈指针的值被破坏
| 2) 堆栈溢出,到达了未定义存储器的区域
| 3) PSP 未经初始化就使用
-------------------------------------------------------------------------------
USTKERR | 在异常处理期间把 SP 的值被破坏
-------------------------------------------------------------------------------
IMPRECISERR | LDM/STM 指令造成了非精确总线 fault
-------------------------------------------------------------------------------
PRECISERR | 在数据访问期间的总线错误,可查看 BFAR 获得具体地址
-------------------------------------------------------------------------------
IBUSERR | 同 MemManage fault 中的 IACCVIOL
-------------------------------------------------------------------------------
用法 fault 状态寄存器(UFSR)提供的讯息
-------------------------------------------------------------------------------
位 | 可能的原因
-------------------------------------------------------------------------------
DIVBYZERO | 发生了除零操作,引发此 fault 的指令可以从入栈的 PC 读取
-------------------------------------------------------------------------------
UNALIGNED | 当 UNALIGN_TRP 置位时发生未对齐访问,
引发此 fault 的指令可以从入栈的 PC 读取
-------------------------------------------------------------------------------
NOCP | 企图执行一个不存在的协处理器指令,
引发此 fault 的指令可以从入栈的PC读取
-------------------------------------------------------------------------------
INVPC | EXC_RETURN 无效
| 1) 异常返回时使用了无效的 EXC_RETURN,如:
| 当 EXC_RETURN = 0xFFFF_FFF1 时却要返回线程模式
| 当 EXC_RETURN = 0xFFFF_FFF9 时却要返回 handler 模式
| 2) 由于 SP/LR 或者堆栈内容被破坏导致返回异常
| 3) ICI/IT 位对当前指令无效,LDM/STM 指令被异常打断后,
| 在异常服务例程中更改了入栈的 PC,
| 结果在中断返回时,非零的 ICI 位段作用到了不使用 ICI 位段的指令上
-------------------------------------------------------------------------------
INVSTATE | EPSR.T 或者 EPSR.IT 错误
| 1) 加载到 PC 中的跳转地址值是偶数(LSB = 0)
| 2) 向量地址的 LSB = 0
| 3) 入栈的 PSR 在异常处理过程中被破坏,使得在返回时内核尝试进入 ARM 状态
-------------------------------------------------------------------------------
UNDEFINSTR | 未定义指令
| 1) 使用了当前 ARCH 不支持的指令
| 2) 代码段中的数据被破坏
| 3) 链接时加载了 ARM 目标码,请检查编译阶段的设置
| 4) 指令对齐的问题。例如,在使用 GNU 工具链时,
忘记了在 .ascii 后使用 .align,就可能导致下一条指令没有对齐
-------------------------------------------------------------------------------
硬 fault 状态寄存器(HSFR)提供的讯息
-------------------------------------------------------------------------------
位 | 可能的原因
-------------------------------------------------------------------------------
DEBUGEVF | 因调试事件导致的 fault
-------------------------------------------------------------------------------
FORCED | fault “上访” 为HardFault, 需要分析其他寄存器
-------------------------------------------------------------------------------
VECTBL | 取向量失败
| 1) 在取向量过程中发生总线 fault
| 2) 向量表偏移量设置有误
-------------------------------------------------------------------------------