简介:
CmBacktrace 是一个轻量级、跨平台针对CoretexM架构的开源嵌入式软件崩溃堆栈跟踪库。它通过捕获程序崩溃时的寄存器值并解析函数调用栈,帮助开发者快速定位问题。主要特点包括低内存占用、支持多种平台、易于集成、提供详细的堆栈信息,以及灵活配置。使用步骤包括初始化库、捕捉崩溃信息并解析堆栈。CmBacktrace 适用于调试崩溃问题、异常监控和质量保证,显著提高了嵌入式系统开发中的调试效率
CmBacktrace 移植适配
以下是CmBacktrace 的移植流程说明,我们可以参照该流程进行适配,对应代码可以从github 获取(https://github.com/armink/CmBacktrace)。
CmBacktrace 的源码文件只有三个文件,是很精简的,将如下三个文件加入工程即可,本地使用的IAR环境。
* fault_test.c - 文件主要是测试代码触发hardfault异常
* cmb_fault.s - 文件主要负责对接hardfault 异常
* cm_backtrace.c - 文件主要负责解析异常状态寄存器信息输出异常原因及输出异常函数的调用路径地址信息,提供给add2line 工具接续出异常调用的函数调用栈。
CmBacktrace 配置
本地使用的RA8芯片,是M85 core 最新的cmbacktrace 还未支持M85,但是已经支持了相近的M33,本地使用M33配置,对应的OS 为freertos
#ifndef _CMB_USER_CFG_H_ #define _CMB_USER_CFG_H_ #include <stdio.h> /* print line, must config by user */ #define cmb_println(...) printf(__VA_ARGS__);printf("\r\n") /* 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_FREERTOS /* cpu platform type, must config by user */ #define CMB_CPU_PLATFORM_TYPE 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_ENGLISH #endif /* end of _CMB_USER_CFG_H_ */
适配Freertos
Cmbacktrace 适配到freertos 要依赖系统实现获取当前任务信息的接口需要修改freertos task.c 源码文件,在task.c中添加如下实现函数。
/*-----------------------------------------------------------*/ /*< Support For CmBacktrace >*/ #if ( ( portSTACK_GROWTH > 0 ) && ( configRECORD_STACK_HIGH_ADDRESS != 1 ) ) #error "portSTACK_GROWTH > 0 must define configRECORD_STACK_HIGH_ADDRESS == 1" #endif uint32_t * vTaskStackAddr() { return pxCurrentTCB->pxStack; } uint32_t vTaskStackSize() { #if ( portSTACK_GROWTH > 0 ) return (pxCurrentTCB->pxStack - pxCurrentTCB->pxEndOfStack + 1); #else /* ( portSTACK_GROWTH > 0 )*/ return (pxCurrentTCB->pxEndOfStack - pxCurrentTCB->pxStack + 1); #endif /* ( portSTACK_GROWTH > 0 )*/ } char * vTaskName() { return pxCurrentTCB->pcTaskName; } /*-----------------------------------------------------------*/
在之前的帖子中我们已经实现了任务栈最大使用深度的信息,我们修改代码在hardfault 输出信息中,添加对应的输出可以方便我们插卡任务栈的使用情况是否发生栈溢出。
diff --git a/ra/fsp_5.5.0/fsp-5.5.0/CmBacktrace/cm_backtrace/cm_backtrace.c b/ra/fsp_5.5.0/fsp-5.5.0/CmBacktrace/cm_backtrace/cm_backtrace.c index 3e76321..49119c8 100644 --- a/ra/fsp_5.5.0/fsp-5.5.0/CmBacktrace/cm_backtrace/cm_backtrace.c +++ b/ra/fsp_5.5.0/fsp-5.5.0/CmBacktrace/cm_backtrace/cm_backtrace.c @@ -714,4 +714,8 @@ void cm_backtrace_fault(uint32_t fault_handler_lr, uint32_t fault_handler_sp) { #endif print_call_stack(stack_pointer); + { + extern unsigned int stack(char argc,char ** argv); + stack(0,NULL); + } }
功能验证
任务栈溢出验证,cortexM33/M85 架构相对M4 的core 在硬件设计上添加了PSPLIM寄存器该寄存器,当该寄存器的值大于PSP的值会触发硬件上的异常状态,在硬件层次上支持了堆栈溢出监测功能,freertos 在任务栈初始化时回将任务战的末端地址+8 配置到PSPLIM寄存器中,一旦越过该位置回记录对应的异常状态。
对应的状态寄存器如下:
本地修改代码,减小任务栈的大小触发任务栈溢出,运行结果如下:
从输出结果可以看出,异常发生在shell 任务,对应的STKOF 状态也已经被更新为over flow,软件打印的任务栈使用量显示也已经达到100%,输出信息可以轻松定位出shell 任务发生了栈溢出。debug 查看异常寄存器也可以读取到STKOF标志
shell 任务对应的PSP 和 PSPLIM 数值
添加如下测试代码触发其他异常验证。
/* * fault_test.c * * Created on: 2016/12/25 * Author: Armink */ #include <stdio.h> #include "littleshell.h" void fault_test_by_unalign(void) { volatile int * SCB_CCR = (volatile int *) 0xE000ED14; // SCB->CCR volatile int * p; volatile int value; *SCB_CCR |= (1 << 3); /* bit3: UNALIGN_TRP. */ p = (int *) 0x00; value = *p; printf("addr:0x%02X value:0x%08X\r\n", (int) p, value); p = (int *) 0x04; value = *p; printf("addr:0x%02X value:0x%08X\r\n", (int) p, value); p = (int *) 0x03; value = *p; printf("addr:0x%02X value:0x%08X\r\n", (int) p, value); } int hard1(char argc,char ** argv) { fault_test_by_unalign(); return 0; } LTSH_FUNCTION_EXPORT(hard1,"test hard fault1") void fault_test_by_div0(void) { volatile int * SCB_CCR = (volatile int *) 0xE000ED14; // SCB->CCR int x, y, z; *SCB_CCR |= (1 << 4); /* bit4: DIV_0_TRP. */ x = 10; y = 0; z = x / y; printf("z:%d\n", z); } int hard2(char argc,char ** argv) { fault_test_by_div0(); return 0; } LTSH_FUNCTION_EXPORT(hard2,"test hard fault2")
输入hard1 命令触发异常运行结果如下
add2line 工具使用说明如下
按照提示的“addr2line -e iar_vision_board.out -afpiC 02005ebc 02007b18 020064a6” 命令输出解析出函数调用栈,执行结果如下:
从结果可以看出异常发生的异常点,Cmbacktrace 是个定位coredump 代码的一大利器。