1. 修改使用延迟写入缓存, 写入页, 写入备份

This commit is contained in:
coffee 2025-12-06 09:54:51 +08:00
parent 247e211168
commit 176709e37d
2 changed files with 120 additions and 98 deletions

View File

@ -1,7 +1,7 @@
/** /**
* : 2025-11-27 * : 2025-11-27
* : coffee * : coffee
* : Flash通用服务模块, Flash操作的完备性, * : Flash通用服务模块, Flash操作的完备性, , 使,
*/ */
@ -45,9 +45,19 @@
#define HFLASH_TIMER_ID 0 #define HFLASH_TIMER_ID 0
#endif #endif
///< 同步时间ms ///< 同步缓存页时间ms
#ifndef HFLASH_SYNC_TIME #ifndef HFLASH_SYNC_CACHE_PAGE_TIME
#define HFLASH_SYNC_TIME 2000 #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 #endif
///< Flash地址类型 ///< 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); 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 addr
* @param offset * @param offset
* @param data * @param data
@ -297,4 +307,9 @@ uint32_t HFlashGetCrc32(HFlashAddr_t addr);
*/ */
uint32_t HFlashCalcCrc32(HFlashAddr_t addr); uint32_t HFlashCalcCrc32(HFlashAddr_t addr);
/**
* @brief HFlashSync Flash数据,
*/
void HFlashSync();
#endif // __H_FLASH_SERVER_H__ #endif // __H_FLASH_SERVER_H__

View File

