Files
TAIXIN/sdk/app/debug_log_msi/log_save_msi.c

292 lines
11 KiB
C
Raw Permalink Normal View History

#include "log_save_msi.h"
// 接收debug_stream的log保存到sd卡
#define LOG_MALLOC av_psram_malloc
#define LOG_FREE av_psram_free
#define LOG_SIZE_UINT (100 * 1024)
#define SAVE_RESERVE_SIZE (10 + 1 + 8 + 1)
#define SAVE_FLAG_FORMAT "[%08d]:log end\n"
#define WRITE_DROP_DATA_FLAG "[%08d]:interrupt drop\n"
#define LOG_SAVE_PATH "0:log"
static int32 log_save_work(struct os_work *work)
{
struct log_save_s *log_s = (struct log_save_s *) work;
struct framebuff *get_f;
struct msi *s = log_s->s;
uint32_t tell = 0;
char filename[64];
int ret = 0;
// 尝试接收数据,看看是否有需要写入到sd卡或者缓冲区buf
get_f = msi_get_fb(s, 0);
if (get_f && get_f->rev != 0)
{
log_s->drop_data_flag = 1;
}
if (get_f)
{
uint32_t write_cache_size = get_f->len;
// 要先判断缓冲区是否足够空间,如果不够,则先将缓冲区写入到sd卡,然后再将数据拷贝到缓冲区
if (log_s->start_offset + log_s->offset + write_cache_size + SAVE_RESERVE_SIZE > CACHE_SIZE)
{
// 将当前缓冲区写入sd卡,然后再将数据拷贝到缓冲区
if (!log_s->fp)
{
struct tm *time_info;
struct timeval ptimeval;
gettimeofday(&ptimeval, NULL);
time_t time_val = (time_t) ptimeval.tv_sec;
time_info = gmtime(&time_val);
uint32_t year = time_info->tm_year + 1900;
uint32_t mon = time_info->tm_mon + 1;
uint32_t day = time_info->tm_mday;
uint32_t hour = time_info->tm_hour;
uint32_t min = time_info->tm_min;
uint32_t sec = time_info->tm_sec;
uint32_t ms = os_jiffies() % 1000;
os_sprintf((char *) filename, "%s/%04d%02d%02d%02d%02d%02d%03d.txt", LOG_SAVE_PATH, year, mon, day, hour, min, sec, ms);
log_s->fp = osal_fopen_auto((const char *) filename, "wb", 0);
log_s->filesize = 0;
if (log_s->fp)
{
log_s->filesize = LOG_SIZE_UINT;
tell = osal_ftell(log_s->fp);
// 预分配文件簇
osal_fseek(log_s->fp, log_s->filesize);
osal_fseek(log_s->fp, tell);
}
log_s->lastupdate_file_time = os_jiffies();
log_s->last_syn_time = os_jiffies();
}
if (log_s->fp)
{
tell = osal_ftell(log_s->fp);
if (log_s->filesize < tell + log_s->offset)
{
log_s->filesize += LOG_SIZE_UINT;
}
// 预分配文件簇
osal_fseek(log_s->fp, log_s->filesize);
osal_fseek(log_s->fp, tell);
// 如果有漏数据,则在这里写入一个特殊标志,代表曾经漏过数据,不保证漏数据多少,只是一个标志
if (log_s->drop_data_flag)
{
os_sprintf(filename, WRITE_DROP_DATA_FLAG, (uint32_t) os_jiffies());
osal_fwrite(filename, strlen(filename), 1, log_s->fp);
log_s->drop_data_flag = 0;
}
ret = osal_fwrite(log_s->save_buf + log_s->start_offset, log_s->offset + SAVE_RESERVE_SIZE, 1, log_s->fp);
tell = osal_ftell(log_s->fp);
osal_fseek(log_s->fp, tell - SAVE_RESERVE_SIZE);
if (!ret)
{
osal_ftruncate(log_s->fp);
osal_fclose(log_s->fp);
log_s->fp = NULL;
}
log_s->start_offset = 0;
log_s->offset = 0;
}
// 重新将获取到的数据保存到save_buf,可能要考虑没有sd卡的情况?
// 没有sd卡,直接丢弃?
// 理论这里offset一定是从0开始
if (log_s->fp)
{
// 判断当前位置,调整start_offset,作为对齐使用
uint32_t tell = osal_ftell(log_s->fp);
log_s->start_offset = 4 - tell % 4;
hw_memcpy(log_s->save_buf + log_s->start_offset + log_s->offset, get_f->data, write_cache_size);
os_sprintf((char *) log_s->save_buf + log_s->start_offset + log_s->offset + write_cache_size, SAVE_FLAG_FORMAT, osal_ftell(log_s->fp));
log_s->offset = write_cache_size;
}
}
// 缓冲区足够,直接拷贝
else
{
// 将当前缓冲区写入sd卡,然后再将数据拷贝到缓冲区
if (!log_s->fp)
{
struct tm *time_info;
struct timeval ptimeval;
gettimeofday(&ptimeval, NULL);
time_t time_val = (time_t) ptimeval.tv_sec;
time_info = gmtime(&time_val);
uint32_t year = time_info->tm_year + 1900;
uint32_t mon = time_info->tm_mon + 1;
uint32_t day = time_info->tm_mday;
uint32_t hour = time_info->tm_hour;
uint32_t min = time_info->tm_min;
uint32_t sec = time_info->tm_sec;
uint32_t ms = os_jiffies() % 1000;
os_sprintf((char *) filename, "%s/%04d%02d%02d%02d%02d%02d%03d.txt", LOG_SAVE_PATH, year, mon, day, hour, min, sec, ms);
log_s->fp = osal_fopen_auto((const char *) filename, "wb", 0);
log_s->filesize = 0;
log_s->lastupdate_file_time = os_jiffies();
log_s->last_syn_time = os_jiffies();
}
if (log_s->fp)
{
hw_memcpy(log_s->save_buf + log_s->start_offset + log_s->offset, get_f->data, write_cache_size);
os_sprintf((char *) log_s->save_buf + log_s->start_offset + log_s->offset + write_cache_size, SAVE_FLAG_FORMAT, osal_ftell(log_s->fp) + log_s->offset + write_cache_size);
log_s->offset += write_cache_size;
}
}
msi_delete_fb(NULL, get_f);
}
// 如果存在文件,要判断是否需要更换文件保存log
if (log_s->fp && (os_jiffies() - log_s->lastupdate_file_time > log_s->update_file_interval))
{
if (log_s->offset)
{
// 如果有漏数据,则在这里写入一个特殊标志,代表曾经漏过数据,不保证漏数据多少,只是一个标志
if (log_s->drop_data_flag)
{
os_sprintf(filename, WRITE_DROP_DATA_FLAG, (uint32_t) os_jiffies());
osal_fwrite(filename, strlen(filename), 1, log_s->fp);
log_s->drop_data_flag = 0;
}
osal_fwrite(log_s->save_buf + log_s->start_offset, log_s->offset, 1, log_s->fp);
}
log_s->last_syn_time = os_jiffies();
log_s->lastupdate_file_time = os_jiffies();
osal_ftruncate(log_s->fp);
osal_fclose(log_s->fp);
log_s->fp = NULL;
log_s->start_offset = 0;
log_s->offset = 0;
}
// 先判断是否要切换下一个文件去记录log
// 去同步一下
if (os_jiffies() - log_s->last_syn_time > log_s->syn_interval)
{
if (log_s->fp)
{
if (log_s->offset)
{
if (log_s->fp)
{
tell = osal_ftell(log_s->fp);
if (log_s->filesize < tell + log_s->offset)
{
log_s->filesize += LOG_SIZE_UINT;
}
// 预分配文件簇
osal_fseek(log_s->fp, log_s->filesize);
osal_fseek(log_s->fp, tell);
}
// 如果有漏数据,则在这里写入一个特殊标志,代表曾经漏过数据,不保证漏数据多少,只是一个标志
if (log_s->drop_data_flag)
{
os_sprintf(filename, WRITE_DROP_DATA_FLAG, (uint32_t) os_jiffies());
osal_fwrite(filename, strlen(filename), 1, log_s->fp);
log_s->drop_data_flag = 0;
}
ret = osal_fwrite(log_s->save_buf + log_s->start_offset, log_s->offset + SAVE_RESERVE_SIZE, 1, log_s->fp);
tell = osal_ftell(log_s->fp);
osal_fseek(log_s->fp, tell - SAVE_RESERVE_SIZE);
tell = osal_ftell(log_s->fp);
if (!ret)
{
osal_ftruncate(log_s->fp);
osal_fclose(log_s->fp);
log_s->fp = NULL;
goto __log_save_work_end;
}
log_s->start_offset = 0;
log_s->offset = 0;
}
osal_fsync(log_s->fp);
}
else
{
log_s->start_offset = 0;
log_s->offset = 0;
}
log_s->last_syn_time = os_jiffies();
}
__log_save_work_end:
os_run_work_delay(work, 1);
return 0;
}
static int32_t log_save_action(struct msi *msi, uint32_t cmd_id, uint32_t param1, uint32_t param2)
{
int32_t ret = RET_OK;
struct log_save_s *log_s = (struct log_save_s *) msi->priv;
switch (cmd_id)
{
case MSI_CMD_POST_DESTROY:
{
if (log_s->fp)
{
osal_ftruncate(log_s->fp);
osal_fclose(log_s->fp);
}
if (log_s)
{
LOG_FREE(log_s);
msi->priv = NULL;
}
}
break;
case MSI_CMD_PRE_DESTROY:
{
os_work_cancle2(&log_s->work, 1);
}
break;
case MSI_CMD_FREE_FB:
{
}
break;
}
return ret;
}
void *creat_log_save_stream(const char *name, uint32_t syn_interval, uint32_t update_file_interval)
{
struct log_save_s *log_s = (struct log_save_s *) LOG_MALLOC(sizeof(struct log_save_s));
struct msi *s = NULL;
if (log_s)
{
memset(log_s, 0, sizeof(struct log_save_s));
log_s->syn_interval = syn_interval;
log_s->update_file_interval = update_file_interval;
s = msi_new(name, 10, NULL);
if (s)
{
s->action = log_save_action;
s->priv = (void *) log_s;
s->enable = 1;
log_s->s = s;
OS_WORK_INIT(&log_s->work, log_save_work, 0);
os_run_work_delay(&log_s->work, 1);
}
else
{
LOG_FREE(log_s);
log_s = NULL;
}
}
return s;
}