[关闭]
@armink 2017-05-22T06:11:09.000000Z 字数 3981 阅读 1740

CmBacktrace: ARM Cortex-M 系列 MCU 错误追踪库

其他开源

GitHub release GitHub commits MIT licensed

0、CmBacktrace 是什么

CmBacktrace (Cortex Microcontroller Backtrace)是一款针对 ARM Cortex-M 系列 MCU 的错误代码自动追踪、定位,错误原因自动分析的开源库。主要特性如下:

1、为什么选择 CmBacktrace

入门新人 :对于从 C51 、MSP430 等简单单片机转而使用更加复杂的 ARM 新人来说,时不时出现的 "hard falut" 死机会让新人瞬间懵掉。定位错误的方法也往往是连接上仿真器,一步步 F10/F11 单步,定位到具体的错误代码,再去猜测、排除、推敲错误原因,这种过程十分痛苦。

熟练老手 :慢慢的大家知道可以通过故障寄存器信息来定位故障原因及故障代码地址,虽然这样能解决一小部分问题,但是重复的、繁琐的分析过程也会耽误很多时间。而且对于一些复杂问题,只依靠代码地址是无法解决的,必须得还原错误现场的函数调用逻辑关系。虽然连接仿真器可以查看到的函数调用栈,但故障状态下是无法显示的,所以还是得一步步 F10/F11 单步去定位错误代码的位置。另外,还有两种场景,

所以定位这类问题就显得难上加难。

使用本库 :上述所有问题都迎刃而解,可以将错误信息输出到控制台上,还可以将错误信息使用 EasyFlash 的 Log 功能保存至 Flash 中,设备死机后重启依然能够读取上次的错误信息。CmBacktrace 输出的信息包括函数调用栈、故障诊断结果、堆栈、故障寄存器及产品固件信息,极大的提升了错误定位的效率及准确性。

俗话说,工欲善其事,必先利其器。所以有时候做事效率低的原因也许是,你会用的工具种类太少。

合作、贡献 :开源软件的发展离不开大家的支持,欢迎大家多提建议,也希望更多的人一起参与进来,共同提高 。如果觉得这个开源项目很赞,可以点击 项目主页 (Github|OSChina|Coding) 右上角的 Star ,同时把它推荐给更多有需要的朋友。

2、CmBacktrace 如何使用

2.1 演示

该演示分如下几个步骤:

cm_backtrace_demo

2.2 Demo

目录 平台 链接
\demos\non_os\stm32f10x 裸机 STM32 Cortex-M3 点击查看
\demos\os\rtthread\stm32f4xx RT-Thread STM32 Cortex-M4 点击查看
\demos\os\ucosii\stm32f10x UCOSII STM32 Cortex-M3 点击查看
\demos\os\freertos\stm32f10x FreeRTOS STM32 Cortex-M3 点击查看

2.3 移植说明

2.3.1 准备工作

2.3.2 配置说明

配置文件名: 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_def.h 中选择,更多灵活的配置请阅读源码

2.4 API 说明

2.4.1 库初始化

  1. void cm_backtrace_init(const char *firmware_name, const char *hardware_ver, const char *software_ver)
参数 描述
firmware_name 固件名称,需与编译器生成的固件名称对应
hardware_ver 固件对应的硬件版本号
software_ver 固件的软件版本号

注意 :以上入参将会在断言或故障时输出,主要起了追溯的作用

2.4.2 获取函数调用栈

  1. size_t cm_backtrace_call_stack(uint32_t *buffer, size_t size, uint32_t sp)
参数 描述
buffer 存储函数调用栈的缓冲区
size 缓冲区大小
sp 待获取的堆栈指针

示例:

  1. /* 建立深度为 16 的函数调用栈缓冲区,深度大小不应该超过 CMB_CALL_STACK_MAX_DEPTH(默认16) */
  2. uint32_t call_stack[16] = {0};
  3. size_t i, depth = 0;
  4. /* 获取当前环境下的函数调用栈,每个元素将会以 32 位地址形式存储, depth 为函数调用栈实际深度 */
  5. depth = cm_backtrace_call_stack(call_stack, sizeof(call_stack), __get_SP());
  6. /* 输出当前函数调用栈信息
  7. * 注意:查看函数名称及具体行号时,需要使用 addr2line 工具转换
  8. */
  9. for (i = 0; i < depth; i++) {
  10. printf("%08x ", call_stack[i]);
  11. }

2.4.3 追踪断言错误信息

  1. void cm_backtrace_assert(uint32_t sp)
参数 描述
sp 断言环境时的堆栈指针

注意 :入参 SP 尽量在断言函数内部获取,而且尽可能靠近断言函数开始的位置。当在断言函数的子函数中(例如:在 RT-Thread 的断言钩子方法中)使用时,由于函数嵌套会存在寄存器入栈的操作,此时再获取 SP 将发生变化,就需要人为调整(加减固定的偏差值)入参值,所以作为新手 不建议在断言的子函数 中使用该函数。

2.4.4 追踪故障错误信息

  1. void cm_backtrace_fault(uint32_t fault_handler_lr, uint32_t fault_handler_sp)
参数 描述
fault_handler_lr 故障处理函数环境下的 LR 寄存器值
fault_handler_sp 故障处理函数环境下的 SP 寄存器值

该函数可以在故障处理函数(例如: HardFault_Handler)中调用。另外,库本身提供了 HardFault 处理的汇编文件(点击查看,需根据自己编译器进行选择),会在故障时自动调用 cm_backtrace_fault 方法。所以移植时,最简单的方式就是直接使用该汇编文件。

2.5 常见问题

2.5.1 编译出错,提示需要 C99 支持

点击查看教程:一步开启 Keil/IAR/GCC 的 C99 支持

2.5.2 如何查看到函数调用栈中函数的具体名称及代码行号

点击查看教程:如何使用 addr2line 工具获取函数调用栈详细信息

2.5.3 故障处理函数:HardFault_Handler 重复定义

在使用了本库提供的 cmb_fault.s 汇编文件时,因为该汇编文件内部已经定义了 HardFault_Handler ,所以如果项目中还有其他地方定义了该函数,则会提示 HardFault_Handler 被重复定义的错误。此时有两种解决方法:

2.6 许可

采用 MIT 开源协议,细节请阅读项目中的 LICENSE 文件内容。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注