258 lines
7.3 KiB
C
258 lines
7.3 KiB
C
/*----------------------------------------------------------------------------
|
|
* Copyright (c) Fenda Technologies Co., Ltd. 2020. All rights reserved.
|
|
*
|
|
* Description: log_port.c
|
|
*
|
|
* Author: saimen
|
|
*
|
|
* Create: 2022-7-16
|
|
*--------------------------------------------------------------------------*/
|
|
//lib
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <assert.h>
|
|
#include <time.h>
|
|
//os
|
|
#include "FreeRTOS.h"
|
|
#include "semphr.h"
|
|
//sdk
|
|
#include "apollo4b.h"
|
|
//#include "am_mcu_apollo.h"
|
|
//drv
|
|
#include "sys_typedef.h"
|
|
#include "sys_config.h"
|
|
#include "rtc_api.h"
|
|
#include "fs_api.h"
|
|
//user
|
|
#include "fs_user_init.h"
|
|
#include "log_port.h"
|
|
#include "cm_backtrace.h"
|
|
#include "task_ancillary.h"
|
|
|
|
|
|
#define ENABLE_STATIC_PRINT false
|
|
extern uint32_t am_util_stdio_printf(const char *pcFmt, ...);
|
|
#define static_print_remind(...) am_util_stdio_printf(__VA_ARGS__)
|
|
#if ENABLE_STATIC_PRINT
|
|
#define static_print_info(...) am_util_stdio_printf(__VA_ARGS__)
|
|
#else
|
|
#define static_print_info(...)
|
|
#endif
|
|
|
|
//fs log
|
|
#define LOG_DIR_DEFINE DIR_DATA_LOG
|
|
#define LOG_FILE_FULL_NAME_DEFINE "/FD/log_device.bin"
|
|
#define LOG_FILE_MAX_NUMBER (3) //日志文件的最大个数
|
|
#define LOG_FILE_MAX_SIZE (100*1024) //单个日志文件的最大尺寸
|
|
#define LOG_FILE_PATH_MAX 64 //日志数据文件绝对路径的最大长度
|
|
|
|
static SemaphoreHandle_t g_log_mutex_handle = NULL;
|
|
|
|
/**
|
|
* @brief 创建日志模块嵌套互斥锁
|
|
* @retval int| 返回错误码,0=成功.
|
|
*/
|
|
int log_port_create_lock(void)
|
|
{
|
|
g_log_mutex_handle = xSemaphoreCreateRecursiveMutex();
|
|
if(g_log_mutex_handle == NULL)
|
|
{
|
|
static_print_remind("log create mutex failed\r\n");
|
|
return -1;
|
|
} else {
|
|
static_print_remind("log create mutex success\r\n");
|
|
}
|
|
|
|
return RET_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief 日志模块获取锁
|
|
* @param type:DATA_LOG_TYPE|需要获取锁的日志种类
|
|
* @retval int| 返回错误码,0=成功.
|
|
*/
|
|
int log_port_lock(void)
|
|
{
|
|
BaseType_t ret;
|
|
|
|
//在中断函数中,放弃获取锁
|
|
if (__get_IPSR() != 0) {
|
|
return 0;
|
|
}
|
|
|
|
if(g_log_mutex_handle != NULL) {
|
|
ret = xSemaphoreTakeRecursive(g_log_mutex_handle, portMAX_DELAY);
|
|
if(ret != pdTRUE) {
|
|
static_print_remind("log take mutex failed, call ret false\r\n");
|
|
return -1;
|
|
} else {
|
|
static_print_info("log take mutex success\r\n");
|
|
}
|
|
} else {
|
|
static_print_info("log take mutex failed, mutex is null\r\n");
|
|
}
|
|
|
|
return RET_SUCCESS;;
|
|
}
|
|
|
|
/**
|
|
* @brief 日志模块释放锁
|
|
* @param type:DATA_LOG_TYPE|需要释放锁的日志种类
|
|
* @retval int| 返回错误码,0=成功.
|
|
*/
|
|
int log_port_unlock(void)
|
|
{
|
|
BaseType_t ret;
|
|
|
|
//在中断函数中,放弃释放锁
|
|
if (__get_IPSR() != 0) {
|
|
return 0;
|
|
}
|
|
|
|
if(g_log_mutex_handle != NULL) {
|
|
ret = xSemaphoreGiveRecursive(g_log_mutex_handle);
|
|
if(ret != pdTRUE) {
|
|
static_print_remind("log give mutex failed, call ret false\r\n");
|
|
return -1;
|
|
} else {
|
|
static_print_info("log give mutex success\r\n");
|
|
}
|
|
} else {
|
|
static_print_info("log give mutex failed, mutex is null\r\n");
|
|
}
|
|
|
|
return RET_SUCCESS;;
|
|
}
|
|
|
|
/**
|
|
* @brief 日志模块事件通知
|
|
* @param event 需要释放事件
|
|
* @retval int| 返回错误码,0=成功.
|
|
*/
|
|
int log_port_notify(uint32_t event)
|
|
{
|
|
int ret;
|
|
|
|
switch(event)
|
|
{
|
|
case LOG_EVENT_CACHE_FULL:
|
|
task_ancillary_notify(ANCILLARY_MSG_LOG_BUF_FULL, NULL);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
return RET_SUCCESS;;
|
|
}
|
|
|
|
/**
|
|
* @brief 根据时间戳及日志种类拼接日志文件的绝对路径.
|
|
* @param type:DATA_LOG_TYPE|日志种类.
|
|
* @param timestamp:UINT32|unix时间戳.
|
|
* @param buf:char*|缓存绝对路径的指针.
|
|
* @retval int|返回路径的长度.
|
|
*/
|
|
int log_port_get_full_path(uint32_t index, char *buf)
|
|
{
|
|
#if 1
|
|
uint8_t i;
|
|
int ret;
|
|
char dir[64];
|
|
struct tm *p_time;
|
|
char *name_file;
|
|
bool is_dir;
|
|
|
|
name_file = buf;
|
|
ret = fs_user_get_newest_file_exclude_child_dir(LOG_DIR_DEFINE,name_file);
|
|
if(ret)
|
|
{
|
|
ret = fs_api_stat(name_file,&is_dir);
|
|
}
|
|
else
|
|
{
|
|
ret = RET_ERROR;
|
|
}
|
|
if(ret > LOG_FILE_MAX_SIZE || ret < 0)
|
|
{
|
|
p_time = rtc_api_get_utc_time();
|
|
#if 1
|
|
sprintf(name_file, "%s/%02d%02d%02d%02d%02d%02d.bin", LOG_DIR_DEFINE, p_time->tm_year+1900, p_time->tm_mon+1, \
|
|
p_time->tm_mday, p_time->tm_hour, p_time->tm_min, p_time->tm_sec);
|
|
#else
|
|
sprintf(name_file, "%s",LOG_FILE_FULL_NAME_DEFINE);
|
|
#endif
|
|
}
|
|
|
|
if(fs_api_file_exist(name_file) < RET_SUCCESS)
|
|
{
|
|
fs_user_get_dir_by_full_path(name_file, dir);
|
|
static_print_info("file [%s] not exist, dir[%s]\r\n", name_file,dir);
|
|
if(fs_api_dir_exist(dir) != RET_SUCCESS)
|
|
{
|
|
static_print_info("dir [%s] not exist, create dir\r\n", dir);
|
|
ret = fs_user_create_dir(dir);
|
|
if(ret != 0)
|
|
{
|
|
static_print_remind("create dir [%s] failed:%d\r\n", dir,ret);
|
|
return ret;
|
|
}
|
|
}
|
|
ret = fs_api_file_create(name_file);
|
|
static_print_info("fs_api_file_create()=%d\r\n",ret);
|
|
// fs_user_print_dir_list(dir);
|
|
}
|
|
|
|
if (fs_user_get_file_number_exclude_child_dir(LOG_DIR_DEFINE)>LOG_FILE_MAX_NUMBER)
|
|
{
|
|
for(i=0;i<3;i++)//最多执行3次
|
|
{
|
|
if(fs_user_delete_oldest_file_exclude_child_dir(LOG_DIR_DEFINE,LOG_FILE_MAX_NUMBER) < LOG_FILE_MAX_NUMBER)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static_print_info("log_port_get_full_path():%s\r\n",buf);
|
|
return RET_SUCCESS;
|
|
#endif
|
|
}
|
|
|
|
int log_port_read_file(char *path, uint32_t offset, uint8_t *dat, uint32_t len)
|
|
{
|
|
return fs_api_file_load(path, offset, dat, len);
|
|
}
|
|
|
|
/**
|
|
* @brief 写入数据到文件.
|
|
* @param path:const char *|文件的绝对路径.
|
|
* @param dat:const uint8_t *|数据指针.
|
|
* @param len:UINT16|数据的长度.
|
|
* @param newPath:const char *|当文件超出大小时,新建文件的绝对路径.
|
|
* @param useNewPath:bool *|传参给调用者是否使用了新路径
|
|
* @retval int|返回写入的数据长度,负数表示错误码.
|
|
* @note 新建文件的目录与旧文件的目录必须相同,只能是文件名不同.
|
|
*/
|
|
int log_port_write_file(char *path, uint8_t *dat, uint16_t len)
|
|
{
|
|
int err = 0;
|
|
uint32_t size;
|
|
bool is_dir;
|
|
|
|
size = fs_api_stat(path,&is_dir);
|
|
if((size + len) > LOG_FILE_MAX_NUMBER)
|
|
{
|
|
log_port_get_full_path(0, path);
|
|
static_print_info("file [%s] size reach limit[size:%d |wrt:%d] new \r\n", path, size, len);
|
|
err = fs_api_file_append(path, dat, len);
|
|
}
|
|
else
|
|
{
|
|
err = fs_api_file_append(path, dat, len);
|
|
}
|
|
|
|
static_print_info("file [%s] write bytes: %d, now total size: %d bytes\r\n", path, len, fs_api_stat(path,&is_dir));
|
|
|
|
return err;
|
|
}
|