亲测可用的RT1052+FreeRTOS10.3移植CmBacktrace方法——2022.11.12

搜遍全网都找不到一个靠谱的RT1052可用的移植方法,自己弄了一个分享出来,禁止一切形式未经许可的转载复制。

CmBacktrace

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 编译器;

源码仓库地址https://github.com/armink/CmBacktrace

移植CmBacktrace

前期准备

  1. CmBacktrace源码
  2. 任意RT1052+FreeRTOS V10的keil工程(所有i.MX RT系列都可以)

移植过程

添加CmBacktrace到工程

把下载到的cm_backtrace文件夹复制到工程目录下,我这里为了方便,直接用官方sdk里的demo工程做演示了😆。实际情况以实际工程为准,步骤是一样的。
在这里插入图片描述


打开工程,在工程里添加源文件和包含路径
在这里插入图片描述
在这里插入图片描述


右键点击工程界面左边添加好的cmb_fault.S,点击Options for File ‘cmb_fault.S’,在Asm选项卡按照图中选择
在这里插入图片描述

配置CmBacktrace

需要配置的有cmb_cfg.h和cmb_def.h两个文件。
先打开工程目录下的cmb_cfg.h,这个文件用来配置CmBacktrace,每个配置项的具体含义如下:

配置项功能说明
cmb_println(…)输出诊断信息必须配置
CMB_USING_BARE_METAL_PLATFORM使能裸机平台配置在裸机上用就开这个宏
CMB_USING_OS_PLATFORM使能RTOS平台配置在rtos上用就开这个宏
CMB_OS_PLATFORM_TYPE选择RTOS类型在rtos上用必须配置
CMB_CPU_PLATFORM_TYPE选择MCU内核类型必须配置
CMB_USING_DUMP_STACK_INFO使能Dump堆栈信息功能需要时配置
CMB_PRINT_LANGUAGE选择输出语言需要时配置,默认英文

表格的第1、3、4、5、7行是我们需要配置的项,具体配置如下:

#ifndef _CMB_CFG_H_
#define _CMB_CFG_H_

#include "fsl_debug_console.h"

/* print line, must config by user */
#define cmb_println(...)               PRINTF(__VA_ARGS__);PRINTF("\r\n")/* e.g., PRINTF(__VA_ARGS__);PRINTF("\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_FREERTOS/* CMB_OS_PLATFORM_RTT or CMB_OS_PLATFORM_UCOSII or CMB_OS_PLATFORM_UCOSIII or CMB_OS_PLATFORM_FREERTOS */
/* 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 */
/* enable dump stack information */
/* #define CMB_USING_DUMP_STACK_INFO */
/* language of print information */
#define CMB_PRINT_LANGUAGE           CMB_PRINT_LANGUAGE_ENGLISH/*    CMB_PRINT_LANGUAGE_ENGLISH(default) or CMB_PRINT_LANGUAGE_CHINESE */
#endif /* _CMB_CFG_H_ */

然后是cmb_def.h,需要把栈节区和代码节区的名字改一下,这里不受具体工程配置的影响,也就是说不管代码和堆栈实际放在哪里,只要名字和分散加载里的定义的一样就能用,代码节区名字一定要和分散加载文件保持一致,具体改成下面这样:

#if defined(__ARMCC_VERSION)
    /* C stack block name, default is STACK */
    #ifndef CMB_CSTACK_BLOCK_NAME
    #define CMB_CSTACK_BLOCK_NAME          Image$$ARM_LIB_STACK$$ZI
    #endif
    /* code section name, default is ER_IROM1 */
    #ifndef CMB_CODE_SECTION_NAME
    #define CMB_CODE_SECTION_NAME          ER_m_text
    #endif

接着到cm_backtrace.c,找到587行的cmb_println,在下图位置加一个空格。
在这里插入图片描述

适配FreeRTOS

配置好CmBacktrace以后,还需要改一下FreeRTOS的源码,不用担心不用怕,只是加几行获取任务栈信息的函数而已😊,并不会影响原本FreeRTOS的功能。

首先打开FreeRTOSConfig.h把下图这个宏关掉,不然会影响到实际使用效果,这个是FreeRTOS自带的任务调试功能,可以打印任务信息。
在这里插入图片描述

