stm32_ota/HARDWARE/LOGFLASH/logflash.c

158 lines
8.7 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#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) ;
}