Easylooger本身是带日志输出到文件功能的,但是Easylogger本身源码用的不是Fafts的接口函数,所以需要移植。
要让Easylogger能够输出日志到sd卡总共分三补。
第一步,移植STM32+SD卡驱动。
第二步,移植stm32+FAFTS文件系统。
第三步,修改Easylogger日志输出驱动文件。
由于第一步和第二步网上教程比较多,就不再重复写,同时Easylogger移植的文章也不少也就不写了。只写关键的第三步,如何修改Easylogger日志输出驱动文件,使调用log_x("日志")是能输出日志到sd卡,并按照日期和时间进行存储。
最终实现功能是按日期建立文件夹,并按照时间存成不同的log文件。
首先修改ElogFileCfg结构体增加int current;当前用用户名序号。
typedef struct {
char *name; /* file name */
size_t max_size; /* file max size */
int max_rotate; /* max rotate file count */
int current; /* current file name num */
} ElogFileCfg;
核心的"elog_file.c"修改如下:里面有个获取rtc日期需要用户自己实现。
/*
* 自动根据日期建立文件夹,并根据时间创建对应的日志文件,
* 文件大小由ELOG_FILE_MAX_SIZE决定。
*/
#define LOG_TAG "elog.file"
#include
#include
#include
#include
#include "elog_file.h"
#include "ff.h"
size_t elog_file_get_strtime(char *s,size_t maxsize);
/* initialize OK flag */
static bool init_ok = false;
static FIL logfile;
static ElogFileCfg local_cfg;
static char logname[100];
static char dir_path[20];
/**
* @brief 获取新的文件名字
* @param[in] name:文件名指针
* @param[in] len:文件名字最大长度
* @retval 0:成功,-1:失败
*/
uint8_t elog_get_new_name(char *name,uint8_t len)
{
uint16_t i;
char path[256];
char time_str[20];
FIL tmp_fp;
elog_file_get_strtime(time_str,20);
for (i = 0; i < ELOG_FILE_MAX_ROTATE; i++) {
snprintf(path, len, "%s/%s_%d", dir_path,time_str,i);
if(f_open(&tmp_fp, path, FA_READ) == FR_OK){
/*能打开说明已经存在*/
f_close(&tmp_fp);
}else{
strcpy(name,path);
return 0;
}
}
return -1;
}
ElogErrCode elog_file_init(void)
{
ElogErrCode result = ELOG_NO_ERR;
ElogFileCfg cfg;
FRESULT f_res;
/* 得到当前日期 */
time_t t;
struct tm *info;
t = rtc_readBJtime();
info = gmtime(&t);
strftime(dir_path,20,"0:/%Y%m%d",info);
if (init_ok)
goto __exit;
elog_file_port_init();
/*新建对应文件夹*/
f_res = f_mkdir(dir_path);
if(f_res != FR_OK)
{
}
cfg.max_size = ELOG_FILE_MAX_SIZE;
cfg.max_rotate = ELOG_FILE_MAX_ROTATE;
elog_get_new_name(logname,100);
cfg.name = logname;
elog_file_config(&cfg);
init_ok = true;
__exit:
return result;
}
/**
* @brief 返回当前时间的字符串 格式为012951
* @param s:指向目标数组的指针,用来复制产生的 C 字符串
* @param maxsize: 被复制到 str 的最大字符数。
* @retval 如果产生的 C 字符串小于 size 个字符(包括空结束字符),
* 则会返回复制到 str 中的字符总数(不包括空结束字符),否则返回零。
*/
size_t elog_file_get_strtime(char *s,size_t maxsize) {
time_t t;
struct tm *info;
t = rtc_readBJtime();
info = gmtime(&t);
return strftime(s,maxsize,"%H%M%S",info);
}
void elog_file_write(const char *log, size_t size)
{
size_t file_size = 0;
uint32_t byteswritten;
static size_t save_size = 0;
ELOG_ASSERT(init_ok);
ELOG_ASSERT(log);
elog_file_port_lock();
//f_lseek(&logfile,f_size(&logfile));
file_size = f_size(&logfile);
if (unlikely(file_size > local_cfg.max_size)) {
/* 关闭当前文件 */
f_close(&logfile);
/* 寻找新的文件名 */
elog_get_new_name(logname,100);
/* reopen the file */
f_open(&logfile, logname, FA_OPEN_ALWAYS | FA_WRITE);
}
f_write(&logfile, log, size, (void *)&byteswritten);
/*2k 一存 */
if(file_size - save_size >= 2048)
{
save_size = file_size;
f_sync(&logfile);
}
elog_file_port_unlock();
}
void elog_file_deinit(void)
{
ELOG_ASSERT(init_ok);
ElogFileCfg cfg = {NULL, 0, 0};
elog_file_config(&cfg);
elog_file_port_deinit();
init_ok = false;
}
void elog_file_config(ElogFileCfg *cfg)
{
FRESULT res;
elog_file_port_lock();
if (cfg != NULL) {
local_cfg.name = cfg->name;
local_cfg.max_size = cfg->max_size;
local_cfg.max_rotate = cfg->max_rotate;
if (local_cfg.name != NULL && strlen(local_cfg.name) > 0)
{
res = f_open(&logfile, local_cfg.name, FA_OPEN_ALWAYS | FA_WRITE);
if( res != FR_OK)
{
printf("open error = %d\n",res);
}
}
}
elog_file_port_unlock();
}
"elog_port.c"核心修改如下:
/**
* EasyLogger port initialize
*
* @return result
*/
ElogErrCode elog_port_init(void) {
ElogErrCode result = ELOG_NO_ERR;
output_lock = xSemaphoreCreateBinary();
if(output_lock != NULL)
{
xSemaphoreGive(output_lock);
}
#if ELOG_FILE_ENABLE
elog_file_init();
#endif
isActive = 1;
return result;
}
/**
* EasyLogger port deinitialize
*
*/
void elog_port_deinit(void) {
/* add your code here */
#if ELOG_FILE_ENABLE
elog_file_deinit();
#endif
isActive = 0;
}
/**
* output log port interface
*
* @param log output of log
* @param size log size
*/
void elog_port_output(const char *log, size_t size) {
if(isActive){f
#if ELOG_FILE_ENABLE
/* write the file */
elog_file_write(log, size);
#endif
}
}
"elog_file_cfg.h"核心代码如下:
#ifndef _ELOG_FILE_CFG_H_
#define _ELOG_FILE_CFG_H_
/* EasyLogger file log plugin's using file name */
#define ELOG_FILE_NAME "0:mylog/log"/* @note you must define it for a value */
/* EasyLogger file log plugin's using file max size */
#define ELOG_FILE_MAX_SIZE (1024*100) /* @note you must define it for a value */
/* EasyLogger file log plugin's using max rotate file count */
#define ELOG_FILE_MAX_ROTATE (10000) /* @note you must define it for a value */
#endif /* _ELOG_FILE_CFG_H_ */
"elog_file_port.c"核心代码如下:
#include "elog_file.h"
#include "freertos.h"
#include "task.h"
#include "ff.h"
#include "ff_gen_drv.h"
#include "./drivers/sd_diskio.h"
uint8_t lock = 0;
static char SDPath[4]; /* SD disk logical drive path */
static FATFS SDFatFs; /* File system object for SD disk logical drive */
/**
* EasyLogger flile log pulgin port initialize
*
* @return result
*/
ElogErrCode elog_file_port_init(void)
{
uint32_t res;
ElogErrCode result = ELOG_NO_ERR;
if(FATFS_LinkDriver(&SD_Driver, SDPath) == 0)
{
printf("easylogger Link the SD Disk I/O driver success\n");
}
/*##-2- Register the file system object to the FatFs module ##############*/
res = f_mount(&SDFatFs, (TCHAR const*)SDPath, 0);
if( res != FR_OK)
{
printf("Register the file system object to the FatFs module failed %ld \n",res);
}
/* add your code here */
return result;
}
/**
* file log lock
*/
void elog_file_port_lock(void) {
/* add your code here */
while(lock)
{
vTaskDelay(1);
}
lock = 1;
}
/**
* file log unlock
*/
void elog_file_port_unlock(void) {
/* add your code here */
lock = 0;
}
/**
* file log deinit
*/
void elog_file_port_deinit(void) {
/* add your code here */
}