前两天在CSDN上面刷到一些介绍开源项目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。
log.c for mcu主要实现的功能如下:
原本的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(...)
等宏的括号内的字符串或者可变参数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不会产生效果。
log.c使用函数void log_set_quiet(bool enable)
进行静默使能,按如下方式调用即可关闭log输出功能。
log_set_quiet(true);
log.c使用函数void log_set_level(int level)
进行低等级log输出屏蔽,低于该函数设置的等级的log输出会被屏蔽。默认屏蔽等级设置为LOG_TRACE
,即最低的等级0,所以所有log函数都可以输出。
log.c使用函数const char* log_level_string(int level)
返回log等级对应的字符串名称,可以方便的了解LOG_DEBUG
等字符串对应的log等级,和函数void log_set_level(int level)
配合使用。
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);
log_Event
进行删减,剔除不需要用的成员;同时删除不需要用的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)
将上述章节描述的修改之后的log.c和log.h文件添加到实现串口标准打印输出的程序,同时在main函数中调用相关函数即可,最后基于S32K144EVB-Q100开发板进行测试。
关于实现串口标准打印输出的程序,可以参考如下文章的1.3.3章节。
基于S32K144平台实现两种软件定时器_Auto FAE进阶之路的博客-CSDN博客
基础功能的main函数编写如下:
使用普通串口工具打印的信息如下:
在
#define LOG_USE_COLOR
使用putty终端工具打印的信息如下:
因为正常情况下,MCU串口打印很少使用putty,所以后面的功能演示会取消颜色识别功能。
注释宏定义LOG_USE_COLOR
,并修改main函数如下:
使用普通串口工具打印的信息如下:
main函数修改如下:
使用普通串口工具打印的信息如下:
main函数修改如下:
使用普通串口工具打印的信息如下:
相关例程已上传百度网盘,链接如下:
如果觉得文章对您有用,帮忙点个关注!!!