一、MCU笔记:通用等级日志库。带freertos的MCU上,因线程栈空间分配不足,发生Default_Handler,多次调用vsnprintf等发生崩溃。

项目场景:

在带freertos的MCU上使用一套公用的日志lib库SysLog。
1、库通过freertos的队列来实现。各模块在打印日志时入队列,一个内部专用的线程用于打印。
2、在头文件中,通过可变参数来实现参数输入。
3、通过vsnprintf、vsprintf,snprintf,sprintf等函数将可变参数转换成字符数组。

问题描述

1、在test thread中进行频繁的日志打印,此线程栈空间512

while (1)
    {
        U16 randData = (U16)rand();

        for(U8 i = 0; i < 10; i++)
        {
        	clog_e("testt %d\r\n", randData);
        }

        vTaskDelay (randData%3);
    }

2、而后会在Syslog中,将可变参数转换成字符数组时出现崩溃,进入Default_Handler。使用四种转换函数皆无法解决。

宏定义进行等级区分:

#define clog_d(fmt, ...)        SysLogQueue(E_SYS_LOG_MSG_DEBUG,   "[DEBUG]: "fmt,   ##__VA_ARGS__)
#define clog_i(fmt, ...)        SysLogQueue(E_SYS_LOG_MSG_INFO,    "[INFO]: "fmt,    ##__VA_ARGS__)
#define clog_w(fmt, ...)        SysLogQueue(E_SYS_LOG_MSG_WARNING, "[WARNING]: "fmt, ##__VA_ARGS__)
#define clog_e(fmt, ...)        SysLogQueue(E_SYS_LOG_MSG_ERROR,   "[ERROR]: "fmt,   ##__VA_ARGS__)

可变参数到字符数组的转化:

void SysLogQueue(SysLogMsgLevel loglevel, const char *message, ...)
{
    if(gSyslogInitialized != E_SYS_LOG_INIT_STATUS )
    {
        return;
    }

    if(((loglevel + 1) > gLogLevel) && (gLogCtrl != E_SYS_LOG_NONE))
    {
		va_list args;
		va_start(args, message);
		vsnprintf(gLogBuf, configLOGGING_MAX_MESSAGE_LENGTH - 1, message, args);
		va_end(args);
		LogPrintf( gLogBuf );
    }

    return;
}

原因分析:

1、逐步屏蔽,堆栈回溯调试
2、而后将日志打印的代码防到另一个栈空间为1024的线程中,恢复正常。

解决方案:

1、深层次频繁调用此日志的线程,freertos栈空间分配不能过小。

  • 11
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
FreeRTOS 中,当系统发生硬件故障(如访问无效的内存地址或执行非法指令)时,会触发 HardFault_Handler。HardFault_Handler 是一个特殊的异常处理函数,用于处理硬件故障。 进入 HardFault_Handler 的过程如下: 1. 当发生硬件故障时,处理器会将当前的上下文信息(寄存器状态、堆等)保存到特定的存储区域。 2. 处理器会跳转到预定义的 HardFault_Handler 函数。 3. 在 HardFault_Handler 中,你可以根据需要进行一些处理,例如记录日志、重启系统等。 要进入 HardFault_Handler,你可以在 FreeRTOS 中通过以下步骤进行设置: 1. 在你的代码中包含 CMSIS(Cortex Microcontroller Software Interface Standard)头文件,通常是 "core_cm3.h"、"core_cm4.h" 或类似的。 2. 实现 HardFault_Handler 函数,并在其中添加你的处理逻辑。例如,你可以通过读取相应的寄存器状态来分析故障原因,并采取适当的措施。 3. 使用 CMSIS 提供的宏将 HardFault_Handler 函数注册为 HardFault 异常的处理函数。例如,在 ARM Cortex-M 系列处理器中,你可以使用以下代码进行注册: ```c void HardFault_Handler(void) { // 处理逻辑 } __attribute__((naked)) void HardFault_Handler(void) { __asm volatile ( "tst lr, #4\n" "ite eq\n" "mrseq r0, msp\n" "mrsne r0, psp\n" "ldr r1, [r0, #24]\n" "ldr r2, handler_address_const\n" "bx r2\n" "handler_address_const: .word HardFault_Handler_C\n" ); } ``` 这段代码将 HardFault_Handler 注册为 HardFault 异常的处理函数,并将其与 HardFault_Handler_C 函数关联起来。 请注意,以上代码是针对 ARM Cortex-M 系列处理器的示例,如果你使用的是其他类型的处理器,请参考相应的文档和头文件来进行配置。此外,根据你的需求,你可能还需要对 HardFault_Handler 函数进行适当的修改和扩展。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值