EasyLogger#

EasyLogger官网 的文档已经很详细了,这儿只是记录使用过程

elog.c 文件中首先定义了一个 elog 对象,以及每行输出内容的行缓存 log_buf,缓存区的大小由 ELOG_LINE_BUF_SIZE 决定。 当我们在源文件中调用日志打印函数时,它们都将最后调用 elog_output 函数来完成log_buf的初始化,最终由 elog_port_output 完成最终的输出

flowchart TB 1{日志级别大于 过滤级别} 2{日志级别大于 tag对应的 过滤级别} 3{tag关键字过滤} 4[elog加锁] 5[输出颜色字段首部] 6[根据fmt_set输出级别标志] 7[根据fmt_set输出tag] 8[根据fmt_set输出时间、进程名、线程名] 9[根据fmt_set输出文件名、行号、函数名] 10{关键字过滤} 11[输出颜色字段尾部] 12[添加行尾符] 13[调用 elog_port_output 进行最终的输出] 14[elog解锁] 1 --No --> 2 --No --> 3 --Yes--> 4; 4 --> 5 --> 6 --> 7 --> 8 --> 9 --> 10 --Yes--> 11 --> 12 --> 13 --> 14; 1 --Yes--> e[返回]; 2 --Yes--> e; 3 --No --> e; 10 --No --> 14; 14 --> e;

elog_output流程图#

从流程图不难看出:
  1. 过滤优先级:级别 > TAG过滤级别 > tag关键字过滤 > 内容关键字过滤

  2. 输出优先级:异步输出 > 缓存输出 > 直接输出

日志无法输出到串口#

问题描述:

当在项目中将stdout定向到ITM时,日志输出正常。但把stdout重定向串口时,日志只打印前面几个字符后就无输出了。

[Info] System core frequency: 48000000Hz
I/

从输出结果可以看出,使用printf输出正常,但使用`log_i`输出时就会被阻塞而无输出

排查过程:

在 stdout_USART.c 的 stdout_putchar 函数打上断点调试

 92int stdout_putchar (int ch) {
 93uint8_t buf[1];
 94
 95buf[0] = ch;
 96if (ptrUSART->Send(buf, 1) != ARM_DRIVER_OK) {
 97    return (-1);
 98}
 99while (ptrUSART->GetTxCount() != 1);
100return (ch);
101}

结果断点调试又能正常输出,但一旦将断点取消全速运行就又会阻塞无输出。 结合上面直接使用 printf 函数输出又正常的现象,这两都之间的区别就在于: EasyLogger在输出前后加了 elog_port_output_lockelog_port_output_unlock ,而这两个函数内空又如下:

void elog_port_output_lock(void)
{
    __disable_irq();
}

void elog_port_output_unlock(void)
{
    __enable_irq();
}

可能的原因就是当调用 elog_port_output_lock 函数时,串口当前字符还未发送完成,但时中断又被禁用了。 所以当串口发送完当前字符后产生中断标志,但无法进入中断处就被阻塞了

处理方法:
  1. 注释掉 elog_port_output_lockelog_port_output_unlock 中的中断开关语句