一、Easylogger 的相关文件解析
这些代码是 Easylogger(一款轻量级嵌入式日志库)的核心配置项(位于 elog_cfg.h 中),用于控制日志库的功能开关、输出级别、缓冲区大小等关键特性。下面逐一解释每个配置的作用:
1. 日志输出总开关
#define ELOG_OUTPUT_ENABLE
- 作用:定义此宏时,日志库会开启输出功能(日志能正常打印);如果注释掉(// #define ELOG_OUTPUT_ENABLE),所有日志输出会被禁用(节省资源,适合发布版本)。
- 场景:调试阶段保留,正式发布时可注释以关闭所有日志。
2. 静态日志输出级别
#define ELOG_OUTPUT_LVL ELOG_LVL_VERBOSE
- 作用:设置全局日志输出的最低级别,只有级别大于等于此值的日志才会被打印。
- 日志级别范围(从低到高,优先级递增):
ELOG_LVL_ASSERT:断言错误(最高优先级,通常用于致命错误)ELOG_LVL_ERROR:错误(如功能失败)ELOG_LVL_WARN:警告(如不影响运行但需注意的情况)ELOG_LVL_INFO:信息(如正常流程节点)ELOG_LVL_DEBUG:调试(如变量值、函数调用)ELOG_LVL_VERBOSE:详细信息(最冗余,如每步操作的细节)
- 示例:若设为
ELOG_LVL_INFO,则 INFO、WARN、ERROR、ASSERT 级别的日志会输出,DEBUG 和 VERBOSE 会被过滤。
3. 断言检查开关
#define ELOG_ASSERT_ENABLE
- 作用:定义此宏时,日志库会启用 elog_assert() 断言功能(类似 C 标准库的 assert()),当断言条件不满足时,会打印断言日志并触发错误处理(如程序终止)。
- 场景:调试阶段用于检查关键条件(如指针不为空、参数合法),发布版本可注释以关闭断言(减少资源消耗)。
4. 单条日志的缓冲区大小
#define ELOG_LINE_BUF_SIZE 1024
- 作用:设置每条日志在内存中临时存储的缓冲区大小(单位:字节)。
- 注意:
- 若单条日志内容过长(超过此值),会被截断(只保留前 1024 字节)。
- 数值越大,单条日志可容纳的内容越多,但会消耗更多 RAM(嵌入式系统需权衡)
5. 行号输出的最大长度
#define ELOG_LINE_NUM_MAX_LEN 5
- 作用:限制日志中输出的'代码行号'的最大字符长度(默认 5 位)。
- 示例:若代码行号是 12345,会完整输出;若行号是 123456(6 位),会被截断为 23456(只保留最后 5 位)。
- 目的:控制日志格式的整齐性,避免行号过长导致日志排版混乱。
6. 过滤标签的最大长度
#define ELOG_FILTER_TAG_MAX_LEN 30
- 作用:Easylogger 支持按'标签(tag)'过滤日志(如 elog_i("uart", "recv data") 中的 "uart" 是标签),此配置限制标签的最大字符长度(30 字节)。
- 注意:超过长度的标签会被截断,确保过滤功能正常工作。
7. 过滤关键字的最大长度
#define ELOG_FILTER_KW_MAX_LEN 16
- 作用:支持按'关键字(keyword)'过滤日志(如只输出包含 "error" 的日志),此配置限制关键字的最大长度(16 字节)。
8. 标签级别过滤的最大数量
#define ELOG_FILTER_TAG_LVL_MAX_NUM 5
- 作用:Easylogger 支持为不同标签设置独立的日志级别(如 uart 标签只输出 ERROR 及以上,i2c 标签输出 DEBUG 及以上),此配置限制这种'标签 - 级别'映射的最大数量(最多 5 组)。
- 场景:当需要对多个模块(标签)设置不同日志级别时,若超过 5 组,需增大此值。
9. 换行符定义
#define ELOG_NEWLINE_SIGN "\n"
- 作用:定义日志结尾的换行符号。
- 说明:
- 大多数系统用 "\n"(换行);
- 部分 Windows 环境可能需要 "\r\n"(回车 + 换行),可在此修改。
总结
这些配置项是 Easylogger 的'总开关'和'参数调节器',核心作用是:
- 控制日志是否输出、输出哪些级别的日志(ELOG_OUTPUT_ENABLE、ELOG_OUTPUT_LVL);
- 平衡日志功能和资源消耗(ELOG_LINE_BUF_SIZE、ELOG_ASSERT_ENABLE);
- 适配不同场景的日志格式和过滤需求(标签长度、换行符等)。
实际使用时,可根据嵌入式系统的 RAM/ROM 资源、调试需求灵活调整(例如:调试阶段开全量日志,发布阶段关闭输出或只保留错误级别)。
还有一些 Easylogger 库中与日志样式、输出格式、异步 / 缓冲模式相关的高级设置
1. 日志颜色配置(终端彩色输出)
#define ELOG_COLOR_ENABLE
#define ELOG_COLOR_ASSERT (F_MAGENTA B_NULL S_NORMAL)
#define ELOG_COLOR_ERROR (F_RED B_NULL S_NORMAL)
#define ELOG_COLOR_WARN (F_YELLOW B_NULL S_NORMAL)
#define ELOG_COLOR_INFO (F_CYAN B_NULL S_NORMAL)
#define ELOG_COLOR_DEBUG (F_GREEN B_NULL S_NORMAL)
#define ELOG_COLOR_VERBOSE (F_BLUE B_NULL S_NORMAL)
- ELOG_COLOR_ENABLE:开启日志彩色输出(仅在支持 ANSI 颜色码的终端有效,如 Linux 终端、VS Code 终端等)。注释此宏则关闭彩色,所有日志为默认颜色。
- 颜色宏的含义(以 F_MAGENTA B_NULL S_NORMAL 为例):
- F_XXX:前景色(文字颜色),如 F_RED(红色)、F_GREEN(绿色)。
- B_XXX:背景色,B_NULL 表示无背景色(默认)。
- S_XXX:文字样式,S_NORMAL 表示正常,S_BOLD 表示加粗(部分库支持)。
- 作用:通过颜色区分不同级别日志,直观识别重要信息(如错误用红色,警告用黄色)。
2. 日志格式配置(附加信息开关)
#define ELOG_FMT_USING_FUNC
#define ELOG_FMT_USING_DIR
#define ELOG_FMT_USING_LINE
这些宏控制日志中是否包含额外调试信息,默认会拼接在日志内容前,格式类似:[时间] [级别] [标签] [文件路径:行号@函数名] 日志内容
- ELOG_FMT_USING_FUNC:启用则输出函数名(如 main@),方便定位日志所在函数。
- ELOG_FMT_USING_DIR:启用则输出文件路径(如 src/main.c),方便定位日志所在文件。
- ELOG_FMT_USING_LINE:启用则输出代码行号(如 123),配合文件路径快速找到代码位置。
- 使用建议:调试阶段全开启,发布阶段可注释(减少日志长度,节省带宽 / 存储)。
3. 异步输出模式配置(非阻塞日志)
#define ELOG_ASYNC_OUTPUT_ENABLE
#define ELOG_ASYNC_OUTPUT_LVL ELOG_LVL_ASSERT
#define ELOG_ASYNC_OUTPUT_BUF_SIZE (ELOG_LINE_BUF_SIZE * 10)
#define ELOG_ASYNC_LINE_OUTPUT
#define ELOG_ASYNC_OUTPUT_USING_PTHREAD
- ELOG_ASYNC_OUTPUT_ENABLE:开启异步输出模式。此时日志不会立即打印,而是先存入缓冲区,由后台线程异步处理(避免日志打印阻塞主程序)。
详细解析一下异步输出的处理逻辑:
'后台线程异步处理'是一种让日志打印不干扰主程序运行的技术,核心是让日志输出工作在'后台'偷偷完成,主程序不用等待它结束。
在 Easylogger 中,'后台线程异步处理'的具体流程是:
- 主程序写入日志:当你调用 elog_i("tag", "hello") 输出日志时,日志不会直接发送到串口 / 终端,而是快速存入一块内存缓冲区(类似'快递箱'),主程序写完就立刻返回,继续执行下一行代码(几乎不耽误时间)。
- 后台线程独立工作:日志库会创建一个专门的'后台线程',这个线程独立于主程序运行,它的唯一任务是:
- 定期检查缓冲区是否有新日志;
- 如果有,就把日志从缓冲区取出来,发送到实际的输出设备(如串口、文件、上位机);
- 处理完后,继续等待下一批日志。
- 两者互不干扰:主程序写日志时,不用等待日志实际输出完成;后台线程输出日志时,也不会影响主程序的正常运行(比如不会打断传感器采集、电机控制等关键任务)。
注意:后台线程需要系统支持多线程(如 RT-Thread、FreeRTOS、Linux pthread),如果是纯裸机系统(无操作系统),则无法使用异步模式,只能用缓冲模式。
- ELOG_ASYNC_OUTPUT_LVL:设置异步输出的最高级别。例如设为 ELOG_LVL_ASSERT 时:
- ASSERT 级别日志异步输出(存入缓冲区,后台处理);
- 比 ASSERT 级别低的日志(如 ERROR、WARN 等)同步输出(立即打印)。
- (级别优先级:ASSERT > ERROR > WARN > ... > VERBOSE)
- ELOG_ASYNC_OUTPUT_BUF_SIZE:异步缓冲区大小(默认 10 倍单行缓冲区),用于暂存异步日志。若日志产生过快填满缓冲区,新日志可能被丢弃(需根据系统吞吐量调整)。
- ELOG_ASYNC_LINE_OUTPUT:强制异步日志必须以换行符结尾,确保后台线程按行解析输出(避免日志内容错乱)。
- ELOG_ASYNC_OUTPUT_USING_PTHREAD:指定异步模式使用 POSIX 线程库(pthread)实现后台线程(适用于 Linux、RT-Thread 等支持 pthread 的系统)。
4. 缓冲输出模式配置(批量打印)
#define ELOG_BUF_OUTPUT_ENABLE
#define ELOG_BUF_OUTPUT_BUF_SIZE (ELOG_LINE_BUF_SIZE * 10)
- ELOG_BUF_OUTPUT_ENABLE:开启缓冲输出模式。日志会先存入缓冲区,当缓冲区满或手动触发时,批量输出到目标设备(如串口、文件)。
- ELOG_BUF_OUTPUT_BUF_SIZE:缓冲区大小(默认 10 倍单行缓冲区),用于暂存待批量输出的日志。
- 与异步模式的区别:
- 缓冲模式:无后台线程,由主程序在合适时机(如缓冲区满)主动批量输出,仍可能阻塞但次数减少。
- 异步模式:由后台线程处理输出,主程序完全非阻塞(但依赖线程支持)。
- 适用场景:资源受限的嵌入式系统(无线程支持时),通过批量输出减少 IO 操作次数(如串口打印较耗时,批量输出更高效)。
二、移植 Easylogger
1. 使用 CubeMX 配置一个初始化串口的工程(此处以串口为例)
首先选择好对应的芯片型号,然后配置 sys: 使用晶振做时钟源: 配置串口,默认配置就行: 时钟树配置,频率最大即可: 生成 .c 和 .h 文件: 最后直接生成工程。
2. 移植代码
新建一个 Middlewares 的文件夹,将 easylogger 的源码复制进去。
添加组以及相关文件:
添加头文件路径。
此时有一个报错,注释这两个宏定义即可。
对串口进行重定义(记得开启微库),并对 elog_port.c 进行重写:
%s:表示输出字符串。
.*:是一个特殊的长度控制符,用于指定字符串的输出长度。其中 * 会从后续参数中获取长度值(这里就是 size)。
例如:如果 log 是 "hello",size 是 3,则 printf("%.*s", 3, "hello") 会输出 hel(只取前 3 个字符)。
3. 添加调试函数
会发现没有换行,调整一下。 输出 TAG,这个标签可以进行自定义,#define TAG "MAIN" 这个标签是字符格式。 log_XX 这个函数不能打印自定义标签,这个函数默认打印的是 NO_TAG。 要使用 elog_xx 函数。
4. 最终效果
运行后可见日志输出正常。

