#include "spiflash.h" #include "rtthread.h" #include "DebugCmd.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); *rData = rt_malloc(LogLen); if(*rData == NULL) return 0; 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); //读取片尾数据 return 0; } /***************************************************************************************** * 函数名称: WritePara * 功能描述: 写入参数 * 参 数: Para, 网管参数 ParaLen, 参数长度 * 返 回 值: 无 *****************************************************************************************/ int WritePara(uint8_t *Para, uint32_t ParaLen) { SpiFlashEraseSector(GATEWEY_PARA_SAV_ADDR); SpiFlashWriteAnyLengthData(Para, GATEWEY_PARA_SAV_ADDR, ParaLen); //读取片尾数据 return 0; } /* USER CODE END */