log先记录在内部flash,然后导出到u盘
/*
* user_flash.c
*
* Created on: Jun 2, 2023
* Author: Administrator
*/
#include "user_flash.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include "type.h"
#include "LLCC68_example_recive.h"
#include "ff.h"
#include "file.h"
#include "media_play_api.h"
volatile int LogNum = 0;//log 数目
#define LOG_TIME_OUT (5)
/* snail 总共32K,一块4K,总共8块,实际只用前4块(16K)*/
#define LOG_BAK_OFFSET (AUDIO_EFFECT_ADDR) // BP 信息在Flash中的起始地址
#define LOG_BAK_CNT (8) // BP 信息存储区域个数,小于8
#define LOG_BLOCK_SIZE (4096) // BP 信息存数区域大小
//第1块只存放 logBak 与 logLen
//第234块存放LOG
static uint32_t logBak = 1;//LOG当前存放的第几块
static uint32_t logLen = 0;//LOG当前块的长度
/* 擦除32K */
static void LogFlashErase(void)
{
int i;
for(i=0; i<LOG_BAK_CNT; i++)
{
/* SECTOR_ERASE 擦除一个扇区,一个扇区4096 byte */
SpiFlashErase(SECTOR_ERASE, (LOG_BAK_OFFSET + i * LOG_BLOCK_SIZE) /4096 , 1);
//APP_DBG("Erase Flash ok (%d)\n", i);
}
}
/* 设置 logBak logLen */
static void logLenlogBakSet(uint32_t *bak, uint32_t *len)
{
SpiFlashErase(SECTOR_ERASE, (LOG_BAK_OFFSET + 0 * LOG_BLOCK_SIZE) /4096 , 1);
SpiFlashWrite(LOG_BAK_OFFSET, (uint8_t*)bak, 4, LOG_TIME_OUT);
SpiFlashWrite(LOG_BAK_OFFSET+4, (uint8_t*)len, 4, LOG_TIME_OUT);
}
/* 获取 logBak logLen */
static void logLenlogBakGet(uint32_t *bak, uint32_t *len)
{
uint8_t buff[10] = {0};
SpiFlashRead(LOG_BAK_OFFSET, buff, 10, LOG_TIME_OUT);
log_hex(buff, 10);
*bak = (buff[0] & 0x000000FF) | (((buff[1]) << 8) & 0x0000FF00) | (((buff[2]) << 16) & 0x00FF0000) | (((buff[3]) << 24) & 0xFF000000);
*len = (buff[4] & 0x000000FF) | (((buff[5]) << 8) & 0x0000FF00) | (((buff[6]) << 16) & 0x00FF0000) | (((buff[7]) << 24) & 0xFF000000);
/* 处理第一次 */
if(*bak < 1 || *bak > 3)//logBak 只能是123
{
APP_DBG("[FLASH] 处理第一次\n");
*bak = 1;
*len = 0;
}
}
//长度必须为8
static void LogFlashWrite(uint8_t* Buffer, uint32_t Length)
{
logLenlogBakGet(&logBak, &logLen);
/* 判断当前块是否已经满了,满了需要抹掉新的块 */
if(logLen >= 4095)
{
APP_DBG("[FLASH] 当前块已满\n");
logLen = 0;
logBak++;
/* logBak只能是123 */
if(logBak >= 4) logBak = 1;
SpiFlashErase(SECTOR_ERASE, (LOG_BAK_OFFSET + logBak * LOG_BLOCK_SIZE) /4096 , 1);
}
APP_DBG("[FLASH] logBak = %d logLen = %d\n", (int)logBak, (int)logLen);
/* 写入日志 */
SpiFlashWrite(LOG_BAK_OFFSET + logBak * LOG_BLOCK_SIZE + logLen, Buffer, Length, LOG_TIME_OUT);
/* 写入长度 */
logLen += Length;
logLenlogBakSet(&logBak, &logLen);
}
/** 记录LOG
* ch 车道
* event 事件
* */
void LogRecord(uint8_t ch, uint8_t event)
{
uint8_t str[8] = {0};
/* 2023年,只要23 */
str[0] = (uint16_t)gRtcTime.Year % 100;
str[1] = (uint8_t)gRtcTime.Mon;
str[2] = (uint8_t)gRtcTime.Date;
str[3] = (uint8_t)gRtcTime.Hour;
str[4] = (uint8_t)gRtcTime.Min;
str[5] = (uint8_t)gRtcTime.Sec;
str[6] = ch;
str[7] = event;
log_hex(str, 8);
LogFlashWrite(str, 8);
LogNumGet();
}
/** 读取全部LOG
* */
void LogRead(void)
{
int log_number = 0;//写入的时候统计log行数
int i, j;
uint8_t logbuff[8];//临时LOG缓冲区
uint32_t logbak;//临时变量
FIL file; /* 文件对象 */
FRESULT f_res; /* 文件操作结果 */
UINT fnum; /* 文件成功读写数量 */
UINT WriteLen = 0; /* 写缓冲区 的长度 */
BYTE WriteBuffer[128] = {0}; /* 写缓冲区 */
f_res = f_open(&file, "0:log.txt", FA_CREATE_ALWAYS | FA_WRITE);
if(f_res != FR_OK) return;
logLenlogBakGet(&logBak, &logLen);//先获取当前的位置,在第几块,log长度
logbak = logBak;
/* 1 2 3 假如当前在第1块, 那么就要 2 3 1 遍历输出 */
/* 1 2 3 假如当前在第2块, 那么就要 3 1 2 遍历输出 */
for(j = 0; j < 3; j++)//总共有三块,循环三次
{
if(++logbak == 4) logbak = 1;//第3块结束,到第4块的时候要回到第1块
APP_DBG("logbak = %d\n", (int)logbak);
for(i = 0; i < 512; i++)//一个块4096BYTE,一次读取8,需要读取512次 loglen>>3 == loglen/8
{
SpiFlashRead(LOG_BAK_OFFSET + logbak * LOG_BLOCK_SIZE + i*8, logbuff, 8, LOG_TIME_OUT);
if(logbuff[0] == 0xFF && logbuff[1] == 0xFF && logbuff[2] == 0xFF && logbuff[3] == 0xFF) break; //如果全是F 就是没数据,跳出(判断4个可以证明了)
/*2023/06/05 16:21:05 *///len = 20
sprintf((char*)WriteBuffer, "%04d: 20%02d/%02d/%02d %02d:%02d:%02d ", ++log_number,
(uint16_t)logbuff[0],
(uint8_t)logbuff[1],
(uint8_t)logbuff[2],
(uint8_t)logbuff[3],
(uint8_t)logbuff[4],
(uint8_t)logbuff[5]);
// log_hex(logbuff, 8);
switch(logbuff[7])
{
case 1: WriteLen = sprintf((char*)WriteBuffer+26, "收费站%02d车道有行人误闯!\n", logbuff[6]); break;//行人误闯
case 2: break;
default: break;
}
// APP_DBG("%s\n", WriteBuffer);
f_write(&file, WriteBuffer, WriteLen+26, &fnum);
}
}
/* 不再读写,关闭文件 */
f_close(&file);
}
/* ===============file=============== */
void logFlieWrite(void)
{
FIL file; /* 文件对象 */
FRESULT f_res; /* 文件操作结果 */
UINT fnum; /* 文件成功读写数量 */
BYTE ReadBuffer[1024] = {0}; /* 读缓冲区 */
BYTE WriteBuffer[] = /* 写缓冲区 */
"哈哈哈小明\n";
f_res = f_open(&file, "0:log.txt", FA_CREATE_ALWAYS | FA_WRITE);
if(f_res != FR_OK)
{
APP_DBG("open file error : %d\r\n", f_res);
return;
}
else
{
APP_DBG("open file sucess!!! \r\n");
}
f_res = f_write(&file, WriteBuffer, sizeof(WriteBuffer), &fnum);
if(f_res == FR_OK)
{
APP_DBG("write file sucess!!! (%d)\n", fnum);
APP_DBG("write Data : %s\r\n", WriteBuffer);
}
else
{
APP_DBG("write file error : %d\r\n", f_res);
}
/* 不再读写,关闭文件 */
f_close(&file);
}
void LogTask(void)
{
//LogFlashErase();
#if 0/*logBak logLen 读写测试*/
uint32_t a, b;
logBak++;
logLen++;
APP_DBG("logBak = %d logLen = %d\n", logBak, logLen);
logLenlogBakSet(&logBak, &logLen);
logLenlogBakGet(&a, &b);
APP_DBG("logBak = %d logLen = %d\n", (int)a, (int)b);
#endif
#if 0/*写log测试*/
static int i = 0;
i++;
for(i = 0; i < 128; i++)
LogRecord(i, 1);
#endif
#if 0/*读log测试*/
LogRead();
#endif
#if 0/*写文件测试*/
logFlieWrite();
#endif
}
//bool get_user_addr(void)
//{
// FIL file; /* 文件对象 */
// FRESULT f_res; /* 文件操作结果 */
// UINT fnum; /* 文件成功读写数量 */
// BYTE ReadBuffer[32] = {0}; /* 读缓冲区 */
//
// f_res = f_open(&file, "0:addr_user.txt", FA_READ);
// if(f_res != FR_OK)
// {
// APP_DBG("open file error : %d\r\n", f_res);
// return FALSE;
// }
// else
// {
// APP_DBG("open file sucess!!! \r\n");
// }
//
// f_res = f_read(&file, ReadBuffer, sizeof(ReadBuffer), &fnum);
// if(f_res == FR_OK)
// {
// APP_DBG("read file sucess!!! (%d)\n", fnum);
// APP_DBG("read Data : %s\r\n", ReadBuffer);
//
// userAddr = atoi(ReadBuffer);//存放命令后面的数字
// DBG("OK userAddr = %d\n", userAddr);
// }
// else
// {
// APP_DBG("read file error : %d\r\n", f_res);
// }
//
// LogNumGet();
//
// /* 不再读写,关闭文件 */
// f_close(&file);
// return TRUE;
//}
void LogNumGet(void)
{
int j;
uint8_t logbuff[8];//临时LOG缓冲区
uint32_t logbak;//临时变量
uint32_t loglen;//临时变量
logLenlogBakGet(&logBak, &logLen);//先获取当前的位置,在第几块,log长度
logbak = logBak;
loglen = logLen;
/* 访问下一块 */
if(++logbak == 4) logbak = 1;//第3块结束,到第4块的时候要回到第1块
SpiFlashRead(LOG_BAK_OFFSET + logbak * LOG_BLOCK_SIZE, logbuff, 8, LOG_TIME_OUT);
if(logbuff[0] == 0xFF && logbuff[1] == 0xFF && logbuff[2] == 0xFF && logbuff[3] == 0xFF)//如果全是F 就是没数据(判断4个可以证明了)
{
logbak = logBak;
/* 访问上一块 */
if(--logbak == 0) logbak = 3;//第3块结束,到第4块的时候要回到第1块
SpiFlashRead(LOG_BAK_OFFSET + logbak * LOG_BLOCK_SIZE, logbuff, 8, LOG_TIME_OUT);
if(logbuff[0] == 0xFF && logbuff[1] == 0xFF && logbuff[2] == 0xFF && logbuff[3] == 0xFF)//如果全是F 就是没数据(判断4个可以证明了)
{
LogNum = loglen>>3;
}
else
{
LogNum = 512 + (loglen>>3);
}
}
else
{
LogNum = 1024 + (loglen>>3);
}
}
/*
* user_flash.h
*
* Created on: Jun 2, 2023
* Author: Administrator
*/
#ifndef BT_AUDIO_APP_SRC_USER_USER_FLASH_H_
#define BT_AUDIO_APP_SRC_USER_USER_FLASH_H_
#include "type.h"
#include "flash_config.h"
#include "spi_flash.h"
#include "debug.h"
#include "STR7565.h"
extern void LogRecord(uint8_t ch, uint8_t event);
extern void LogRead(void);
extern void LogTask(void);
#endif /* BT_AUDIO_APP_SRC_USER_USER_FLASH_H_ */