diff --git a/include/HFlashServer.h b/include/HFlashServer.h index d3567da..d136345 100644 --- a/include/HFlashServer.h +++ b/include/HFlashServer.h @@ -63,6 +63,7 @@ typedef union HFlashPageInfo { uint32_t useSize : 24; ///< 使用大小 uint16_t version; ///< 当前页数据的版本 uint32_t modifyCount; ///< 修改次数 + uint8_t invalid : 1; ///< 无效标志 }; } HFlashPageInfo; @@ -162,7 +163,7 @@ void HFlashRegister(HFlashAddr_t addr, uint32_t size); * @param size 写入数据大小 * @return 1: 写入成功 0: 写入失败 */ -uint8_t HFlashWrite(HFlashAddr_t addr, void *data, uint32_t size); +uint8_t HFlashWrite(HFlashAddr_t addr, const void *data, uint32_t size); /** * @brief HFlashWriteOffset 写入从原始地址偏移后的地方写入数据, 如果偏移后的写入大小超过原未使用, 超出部分会自动写入0填充 @@ -172,7 +173,17 @@ uint8_t HFlashWrite(HFlashAddr_t addr, void *data, uint32_t size); * @param size 写入数据大小 * @return 1: 写入成功 0: 写入失败 */ -uint8_t HFlashWriteOffset(HFlashAddr_t addr, uint32_t offset, void *data, uint32_t size); +uint8_t HFlashWriteOffset(HFlashAddr_t addr, uint32_t offset, const void *data, uint32_t size); + +/** + * @brief HFlashWriteRawOffset 写入原始地址偏移后的位置写入Flash数据, 超出部分不自动填充, 延后计算CRC, 仅提供给一些库使用, 请勿使用 + * @param addr 需要注册的地址 + * @param offset 地址偏移 + * @param data 写入数据 + * @param size 写入数据大小 + * @return 1: 写入成功 0: 写入失败 + */ +uint8_t HFlashWriteRawOffset(HFlashAddr_t addr, uint32_t offset, const void *data, uint32_t size); /** * @brief HFlashStreamBegin 开始流式写入, 重置使用长度 @@ -187,7 +198,7 @@ void HFlashStreamBegin(HFlashAddr_t addr); * @param size 写入数据大小 * @return 1: 写入成功 0: 写入失败 */ -uint8_t HFlashStreamWrite(HFlashAddr_t addr, void *data, uint32_t size); +uint8_t HFlashStreamWrite(HFlashAddr_t addr, const void *data, uint32_t size); /** * @brief HFlashStreamEnd 结束流式写入, 计算CRC @@ -202,7 +213,7 @@ void HFlashStreamEnd(HFlashAddr_t addr); * @param size 写入数据大小 * @return 1: 写入成功 0: 写入失败 */ -uint8_t HFlashRawWrite(HFlashAddr_t addr, void *data, uint32_t size); +uint8_t HFlashRawWrite(HFlashAddr_t addr, const void *data, uint32_t size); /** * @brief HFlashRead 读取Flash数据 diff --git a/src/HFlashServer.c b/src/HFlashServer.c index 15cca52..e2feba7 100644 --- a/src/HFlashServer.c +++ b/src/HFlashServer.c @@ -39,7 +39,7 @@ uint32_t HSCrc32Get() #ifdef USE_STD_MEM #define FATAL_ERROR(format, ...) LogE(format, ##__VA_ARGS__); #else -#define FATAL_ERROR(format, ...) LogE(format, ##__VA_ARGS__); while(1); +#define FATAL_ERROR(format, ...) while (1) { LogE(format, ##__VA_ARGS__); HShellRun(); }; #endif // 最大热度 @@ -50,12 +50,16 @@ uint32_t HSCrc32Get() enum eShell { - kShellPageInfo, ///< 查看页表信息 + kShellPageInfo, ///< 查看页表信息 + kShellDelUseDataPage, ///< 删除页表使用数据 + kShellDelPage, ///< 删除页 kShellMax, }; static HShellMatch sShellMatch[] = { HSHELL_MATCH_ITEM(kShellPageInfo, "pageInfo"), + HSHELL_MATCH_ITEM(kShellDelUseDataPage, "pagedelUseData"), + HSHELL_MATCH_ITEM(kShellDelPage, "pageDel"), }; @@ -90,12 +94,19 @@ static union PageInfo sPageInfo; // 备份定时器 static HTimer_t sBackupTimer = HTIMER_INVALID; -// 需要备份的保护区地址页偏移 +// 延后计算CRC定时器 +static HTimer_t sDelayCrc32Timer = HTIMER_INVALID; + +// 存储需要备份的保护区地址页偏移 static HVECTOR_DEFINE32(sNeedBackupOffset, 10); +// 存储需要延后计算CRC的记录地址 +static HVECTOR_DEFINE32(sDelayCalcCrc32, 3); static uint8_t RestoreBackup(HFlashAddr_t srcAddr, HFlashAddr_t dstAddr, uint32_t size); static void StartBackupTimer(); +static HFlashCacheInfo *FindCache(HFlashAddr_t addr); +static void WriteCachePage(HFlashCacheInfo *info); ///< 检查地址是否在双备份保护区内 static uint8_t IsProtect(HFlashAddr_t addr, uint32_t size) @@ -147,7 +158,7 @@ static uint8_t EraseFlash(HFlashAddr_t addr) * @param call 拷贝回调, dest缓存, src已经调整好位置的指针, buffSize需要拷贝的数据大小, userData用户数据 * @return 写入是否成功 */ -static uint8_t WriteData(HFlashAddr_t addr, void *data, uint32_t size, void(*call)(void *dest, const void *src, uint16_t buffSize, void *userData), void *userData) +static uint8_t WriteData(HFlashAddr_t addr, const void *data, uint32_t size, void(*call)(void *dest, const void *src, uint16_t buffSize, void *userData), void *userData) { if (sInfo.write == NULL) { FATAL_ERROR("write is null"); @@ -231,7 +242,7 @@ static void _WriteFlashHelper(void *dest, const void *src, uint16_t buffSize, vo memcpy(dest, src, buffSize); } -static uint8_t WriteFlash(HFlashAddr_t addr, void *data, uint32_t size) +static uint8_t WriteFlash(HFlashAddr_t addr, const void *data, uint32_t size) { return WriteData(addr, data, size, _WriteFlashHelper, NULL); } @@ -334,7 +345,6 @@ static void AddBackupAddr(uint32_t addr, uint32_t size) } } - static uint32_t GetFlashCrc32(HFlashAddr_t addr, uint32_t size) { if (size == 0) { @@ -362,6 +372,57 @@ static uint32_t GetFlashCrc32(HFlashAddr_t addr, uint32_t size) return HSCrc32Get(); } +static void SyncDelayCrc32() +{ + LogD("Start sync DelayCrc32"); + if (sDelayCrc32Timer != HTIMER_INVALID) { + HTimerRemove(sDelayCrc32Timer); + sDelayCrc32Timer = HTIMER_INVALID; + } + + for (uint16_t i = 0; i < HVectorGetUseLen(sDelayCalcCrc32); ++i) { + const uint32_t addr = HVectorGetData(sDelayCalcCrc32, i); + HFlashCacheInfo *cache = FindCache(addr); + if (cache == NULL) { + LogE("addr[0x%08x], cache not found", addr); + continue; + } + + cache->info.crc32 = GetFlashCrc32(addr, cache->info.useSize); + WriteCachePage(cache); + } + + HVectorClear(sDelayCalcCrc32); +} + +static void StartDelayCrc32Timer() +{ + if (sDelayCrc32Timer != HTIMER_INVALID) { + HTimerRemove(sDelayCrc32Timer); + sDelayCrc32Timer = HTIMER_INVALID; + } + + sDelayCrc32Timer = HTimerAdd(HFLASH_TIMER_ID, HFLASH_SYNC_TIME, SyncDelayCrc32, kHTimerOnce); +} + +static void AddDelayCrc32(HFlashAddr_t addr) +{ + do { + const HVectorLenType index = HVectorFindData(sDelayCalcCrc32, addr); + if (index != HVECTOR_ERROR) { + break; + } + + if (HVectorAddData(sDelayCalcCrc32, addr)) { + break; + } + + SyncDelayCrc32(); + } while (0); + + StartDelayCrc32Timer(); +} + static uint8_t RestoreBackup(HFlashAddr_t srcAddr, HFlashAddr_t dstAddr, uint32_t size) { const uint16_t mallocSize = 1024; @@ -534,10 +595,25 @@ static uint8_t ScanPage(uint8_t (*call)(uint32_t index, HFlashPageInfo *info, vo ///< 检查是否重叠, 重叠返回1 static uint8_t _CreatePageInfoHelper(uint32_t index, HFlashPageInfo *info, void *userData) { + if (info->invalid) { + return 0; + } + HFlashPageInfo *cache = (HFlashPageInfo *)userData; return IsOverLap(info->addr, info->size, cache->addr, cache->size); } +static uint8_t ScanAvailablePage(uint32_t index, HFlashPageInfo *info, void *userData) +{ + uint32_t *result = (uint32_t *)userData; + if (info->invalid == 0) { + return 0; + } + + *result = index; + return 1; +} + static uint8_t CreatePageInfo(HFlashAddr_t addr, uint32_t size) { HFlashPageInfo info; @@ -550,13 +626,21 @@ static uint8_t CreatePageInfo(HFlashAddr_t addr, uint32_t size) return 0; } + uint32_t index = 0; + if (ScanPage(ScanAvailablePage, &index)) { + // 如果找到空闲页, 覆盖之前的页 + info.crc32 = GetFlashCrc32(info.addr, info.useSize); + WritePage(index, &info); + return 1; + } + if (sPageInfo.useNum >= sPageInfo.pageNum) { FATAL_ERROR("page table is full"); return 0; } // 写入新页表 - const uint32_t index = sPageInfo.useNum++; + index = sPageInfo.useNum++; info.crc32 = GetFlashCrc32(info.addr, info.useSize); WritePage(index, &info); @@ -565,6 +649,10 @@ static uint8_t CreatePageInfo(HFlashAddr_t addr, uint32_t size) static uint8_t _FindCacheHelper(uint32_t index, HFlashPageInfo *info, void *userData) { + if (info->invalid) { + return 0; + } + HFlashCacheInfo *cache = (HFlashCacheInfo *)userData; if (info->addr != cache->info.addr) { return 0; @@ -689,12 +777,12 @@ static uint8_t _Print(uint32_t index, HFlashPageInfo *info, void *userData) { uint32_t *arg1 = (uint32_t *)userData; if (*arg1 == -1) { - HSHELL_PRINTFL("page[%d], addr[0x%08x], useSize[0x%x], size[0x%x], modifyCount[%d], crc32[0x%x], version[%d]", index, info->addr, info->useSize, info->size, info->modifyCount, info->crc32, info->version); + HSHELL_PRINTFL("page[%d], invalid[%d], addr[0x%08x][%u], useSize[0x%x][%d], size[0x%x][%d], modifyCount[%d], crc32[0x%x], version[%d]", index, info->invalid, info->addr, info->addr, info->useSize, info->useSize, info->size, info->size, info->modifyCount, info->crc32, info->version); return 0; } if (index == *arg1) { - HSHELL_PRINTFL("page[%d], addr[0x%08x], useSize[0x%x], size[0x%x], modifyCount[%d], crc32[0x%x], version[%d]", index, info->addr, info->useSize, info->size, info->modifyCount, info->crc32, info->version); + HSHELL_PRINTFL("page[%d], invalid[%d], addr[0x%08x][%u], useSize[0x%x][%d], size[0x%x][%d], modifyCount[%d], crc32[0x%x], version[%d]", index, info->invalid, info->addr, info->addr, info->useSize, info->useSize, info->size, info->size, info->modifyCount, info->crc32, info->version); return 1; } @@ -704,13 +792,36 @@ static uint8_t _Print(uint32_t index, HFlashPageInfo *info, void *userData) static void Shell(HSHELL_FUNC_ARGS) { uint32_t arg1 = 0; - if (HSHellToUint32(tokens, tokensLen, 0, &arg1) == 0) { + if (HSHellToUint32(tokens, tokensLen, 1, &arg1) == 0) { arg1 = -1; } switch (key) { case kShellPageInfo: { ScanPage(_Print, &arg1); + for (uint16_t i = 0; i < sInfo.pageCacheUseNum; ++i) { + HSHELL_PRINTFL("Cache index[%d], addr[0x%08x], useSize[0x%x][%d], size[0x%x][%d], modifyCount[%d], crc32[0x%x], version[%d]", i, sInfo.pageCache[i].info.addr, sInfo.pageCache[i].info.useSize, sInfo.pageCache[i].info.useSize, sInfo.pageCache[i].info.size, sInfo.pageCache[i].info.size, sInfo.pageCache[i].info.modifyCount, sInfo.pageCache[i].info.crc32, sInfo.pageCache[i].info.version); + } + } break; + case kShellDelUseDataPage: { + HFlashCacheInfo *cache = FindCache(arg1); + if (cache == NULL) { + HSHELL_PRINTFL("addr[0x%08x] not register", arg1); + return ; + } + + cache->info.useSize = 0; + WriteCachePage(cache); + } break; + case kShellDelPage: { + HFlashCacheInfo *cache = FindCache(arg1); + if (cache == NULL) { + HSHELL_PRINTFL("addr[0x%08x] not register", arg1); + return ; + } + + cache->info.invalid = 1; + WriteCachePage(cache); } break; default: break; @@ -778,6 +889,10 @@ void HFlashInitCheck() ///< 检查是否重叠, 重叠返回1 static uint8_t _CheckOverLap(uint32_t index, HFlashPageInfo *info, void *userData) { + if (info->invalid) { + return 0; + } + HFlashCacheInfo *cache = (HFlashCacheInfo *)userData; if (cache->pos == index) { return 0; @@ -823,6 +938,7 @@ void HFlashRegister(HFlashAddr_t addr, uint32_t size) if (cache->info.useSize > size) { LogE("addr[0x%08x] useSize[%d] > size[%d]", addr, cache->info.useSize, size); cache->info.useSize = 0; + cache->waitWrite = 1; } // 检查是否在保护区域, 不是保护区域不需要检查crc校验 @@ -873,7 +989,7 @@ void HFlashRegister(HFlashAddr_t addr, uint32_t size) WriteCachePage(cache); } -uint8_t HFlashWrite(HFlashAddr_t addr, void *data, uint32_t size) +uint8_t HFlashWrite(HFlashAddr_t addr, const void *data, uint32_t size) { // 检查是否存在致命性错误, 使用的地址不在注册页表中 uint8_t result = 0; @@ -910,7 +1026,7 @@ uint8_t HFlashWrite(HFlashAddr_t addr, void *data, uint32_t size) return result; } -uint8_t HFlashWriteOffset(HFlashAddr_t addr, uint32_t offset, void *data, uint32_t size) +static uint8_t WriteOffset(HFlashAddr_t addr, uint32_t offset, const void *data, uint32_t size, uint8_t needSetZero) { uint8_t result = 0; HFlashCacheInfo *cache = FindCache(addr); @@ -928,7 +1044,7 @@ uint8_t HFlashWriteOffset(HFlashAddr_t addr, uint32_t offset, void *data, uint32 // 更新使用长度, 将跨越的部分填充0 if (cache->info.useSize < useSize) { - if (cache->info.useSize < offset) { + if (needSetZero && cache->info.useSize < offset) { WriteFlashValue(addr + cache->info.useSize, offset - cache->info.useSize, 0); } @@ -936,8 +1052,13 @@ uint8_t HFlashWriteOffset(HFlashAddr_t addr, uint32_t offset, void *data, uint32 } result = WriteFlash(addr + offset, data, size); - cache->info.crc32 = GetFlashCrc32(addr, cache->info.useSize); - WriteCachePage(cache); + if (needSetZero) { + cache->info.crc32 = GetFlashCrc32(addr, cache->info.useSize); + WriteCachePage(cache); + } else { + cache->waitWrite = 1; + AddDelayCrc32(addr); + } // 检查是否在保护区域, 需要的话需要写入等待备份 if (IsProtect(addr, size)) { @@ -947,6 +1068,16 @@ uint8_t HFlashWriteOffset(HFlashAddr_t addr, uint32_t offset, void *data, uint32 return result; } +uint8_t HFlashWriteOffset(HFlashAddr_t addr, uint32_t offset, const void *data, uint32_t size) +{ + return WriteOffset(addr, offset, data, size, 1); +} + +uint8_t HFlashWriteRawOffset(HFlashAddr_t addr, uint32_t offset, const void *data, uint32_t size) +{ + return WriteOffset(addr, offset, data, size, 0); +} + void HFlashStreamBegin(HFlashAddr_t addr) { HFlashCacheInfo *cache = FindCache(addr); @@ -960,7 +1091,7 @@ void HFlashStreamBegin(HFlashAddr_t addr) cache->info.useSize = 0; } -uint8_t HFlashStreamWrite(HFlashAddr_t addr, void *data, uint32_t size) +uint8_t HFlashStreamWrite(HFlashAddr_t addr, const void *data, uint32_t size) { uint8_t result = 0; HFlashCacheInfo *cache = FindCache(addr); @@ -998,7 +1129,7 @@ void HFlashStreamEnd(HFlashAddr_t addr) WriteCachePage(cache); } -uint8_t HFlashRawWrite(HFlashAddr_t addr, void *data, uint32_t size) +uint8_t HFlashRawWrite(HFlashAddr_t addr, const void *data, uint32_t size) { return WriteFlash(addr, data, size); } @@ -1038,12 +1169,13 @@ uint8_t HFlashReadOffset(HFlashAddr_t addr, uint32_t offset, void *data, uint32_ // 读取的数据超出使用长度, 将使用长度后面填充0 const uint32_t useSize = offset + size; - const uint32_t remain = useSize - cache->info.useSize; - if (cache->info.useSize < useSize) { + if (useSize > cache->info.useSize) { + const uint32_t remain = useSize - cache->info.useSize; memset((uint8_t *)data + size - remain, 0, remain); + size -= remain; } - return ReadFlash(addr + offset, data, size - remain); + return ReadFlash(addr + offset, data, size); } uint8_t HFlashRawRead(HFlashAddr_t addr, void *data, uint32_t size)