初始版本

This commit is contained in:
2026-04-23 13:56:52 +08:00
parent 6c611f1fa3
commit 23ab9ca0f9
252 changed files with 136838 additions and 0 deletions
+497
View File
@@ -0,0 +1,497 @@
#include "spiflash.h"
#include "rtthread.h"
#include "DebugCmd.h"
#include "Public.h"
//#define FLASH_TEST
#ifdef FLASH_TEST
uint8_t flashtestbuff[SPIFLASH_SIZE];
#endif
static uint8_t SpiFlashReadByte(void)
{
return Spi1SendReceive(0);
}
static void SpiFlashSendByte(uint8_t sData)
{
Spi1SendReceive(sData);
}
static void SpiFlashWriteEnable(void)
{
SpiFlashClrNss();
SpiFlashSendByte(SPIFLASH_CMD_WREN);
SpiFlashSetNss();
}
static void SpiFlashWaitForWriteEnd(void)
{
uint8_t flashstatus = 0;
SpiFlashClrNss();
SpiFlashSendByte(SPIFLASH_CMD_RDSR);
do{
flashstatus = SpiFlashReadByte();
}
while ((flashstatus & SPIFLASH_WIP_FLAG) == SPIFLASH_WIP_FLAG);
SpiFlashSetNss();
}
//扇区擦除
void SpiFlashEraseSector(uint32_t SectorAddr)
{
#ifdef FLASH_TEST
memset(&flashtestbuff[SectorAddr], 0xff, 4096);
#else
SpiFlashWriteEnable();
SpiFlashWaitForWriteEnd();
SpiFlashClrNss();
SpiFlashSendByte(SPIFLASH_CMD_SE);
SpiFlashSendByte((SectorAddr >> 16) & 0x00FF);
SpiFlashSendByte((SectorAddr >> 8) & 0x00FF);
SpiFlashSendByte(SectorAddr & 0x00FF);
SpiFlashSetNss();
SpiFlashWaitForWriteEnd();
#endif
}
//整片擦除
void SpiFlashEraseChip(void)
{
SpiFlashWriteEnable();
SpiFlashClrNss();
SpiFlashSendByte(SPIFLASH_CMD_BE);
SpiFlashSetNss();
SpiFlashWaitForWriteEnd();
}
//写数据
void SpiFlashWriteData(uint8_t* wData, uint32_t wAddr, uint16_t wLen)
{
#ifdef FLASH_TEST
memcpy(&flashtestbuff[wAddr], wData, wLen);
#else
SpiFlashWriteEnable();
SpiFlashClrNss();
SpiFlashSendByte(SPIFLASH_CMD_WRITE);
SpiFlashSendByte((wAddr >> 16) & 0x00FF);
SpiFlashSendByte((wAddr >> 8) & 0x00FF);
SpiFlashSendByte(wAddr & 0x00FF);
for(int i = 0; i < wLen; i++) {
SpiFlashSendByte(wData[i]);
}
SpiFlashSetNss();
SpiFlashWaitForWriteEnd();
#endif
}
void SpiFlashWriteAnyLengthData(uint8_t* wData, uint32_t wAddr, uint16_t wLen)
{
uint16_t PageCnt; //需要写入页数
uint16_t FirstPageWriteSize; //在起始地址不为页起始地址的情况下,先写入当前页剩余空间
uint16_t LastPageWriteSize; //最后一页写入长度
uint32_t AddrOffset = 0;
uint32_t WriteAddr;
LogHeader LogH;
WriteAddr = wAddr;
//写入的长度超出最大空间,从起始开始写起
if((WriteAddr + wLen) > SPIFLASH_SIZE) {
LogH = (LogHeader)wData;
WriteAddr = LOG_SAV_START_SECTOR * SPIFLASH_SECTORSIZE;
LogH->LogEndAddr = WriteAddr + wLen;
}
uint16_t FirstPageRemainSpace = SPIFLASH_PAGESIZE - (WriteAddr % SPIFLASH_PAGESIZE);
// //判断是否跨扇区,跨扇区需要先擦除下一扇区
// CheckDelSecter(wAddr, wLen);
if(wLen < FirstPageRemainSpace) {
FirstPageWriteSize = wLen; //计算首页写入长度
PageCnt = 0;
LastPageWriteSize = 0;
}
else {
// FirstPageWriteSize = FirstPageRemainSpace % SPIFLASH_PAGESIZE;
// PageCnt = (wLen - (FirstPageWriteSize % SPIFLASH_PAGESIZE)) / SPIFLASH_PAGESIZE; //计算需要写入多少整页
// LastPageWriteSize = (wLen - (FirstPageWriteSize % SPIFLASH_PAGESIZE)) % SPIFLASH_PAGESIZE; //计算剩余需要写入的长度
FirstPageWriteSize = FirstPageRemainSpace;
PageCnt = (wLen - FirstPageWriteSize) / SPIFLASH_PAGESIZE; //计算需要写入多少整页
LastPageWriteSize = (wLen - FirstPageWriteSize) % SPIFLASH_PAGESIZE; //计算剩余需要写入的长度
}
if(FirstPageWriteSize > 0) {
SpiFlashWriteData(&wData[AddrOffset], WriteAddr, FirstPageWriteSize);
AddrOffset += FirstPageWriteSize;
WriteAddr += FirstPageWriteSize;
}
for(int i = 0; i < PageCnt; i++) {
SpiFlashWriteData(&wData[AddrOffset], WriteAddr, SPIFLASH_PAGESIZE);
AddrOffset += SPIFLASH_PAGESIZE;
WriteAddr += SPIFLASH_PAGESIZE;
}
if(LastPageWriteSize > 0) {
SpiFlashWriteData(&wData[AddrOffset], WriteAddr, LastPageWriteSize);
}
}
void SpiFlashReadAnyLengthData(uint8_t* rData, uint32_t rAddr, uint16_t rLen)
{
#ifdef FLASH_TEST
memcpy(rData, &flashtestbuff[rAddr], rLen);
#else
SpiFlashClrNss();
SpiFlashSendByte(SPIFLASH_CMD_READ);
SpiFlashSendByte((rAddr >> 16) & 0x00FF);
SpiFlashSendByte((rAddr >> 8) & 0x00FF);
SpiFlashSendByte(rAddr & 0x00FF);
for(int i = 0; i < rLen; i++) {
rData[i] = SpiFlashReadByte();
}
SpiFlashSetNss();
#endif
}
uint32_t SpiFlashReadId(void)
{
uint32_t Temp = 0, Temp0 = 0, Temp1 = 0, Temp2 = 0;
SpiFlashClrNss();
SpiFlashSendByte(0x9F);
Temp0 = SpiFlashReadByte();
Temp1 = SpiFlashReadByte();
Temp2 = SpiFlashReadByte();
SpiFlashSetNss();
Temp = (Temp0 << 16) | (Temp1 << 8) | Temp2;
return Temp;
}
typedef struct {
uint16_t Flag;
uint16_t LoopSavFlag; //循环存储标志
uint32_t LogCnt; //日志最大数量
uint32_t FirstLogStartAddr; //第一个数据的起始地址
uint32_t LastLogEndAddr; //最后一个数据的结束地址
}LogNumSav_t;
static LogNumSav_t LogNumArray[256];
static __IO uint32_t gLogCnt = 0;
static __IO uint32_t FirstLogStartAddr = 0; //第一个日志起始地址
static __IO uint32_t LastLogEndAddr = 0; //最后一个日志结束地址
static __IO uint16_t LoopSavFlag = 0; //循环存储标志
static uint16_t LogNumIdx;
uint16_t ReadLoopSavFlag(void)
{
return LoopSavFlag;
}
void SetLoopSavFlag(uint16_t LoopFlag)
{
LoopSavFlag = LoopFlag;
}
uint32_t ReadLogNum(void)
{
return gLogCnt;
}
void SetLogNum(uint32_t LogCnt)
{
gLogCnt = LogCnt;
}
uint32_t ReadFirstLogStartAddr(void)
{
return FirstLogStartAddr;
}
void SetFirstLogStartAddr(uint32_t FLStartAddr)
{
FirstLogStartAddr = FLStartAddr;
}
uint32_t ReadLastLogEndAddr(void)
{
return LastLogEndAddr;
}
void SetLastLogEndAddr(uint32_t LLEndAddr)
{
LastLogEndAddr = LLEndAddr;
}
void LogInit(void)
{
LogNumIdx = 0xffff;
SpiFlashReadId();
SpiFlashReadAnyLengthData((uint8_t *)&LogNumArray, LOG_INFO_START_SECTOR * SPIFLASH_SECTORSIZE, sizeof(LogNumArray));
for(int i = 0; i < 256; i++) {
if(LogNumArray[i].Flag != LOG_INFO_SAV_FLAG) {
LogNumIdx = i;
break;
}
}
if(LogNumIdx == 0xffff) { //256条记录满,读最后一条记录
LogNumIdx = 0;
SetLogNum(LogNumArray[255].LogCnt);
SetLoopSavFlag(LogNumArray[255].LoopSavFlag);
SetFirstLogStartAddr(LogNumArray[255].FirstLogStartAddr);
SetLastLogEndAddr(LogNumArray[255].LastLogEndAddr);
return;
}
if(LogNumIdx == 0) { //没有记录
LogNumIdx = 0;
SetLogNum(0);
SetLoopSavFlag(0);
SetFirstLogStartAddr(LOG_SAV_START_SECTOR * SPIFLASH_SECTORSIZE);
SetLastLogEndAddr(LOG_SAV_START_SECTOR * SPIFLASH_SECTORSIZE);
return;
}
SetLogNum(LogNumArray[LogNumIdx-1].LogCnt);
SetLoopSavFlag(LogNumArray[LogNumIdx-1].LoopSavFlag);
SetFirstLogStartAddr(LogNumArray[LogNumIdx-1].FirstLogStartAddr);
SetLastLogEndAddr(LogNumArray[LogNumIdx-1].LastLogEndAddr);
}
void SavLogNum(uint32_t LogNum)
{
LogNumSav_t CLogSav;
if(LogNum == 0) {
LogNumIdx = 0;
SetLogNum(0);
SetLoopSavFlag(0);
SetFirstLogStartAddr(LOG_SAV_START_SECTOR * SPIFLASH_SECTORSIZE);
SetLastLogEndAddr(LOG_SAV_START_SECTOR * SPIFLASH_SECTORSIZE);
SpiFlashEraseSector(LOG_INFO_START_SECTOR * SPIFLASH_SECTORSIZE);
return;
}
SetLogNum(LogNum);
CLogSav.Flag = LOG_INFO_SAV_FLAG;
CLogSav.LogCnt = LogNum;
CLogSav.FirstLogStartAddr = ReadFirstLogStartAddr();
CLogSav.LastLogEndAddr = ReadLastLogEndAddr();
if(LogNumIdx == 256) {
SpiFlashEraseSector(LOG_INFO_START_SECTOR * SPIFLASH_SECTORSIZE);
LogNumIdx = 0;
}
SpiFlashWriteData((uint8_t *)&CLogSav, LogNumIdx * sizeof(LogNumSav_t) + LOG_INFO_START_SECTOR * SPIFLASH_SECTORSIZE, sizeof(LogNumSav_t));
LogNumIdx++;
}
/*****************************************************************************************
* 函数名称: CheckDelSecter
* 功能描述: 检查需要删除的扇区,跨扇区删除下一扇区,如果到了删除最后一个扇区,循环到起始扇区
* 参 数: wAddr, 写入地址
wLen, 写入长度
* 返 回 值: 返回写入起始地址
*****************************************************************************************/
uint8_t LogBuff[LOG_SAV_SIZE_MAX];
const uint8_t SavFlag[4] ={0xAA, 0x55, 0x55, 0xAA};
void CheckDelSecter(uint32_t wAddr, uint16_t wLen)
{
uint32_t DelOffsetAddr, FindFirstLogAddr; //存储起始地址
uint32_t DelSectorNum = 0;
uint32_t SurplusSpace = SPIFLASH_SECTORSIZE - (wAddr % SPIFLASH_SECTORSIZE);
if((wAddr + wLen) > SPIFLASH_SIZE) {
DelOffsetAddr = LOG_SAV_START_SECTOR * SPIFLASH_SECTORSIZE;
SetLastLogEndAddr(DelOffsetAddr + wLen);
SetLoopSavFlag(1);
SpiFlashEraseSector(DelOffsetAddr);
FindFirstLogAddr = DelOffsetAddr + SPIFLASH_SECTORSIZE;
}
else {
if(wLen < SurplusSpace) { //长度没有超过扇区剩余容量
SetLastLogEndAddr(wAddr + wLen);
return;
}
DelOffsetAddr = (wAddr / SPIFLASH_SECTORSIZE + 1) * SPIFLASH_SECTORSIZE;
DelSectorNum = (wLen - SurplusSpace) / SPIFLASH_SECTORSIZE + 1;
SetLastLogEndAddr(wAddr + wLen);
for(int i = 0; i < DelSectorNum; i++) {
SpiFlashEraseSector(DelOffsetAddr);
DelOffsetAddr += SPIFLASH_SECTORSIZE;
}
if(DelOffsetAddr == SPIFLASH_SIZE) {
DelOffsetAddr = LOG_SAV_START_SECTOR * SPIFLASH_SECTORSIZE;
}
FindFirstLogAddr = DelOffsetAddr;
}
if(!ReadLoopSavFlag())
return;
uint32_t ReadAddr = FindFirstLogAddr;
while(1) {
SpiFlashReadAnyLengthData(LogBuff, ReadAddr, LOG_SAV_SIZE_MAX);
int i;
for(i = 0; i < LOG_SAV_SIZE_MAX; i++) {
if(memcmp(&LogBuff[i], SavFlag, 4) == 0) {
SetFirstLogStartAddr(ReadAddr + i);
return;;
}
}
if(i == LOG_SAV_SIZE_MAX) {
ReadAddr += LOG_SAV_SIZE_MAX;
if(ReadAddr >= SPIFLASH_SIZE) { //找不到下一条数据,重置flash
Debug_Printf("Add LOG Error, Next Data No Find!\r\n");
SetLogNum(0);
SetLoopSavFlag(0);
SetFirstLogStartAddr(LOG_SAV_START_SECTOR * SPIFLASH_SECTORSIZE);
SetLastLogEndAddr(LOG_SAV_START_SECTOR * SPIFLASH_SECTORSIZE);
return;
}
}
}
}
uint8_t LogBuffTemp[LOG_SAV_SIZE_MAX];
void AddLog(uint8_t *wData, uint32_t wLen)
{
//const uint8_t SavFlag[4] ={0xAA, 0x55, 0x55, 0xAA};
uint32_t LogNum;
uint32_t LogSize;
//uint32_t FLStartAddr;
uint32_t LLEndAddr;
// uint32_t SectorN;
LogHeader LogH;
LogH = (LogHeader)LogBuffTemp;
LogNum = ReadLogNum();
if(LogNum == 0) {
SetFirstLogStartAddr(LOG_SAV_START_SECTOR * SPIFLASH_SECTORSIZE);
SetLastLogEndAddr(LOG_SAV_START_SECTOR * SPIFLASH_SECTORSIZE);
SpiFlashEraseSector(LOG_SAV_START_SECTOR * SPIFLASH_SECTORSIZE);
}
//FLStartAddr = ReadFirstLogStartAddr();
LLEndAddr = ReadLastLogEndAddr();
LogNum++;
LogH->LogSavFlag = LOG_SAV_FLAG;
LogH->LogIdx = LogNum;
LogSize = wLen + sizeof(LogHeader_t);
LogH->LogEndAddr = LLEndAddr + LogSize;
LogH->TimeStamp = TimeTs();
memcpy(&LogBuffTemp[sizeof(LogHeader_t)], wData, wLen);
//判断是否跨扇区,跨扇区需要先擦除下一扇区
CheckDelSecter(LLEndAddr, LogSize);
if(LogH->LogEndAddr > SPIFLASH_SIZE) {
LLEndAddr = LOG_SAV_START_SECTOR * SPIFLASH_SECTORSIZE;
LogH->LogEndAddr = ReadLastLogEndAddr();
}
SpiFlashWriteAnyLengthData(LogBuffTemp, LLEndAddr, LogSize);
SavLogNum(LogNum);
//Debug_Printf("Add LOG: %d,endaddr = %d\r\n", LogNum, ReadLastLogEndAddr());
}
/*****************************************************************************************
* 函数名称: ReadLog
* 功能描述: 读取日志
* 参 数: Header, 上一包日志头信息,连续读取时传入上一包数据信息,缩短日志遍历时间,
Header->LogEndAddr为0读取第一包数据,LogIdx数据无效
rData, 日志出口,需要释放
LogIdx, 读取的日志的序号,为0读取Header->LogEndAddr对应日志
* 返 回 值: 返回数据长度
*****************************************************************************************/
int ReadLog(LogHeader Header, uint8_t **rData, uint32_t LogIdx)
{
uint32_t FSAddr;
int LogLen = 0;
//bool FirstIdx = false;
if(Header == NULL)
return 0;
if(Header->LogEndAddr == 0) {
Header->LogEndAddr = ReadFirstLogStartAddr();
LogIdx = 0;
}
if(LogIdx == 1) {
FSAddr = ReadFirstLogStartAddr();
}
else
FSAddr = Header->LogEndAddr;
while(1) {
SpiFlashReadAnyLengthData((uint8_t *)Header, FSAddr, sizeof(LogHeader_t));
if(Header->LogSavFlag != LOG_SAV_FLAG) {
if((SPIFLASH_SIZE - FSAddr) < LOG_SAV_SIZE_MAX) { //判断是否到片尾
FSAddr = LOG_SAV_START_SECTOR * SPIFLASH_SECTOR_NUM;
continue;
}
else
return 0;
}
if(LogIdx == 0) {
LogIdx = Header->LogIdx;
}
else if(Header->LogIdx != LogIdx) {
FSAddr = Header->LogEndAddr;
continue;
}
if(Header->LogIdx == LogIdx) {
if(*rData == NULL)
return sizeof(LogHeader_t);
SpiFlashReadAnyLengthData(LogBuffTemp, FSAddr, Header->LogEndAddr - FSAddr);
LogLen = Header->LogEndAddr - FSAddr - sizeof(LogHeader_t);
void *pTemp = rt_malloc(LogLen);
if(pTemp == NULL)
return 0;
*rData =pTemp;
memcpy(*rData, &LogBuffTemp[sizeof(LogHeader_t)], LogLen);
break;
}
}
return LogLen;
}
/*****************************************************************************************
* 函数名称: ReadPara
* 功能描述: 读取参数
* 参 数: Para, 网关参数
ParaLen, 参数长度
* 返 回 值: 无
*****************************************************************************************/
int ReadPara(uint8_t *Para, uint32_t ParaLen)
{
SpiFlashReadAnyLengthData(Para, GATEWEY_PARA_SAV_ADDR, ParaLen); //读取片尾数据
uint16_t Check = CRC_Modbus(0xA001, Para, ParaLen - 2);
GWConfigPara CfgPara = (GWConfigPara)Para;
if(CfgPara->crc16 != Check)
return -1;
return 0;
}
/*****************************************************************************************
* 函数名称: WritePara
* 功能描述: 写入参数
* 参 数: Para, 网关参数
ParaLen, 参数长度
* 返 回 值: 无
*****************************************************************************************/
int WritePara(uint8_t *Para, uint32_t ParaLen)
{
SpiFlashEraseSector(GATEWEY_PARA_SAV_ADDR);
uint16_t Check = CRC_Modbus(0xA001, Para, ParaLen - 2);
GWConfigPara CfgPara = (GWConfigPara)Para;
CfgPara->crc16 = Check;
SpiFlashWriteAnyLengthData(Para, GATEWEY_PARA_SAV_ADDR, ParaLen); //读取片尾数据
return 0;
}
/* USER CODE END */