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
* : 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__

View File

@ -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);
// 备份页表数据
const uint32_t crcValue = GetFlashCrc32(AdjustPageAddr(sInfo.pageBackupAddr), AdjustPageByte(sPageInfo.useNum));
if (crcValue != sPageInfo.crc32) {
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) {
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);
cache->waitCrc = 1;
WriteCachePage(cache);
} else {
cache->waitWrite = 1;
AddDelayCrc32(addr);
}
// 检查是否在保护区域, 需要的话需要写入等待备份
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,17 +1284,13 @@ 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);
}
}
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();
}