1.前言
前两天在优快云上面刷到一些介绍开源项目log.c的文章,称赞log.c是一款轻量级日志库,使用简单。笔者怀着兴趣去log.c的github仓库学习了一下,地址如下:
GitHub - rxi/log.c: A simple logging library implemented in C99
从log.c的源码看,非常适合用在嵌入式Linux系统中,但是在MCU中却没法直接使用。因此,笔者对log.c的源码进行修改,使其能够用在MCU中,并保留原本log.c开源项目的大部分功能,下文称此项目为log.c for mcu。
2.功能
log.c for mcu主要实现的功能如下:
- 基础log输出功能
- 增加颜色识别
- 增加log输出静默功能
- 增加低等级log输出屏蔽功能
- 增加查询log等级对应的字符串名称的功能
2.1 基础打印功能
原本的log.c项目实现了六种log输出等级,如下所示,本质上都是对void log_log(int level, const char *file, int line, const char *fmt, ...)
的简单封装,log.c for mcu也要实现该功能。
#define log_trace(...) log_log(LOG_TRACE, __FILE__, __LINE__, __VA_ARGS__)
#define log_debug(...) log_log(LOG_DEBUG, __FILE__, __LINE__, __VA_ARGS__)
#define log_info(...) log_log(LOG_INFO, __FILE__, __LINE__, __VA_ARGS__)
#define log_warn(...) log_log(LOG_WARN, __FILE__, __LINE__, __VA_ARGS__)
#define log_error(...) log_log(LOG_ERROR, __FILE__, __LINE__, __VA_ARGS__)
#define log_fatal(...) log_log(LOG_FATAL, __FILE__, __LINE__, __VA_ARGS__)
其中,
__FILE__
代表log输出函数所在的文件__LINE__
代表log输出函数所在的行号__VA_ARGS__
传输log_trace(...)
等宏的括号内的字符串或者可变参数
2.2 增加颜色识别
log.c中增加宏定义LOG_USE_COLOR
即可实现几种log以不同颜色输出,显示效果如下:
受宏定义LOG_USE_COLOR
影响的主要代码如下:
#ifdef LOG_USE_COLOR
static const char *level_colors[] = {
"\x1b[94m", "\x1b[36m", "\x1b[32m", "\x1b[33m", "\x1b[31m", "\x1b[35m"
};
#endif
static void stdout_callback(log_Event *ev) {
char buf[16];
buf[strftime(buf, sizeof(buf), "%H:%M:%S", ev->time)] = '\0';
#ifdef LOG_USE_COLOR
fprintf(
ev->udata, "%s %s%-5s\x1b[0m \x1b[90m%s:%d:\x1b[0m ",
buf, level_colors[ev->level], level_strings[ev->level],
ev->file, ev->line);
#else
fprintf(
ev->udata, "%s %-5s %s:%d: ",
buf, level_strings[ev->level], ev->file, ev->line);
#endif
vfprintf(ev->udata, ev->fmt, ev->ap);
fprintf(ev->udata, "\n");
fflush(ev->udata);
}
这段代码使用的fprintf函数以及vfprintf函数在MCU中并不实用,在log.c for mcu中会修改成printf函数和vprintf函数。
需要注意的是,
"\x1b[94m"
这些配置打印信息显示不同颜色的方式,只有在putty这些终端工具才能产生效果,普通的串口工具如sscom不会产生效果。
2.3 增加log输出静默功能
log.c使用函数void log_set_quiet(bool enable)
进行静默使能,按如下方式调用即可关闭log输出功能。
log_set_quiet(true);
2.4 增加低等级log输出屏蔽功能
log.c使用函数void log_set_level(int level)
进行低等级log输出屏蔽,低于该函数设置的等级的log输出会被屏蔽。默认屏蔽等级设置为LOG_TRACE
,即最低的等级0,所以所有log函数都可以输出。
2.5 增加查询log等级对应的字符串名称的功能
log.c使用函数const char* log_level_string(int level)
返回log等级对应的字符串名称,可以方便的了解LOG_DEBUG
等字符串对应的log等级,和函数void log_set_level(int level)
配合使用。
2.6 其他功能
log.c还有三个功能函数,在MCU裸机中没有用武之地,所以就不移植了。
int log_add_callback(log_LogFn fn, void *udata, int level);
int log_add_fp(FILE *fp, int level);
void log_set_lock(log_LockFn fn, void *udata);
3.源代码修改
3.1 <log.h>修改
- 对结构体
log_Event
进行删减,剔除不需要用的成员;同时删除不需要用的typedef自定义的数据类型。
- 删除用不到的函数
3.2 <log.c>修改
- 删除不需要用的typedef自定义的数据类型,对结构体
L
进行删减。
- 修改函数
static void stdout_callback(log_Event *ev)
的内部实现,使其能够在MCU中运行使用。
- 修改函数
void log_log(int level, const char *file, int line, const char *fmt, ...)
的内部实现,和第2点是主要的修改点。
- 删除如下不需要使用的函数。
static void file_callback(log_Event *ev)
static void lock(void)
static void unlock(void)
void log_set_lock(log_LockFn fn, void *udata)
int log_add_callback(log_LogFn fn, void *udata, int level)
int log_add_fp(FILE *fp, int level)
static void init_event(log_Event *ev, void *udata)
4.测试
将上述章节描述的修改之后的log.c和log.h文件添加到实现串口标准打印输出的程序,同时在main函数中调用相关函数即可,最后基于S32K144EVB-Q100开发板进行测试。
关于实现串口标准打印输出的程序,可以参考如下文章的1.3.3章节。
基于S32K144平台实现两种软件定时器_Auto FAE进阶之路的博客-优快云博客
4.1 测试基础log输出功能
4.1.1 main函数编写
基础功能的main函数编写如下:
4.1.2 测试情况
使用普通串口工具打印的信息如下:
4.2 测试颜色识别功能
4.2.1 代码修改
在<log.h>中增加如下宏定义:
#define LOG_USE_COLOR
4.2.2 测试情况
使用putty终端工具打印的信息如下:
4.3 测试log输出静默功能
因为正常情况下,MCU串口打印很少使用putty,所以后面的功能演示会取消颜色识别功能。
4.3.1 main函数编写
注释宏定义LOG_USE_COLOR
,并修改main函数如下:
4.3.2 测试情况
使用普通串口工具打印的信息如下:
4.4 测试低等级log输出屏蔽功能
4.4.1 main函数编写
main函数修改如下:
4.4.2 测试情况
使用普通串口工具打印的信息如下:
4.5 测试查询log等级对应的字符串名称的功能
4.5.1 main函数编写
main函数修改如下:
4.5.2 测试情况
使用普通串口工具打印的信息如下:
5.例程分享
相关例程已上传百度网盘,链接如下:
- 链接:https://pan.baidu.com/s/1aSYqoXwDROoX0gMfQvBHtQ
- 提取码:j3av
如果觉得文章对您有用,帮忙点个关注!!!