158 lines
8.7 KiB
C
158 lines
8.7 KiB
C
#include "logflash.h"
|
||
#include <string.h>
|
||
#include "sysport.h"
|
||
#include "rtc.h"
|
||
#include "user_flash.h"
|
||
|
||
/********************************************************************************
|
||
* @file logflash.c
|
||
* @author 晏诚科技 Mr.Wang
|
||
* @version V1.0.0
|
||
* @date 11-Dec-2018
|
||
* @brief MCU未使用的FLASH空间用于硬件日志的存储
|
||
******************************************************************************
|
||
* @attention:LogoFlashInfo区域(占用1页空间,区域起始地址:LOGFLASH_INFO_ADDRESS)存放uLogFlash共用体信息,用来纪录logflash运行的信息。
|
||
* LogoFlash区域(内部FLASH余下的所有空间,区域其实地址为:LOGFLASH_START_ADDRESS)紧跟LogoFlashInfo区域后面,用于存放LOG数据。
|
||
* @use:
|
||
* 先调用void LogFlash_Init(void)初始化,上层需要定义LOG_AREA_ADDR地址
|
||
*******************************************************************************/
|
||
|
||
/*****************************************
|
||
*供内部使用常变量
|
||
****************************************/
|
||
LogFlash_u uLogFlash ; //LogFlash信息共用体变量uLogFlash,存放logflash相关信息
|
||
|
||
/****************************************************************************
|
||
* 名 称:void LogFlash_Init(void)
|
||
* 功 能:初始化LogFlash相关配置信息结构体uLogFlash,串口输出历史LOG
|
||
****************************************************************************/
|
||
void LogFlash_Init(void)
|
||
{
|
||
Read_Flash_Byte(LOGFLASH_INFO_ADDRESS, uLogFlash.bytes, sizeof(LogFlash_s)) ; //读取存在flash中LogoFlashInfo区域存储的LogFlash信息共用体数据
|
||
if( (uLogFlash.sLogFlash.head == 0x50505050) && (uLogFlash.sLogFlash.tail == 0x05050505)) /*条件成立说明LogFlash已经被配置过*/
|
||
{
|
||
AppLogPrintf("Log Flash存储溢出:%d次 。\r\n本地LOG: ", uLogFlash.sLogFlash.overflowCounter) ; //输出LogoFlash区域存储溢出的次数
|
||
ReadLogFromFlash(LOGFLASH_START_ADDRESS, uLogFlash.sLogFlash.writeOffset) ; //将现存的所有LOG读出,通过debug串口输出
|
||
uLogFlash.sLogFlash.overflowCounter = 0 ; //串口输出LOG后,将LogoFlash区域存储溢出的次数清零。
|
||
Refresh_LogFlash_Info() ; //更新存在flash中LogoFlashInfo区域存储的LogFlash信息共用体数据
|
||
return ;
|
||
}
|
||
else /*条件不成立说明LogFlash第一次被初始化*/
|
||
{
|
||
uLogFlash.sLogFlash.head = 0x50505050 ; //uLogFlash信息 数据头
|
||
uLogFlash.sLogFlash.tail = 0x05050505 ; //uLogFlash信息 数据尾
|
||
uLogFlash.sLogFlash.overflowCounter = 0 ; //uLogFlash信息 存储区域溢出次数
|
||
Erase_LogFlash() ; //将LogoFlash存储区域擦除
|
||
}
|
||
}
|
||
|
||
/**************************************************************************************************
|
||
* 名 称:void Erase_LogFlash(void)
|
||
* 功能说明:擦除LogFlash存储区的所有数据
|
||
* 调用方法:外部调用
|
||
*************************************************************************************************/
|
||
void Erase_LogFlash(void)
|
||
{
|
||
FLASH_Unlock(); //解锁FLASH
|
||
for( uint8_t n = 0; n< LOGFLASH_SIZE/FLASH_PAGE_SIZE; n++) //循环页,擦除LOGFLASH区域
|
||
{
|
||
FLASH_ErasePage(LOGFLASH_START_ADDRESS+n*FLASH_PAGE_SIZE) ;//擦除一页数据
|
||
}
|
||
uLogFlash.sLogFlash.writeOffset = 0 ; //uLogFlash信息 写偏移量清零
|
||
uLogFlash.sLogFlash.readOffset = 0 ; //uLogFlash信息 读偏移量清零
|
||
Refresh_LogFlash_Info() ; //将uLogFlash共用体数据存储到LogoFlashInfo区域中
|
||
FLASH_Lock(); //FLASH上锁
|
||
}
|
||
|
||
/****************************************************************************
|
||
* 名 称:void Refresh_LogFlash_Info(void)
|
||
* 功 能:读取存在flash中LogoFlashInfo区域存储的LogFlash信息共用体数据,即将uLogFlash
|
||
* 共用体数据存储到LogoFlashInfo区域中。
|
||
****************************************************************************/
|
||
void Refresh_LogFlash_Info(void)
|
||
{
|
||
FLASH_ErasePage(LOGFLASH_INFO_ADDRESS) ; //擦除LogoFlashInfo区域
|
||
Write_Flash_OnePage(LOGFLASH_INFO_ADDRESS, uLogFlash.bytes, sizeof(LogFlash_s)) ; //将uLogFlash共用体数据存储到LogoFlashInfo区域中
|
||
}
|
||
|
||
/****************************************************************************
|
||
* 名 称:void WriteLogToFlash(char *buffer)
|
||
* 功 能:向FLASH写入buffer
|
||
* 入口参数:
|
||
* @param1 *buffer 需要写入FLASH中数据缓冲区的指针
|
||
****************************************************************************/
|
||
void WriteLogToFlash(char *buffer)
|
||
{
|
||
uint16_t bufferLen = strlen(buffer) + 20 ; //计算需要分配的内存空间长度,多分配20bytes用于存储uCalendar.bytes等数据
|
||
char* logWriteBuffer = portMalloc(bufferLen) ; //分配内存
|
||
uint16_t outLen = 0, index = 0, timeOut = 0 ;
|
||
outLen = snprintf((char*)(logWriteBuffer), bufferLen, "*%s %s* ",(const char*)&uCalendar.bytes[11], buffer) ; //拼接字符串,防止logFlashBuffer越界
|
||
outLen = outLen/2+(outLen%2) ; //将logLen强制改变为2的倍数 将logLen字节长度转为半字长度
|
||
FLASH_Unlock(); //FLASH解锁
|
||
FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR) ; //清FLASH标志位
|
||
for( timeOut=0; (SET == FLASH_GetFlagStatus(FLASH_FLAG_BSY)); timeOut++)
|
||
{
|
||
Wait_For_Nms(10) ;
|
||
if( timeOut>10 )
|
||
{
|
||
ErrorLogPrintf("写Flash忙等待超时!") ;
|
||
FLASH_Unlock(); //FLASH解锁
|
||
portFree(logWriteBuffer) ;
|
||
return ;
|
||
}
|
||
}
|
||
uint16_t halfWord ;
|
||
while(outLen--)
|
||
{
|
||
FLASH_ClearFlag( FLASH_FLAG_EOP ) ;
|
||
halfWord = *(logWriteBuffer+(index++)) ; //取uint16_t类型数据halfWord LSB
|
||
if( (halfWord & 0x00FF) == 0x0000) //将halfWord中的空字符(0x00)用“——”符号(0x2D)替换
|
||
halfWord = halfWord | 0x002D ;
|
||
halfWord |= *(logWriteBuffer+(index++)) << 8 ; //取uint16_t类型数据halfWord HSB
|
||
if( (halfWord & 0xFF00) == 0x0000)
|
||
halfWord = halfWord | 0x2D00 ;
|
||
|
||
if( (uLogFlash.sLogFlash.writeOffset) >= (LOGFLASH_SIZE - bufferLen) ) //地址超出FLASH范围后重新开始写
|
||
{
|
||
uLogFlash.sLogFlash.writeOffset = 0 ;
|
||
uLogFlash.sLogFlash.overflowCounter++ ; //溢出计数器加一
|
||
}
|
||
if( ( (LOGFLASH_START_ADDRESS + uLogFlash.sLogFlash.writeOffset) % FLASH_PAGE_SIZE ) == 0 ) //写入地址为页首地址则擦除此页
|
||
{
|
||
FLASH_ErasePage(LOGFLASH_START_ADDRESS+uLogFlash.sLogFlash.writeOffset) ;
|
||
}
|
||
FLASH_ProgramHalfWord(LOGFLASH_START_ADDRESS+uLogFlash.sLogFlash.writeOffset, halfWord) ; //地址偏移量先偏移后写,防止FLASH_ERROR_PG错误
|
||
uLogFlash.sLogFlash.writeOffset += 2;
|
||
}
|
||
Refresh_LogFlash_Info() ; //更新存在flash中LogoFlashInfo区域存储的LogFlash信息共用体数据
|
||
FLASH_Lock(); //FLASH上锁
|
||
AppLogPrintf( "Flash偏移长度:%#x", uLogFlash.sLogFlash.writeOffset );
|
||
portFree(logWriteBuffer) ; //释放动态内存空间
|
||
}
|
||
|
||
/****************************************************************************
|
||
* 名 称:void ReadLogFromFlash(uint32_t readAddr, uint32_t length)
|
||
* 功 能:向readAddr地址读出log数据,并通过串口输出
|
||
* 入口参数:
|
||
* @param1 readAddr 读出的地址
|
||
* @param3 length 需要写入数据的长度
|
||
****************************************************************************/
|
||
void ReadLogFromFlash(uint32_t readAddr, uint32_t length)
|
||
{
|
||
uint8_t* logReadBuffer = portMalloc(FLASH_PAGE_SIZE) ;
|
||
uint16_t n = length/FLASH_PAGE_SIZE ;
|
||
while(n--)
|
||
{
|
||
Read_Flash_Byte(readAddr, logReadBuffer, FLASH_PAGE_SIZE) ;
|
||
UARTx_SendData(UART_DEBUG, (char*)logReadBuffer, FLASH_PAGE_SIZE ) ;
|
||
readAddr = readAddr+FLASH_PAGE_SIZE ;
|
||
}
|
||
memset(logReadBuffer, 0, FLASH_PAGE_SIZE) ;
|
||
Read_Flash_Byte(readAddr, logReadBuffer, length%FLASH_PAGE_SIZE ) ;
|
||
UARTx_SendData(UART_DEBUG, (char*)logReadBuffer, length%FLASH_PAGE_SIZE ) ;
|
||
portFree(logReadBuffer) ;
|
||
}
|
||
|
||
|
||
|