@ -72,7 +72,6 @@ union PageInfo {
uint32_t crc32; ///< 页表内容的CRC32校验值 uint32_t crc32; ///< 页表内容的CRC32校验值
uint32_t pageNum : 19; ///< 可用页数量 uint32_t pageNum : 19; ///< 可用页数量
uint32_t useNum : 19; ///< 已使用页数量 uint32_t useNum : 19; ///< 已使用页数量
uint32_t needBackupPage : 1; ///< 是否需要备份页表
}; };
}; };
@ -97,19 +96,20 @@ static union PageInfo sPageInfo;
// 备份定时器 // 备份定时器
static HTimer_t sBackupTimer = HTIMER_INVALID; 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); 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 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 HFlashCacheInfo *FindCache(HFlashAddr_t addr);
static void WriteCachePage(HFlashCacheInfo *info); 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) static uint8_t IsProtect(HFlashAddr_t addr, uint32_t size)
@ -298,17 +298,12 @@ static void SyncBackup()
sBackupTimer = HTIMER_INVALID; sBackupTimer = HTIMER_INVALID;
} }
// 需要备份的数据为空, 说明是二次调用, 上次已经同步了
if (HVectorEmpty(sNeedBackupOffset) && sPageInfo.needBackupPage == 0) {
return ;
}
for (uint16_t i = 0; i < HVectorGetUseLen(sNeedBackupOffset); ++i) { for (uint16_t i = 0; i < HVectorGetUseLen(sNeedBackupOffset); ++i) {
const uint32_t addr = HVectorGetData(sNeedBackupOffset, i); const uint32_t addr = HVectorGetData(sNeedBackupOffset, i);
const uint32_t destAddr = sInfo.protectBackupAddr + (addr - sInfo.protectAddr); const uint32_t destAddr = sInfo.protectBackupAddr + (addr - sInfo.protectAddr);
if (RestoreBackup(addr, destAddr, HFLASH_BLOCK_SIZE) == 0) { if (RestoreBackup(addr, destAddr, HFLASH_BLOCK_SIZE) == 0) {
LogE("RestorePage faild, addr[0x%08x]", addr); LogE("RestorePage faild, addr[0x%08x]", addr);
StartBackupTimer(); StartSyncBackupTimer();
return ; return ;
} }
} }
@ -316,18 +311,21 @@ static void SyncBackup()
HVectorClear(sNeedBackupOffset); HVectorClear(sNeedBackupOffset);
// 备份页表数据 // 备份页表数据
const uint32_t crcValue = GetFlashCrc32(AdjustPageAddr(sInfo.pageBackupAddr), AdjustPageByte(sPageInfo.useNum));
if (crcValue != sPageInfo.crc32) {
RestoreBackup(sInfo.pageAddr, sInfo.pageBackupAddr, AdjustPageByte(sPageInfo.useNum + 1)); RestoreBackup(sInfo.pageAddr, sInfo.pageBackupAddr, AdjustPageByte(sPageInfo.useNum + 1));
sPageInfo.needBackupPage = 0; }
LogD("Sync Backup End");
} }
static void StartBackupTimer() static void StartSyncBackupTimer()
{ {
if (sBackupTimer != HTIMER_INVALID) { if (sBackupTimer != HTIMER_INVALID) {
HTimerRemove(sBackupTimer); HTimerRemove(sBackupTimer);
sBackupTimer = HTIMER_INVALID; 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) static void _AddBackupAddr(uint32_t addr)
@ -351,7 +349,7 @@ static void _AddBackupAddr(uint32_t addr)
} while (0); } while (0);
LogD("Add wait sync addr[0x%08x], size[%d]", addr, HVectorGetUseLen(sNeedBackupOffset)); LogD("Add wait sync addr[0x%08x], size[%d]", addr, HVectorGetUseLen(sNeedBackupOffset));
StartBackupTimer(); StartSyncBackupTimer();
} }
static void AddBackupAddr(uint32_t addr, uint32_t size) 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(); 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) static uint8_t RestoreBackup(HFlashAddr_t srcAddr, HFlashAddr_t dstAddr, uint32_t copySize)
{ {
if (copySize == 0) { if (copySize == 0) {
@ -540,12 +487,32 @@ static uint8_t RestorePage(uint32_t index)
return RestoreBackup(srcAddr, dstAddr, sizeof(HFlashPageInfo)); return RestoreBackup(srcAddr, dstAddr, sizeof(HFlashPageInfo));
} }
static void UpdatePageInfo() static void SyncPageInfo()
{ {
sPageInfo.crc32 = GetFlashCrc32(AdjustPageAddr(sInfo.pageAddr), AdjustPageByte(sPageInfo.useNum)); if (sSyncPageTimer != HTIMER_INVALID) {
WriteFlash(sInfo.pageAddr, &sPageInfo, sizeof(sPageInfo)); 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) 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); const HFlashAddr_t addr = AdjustPageAddrOffset(sInfo.pageAddr, index);
WriteFlash(addr, info, sizeof(HFlashPageInfo)); 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) static void WriteCachePage(HFlashCacheInfo *info)
{ {
++info->info.modifyCount; ++info->info.modifyCount;
info->waitWrite = 0; info->waitWrite = 1;
WritePage(info->pos, &info->info); StartSyncCachePage();
} }
/// 检查是否重叠, 重叠返回1, 非重叠返回0 /// 检查是否重叠, 重叠返回1, 非重叠返回0
@ -770,9 +772,16 @@ static HFlashCacheInfo *FindCache(HFlashAddr_t addr)
++sInfo.pageCacheUseNum; ++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) { 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)); memcpy(&sInfo.pageCache[index], &cache, sizeof(HFlashCacheInfo));
@ -904,7 +913,7 @@ static void Shell(HSHELL_FUNC_ARGS)
} }
sPageInfo.useNum = arg1; sPageInfo.useNum = arg1;
UpdatePageInfo(); SyncPageInfo();
} break; } break;
default: default:
break; break;
@ -998,8 +1007,7 @@ void HFlashRegister(HFlashAddr_t addr, uint32_t size)
LogE("Create addr[0x%08x] size[%d] faild", addr, size); LogE("Create addr[0x%08x] size[%d] faild", addr, size);
} }
sPageInfo.needBackupPage = 1; StartSyncBackupTimer();
StartBackupTimer();
return ; return ;
} }
@ -1135,13 +1143,8 @@ static uint8_t WriteOffset(HFlashAddr_t addr, uint32_t offset, const void *data,
} }
result = WriteFlash(addr + offset, data, size); result = WriteFlash(addr + offset, data, size);
if (needSetZero) { cache->waitCrc = 1;
cache->info.crc32 = GetFlashCrc32(addr, cache->info.useSize);
WriteCachePage(cache); WriteCachePage(cache);
} else {
cache->waitWrite = 1;
AddDelayCrc32(addr);
}
// 检查是否在保护区域, 需要的话需要写入等待备份 // 检查是否在保护区域, 需要的话需要写入等待备份
if (IsProtect(addr, size)) { if (IsProtect(addr, size)) {
@ -1170,6 +1173,7 @@ void HFlashStreamBegin(HFlashAddr_t addr)
} }
cache->waitWrite = 1; cache->waitWrite = 1;
cache->waitCrc = 1;
cache->info.crc32 = 0xFFFFFFFF; cache->info.crc32 = 0xFFFFFFFF;
cache->info.useSize = 0; 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); result = WriteFlash(addr + cache->info.useSize, data, size);
cache->waitWrite = 1; cache->waitWrite = 1;
cache->waitCrc = 1;
cache->info.useSize += size; cache->info.useSize += size;
++cache->info.modifyCount; ++cache->info.modifyCount;
return result; return result;
@ -1203,8 +1208,8 @@ void HFlashStreamEnd(HFlashAddr_t addr)
return ; return ;
} }
cache->waitWrite = 0;
cache->info.crc32 = GetFlashCrc32(addr, cache->info.useSize); cache->info.crc32 = GetFlashCrc32(addr, cache->info.useSize);
cache->waitCrc = 0;
if (IsProtect(addr, cache->info.useSize)) { if (IsProtect(addr, cache->info.useSize)) {
AddBackupAddr(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; const uint16_t oldVersion = cache->info.version;
cache->waitWrite = 1;
cache->info.version = newVersion; cache->info.version = newVersion;
if (callback) { if (callback) {
callback(addr, oldVersion, newVersion, userData); callback(addr, oldVersion, newVersion, userData);
} }
// 如果回调没有进行页写入, 需要进行页写入
if (cache->waitWrite) {
WriteCachePage(cache); WriteCachePage(cache);
}
} }
void HFlashDeleteData(HFlashAddr_t addr) void HFlashDeleteData(HFlashAddr_t addr)
@ -1347,3 +1348,9 @@ uint32_t HFlashCalcCrc32(HFlashAddr_t addr)
return GetFlashCrc32(addr, cache->info.useSize); return GetFlashCrc32(addr, cache->info.useSize);
} }
void HFlashSync()
{
SyncCachePage();
SyncPageInfo();
SyncBackup();
}