From a4795e62c9d88ec4350bde78bd572ede30df4f87 Mon Sep 17 00:00:00 2001 From: coffee Date: Thu, 25 Dec 2025 23:40:02 +0800 Subject: [PATCH] =?UTF-8?q?1.=20=E5=A2=9E=E5=8A=A0=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E5=85=8D=E8=AF=BB=E5=8F=96=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/HFlashMem.h | 8 +++- include/HFlashServer.h | 26 ++++++++----- src/HFlashMem.c | 85 +++++++++++++++++++++++------------------- src/HFlashServer.c | 79 +++++++++++++++++++++++++-------------- 4 files changed, 120 insertions(+), 78 deletions(-) diff --git a/include/HFlashMem.h b/include/HFlashMem.h index a824a3c..c253bb2 100644 --- a/include/HFlashMem.h +++ b/include/HFlashMem.h @@ -39,11 +39,12 @@ typedef struct HFlashMemOpts { uint8_t (*read)(uint32_t addr, void *buf, uint32_t len); ///< 读取Flash uint8_t (*write)(uint32_t addr, const void *buf, uint32_t len); ///< 写入Flash - uint8_t (*ioctl)(uint32_t aadr, uint32_t cmd, void *arg); ///< 控制Flash, 需要外部实现以上eHFlashMemIO指令 + uint8_t (*ioctl)(uint32_t addr, uint32_t cmd, void *arg); ///< 控制Flash, 需要外部实现以上eHFlashMemIO指令 uint8_t *mem; ///< Flash映射内存, 需要4k倍数 HFlashMemCache *cache; ///< 内存缓存 uint16_t memSize; ///< Flash映射内存大小 uint16_t cacheSize; ///< 内存缓存大小 + uint32_t flashSize; ///< Flash大小 } HFlashMemOpts; /** @@ -52,6 +53,11 @@ typedef struct HFlashMemOpts */ void HFlashMemInit(HFlashMemOpts *opts); +/** + * @brief 获取Flash内存操作信息 + */ +const HFlashMemOpts *HFlashMemGetOpt(); + /** * @brief 读取Flash * @param addr 读取地址 diff --git a/include/HFlashServer.h b/include/HFlashServer.h index 05f50df..2c52880 100644 --- a/include/HFlashServer.h +++ b/include/HFlashServer.h @@ -12,12 +12,16 @@ #include -#ifndef USE_STD_MEM -#include "HDSendBuffer.h" +///< 使用Flash内存映射功能 +#ifndef HFLASH_NOT_USE_FLASH_MEM +#define HFLASH_USE_FLASH_MEM #endif -///< 使用Flash内存映射功能 -#define USE_FLASH_MEM +#ifndef USE_STD_MEM +#ifndef HFLASH_USE_FLASH_MEM +#include "HDSendBuffer.h" +#endif // HFLASH_USE_FLASH_MEM +#endif ///< Flash块大小, 按块操作, 2的幂关系 #ifndef HFLASH_BLOCK_SIZE @@ -25,13 +29,14 @@ #endif ///< 获取缓存内存, 需要能申请到大于等于(Flash一块大小) +#ifndef HFLASH_USE_FLASH_MEM #ifndef HFLASH_MALLOC #ifdef USE_STD_MEM #define HFLASH_MALLOC(size) malloc(size) #else #define HFLASH_MALLOC(size) HDSendBufferGet(size) -#endif -#endif +#endif // USE_STD_MEM +#endif // HFLASH_MALLOC ///< 释放缓存 #ifndef HFLASH_FREE @@ -39,8 +44,9 @@ #define HFLASH_FREE(ptr) free(ptr) #else #define HFLASH_FREE(ptr) HDSendBufferFree(ptr) -#endif -#endif +#endif // USE_STD_MEM +#endif // HFLASH_FREE +#endif // HFLASH_USE_FLASH_MEM ///< 定时器ID #ifndef HFLASH_TIMER_ID @@ -102,7 +108,7 @@ typedef uint8_t (*HFlashEraseCallback)(HFlashAddr_t addr); * @param size 缓存大小 * @return 1: 读取成功 0: 读取失败 */ -typedef uint8_t (*HFlashReadCallback)(HFlashAddr_t addr, uint8_t *data, uint32_t size); +typedef uint8_t (*HFlashReadCallback)(HFlashAddr_t addr, void *data, uint32_t size); /** * @brief HFlashWriteCallback 写入回调 @@ -111,7 +117,7 @@ typedef uint8_t (*HFlashReadCallback)(HFlashAddr_t addr, uint8_t *data, uint32_t * @param size 缓存大小 * @return 1: 写入成功 0: 写入失败 */ -typedef uint8_t (*HFlashWriteCallback)(HFlashAddr_t addr, uint8_t *data, uint32_t size); +typedef uint8_t (*HFlashWriteCallback)(HFlashAddr_t addr, const void *data, uint32_t size); /** * @brief HFlashInitCallback 设置Flash初始化回调 diff --git a/src/HFlashMem.c b/src/HFlashMem.c index 8d6b6ed..a5bf592 100644 --- a/src/HFlashMem.c +++ b/src/HFlashMem.c @@ -54,7 +54,7 @@ static inline uint8_t *GetMMap(uint16_t offset) { return (uint8_t *)sOpts->mem + offset * HFLASH_BLOCK_SIZE; } -static void SyncCache() +static void WatiErase() { // 如果存在异步等待擦除的, 先等擦除完成 if (sInfo.needWaitErase) { @@ -68,7 +68,11 @@ static void SyncCache() sInfo.needWaitErase = 0; } +} +static void SyncCache() +{ + WatiErase(); for (uint16_t i = 0; i < sInfo.useNum; ++i) { if (sOpts->cache[i].isDirty == 0) { continue; @@ -149,33 +153,16 @@ static void StartSyncCache() } sCheckTimer = HTimerAdd(HFLASH_TIMER_ID, 0, CheckSyncCache, kHTimerLoop); - - // 如果已经在擦除中, 就不需要立刻通知擦除 - if (sInfo.needWaitErase) { - return ; - } - - for (uint16_t i = 0; i < sInfo.useNum; ++i) { - if (sOpts->cache[i].isDirty == 0) { - continue; - } - - if (sOpts->cache[i].eraseStatus != kEraseWait) { - continue; - } - - // 找到一个, 立刻进入擦除状态 - sInfo.needWaitErase = 1; - sOpts->cache[i].eraseStatus = kEraseStart; - sOpts->ioctl(sOpts->cache[i].addr, kHFlashMemIOErase, NULL); - return ; - } - } -static HFlashMemCache *FindCache(uint32_t addr, uint8_t create) +static HFlashMemCache *FindCache(uint32_t addr, uint8_t create, uint8_t needRead) { addr = Align4K(addr); + if (addr + HFLASH_BLOCK_SIZE > sOpts->flashSize) { + LogE("flash addr[0x%08x] size[%d] overflow", addr, sOpts->flashSize); + return 0; + } + for (uint16_t i = 0; i < sInfo.useNum; ++i) { if (addr != sOpts->cache[i].addr) { continue; @@ -193,9 +180,12 @@ static HFlashMemCache *FindCache(uint32_t addr, uint8_t create) if (sInfo.useNum < sOpts->cacheSize) { const uint16_t index = sInfo.useNum; ++sInfo.useNum; - if (sOpts->read(addr, GetMMap(index), HFLASH_BLOCK_SIZE) == 0) { - LogE("addr[0x%08x], read faild", addr); - return NULL; + if (needRead) { + WatiErase(); + if (sOpts->read(addr, GetMMap(index), HFLASH_BLOCK_SIZE) == 0) { + LogE("addr[0x%08x], read faild", addr); + return NULL; + } } memset(sOpts->cache + index, 0, sizeof(HFlashMemCache)); @@ -215,7 +205,6 @@ static HFlashMemCache *FindCache(uint32_t addr, uint8_t create) // 寻找最小热度, 同时空闲的降低温度 const uint8_t currHeat = sOpts->cache[i].heat; sOpts->cache[i].heat >>= 1; - LogD("CurrHead[%d], updateHeat[%d]", currHeat, sOpts->cache[i].heat); if (index == -1) { index = i; minHeat = currHeat; @@ -231,10 +220,13 @@ static HFlashMemCache *FindCache(uint32_t addr, uint8_t create) } if (index != -1) { - // 找到一个空闲且最低温度的 - if (sOpts->read(addr, GetMMap(index), HFLASH_BLOCK_SIZE) == 0) { - LogE("addr[0x%08x], read faild", addr); - return NULL; + if (needRead) { + WatiErase(); + // 找到一个空闲且最低温度的 + if (sOpts->read(addr, GetMMap(index), HFLASH_BLOCK_SIZE) == 0) { + LogE("addr[0x%08x], read faild", addr); + return NULL; + } } memset(sOpts->cache + index, 0, sizeof(HFlashMemCache)); @@ -245,14 +237,14 @@ static HFlashMemCache *FindCache(uint32_t addr, uint8_t create) // 如果在创建模式下, 没有一个空闲的缓存, 就需要先同步脏页, 再获取一个 HFlashMemSync(); - return FindCache(addr, create); + return FindCache(addr, create, needRead); } static uint8_t WriteData(uint32_t addr, const void *buf, uint32_t len, void (*cpCall)(void *dest, const void *src, uint32_t len, void *userData), void *userData) { uint32_t adjustAddr = Align4K(addr); - HFlashMemCache *cache = FindCache(adjustAddr, 1); + HFlashMemCache *cache = FindCache(adjustAddr, 1, (addr != adjustAddr || len < HFLASH_BLOCK_SIZE)); if (cache == NULL) { LogE("addr[0x%08x], write len[%d] faild", addr, len); return 0; @@ -274,7 +266,7 @@ static uint8_t WriteData(uint32_t addr, const void *buf, uint32_t len, void (*cp adjustAddr += HFLASH_BLOCK_SIZE; for (; len >= HFLASH_BLOCK_SIZE; adjustAddr += HFLASH_BLOCK_SIZE, len -= HFLASH_BLOCK_SIZE, bufPtr += HFLASH_BLOCK_SIZE) { - cache = FindCache(adjustAddr, 1); + cache = FindCache(adjustAddr, 1, 0); if (cache == NULL) { LogE("addr[0x%08x], write len[%d] faild", adjustAddr, len); return 0; @@ -285,7 +277,7 @@ static uint8_t WriteData(uint32_t addr, const void *buf, uint32_t len, void (*cp } if (len) { - cache = FindCache(adjustAddr, 1); + cache = FindCache(adjustAddr, 1, 1); if (cache == NULL) { LogE("addr[0x%08x], write len[%d] faild", adjustAddr, len); return 0; @@ -315,6 +307,16 @@ void HFlashMemInit(HFlashMemOpts *opts) FATAL_ERROR("cache is null"); return ; } + + if (IS_4K(sOpts->flashSize) == 0) { + FATAL_ERROR("flash Size not 4k align"); + return ; + } +} + +const HFlashMemOpts *HFlashMemGetOpt() +{ + return sOpts; } uint8_t HFlashMemRead(uint32_t addr, void *buf, uint32_t len) @@ -333,11 +335,16 @@ uint8_t HFlashMemRead(uint32_t addr, void *buf, uint32_t len) const uint32_t offset = addr - pageAddr; const uint32_t remain = HFLASH_BLOCK_SIZE - offset; const uint32_t copyLen = len > remain ? remain : len; - HFlashMemCache *cache = FindCache(pageAddr, 0); + if (pageAddr + HFLASH_BLOCK_SIZE > sOpts->flashSize) { + LogE("flash addr[0x%08x] size[%d] overflow", pageAddr, sOpts->flashSize); + return 0; + } + HFlashMemCache *cache = FindCache(pageAddr, 0, 1); if (cache) { memcpy(p, GetMMap(cache->offset) + offset, copyLen); } else { + WatiErase(); if (sOpts->read(addr, p, copyLen) == 0) { LogE("addr[0x%08x], read faild", addr); return 0; @@ -414,7 +421,7 @@ uint8_t HFlashMemMMapCall(uint32_t addr, uint8_t(*call)(uint32_t addr, uint32_t // 先处理未对齐的部分 if (addr != Align4K(addr)) { - cache = FindCache(addr + offset, 1); + cache = FindCache(addr + offset, 1, 1); if (cache == NULL) { LogE("addr[0x%08x], find cache faild", addr); return 0; @@ -431,7 +438,7 @@ uint8_t HFlashMemMMapCall(uint32_t addr, uint8_t(*call)(uint32_t addr, uint32_t // 剩余处理对齐部分 while (result == 0) { - cache = FindCache(addr + offset, 1); + cache = FindCache(addr + offset, 1, 1); if (cache == NULL) { LogE("addr[0x%08x], find cache faild", addr + offset); return 0; diff --git a/src/HFlashServer.c b/src/HFlashServer.c index 5f0963f..65a5fed 100644 --- a/src/HFlashServer.c +++ b/src/HFlashServer.c @@ -7,12 +7,14 @@ #include "HShellLex.h" #include -#ifdef USE_FLASH_MEM +#ifdef HFLASH_USE_FLASH_MEM #include "HFlashMem.h" #endif #ifndef USE_STD_MEM +#ifndef HFLASH_USE_FLASH_MEM #include "HDSendBuffer.h" +#endif // HFLASH_USE_FLASH_MEM #include "HSCrc32.h" #endif @@ -65,6 +67,10 @@ enum eShell kShellDelUseDataPage, ///< 删除页表使用数据 kShellDelPage, ///< 删除页 kShellResetPage, ///< 重置页 + kShellRestorePage, ///< 恢复页 +#ifdef HFLASH_USE_FLASH_MEM + kShellFlashMemInfo, ///< 查看flash内存信息 +#endif kShellMax, }; @@ -73,6 +79,10 @@ static HShellMatch sShellMatch[] = { HSHELL_MATCH_ITEM(kShellDelUseDataPage, "pageDelUseData"), HSHELL_MATCH_ITEM(kShellDelPage, "pageDel"), HSHELL_MATCH_ITEM(kShellResetPage, "pageReset"), + HSHELL_MATCH_ITEM(kShellRestorePage, "pageRestore"), +#ifdef HFLASH_USE_FLASH_MEM + HSHELL_MATCH_ITEM(kShellFlashMemInfo, "flashMemInfo"), +#endif }; @@ -86,7 +96,7 @@ union PageInfo { }; struct Info { -#ifndef USE_FLASH_MEM +#ifndef HFLASH_USE_FLASH_MEM HFlashReadCallback read; ///< 读取回调 HFlashWriteCallback write; ///< 写入回调 HFlashEraseCallback erase; ///< 擦除回调 @@ -108,7 +118,7 @@ static union PageInfo sPageInfo; // 备份定时器 static HTimer_t sBackupTimer = HTIMER_INVALID; -#ifndef USE_FLASH_MEM +#ifndef HFLASH_USE_FLASH_MEM // 同步页定时器 static HTimer_t sSyncPageTimer = HTIMER_INVALID; @@ -151,7 +161,7 @@ static uint8_t ReadFlashCall(HFlashAddr_t addr, void *data, uint32_t size) if (size == 0) { return 1; } -#ifdef USE_FLASH_MEM +#ifdef HFLASH_USE_FLASH_MEM return HFlashMemRead(addr, data, size); #else if (sInfo.read == NULL) { @@ -159,12 +169,11 @@ static uint8_t ReadFlashCall(HFlashAddr_t addr, void *data, uint32_t size) return 0; } - uint8_t *dataPtr = (uint8_t *)data; - return sInfo.read(addr, dataPtr, size); + return sInfo.read(addr, data, size); #endif } -#ifndef USE_FLASH_MEM +#ifndef HFLASH_USE_FLASH_MEM static uint8_t EraseFlashCall(HFlashAddr_t addr) { if (sInfo.erase == NULL) { @@ -185,12 +194,11 @@ static uint8_t WriteFlashCall(HFlashAddr_t addr, const void *data, uint32_t size return 0; } - uint8_t *dataPtr = (uint8_t *)data; - return sInfo.write(addr, dataPtr, size); + return sInfo.write(addr, data, size); } #endif -#ifndef USE_FLASH_MEM +#ifndef HFLASH_USE_FLASH_MEM /** * @brief 写入数据到Flash * @param addr 写入的Flash地址 @@ -273,7 +281,7 @@ _flashError: } #endif -#ifndef USE_FLASH_MEM +#ifndef HFLASH_USE_FLASH_MEM static void _WriteFlashHelper(void *dest, const void *src, uint16_t buffSize, void *userData) { (void)userData; @@ -283,14 +291,14 @@ static void _WriteFlashHelper(void *dest, const void *src, uint16_t buffSize, vo static uint8_t WriteFlash(HFlashAddr_t addr, const void *data, uint32_t size) { -#ifdef USE_FLASH_MEM +#ifdef HFLASH_USE_FLASH_MEM return HFlashMemWrite(addr, data, size); #else return WriteData(addr, data, size, _WriteFlashHelper, NULL); #endif } -#ifndef USE_FLASH_MEM +#ifndef HFLASH_USE_FLASH_MEM static void _WriteFalshValueHelper(void *dest, const void *src, uint16_t size, void *userData) { uint8_t *value = (uint8_t *)userData; @@ -300,7 +308,7 @@ static void _WriteFalshValueHelper(void *dest, const void *src, uint16_t size, v static uint8_t WriteFlashValue(uint32_t addr, uint32_t size, uint8_t value) { -#ifdef USE_FLASH_MEM +#ifdef HFLASH_USE_FLASH_MEM return HFlashMemSetValue(addr, value, size); #else return WriteData(addr, NULL, size, _WriteFalshValueHelper, &value); @@ -422,7 +430,7 @@ static uint32_t GetFlashCrc32(HFlashAddr_t addr, uint32_t size) } HSCrc32Reset(); -#ifdef USE_FLASH_MEM +#ifdef HFLASH_USE_FLASH_MEM if (HFlashMemMMapCall(addr, _CalcCrc32, &size) == 0) { LogE("addr[0x%08x], size[%d] mmap faild", addr, size); return 0xFFFFFFFF; @@ -455,7 +463,7 @@ static uint8_t RestoreBackup(HFlashAddr_t srcAddr, HFlashAddr_t dstAddr, uint32_ LogD("addr[0x%08x], write size[%d] is 0", srcAddr, copySize); return 1; } -#ifdef USE_FLASH_MEM +#ifdef HFLASH_USE_FLASH_MEM return HFlashMemAddrCopy(srcAddr, dstAddr, copySize); #else uint8_t *buff = (uint8_t *)HFLASH_MALLOC(HFLASH_BLOCK_SIZE); @@ -539,7 +547,7 @@ static uint8_t RestorePage(uint32_t index) static void SyncPageInfo() { -#ifndef USE_FLASH_MEM +#ifndef HFLASH_USE_FLASH_MEM if (sSyncPageTimer != HTIMER_INVALID) { HTimerRemove(sSyncPageTimer); sSyncPageTimer = HTIMER_INVALID; @@ -556,7 +564,7 @@ static void SyncPageInfo() StartSyncBackupTimer(); } -#ifndef USE_FLASH_MEM +#ifndef HFLASH_USE_FLASH_MEM static void StartSyncPageInfo() { if (sSyncPageTimer != HTIMER_INVALID) { @@ -589,7 +597,7 @@ static void WritePage(uint32_t index, HFlashPageInfo *info) const HFlashAddr_t addr = AdjustPageAddrOffset(sInfo.pageAddr, index); WriteFlash(addr, info, sizeof(HFlashPageInfo)); -#ifdef USE_FLASH_MEM +#ifdef HFLASH_USE_FLASH_MEM SyncPageInfo(); #else StartSyncPageInfo(); @@ -599,7 +607,7 @@ static void WritePage(uint32_t index, HFlashPageInfo *info) static void SyncCachePage() { -#ifndef USE_FLASH_MEM +#ifndef HFLASH_USE_FLASH_MEM if (sSyncCacheTimer != HTIMER_INVALID) { HTimerRemove(sSyncCacheTimer); sSyncCacheTimer = HTIMER_INVALID; @@ -620,14 +628,14 @@ static void SyncCachePage() } } -#ifdef USE_FLASH_MEM +#ifdef HFLASH_USE_FLASH_MEM SyncPageInfo(); #else StartSyncPageInfo(); #endif } -#ifndef USE_FLASH_MEM +#ifndef HFLASH_USE_FLASH_MEM static void StartSyncCachePage() { if (sSyncCacheTimer != HTIMER_INVALID) { @@ -644,7 +652,7 @@ static void WriteCachePage(HFlashCacheInfo *info) { ++info->info.modifyCount; info->waitWrite = 1; -#ifdef USE_FLASH_MEM +#ifdef HFLASH_USE_FLASH_MEM SyncCachePage(); SyncPageInfo(); #else @@ -691,7 +699,7 @@ static uint8_t ScanPage(uint8_t (*call)(uint32_t index, HFlashPageInfo *info, vo return 0; } -#ifdef USE_FLASH_MEM +#ifdef HFLASH_USE_FLASH_MEM HFlashPageInfo page; uint8_t result = 0; for (uint32_t i = 0; i < sPageInfo.useNum; ++i) { @@ -883,7 +891,7 @@ static HFlashCacheInfo *FindCache(HFlashAddr_t addr) void HFlashInitCallback(HFlashReadCallback read, HFlashWriteCallback write, HFlashEraseCallback erase) { -#ifndef USE_FLASH_MEM +#ifndef HFLASH_USE_FLASH_MEM sInfo.read = read; sInfo.write = write; sInfo.erase = erase; @@ -974,7 +982,7 @@ static void Shell(HSHELL_FUNC_ARGS) 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); + HSHELL_PRINTFL("Cache index[%d], addr[0x%08x], useSize[0x%x][%d], size[0x%x][%d], modifyCount[%d], crc32[0x%x], version[%d], heat[%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, sInfo.pageCache[i].heat); } } break; case kShellDelUseDataPage: { @@ -1006,6 +1014,21 @@ static void Shell(HSHELL_FUNC_ARGS) sPageInfo.useNum = arg1; SyncPageInfo(); } break; + case kShellRestorePage: { + RestoreBackup(sInfo.pageAddr, sInfo.pageBackupAddr, AdjustPageByte(sPageInfo.pageNum + 1)); + } break; +#ifdef HFLASH_USE_FLASH_MEM + case kShellFlashMemInfo: { + const HFlashMemOpts *opt = HFlashMemGetOpt(); + if (opt == NULL) { + break; + } + + for (uint8_t i = 0; i < opt->cacheSize; ++i) { + HSHELL_PRINTFL("addr[0x%08x], offset[%d], eraseStatus[%d], isDirty[%d], heat[%d]", opt->cache[i].addr, opt->cache[i].offset, opt->cache[i].eraseStatus, opt->cache[i].isDirty, opt->cache[i].heat); + } + } break; +#endif default: break; } @@ -1444,7 +1467,7 @@ void HFlashSync() SyncCachePage(); SyncPageInfo(); SyncBackup(); -#ifdef USE_FLASH_MEM +#ifdef HFLASH_USE_FLASH_MEM HFlashMemSync(); #endif } @@ -1453,7 +1476,7 @@ void HFlashFreeCache() { HFlashSync(); sInfo.pageCacheUseNum = 0; -#ifdef USE_FLASH_MEM +#ifdef HFLASH_USE_FLASH_MEM HFlashMemFreeCache(); #endif }