1. 修改Flash使用内存映射

This commit is contained in:
coffee 2025-12-25 16:20:51 +08:00
parent d6fc4bfd9b
commit 06486210e1
4 changed files with 169 additions and 15 deletions

View File

@ -79,9 +79,31 @@ uint8_t HFlashMemWrite(uint32_t addr, const void *buf, uint32_t len);
*/
uint8_t HFlashMemSetValue(uint32_t addr, uint8_t value, uint32_t len);
/**
* @brief Flash数据拷贝
* @param srcAddr
* @param destAddr
* @param len
*/
uint8_t HFlashMemAddrCopy(uint32_t srcAddr, uint32_t destAddr, uint32_t len);
/**
* @brief Flash数据映射回调
* @param addr
* @param call , 0, ,
* @param arg
* @return call返回值
*/
uint8_t HFlashMemMMapCall(uint32_t addr, uint8_t(*call)(uint32_t addr, uint32_t offset, const uint8_t *data, uint16_t len, void *arg), void *arg);
/**
* @brief Flash
*/
void HFlashMemSync();
/**
* @brief
*/
void HFlashFreeCache();
#endif // __H_FLASH_MEM_H__

View File

@ -17,7 +17,7 @@
#endif
///< 使用Flash内存映射功能
// #define USE_FLASH_MEM
#define USE_FLASH_MEM
///< Flash块大小, 按块操作, 2的幂关系
#ifndef HFLASH_BLOCK_SIZE

View File

@ -386,7 +386,76 @@ uint8_t HFlashMemSetValue(uint32_t addr, uint8_t value, uint32_t len)
return WriteData(addr, NULL, len, _MemSetValueHelper, &value);
}
static void _MemAddrCopy(void *dest, const void *src, uint32_t len, void *userData)
{
uint32_t srcAddr = *(uint32_t *)userData;
HFlashMemRead(srcAddr + (long)src, dest, len);
}
uint8_t HFlashMemAddrCopy(uint32_t srcAddr, uint32_t destAddr, uint32_t len)
{
if (sOpts == NULL) {
return 0;
}
return WriteData(destAddr, NULL, len, _MemAddrCopy, &srcAddr);
}
uint8_t HFlashMemMMapCall(uint32_t addr, uint8_t(*call)(uint32_t addr, uint32_t offset, const uint8_t *data, uint16_t len, void *arg), void *arg)
{
if (sOpts == NULL || call == NULL) {
return 0;
}
uint32_t offset = 0;
HFlashMemCache *cache = NULL;
uint16_t len = 0;
uint8_t result = 0;
// 先处理未对齐的部分
if (addr != Align4K(addr)) {
cache = FindCache(addr + offset, 1);
if (cache == NULL) {
LogE("addr[0x%08x], find cache faild", addr);
return 0;
}
len = HFLASH_BLOCK_SIZE - (addr - cache->addr);
result = call(addr, offset, GetMMap(cache->offset) + (addr - cache->addr), len, arg);
offset += len;
}
if (result) {
return result;
}
// 剩余处理对齐部分
while (result == 0) {
cache = FindCache(addr + offset, 1);
if (cache == NULL) {
LogE("addr[0x%08x], find cache faild", addr + offset);
return 0;
}
result = call(addr + offset, offset, GetMMap(cache->offset), HFLASH_BLOCK_SIZE ,arg);
if (result) {
break;
}
offset += HFLASH_BLOCK_SIZE;
}
return result;
}
void HFlashMemSync()
{
SyncCache();
}
void HFlashFreeCache()
{
HFlashMemSync();
sInfo.useNum = 0;
}

View File

