1. 增加支持免读取优化

This commit is contained in:
coffee 2025-12-25 23:40:02 +08:00
parent 1292ac8fc2
commit a4795e62c9
4 changed files with 120 additions and 78 deletions

View File

@ -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

View File

@ -12,12 +12,16 @@
#include <stdint.h>
#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初始化回调

View File

@ -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;

View File

@ -7,12 +7,14 @@
#include "HShellLex.h"
#include <stdio.h>
#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
}