项目场景:
在带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栈空间分配不能过小。