@ -38,12 +38,18 @@ uint32_t HSCrc32Get()
#endif
// 计算最小值
#define FLASH_MIN(type, a, b) ((b) ^ (((a) ^ (b)) & (-(type)((a) < (b)))))
#define FAST_MIN(type, a, b) ((b) ^ (((a) ^ (b)) & (-(type)((a) < (b)))))
#ifdef USE_STD_MEM
#ifdef USE_FATAL_NOT_LOOP
#define FATAL_ERROR(format, ...) LogE(format, ##__VA_ARGS__);
#else
#define FATAL_ERROR(format, ...) while (1) { LogE(format, ##__VA_ARGS__); HShellRun(); };
__attribute__((weak))
void HDMainLoopCallOverride(uint8_t event)
{
(void)(event);
HShellRun();
}
#define FATAL_ERROR(format, ...) while (1) { LogE(format, ##__VA_ARGS__); HDMainLoopCallOverride(0); };
#endif
// 最大热度
@ -80,9 +86,11 @@ union PageInfo {
};
struct Info {
#ifndef USE_FLASH_MEM
HFlashReadCallback read; ///< 读取回调
HFlashWriteCallback write; ///< 写入回调
HFlashEraseCallback erase; ///< 擦除回调
#endif
HFlashAddr_t pageAddr; ///< 页表地址
HFlashAddr_t pageBackupAddr; ///< 页表备份地址
uint32_t pageSize; ///< 页大小
@ -141,7 +149,9 @@ static uint8_t ReadFlashCall(HFlashAddr_t addr, void *data, uint32_t size)
if (size == 0) {
return 1;
}
#ifdef USE_FLASH_MEM
return HFlashMemRead(addr, data, size);
#else
if (sInfo.read == NULL) {
FATAL_ERROR("read is null");
return 0;
@ -149,8 +159,10 @@ static uint8_t ReadFlashCall(HFlashAddr_t addr, void *data, uint32_t size)
uint8_t *dataPtr = (uint8_t *)data;
return sInfo.read(addr, dataPtr, size);
#endif
}
#ifndef USE_FLASH_MEM
static uint8_t EraseFlashCall(HFlashAddr_t addr)
{
if (sInfo.erase == NULL) {
@ -160,7 +172,6 @@ static uint8_t EraseFlashCall(HFlashAddr_t addr)
return sInfo.erase(addr);
}
static uint8_t WriteFlashCall(HFlashAddr_t addr, const void *data, uint32_t size)
{
if (size == 0) {
@ -175,7 +186,9 @@ static uint8_t WriteFlashCall(HFlashAddr_t addr, const void *data, uint32_t size
uint8_t *dataPtr = (uint8_t *)data;
return sInfo.write(addr, dataPtr, size);
}
#endif
#ifndef USE_FLASH_MEM
/**
* @brief Flash
* @param addr Flash地址
@ -256,31 +269,40 @@ _flashError:
HFLASH_FREE(buff);
return result;
}
#endif
#ifndef USE_FLASH_MEM
static void _WriteFlashHelper(void *dest, const void *src, uint16_t buffSize, void *userData)
{
(void)userData;
memcpy(dest, src, buffSize);
}
#endif
static uint8_t WriteFlash(HFlashAddr_t addr, const void *data, uint32_t size)
{
#ifdef USE_FLASH_MEM
HFlashMemWrite(addr, data, size);
return HFlashMemWrite(addr, data, size);
#else
return WriteData(addr, data, size, _WriteFlashHelper, NULL);
#endif
}
#ifndef USE_FLASH_MEM
static void _WriteFalshValueHelper(void *dest, const void *src, uint16_t size, void *userData)
{
uint8_t *value = (uint8_t *)userData;
memset(dest, *value, size);
}
#endif
static uint8_t WriteFlashValue(uint32_t addr, uint32_t size, uint8_t value)
{
#ifdef USE_FLASH_MEM
return HFlashMemSetValue(addr, value, size);
#else
return WriteData(addr, NULL, size, _WriteFalshValueHelper, &value);
#endif
}
static inline uint32_t AdjustPageAddr(uint32_t addr)
@ -383,6 +405,14 @@ static void AddBackupAddr(uint32_t addr, uint32_t size)
}
}
static uint8_t _CalcCrc32(uint32_t addr, uint32_t offset, const uint8_t *data, uint16_t len, void *args)
{
uint32_t needLen = *(uint32_t *)args;
uint32_t calcLen = FAST_MIN(uint32_t, (needLen - offset), len);
HSCrc32Update(data, calcLen);
return needLen <= offset + len;
}
static uint32_t GetFlashCrc32(HFlashAddr_t addr, uint32_t size)
{
if (size == 0) {
@ -390,6 +420,12 @@ static uint32_t GetFlashCrc32(HFlashAddr_t addr, uint32_t size)
}
HSCrc32Reset();
#ifdef USE_FLASH_MEM
if (HFlashMemMMapCall(addr, _CalcCrc32, &size) == 0) {
LogE("addr[0x%08x], size[%d] mmap faild", addr, size);
return 0xFFFFFFFF;
}
#else
uint8_t *buff = (uint8_t *)HFLASH_MALLOC(HFLASH_BLOCK_SIZE);
if (buff == NULL) {
LogE("addr[0x%08x], write size[%d] malloc faild", addr, size);
@ -397,7 +433,7 @@ static uint32_t GetFlashCrc32(HFlashAddr_t addr, uint32_t size)
}
for (uint32_t i = 0; i < size; i += HFLASH_BLOCK_SIZE) {
const uint32_t remain = FLASH_MIN(uint32_t, size - i, HFLASH_BLOCK_SIZE);
const uint32_t remain = FAST_MIN(uint32_t, size - i, HFLASH_BLOCK_SIZE);
if (ReadFlashCall(addr + i, buff, remain) == 0) {
LogE("addr[0x%08x][0x%08x], size[%d] read faild", addr, addr + i, remain);
break;
@ -407,6 +443,7 @@ static uint32_t GetFlashCrc32(HFlashAddr_t addr, uint32_t size)
}
HFLASH_FREE(buff);
#endif
return HSCrc32Get();
}
@ -416,7 +453,9 @@ 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
return HFlashMemAddrCopy(srcAddr, dstAddr, copySize);
#else
uint8_t *buff = (uint8_t *)HFLASH_MALLOC(HFLASH_BLOCK_SIZE);
if (buff == NULL) {
LogE("addr[0x%08x], write size[%d] malloc faild", srcAddr, copySize);
@ -480,6 +519,7 @@ _FlashError:
HFLASH_FREE(buff);
LogD("Restore srcAddr[0x%08x], dstAddr[0x%08x], size[%d][%d], result[%d]", srcAddr, dstAddr, size, copySize, result);
return result;
#endif
}
///< 恢复指定页表
@ -628,7 +668,24 @@ static uint8_t ScanPage(uint8_t (*call)(uint32_t index, HFlashPageInfo *info, vo
return 0;
}
const uint32_t pageNum = FLASH_MIN(uint32_t, sPageInfo.useNum, (HFLASH_BLOCK_SIZE / sizeof(HFlashPageInfo)));
#ifdef USE_FLASH_MEM
HFlashPageInfo page;
uint8_t result = 0;
for (uint32_t i = 0; i < sPageInfo.useNum; ++i) {
if (HFlashMemRead(AdjustPageAddrOffset(sInfo.pageAddr, i), &page, sizeof(HFlashPageInfo)) == 0) {
LogE("read page table[0x%08x] faild", AdjustPageAddrOffset(sInfo.pageAddr, i));
return 0;
}
result = call(i, &page, userData);
if (result) {
break;
}
}
return result;
#else
const uint32_t pageNum = FAST_MIN(uint32_t, sPageInfo.useNum, (HFLASH_BLOCK_SIZE / sizeof(HFlashPageInfo)));
HFlashPageInfo *buff = (HFlashPageInfo *)HFLASH_MALLOC(pageNum * sizeof(HFlashPageInfo));
if (buff == NULL) {
LogE("malloc faild");
@ -637,7 +694,7 @@ static uint8_t ScanPage(uint8_t (*call)(uint32_t index, HFlashPageInfo *info, vo
uint8_t result = 0;
for (uint32_t i = 0; i < sPageInfo.useNum; i += pageNum) {
const uint32_t num = FLASH_MIN(uint32_t, sPageInfo.useNum - i, pageNum);
const uint32_t num = FAST_MIN(uint32_t, sPageInfo.useNum - i, pageNum);
if (ReadFlashCall(AdjustPageAddrOffset(sInfo.pageAddr, i), buff, AdjustPageByte(num)) == 0) {
LogE("read page table[0x%08x] faild", AdjustPageAddrOffset(sInfo.pageAddr, i));
break;
@ -658,6 +715,7 @@ static uint8_t ScanPage(uint8_t (*call)(uint32_t index, HFlashPageInfo *info, vo
HFLASH_FREE(buff);
return result;
#endif
}
///< 检查是否重叠, 重叠返回1
@ -740,13 +798,13 @@ static HFlashCacheInfo *FindCache(HFlashAddr_t addr)
uint8_t fastCoolDown = 0;
HFlashCacheInfo cache;
for (uint16_t i = 0; i < sInfo.pageCacheUseNum; ++i) {
currMin = FLASH_MIN(uint8_t, currMin, sInfo.pageCache[i].heat);
currMin = FAST_MIN(uint8_t, currMin, sInfo.pageCache[i].heat);
fastCoolDown = fastCoolDown || sInfo.pageCache[i].heat >= MAX_HEAT;
if (sInfo.pageCache[i].info.addr != addr) {
continue;
}
sInfo.pageCache[i].heat = FLASH_MIN(uint8_t, sInfo.pageCache[i].heat + 1, MAX_HEAT);
sInfo.pageCache[i].heat = FAST_MIN(uint8_t, sInfo.pageCache[i].heat + 1, MAX_HEAT);
if (i == 0) {
return &sInfo.pageCache[i];
}
@ -775,7 +833,7 @@ static HFlashCacheInfo *FindCache(HFlashAddr_t addr)
memset(&cache, 0, sizeof(HFlashCacheInfo));
cache.info.addr = addr;
if (ScanPage(_FindCacheHelper, &cache)) {
const uint16_t index = FLASH_MIN(uint16_t, sInfo.pageCacheUseNum, sInfo.pageCacheSize - 1);
const uint16_t index = FAST_MIN(uint16_t, sInfo.pageCacheUseNum, sInfo.pageCacheSize - 1);
if (sInfo.pageCacheUseNum < sInfo.pageCacheSize) {
++sInfo.pageCacheUseNum;
}
@ -802,9 +860,11 @@ static HFlashCacheInfo *FindCache(HFlashAddr_t addr)
void HFlashInitCallback(HFlashReadCallback read, HFlashWriteCallback write, HFlashEraseCallback erase)
{
#ifndef USE_FLASH_MEM
sInfo.read = read;
sInfo.write = write;
sInfo.erase = erase;
#endif
}
void HFlashSetPageCache(HFlashCacheInfo *pageInfo, uint16_t size)
@ -1244,7 +1304,7 @@ uint8_t HFlashRead(HFlashAddr_t addr, void *data, uint32_t size)
memset((uint8_t *)data + cache->info.useSize, 0, size - cache->info.useSize);
}
const uint32_t readSize = FLASH_MIN(uint32_t, size, cache->info.useSize);
const uint32_t readSize = FAST_MIN(uint32_t, size, cache->info.useSize);
return ReadFlashCall(addr, data, readSize);
}
@ -1361,4 +1421,7 @@ void HFlashSync()
SyncCachePage();
SyncPageInfo();
SyncBackup();
#ifdef USE_FLASH_MEM
HFlashMemSync();
#endif
}