前言
当系统拥有文件系统后,可以把日志信息、错误信息、功耗管理(电池电量等),打印到文件,这样,利于问题的分析。
使用ulog组件,发现,LOG_D LOG_I等,默认只能打印到串口,不能打印到文件,用于永久保存。
开发ulog打印信息到文件的接口文件。
实现ulog打印信息到专用LOG文件的功能。
介绍
什么是PM专用的LOG文件?
专门周期性的记录电池电量、电源模式等信息的日志文件。【文件】【专属】,其他的LOG信息,不能写这个文件。
示例:LOG_D、LOG_I等,写到sys.log文件,LOG_PM,写到pm.log文件。
实现方法
这个功能,是接触过的一个项目里实现的,通过修改ulog组件,增加log_id的属性,通过适配file_be,实现log信息写到文件的功能。
通过定义log文件大小、文件个数等属性,实现log文件的管理,如循环写入,而不是一直写一个文件(频繁的日志,时间久了,文件超大!)。
验证Demo:
这里基于STM32L4 pandora,SPI Flash文件系统。
/* 测试代码: LOG_PM */
void pms_log_dump(void *param)
{
g_pms_log_info.deepsleep_ticks = 15 * 1000;
g_pms_log_info.power = 100;
g_pms_log_info.voltage = 3800;
g_pms_log_info.display_time += 5;
g_pms_log_info.module_status = rt_pm_module_get_status();
g_pms_log_info.sleep_mode = rt_pm_get_sleep_mode();
LOG_PM(",%d,%d,%d,%d,%d,0x%x,%d", g_pms_log_info.power,
g_pms_log_info.voltage,
g_pms_log_info.deepsleep_ticks,
g_pms_log_info.wakeup_cnt,
g_pms_log_info.display_time,
g_pms_log_info.module_status,
g_pms_log_info.sleep_mode);
}
msh /log>ls
Directory /log:
pm.log 77149 //PM功耗专属 LOG文件,使用LOG_PM打印的
sys.log 15229 //系统的LOG文件,如通过LOG_D LOG_E等打印的。
具体的实现参考Demo。这里列举一下基本的实现方法:
定义LOG 文件的ID,在:ulog_def.h中
enum _LOG_ID
{
LOG_SYS_ID = 0x00,
LOG_PM_ID,
LOG_MAX_ID,
};
/* LOG_D LOG_I LOG_PM等宏定义【实现部分】,增加LOG_ID属性,对于用户,不关心 /
#if (LOG_LVL >= LOG_LVL_DBG) && (ULOG_OUTPUT_LVL >= LOG_LVL_DBG)
#define ulog_d(LOG_ID, TAG, ...) ulog_output(LOG_ID, LOG_LVL_DBG, TAG, RT_TRUE, VA_ARGS)
#else
#define ulog_d(LOG_ID, TAG, ...)
#endif / (LOG_LVL >= LOG_LVL_DBG) && (ULOG_OUTPUT_LVL >= LOG_LVL_DBG) /
struct ulog_frame
{
/ magic word is 0x10 ('lo') /
rt_uint32_t magic:8;
rt_uint32_t is_raw:1;
rt_uint32_t log_len:23;
rt_uint32_t level;
rt_uint8_t id; / 增加ID属性 */
const char *log;
const char *tag;
};
typedef struct ulog_frame *ulog_frame_t;
struct ulog_backend
{
char name[RT_NAME_MAX];
rt_bool_t support_color;
void (*init) (struct ulog_backend *backend);
void (*output)(struct ulog_backend *backend, rt_uint8_t log_id, rt_uint32_t level, const char *tag, rt_bool_t is_raw, const char *log, size_t len); //增加log_id属性
void (*flush) (struct ulog_backend *backend);
void (*deinit)(struct ulog_backend *backend);
rt_slist_t list;
};
作用就是标识log类型的,如系统log,pm功耗log。
扩展ulog组件,ulog.h ulog.h实现函数,都增加log_id属性。
//ulog.h中,全部增加LOG_ID的属性。通用的LOG_D、LOG_I等,区别于LOG_PM等新定义的。
#define LOG_E(...) ulog_e(LOG_SYS_ID, LOG_TAG, VA_ARGS)
#define LOG_W(...) ulog_w(LOG_SYS_ID, LOG_TAG, VA_ARGS)
#define LOG_I(...) ulog_i(LOG_SYS_ID, LOG_TAG, VA_ARGS)
#define LOG_D(...) ulog_d(LOG_SYS_ID, LOG_TAG, VA_ARGS)
#define LOG_RAW(...) ulog_raw(LOG_SYS_ID, VA_ARGS)
#define LOG_HEX(name, width, buf, size) ulog_hex(LOG_SYS_ID, name, width, buf, size)
#define LOG_PM(...) LOG_PM_OUTPUT(LOG_PM_ID, LOG_TAG, VA_ARGS)
file.be实现ulog to file
struct _log_file
{
const rt_uint8_t id;
rt_int32_t file_fd;
const char *root_path;
const char *log_path;
const char *log_name;
const char file_type;
const rt_uint32_t file_size;
const rt_uint32_t file_num;
};
static struct _log_file _log_file_tbl[] =
{
{ LOG_SYS_ID, -1, "/", "/log/", "sys", ".log", 512 * 1024, 10 }, / 系统的LOG /
{ LOG_PM_ID, -1, "/", "/log/", "pm", ".log", 512 * 1024, 5 }, / PM专用LOG /
};
/ ulog to file,注册 /
int ulog_file_backend_init(void)
{
/ create device filesystem lock */
rt_mutex_init(&log_file_lock, "logfile", RT_IPC_FLAG_FIFO);
ulog_init();
rt_thread_mdelay(1000);
ulog_file.output = ulog_file_backend_output;
ulog_backend_register(&ulog_file, "file", RT_FALSE);
return 0;
}
其他参考demo: file_be.c
运行效果
msh /log>ls
Directory /log:
pm.log 77149
sys.log 15229
msh /log>cat pm.log
11-29 11:28:50 D/pms: ,100,3800,15000,0,20,0x2,0
11-29 11:29:00 D/pms: ,100,3800,15000,0,25,0x2,0
11-29 11:29:10 D/pms: ,100,3800,15000,0,30,0x2,0
11-29 11:29:20 D/pms: ,100,3800,15000,0,35,0x2,0
11-29 11:29:30 D/pms: ,100,3800,15000,0,40,0x2,0
11-29 11:29:40 D/pms: ,100,3800,15000,0,45,0x2,0
/* pm.log 真干净,只有功耗相关的日志,无其他的调试log信息,可以使用python等脚本解析了 */
开启PM专用LOG的方法
/* 功能实现文件 /
rtt_pm_log\rt-thread\components\utilities\ulog\backend\file_be.c
/ 修改的ulog组件文件 */
rtt_pm_log\rt-thread\components\utilities\ulog\ulog.c
rtt_pm_log\rt-thread\components\utilities\ulog\ulog.h
rtt_pm_log\rt-thread\components\utilities\ulog\ulog_def.h
原作者:张世争