From 176709e37d1144b1d34e19c3aa3799e50f81fed1 Mon Sep 17 00:00:00 2001 From: coffee Date: Sat, 6 Dec 2025 09:54:51 +0800 Subject: [PATCH] =?UTF-8?q?1.=20=E4=BF=AE=E6=94=B9=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E5=BB=B6=E8=BF=9F=E5=86=99=E5=85=A5=E7=BC=93=E5=AD=98,=20?= =?UTF-8?q?=E5=86=99=E5=85=A5=E9=A1=B5,=20=E5=86=99=E5=85=A5=E5=A4=87?= =?UTF-8?q?=E4=BB=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/HFlashServer.h | 25 ++++-- src/HFlashServer.c | 193 +++++++++++++++++++++-------------------- 2 files changed, 120 insertions(+), 98 deletions(-) diff --git a/include/HFlashServer.h b/include/HFlashServer.h index acaa7cd..85e42d8 100644 --- a/include/HFlashServer.h +++ b/include/HFlashServer.h @@ -1,7 +1,7 @@ /** * 日期: 2025-11-27 * 作者: coffee - * 描述: Flash通用服务模块, 用于保证Flash操作的完备性, 支持任意长度数据读写 + * 描述: Flash通用服务模块, 用于保证Flash操作的完备性, 支持任意长度数据读写, 因内部使用延后处理, 需要重启时必须调用同步 */ @@ -45,9 +45,19 @@ #define HFLASH_TIMER_ID 0 #endif -///< 同步时间ms -#ifndef HFLASH_SYNC_TIME -#define HFLASH_SYNC_TIME 2000 +///< 同步缓存页时间ms +#ifndef HFLASH_SYNC_CACHE_PAGE_TIME +#define HFLASH_SYNC_CACHE_PAGE_TIME 600 +#endif + +///< 同步页表信息时间ms +#ifndef HFLASH_SYNC_PAGE_INFO_TIME +#define HFLASH_SYNC_PAGE_INFO_TIME 800 +#endif + +///< 同步备份页表信息时间ms +#ifndef HFLASH_SYNC_BACKUP_TIME +#define HFLASH_SYNC_BACKUP_TIME 1000 #endif ///< Flash地址类型 @@ -177,7 +187,7 @@ uint8_t HFlashWrite(HFlashAddr_t addr, const void *data, uint32_t size); uint8_t HFlashWriteOffset(HFlashAddr_t addr, uint32_t offset, const void *data, uint32_t size); /** - * @brief HFlashWriteRawOffset 写入原始地址偏移后的位置写入Flash数据, 超出部分不自动填充, 延后计算CRC, 仅提供给一些库使用, 请勿使用 + * @brief HFlashWriteRawOffset 写入原始地址偏移后的位置写入Flash数据, 超出部分不自动填充, 仅提供给一些库使用, 正常情况请勿使用 * @param addr 需要注册的地址 * @param offset 地址偏移 * @param data 写入数据 @@ -297,4 +307,9 @@ uint32_t HFlashGetCrc32(HFlashAddr_t addr); */ uint32_t HFlashCalcCrc32(HFlashAddr_t addr); +/** + * @brief HFlashSync 执行同步写入Flash数据, 在重启前需要执行 + */ +void HFlashSync(); + #endif // __H_FLASH_SERVER_H__ diff --git a/src/HFlashServer.c b/src/HFlashServer.c index fef1768..14e7cad 100644 --- a/src/HFlashServer.c +++ b/src/HFlashServer.c @@ -72,7 +72,6 @@ union PageInfo { uint32_t crc32; ///< 页表内容的CRC32校验值 uint32_t pageNum : 19; ///< 可用页数量 uint32_t useNum : 19; ///< 已使用页数量 - uint32_t needBackupPage : 1; ///< 是否需要备份页表 }; }; @@ -97,19 +96,20 @@ static union PageInfo sPageInfo; // 备份定时器 static HTimer_t sBackupTimer = HTIMER_INVALID; -// 延后计算CRC定时器 -static HTimer_t sDelayCrc32Timer = HTIMER_INVALID; +// 同步页定时器 +static HTimer_t sSyncPageTimer = HTIMER_INVALID; + +// 同步定时器 +static HTimer_t sSyncCacheTimer = 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 void StartSyncBackupTimer(); static HFlashCacheInfo *FindCache(HFlashAddr_t addr); static void WriteCachePage(HFlashCacheInfo *info); +static uint32_t GetFlashCrc32(HFlashAddr_t addr, uint32_t size); ///< 检查地址是否在双备份保护区内 static uint8_t IsProtect(HFlashAddr_t addr, uint32_t size) @@ -298,17 +298,12 @@ static void SyncBackup() sBackupTimer = HTIMER_INVALID; } - // 需要备份的数据为空, 说明是二次调用, 上次已经同步了 - if (HVectorEmpty(sNeedBackupOffset) && sPageInfo.needBackupPage == 0) { - return ; - } - for (uint16_t i = 0; i < HVectorGetUseLen(sNeedBackupOffset); ++i) { const uint32_t addr = HVectorGetData(sNeedBackupOffset, i); const uint32_t destAddr = sInfo.protectBackupAddr + (addr - sInfo.protectAddr); if (RestoreBackup(addr, destAddr, HFLASH_BLOCK_SIZE) == 0) { LogE("RestorePage faild, addr[0x%08x]", addr); - StartBackupTimer(); + StartSyncBackupTimer(); return ; } } @@ -316,18 +311,21 @@ static void SyncBackup() HVectorClear(sNeedBackupOffset); // 备份页表数据 - RestoreBackup(sInfo.pageAddr, sInfo.pageBackupAddr, AdjustPageByte(sPageInfo.useNum + 1)); - sPageInfo.needBackupPage = 0; + const uint32_t crcValue = GetFlashCrc32(AdjustPageAddr(sInfo.pageBackupAddr), AdjustPageByte(sPageInfo.useNum)); + if (crcValue != sPageInfo.crc32) { + RestoreBackup(sInfo.pageAddr, sInfo.pageBackupAddr, AdjustPageByte(sPageInfo.useNum + 1)); + } + LogD("Sync Backup End"); } -static void StartBackupTimer() +static void StartSyncBackupTimer() { if (sBackupTimer != HTIMER_INVALID) { HTimerRemove(sBackupTimer); sBackupTimer = HTIMER_INVALID; } - sBackupTimer = HTimerAdd(HFLASH_TIMER_ID, HFLASH_SYNC_TIME, SyncBackup, kHTimerOnce); + sBackupTimer = HTimerAdd(HFLASH_TIMER_ID, HFLASH_SYNC_BACKUP_TIME, SyncBackup, kHTimerOnce); } static void _AddBackupAddr(uint32_t addr) @@ -351,7 +349,7 @@ static void _AddBackupAddr(uint32_t addr) } while (0); LogD("Add wait sync addr[0x%08x], size[%d]", addr, HVectorGetUseLen(sNeedBackupOffset)); - StartBackupTimer(); + StartSyncBackupTimer(); } static void AddBackupAddr(uint32_t addr, uint32_t size) @@ -404,57 +402,6 @@ 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 copySize) { if (copySize == 0) { @@ -540,12 +487,32 @@ static uint8_t RestorePage(uint32_t index) return RestoreBackup(srcAddr, dstAddr, sizeof(HFlashPageInfo)); } -static void UpdatePageInfo() +static void SyncPageInfo() { - sPageInfo.crc32 = GetFlashCrc32(AdjustPageAddr(sInfo.pageAddr), AdjustPageByte(sPageInfo.useNum)); - WriteFlash(sInfo.pageAddr, &sPageInfo, sizeof(sPageInfo)); + if (sSyncPageTimer != HTIMER_INVALID) { + HTimerRemove(sSyncPageTimer); + sSyncPageTimer = HTIMER_INVALID; + } - sPageInfo.needBackupPage = 1; + const uint32_t crcValue = GetFlashCrc32(AdjustPageAddr(sInfo.pageAddr), AdjustPageByte(sPageInfo.useNum)); + if (crcValue == sPageInfo.crc32) { + return; + } + + sPageInfo.crc32 = crcValue;; + WriteFlash(sInfo.pageAddr, &sPageInfo, sizeof(sPageInfo)); + StartSyncBackupTimer(); +} + +static void StartSyncPageInfo() +{ + if (sSyncPageTimer != HTIMER_INVALID) { + HTimerRemove(sSyncPageTimer); + sSyncPageTimer = HTIMER_INVALID; + } + + sSyncPageTimer = HTimerAdd(HFLASH_TIMER_ID, HFLASH_SYNC_PAGE_INFO_TIME, SyncPageInfo, kHTimerOnce); + StartSyncBackupTimer(); } static void ReadPage(uint32_t index, HFlashPageInfo *info) @@ -568,15 +535,50 @@ static void WritePage(uint32_t index, HFlashPageInfo *info) const HFlashAddr_t addr = AdjustPageAddrOffset(sInfo.pageAddr, index); WriteFlash(addr, info, sizeof(HFlashPageInfo)); + StartSyncPageInfo(); +} - UpdatePageInfo(); + +static void SyncCachePage() +{ + if (sSyncCacheTimer != HTIMER_INVALID) { + HTimerRemove(sSyncCacheTimer); + sSyncCacheTimer = HTIMER_INVALID; + } + + for (uint32_t i = 0; i < sInfo.pageCacheUseNum; ++i) { + // 更新Crc32 + if (sInfo.pageCache[i].waitCrc) { + sInfo.pageCache[i].waitCrc = 0; + sInfo.pageCache[i].info.crc32 = GetFlashCrc32(sInfo.pageCache[i].info.addr, sInfo.pageCache[i].info.useSize); + sInfo.pageCache[i].waitWrite = 1; + } + + // 写入页表 + if (sInfo.pageCache[i].waitWrite) { + WritePage(sInfo.pageCache[i].pos, &sInfo.pageCache[i].info); + } + } + + StartSyncPageInfo(); +} + +static void StartSyncCachePage() +{ + if (sSyncCacheTimer != HTIMER_INVALID) { + HTimerRemove(sSyncCacheTimer); + sSyncCacheTimer = HTIMER_INVALID; + } + + sSyncCacheTimer = HTimerAdd(HFLASH_TIMER_ID, HFLASH_SYNC_CACHE_PAGE_TIME, SyncCachePage, kHTimerOnce); + StartSyncPageInfo(); } static void WriteCachePage(HFlashCacheInfo *info) { ++info->info.modifyCount; - info->waitWrite = 0; - WritePage(info->pos, &info->info); + info->waitWrite = 1; + StartSyncCachePage(); } /// 检查是否重叠, 重叠返回1, 非重叠返回0 @@ -770,9 +772,16 @@ static HFlashCacheInfo *FindCache(HFlashAddr_t addr) ++sInfo.pageCacheUseNum; } + // 更新Crc32 + if (sInfo.pageCache[index].waitCrc) { + sInfo.pageCache[index].info.crc32 = GetFlashCrc32(sInfo.pageCache[index].info.addr, sInfo.pageCache[index].info.useSize); + sInfo.pageCache[index].waitWrite = 1; + } + // 如果是延迟写入的, 需要先写入再替换 if (sInfo.pageCache[index].waitWrite) { - WriteCachePage(&sInfo.pageCache[index]); + WritePage(sInfo.pageCache[index].pos, &sInfo.pageCache[index].info); + sInfo.pageCache[index].waitWrite = 0; } memcpy(&sInfo.pageCache[index], &cache, sizeof(HFlashCacheInfo)); @@ -904,7 +913,7 @@ static void Shell(HSHELL_FUNC_ARGS) } sPageInfo.useNum = arg1; - UpdatePageInfo(); + SyncPageInfo(); } break; default: break; @@ -998,8 +1007,7 @@ void HFlashRegister(HFlashAddr_t addr, uint32_t size) LogE("Create addr[0x%08x] size[%d] faild", addr, size); } - sPageInfo.needBackupPage = 1; - StartBackupTimer(); + StartSyncBackupTimer(); return ; } @@ -1135,13 +1143,8 @@ static uint8_t WriteOffset(HFlashAddr_t addr, uint32_t offset, const void *data, } result = WriteFlash(addr + offset, data, size); - if (needSetZero) { - cache->info.crc32 = GetFlashCrc32(addr, cache->info.useSize); - WriteCachePage(cache); - } else { - cache->waitWrite = 1; - AddDelayCrc32(addr); - } + cache->waitCrc = 1; + WriteCachePage(cache); // 检查是否在保护区域, 需要的话需要写入等待备份 if (IsProtect(addr, size)) { @@ -1170,6 +1173,7 @@ void HFlashStreamBegin(HFlashAddr_t addr) } cache->waitWrite = 1; + cache->waitCrc = 1; cache->info.crc32 = 0xFFFFFFFF; cache->info.useSize = 0; } @@ -1190,6 +1194,7 @@ uint8_t HFlashStreamWrite(HFlashAddr_t addr, const void *data, uint32_t size) result = WriteFlash(addr + cache->info.useSize, data, size); cache->waitWrite = 1; + cache->waitCrc = 1; cache->info.useSize += size; ++cache->info.modifyCount; return result; @@ -1203,8 +1208,8 @@ void HFlashStreamEnd(HFlashAddr_t addr) return ; } - cache->waitWrite = 0; cache->info.crc32 = GetFlashCrc32(addr, cache->info.useSize); + cache->waitCrc = 0; if (IsProtect(addr, cache->info.useSize)) { AddBackupAddr(addr, cache->info.useSize); } @@ -1279,16 +1284,12 @@ void HFlashUpdateVersion(HFlashAddr_t addr, uint16_t newVersion, HFlashUpdateVer } const uint16_t oldVersion = cache->info.version; - cache->waitWrite = 1; cache->info.version = newVersion; if (callback) { callback(addr, oldVersion, newVersion, userData); } - // 如果回调没有进行页写入, 需要进行页写入 - if (cache->waitWrite) { - WriteCachePage(cache); - } + WriteCachePage(cache); } void HFlashDeleteData(HFlashAddr_t addr) @@ -1347,3 +1348,9 @@ uint32_t HFlashCalcCrc32(HFlashAddr_t addr) return GetFlashCrc32(addr, cache->info.useSize); } +void HFlashSync() +{ + SyncCachePage(); + SyncPageInfo(); + SyncBackup(); +}