简介
CmBacktrace (Cortex Microcontroller Backtrace)是一款针对 ARM Cortex-M 系列 MCU 的错误代码自动追踪、定位,错误原因自动分析的开源库。主要特性如下:
- 支持的错误包括:
- 断言(assert)
- 故障(Hard Fault, Memory Management Fault, Bus Fault, Usage Fault, Debug Fault)
- 故障原因 自动诊断 :可在故障发生时,自动分析出故障的原因,定位发生故障的代码位置,而无需再手动分析繁杂的故障寄存器;
- 输出错误现场的 函数调用栈(需配合 addr2line 工具进行精确定位),还原发生错误时的现场信息,定位问题代码位置、逻辑更加快捷、精准。也可以在正常状态下使用该库,获取当前的函数调用栈;
- 支持 裸机 及以下操作系统平台:
- RT-Thread
- UCOS
- FreeRTOS(需修改源码)
- 根据错误现场状态,输出对应的 线程栈 或 C 主栈;
- 故障诊断信息支持多国语言(目前:简体中文、英文);
- 适配 Cortex-M0/M3/M4/M7 MCU;
- 支持 IAR、KEIL、GCC 编译器;
环境
IDE | Keil 5.30(Windows 11) |
MCU | STM32H750(Cortex M7),Cortex M3/M4 MCU都可以 |
RTOS | RT-Thread |
源码 | https://github.com/armink/CmBacktrace |
移植源码
- 下载源码
git clone https://github.com/armink/CmBacktrace.git
- 将
cm_backtrace
文件夹复制至工程,并将根目录所有源文件添加至工程 - 将
cm_backtrace/fault_handler/keil
下的cmb_fault.s
汇编文件添加至工程,添加后需要把项目原有的HardFault_Handler
注释掉 - 将
cm_backtrace
文件夹添加至头文件路径
配置说明
配置文件名: cmb_cfg.h
,针对不同的平台和场景,用户需要自自行手动配置,常用配置如下:
配置名称 | 功能 | 备注 |
---|---|---|
cmb_println(…) | 错误及诊断信息输出 | 必须配置 |
CMB_USING_BARE_METAL_PLATFORM | 是否使用在裸机平台 | 使用则定义该宏 |
CMB_USING_OS_PLATFORM | 是否使用在操作系统平台 | 操作系统与裸机必须二选一 |
CMB_OS_PLATFORM_TYPE | 操作系统平台 | RTT/UCOSII/UCOSIII/FREERTOS |
CMB_CPU_PLATFORM_TYPE | CPU平台 | M0/M3/M4/M7 |
CMB_USING_DUMP_STACK_INFO | 是否使用 Dump 堆栈的功能 | 使用则定义该宏 |
CMB_PRINT_LANGUAGE | 输出信息时的语言 | CHINESE/ENGLISH |
根据环境,我这里的cmb_cfg.h
内容如下:
#ifndef _CMB_CFG_H_
#define _CMB_CFG_H_#include <stdio.h>/* print line, must config by user */
#define cmb_println(...) do{printf(__VA_ARGS__);printf("\r\n");}while (0)/* e.g., printf(__VA_ARGS__);printf("\r\n") or SEGGER_RTT_printf(0, __VA_ARGS__);SEGGER_RTT_WriteString(0, "\r\n") */
/* enable bare metal(no OS) platform */
/* #define CMB_USING_BARE_METAL_PLATFORM */
/* enable OS platform */
#define CMB_USING_OS_PLATFORM
/* OS platform type, must config when CMB_USING_OS_PLATFORM is enable */
#define CMB_OS_PLATFORM_TYPE CMB_OS_PLATFORM_RTT /* or CMB_OS_PLATFORM_UCOSII or CMB_OS_PLATFORM_UCOSIII or CMB_OS_PLATFORM_FREERTOS or CMB_OS_PLATFORM_RTX5 */
/* cpu platform type, must config by user */
#define CMB_CPU_PLATFORM_TYPE CMB_CPU_ARM_CORTEX_M7 /* CMB_CPU_ARM_CORTEX_M0 or CMB_CPU_ARM_CORTEX_M3 or CMB_CPU_ARM_CORTEX_M4 or CMB_CPU_ARM_CORTEX_M7 or CMB_CPU_ARM_CORTEX_M33 */
/* enable dump stack information */
#define CMB_USING_DUMP_STACK_INFO
/* language of print information */
#define CMB_PRINT_LANGUAGE CMB_PRINT_LANGUAGE_CHINESE_UTF8 /*CMB_PRINT_LANGUAGE_ENGLISH(default) or CMB_PRINT_LANGUAGE_CHINESE or CMB_PRINT_LANGUAGE_CHINESE_UTF8 */
#endif /* _CMB_CFG_H_ */
实例测试
初始化
在工程最开始调用初始化函数,三个参数依次为固件名称,硬件版本,软件版本
固件名称最好和Options(魔术棒)> Output > Name of Executable一致,方便后续使用addr2line 工具
cm_backtrace_init("STM32H750VB-RTT", "V1.0.0", "V0.0.1");
测试源码
调用关系main() > test2() > test1() > fault_test()
void fault_test()
{volatile int *SCB1 = (volatile int *) 0xFEEEEEEE;*SCB1 |= 0x10;printf("SCB1: %d\r\n", *SCB1);
}void test1()
{printf("test 1 start\r\n");fault_test();printf("test 1 end\r\n");
}void test2()
{printf("test 2 start\r\n");test1();printf("test 2 end\r\n");
}int main(void)
{//......test2();//......
}
日志
由日志可知设备挂掉的原因为非对齐访问
固件名称:STM32H750VB-RTT,硬件版本号:V1.0.0,软件版本号:V0.0.1
在线程(main)中发生错误异常
=========== 线程堆栈信息 ===========addr: 20001040 data: deadbeefaddr: 20001044 data: 2000104caddr: 20001048 data: 20001054addr: 2000104c data: 0800a9e3addr: 20001050 data: 200010ccaddr: 20001054 data: 08008e9faddr: 20001058 data: 23232323addr: 2000105c data: 23232323addr: 20001060 data: 23232323addr: 20001064 data: 23232323addr: 20001068 data: 23232323addr: 2000106c data: 23232323addr: 20001070 data: 23232323addr: 20001074 data: 23232323addr: 20001078 data: 23232323addr: 2000107c data: 23232323addr: 20001080 data: 23232323addr: 20001084 data: 23232323addr: 20001088 data: 23232323addr: 2000108c data: 00000000addr: 20001090 data: deadbeefaddr: 20001094 data: deadbeefaddr: 20001098 data: deadbeefaddr: 2000109c data: deadbeefaddr: 200010a0 data: deadbeefaddr: 200010a4 data: deadbeefaddr: 200010a8 data: deadbeefaddr: 200010ac data: deadbeefaddr: 200010b0 data: 200010c4addr: 200010b4 data: 08009247addr: 200010b8 data: deadbeefaddr: 200010bc data: deadbeefaddr: 200010c0 data: 200010ccaddr: 200010c4 data: 08008f81addr: 200010c8 data: deadbeefaddr: 200010cc data: 08008155
====================================
========================= 寄存器信息 =========================R0 : feeeeeee R1 : f0000000 R2 : 00000000 R3 : 08008a0aR12: 0000c000 LR : 0800a9a7 PC : 08008a76 PSR: 61000000
==============================================================
发生用法错误,原因:企图执行非对齐访问
查看更多函数调用栈信息,请运行:addr2line -e STM32H750VB-RTT.axf -afpiC 08008a76 0800a9a6 0800a9e2 08008e9e 08009246 08008f80
调用addr2line
在生成编译结果的目录右键打开终端,运行日志提示的addr2line的命令
没有addr2line的可以在tools
文件夹获取,因为我装有MinGW
(Minimalist GNU for Windows),所以直接运行:
结果可以很清晰的看到函数调用过程和出错的地方
addr2line -e STM32H750VB-RTT.axf -afpiC 08008a82 0800a9b2 0800a9ee 08008eaa 08009252 08008f8c0x08008a76: fault_test at D:\RT-ThreadStudio\workspace\STM32H750VB-RTT\MDK-ARM/../Core/Src/main.c:21
0x0800a9a6: test1 at D:\RT-ThreadStudio\workspace\STM32H750VB-RTT\MDK-ARM/../Core/Src/main.c:30
0x0800a9e2: test2 at D:\RT-ThreadStudio\workspace\STM32H750VB-RTT\MDK-ARM/../Core/Src/main.c:37
0x08008e9e: main at D:\RT-ThreadStudio\workspace\STM32H750VB-RTT\MDK-ARM/../Core/Src/main.c:83
0x08009246: rt_components_init at D:\RT-ThreadStudio\workspace\STM32H750VB-RTT\MDK-ARM/..\RT-Thread\/src\components.c:127
0x08008f80: main_thread_entry at D:\RT-ThreadStudio\workspace\STM32H750VB-RTT\MDK-ARM/..\RT-Thread\/src\components.c:195