然后打开task.c,在文件最末尾加入下面的代码

/*-----------------------------------------------------------*/
/*< Support For CmBacktrace >*/
uint32_t * vTaskStackAddr()
{
    return pxCurrentTCB->pxStack;
}

uint32_t vTaskStackSize()
{
    #if ( portSTACK_GROWTH > 0 )
    
    return (pxNewTCB->pxEndOfStack - pxNewTCB->pxStack + 1);
    
    #else /* ( portSTACK_GROWTH > 0 )*/
    
    return pxCurrentTCB->uxSizeOfStack;
    
    #endif /* ( portSTACK_GROWTH > 0 )*/
}

char * vTaskName()
{
    return pxCurrentTCB->pcTaskName;
}
/*-----------------------------------------------------------*/

找到下图中的两处地方加入代码:在这里插入图片描述

	#if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) )
		StackType_t		*pxEndOfStack;		/*< Points to the highest valid address for the stack. */
	#else
        UBaseType_t     uxSizeOfStack;      /*< Support For CmBacktrace >*/
  #endif /* ( portSTACK_GROWTH > 0 )*/

在这里插入图片描述

    #else
    pxNewTCB->uxSizeOfStack = ulStackDepth;   /*< Support For CmBacktrace >*/
    #endif /* configRECORD_STACK_HIGH_ADDRESS */

这个时候编译就没有错了。

使用CmBacktrace追踪错误

初始化CmBacktrace

在自己喜欢的地方添加宏定义:

#define APPNAME                        "cmbacktrace_test"
#define HARDWARE_VERSION               "V1.0.0"
#define SOFTWARE_VERSION               "V0.1.0"

在main函数中调用初始化函数;
写一个除零错误的函数模拟hard fault;
创建一个任务调用除零函数模拟任务中错误的情况,main函数完整代码如下:

int main(void)
{
    /* Init board hardware. */
    BOARD_ConfigMPU();
    BOARD_InitBootPins();
    BOARD_InitBootClocks();
    BOARD_InitDebugConsole();
  
    /* CmBacktrace initialize */
    cm_backtrace_init("CmBacktrace", HARDWARE_VERSION, SOFTWARE_VERSION);
  
    if (xTaskCreate(hello_task, "Hello_task", configMINIMAL_STACK_SIZE + 100, NULL, hello_task_PRIORITY, NULL) !=
        pdPASS)
    {
        PRINTF("Task creation failed!.\r\n");
        while (1)
            ;
    }
    if (xTaskCreate(test_task, "test_task", configMINIMAL_STACK_SIZE + 100, NULL, test_task_PRIORITY, NULL) !=
        pdPASS)
    {
        PRINTF("Task creation failed!.\r\n");
        while (1)
            ;
    }
    vTaskStartScheduler();
    for (;;)
        ;
}

/*!
 * @brief Task responsible for printing of "Hello world." message.
 */
static void hello_task(void *pvParameters)
{
    for (;;)
    {
        PRINTF("Hello world.\r\n");
        vTaskSuspend(NULL);
    }
}

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);
}

static void test_task(void *pvParameters)
{
  fault_test_by_div0();
    for (;;)
    {
      PRINTF("cmbacktrace.\r\n");
      vTaskDelay(100);
    }
}

编译并下载运行,在串口助手中可以看到如下输出信息。
要注意的是,不管是debug工程还是release工程,都需要进入keil的debug界面运行代码才会有输出,目前暂时不清楚为啥。
在这里插入图片描述

定位到具体的出错代码

串口打印出了当前发生的是哪种hard fault,定位到具体的代码还需要addr2line工具,工具的可执行文件addr2line.exe就在一开始下载的源码包的tools\addr2line\win64路径下。
解压addr2line.exe到工程.axf文件所在的文件夹,并在此文件夹下打开命令行工具,墙裂建议安装Windows Terminal,用过最好用的win命令行工具。
在这里插入图片描述

打开工具以后,把串口助手最后一行打印的命令复制到命令行工具内,把cmbacktrace.axf替换成自己工程里的文件名。不管后缀是.out还是.axf都是可以的,然后回车就能看到具体的出错代码位置。
在这里插入图片描述
在这里插入图片描述

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值