亲测可用的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工程做演示了😆。实际情况以实际工程为准,步骤是一样的。

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

打开工程,在工程里添加源文件和包含路径

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

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

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

; 配置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"

#define cmb_println(...)               PRINTF(__VA_ARGS__);PRINTF("\r\n")

#define CMB_USING_OS_PLATFORM

#define CMB_OS_PLATFORM_TYPE           CMB_OS_PLATFORM_FREERTOS

#define CMB_CPU_PLATFORM_TYPE          CMB_CPU_ARM_CORTEX_M7

#define CMB_PRINT_LANGUAGE           CMB_PRINT_LANGUAGE_ENGLISH
#endif

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

#if defined(__ARMCC_VERSION)

    #ifndef CMB_CSTACK_BLOCK_NAME
    #define CMB_CSTACK_BLOCK_NAME          Image$$ARM_LIB_STACK$$ZI
    #endif

    #ifndef CMB_CODE_SECTION_NAME
    #define CMB_CODE_SECTION_NAME          ER_m_text
    #endif

接着到cm_backtrace.c,找到587行的cmb_println,在下图位置加一个空格。

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

适配FreeRTOS

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

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

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

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


uint32_t * vTaskStackAddr()
{
    return pxCurrentTCB->pxStack;
}

uint32_t vTaskStackSize()
{
    #if ( portSTACK_GROWTH > 0 )

    return (pxNewTCB->pxEndOfStack - pxNewTCB->pxStack + 1);

    #else

    return pxCurrentTCB->uxSizeOfStack;

    #endif
}

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

亲测可用的RT1052+FreeRTOS10.3移植CmBacktrace方法——2022.11.12
    #if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) )
        StackType_t     *pxEndOfStack;
    #else
        UBaseType_t     uxSizeOfStack;
  #endif

亲测可用的RT1052+FreeRTOS10.3移植CmBacktrace方法——2022.11.12
    #else
    pxNewTCB->uxSizeOfStack = ulStackDepth;
    #endif

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

使用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)
{

    BOARD_ConfigMPU();
    BOARD_InitBootPins();
    BOARD_InitBootClocks();
    BOARD_InitDebugConsole();

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

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;
    int x, y, z;

    *SCB_CCR |= (1 << 4);

    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界面运行代码才会有输出,目前暂时不清楚为啥。

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

定位到具体的出错代码

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

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

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

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

Original: https://blog.csdn.net/zzz_xxj/article/details/127810268
Author: ZZZ_XXJ
Title: 亲测可用的RT1052+FreeRTOS10.3移植CmBacktrace方法——2022.11.12

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/659413/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球