1. 完成FlashMem

This commit is contained in:
coffee 2025-12-20 22:10:35 +08:00
parent 151d1565d6
commit 6663ede808
5 changed files with 116 additions and 14 deletions

View File

@ -36,6 +36,7 @@ typedef struct HFlashMemCache
uint16_t offset; ///< 内存偏移
uint16_t eraseStatus : 2; ///< 擦除状态
uint16_t isDirty : 1; ///< 是否脏页
uint16_t heat : 4; ///< 热度优先级
} HFlashMemCache;
///< 内存操作, 回调返回0表示失败
@ -61,6 +62,7 @@ void HFlashMemInit(HFlashMemOpts *opts);
* @param addr
* @param buf
* @param len
* @return 1, 0
*/
uint8_t HFlashMemRead(uint32_t addr, void *buf, uint32_t len);
@ -69,9 +71,19 @@ uint8_t HFlashMemRead(uint32_t addr, void *buf, uint32_t len);
* @param addr
* @param buf
* @param len
* @return 1, 0
*/
uint8_t HFlashMemWrite(uint32_t addr, const void *buf, uint32_t len);
/**
* @brief Flash值
* @param addr
* @param value
* @param len
* @return 1, 0
*/
uint8_t HFlashMemSetValue(uint32_t addr, uint8_t value, uint32_t len);
/**
* @brief Flash
*/

View File

@ -16,6 +16,8 @@
#include "HDSendBuffer.h"
#endif
///< 使用Flash内存映射功能
// #define USE_FLASH_MEM
///< Flash块大小, 按块操作, 2的幂关系
#ifndef HFLASH_BLOCK_SIZE

View File

@ -36,8 +36,8 @@ typedef uint32_t HProtocolBindFunc_t;
///< 协议回调
typedef void (*HProtocolBindCallback)(HProtocolBind_t index, uint8_t* data, uint16_t len);
#define HPROTOCOL_BIND_CALL_ARGS HProtocolBind_t index, uint8_t* data, uint16_t len
#define HPROTOCOL_IS_TIMEOUT() (data == NULL && len == 0)
#define HPROTOCOL_BIND_CALL_ARGS HProtocolBind_t _index, uint8_t* _data, uint16_t _len
#define HPROTOCOL_IS_TIMEOUT() (_data == NULL && _len == 0)
///< 协议会话
typedef struct HProtocolBindInfo

View File

@ -16,6 +16,12 @@
// 是否对齐页
#define IS_4K(size) ((size & (HFLASH_BLOCK_SIZE - 1)) == 0)
// 最大热度
#define MAX_HEAT ((1 << 4) - 1)
// 快速最小值
#define FAST_MIN(type, a, b) ((b) ^ (((a) ^ (b)) & (-(type)((a) < (b)))))
enum eErase
{
kEraseWait, ///< 等待擦除
@ -140,6 +146,28 @@ static void StartSyncCache()
}
sCheckTimer = HTimerAdd(HFLASH_TIMER_ID, 1, 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)
@ -150,6 +178,7 @@ static HFlashMemCache *FindCache(uint32_t addr, uint8_t create)
continue;
}
sOpts->cache[i].heat = FAST_MIN(uint8_t, sOpts->cache[i].heat + 1, MAX_HEAT);
return sOpts->cache + i;
}
@ -169,24 +198,46 @@ static HFlashMemCache *FindCache(uint32_t addr, uint8_t create)
memset(sOpts->cache + index, 0, sizeof(HFlashMemCache));
sOpts->cache[index].addr = addr;
sOpts->cache[index].offset = index;
sOpts->cache[index].heat = FAST_MIN(uint8_t, sOpts->cache[index].heat + 1, MAX_HEAT);
return sOpts->cache + index;
}
// 从尾巴开始找旧的并且已经不是脏页的
for (int32_t i = sInfo.useNum - 1; i > 0; --i) {
int16_t index = -1;
uint8_t minHeat = MAX_HEAT;
for (uint16_t i = 0; i < sInfo.useNum; ++i) {
if (sOpts->cache[i].eraseStatus || sOpts->cache[i].isDirty) {
continue;
}
if (sOpts->read(addr, GetMMap(i), HFLASH_BLOCK_SIZE) == 0) {
// 寻找最小热度, 同时空闲的降低温度
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;
continue;
}
if (currHeat > minHeat) {
continue;
}
index = i;
minHeat = currHeat;
}
if (index != -1) {
// 找到一个空闲且最低温度的
if (sOpts->read(addr, GetMMap(index), HFLASH_BLOCK_SIZE) == 0) {
LogE("addr[0x%08x], read faild", addr);
return NULL;
}
memset(sOpts->cache + i, 0, sizeof(HFlashMemCache));
sOpts->cache[i].addr = addr;
sOpts->cache[i].offset = i;
return sOpts->cache + i;
memset(sOpts->cache + index, 0, sizeof(HFlashMemCache));
sOpts->cache[index].addr = addr;
sOpts->cache[index].offset = index;
return sOpts->cache + index;
}
// 如果在创建模式下, 没有一个空闲的缓存, 就需要先同步脏页, 再获取一个
@ -195,7 +246,7 @@ static HFlashMemCache *FindCache(uint32_t addr, uint8_t create)
}
static uint8_t WriteData(uint32_t addr, const void *buf, uint32_t len)
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);
@ -214,7 +265,7 @@ static uint8_t WriteData(uint32_t addr, const void *buf, uint32_t len)
// 先处理首页
cache->isDirty = 1;
memcpy(GetMMap(cache->offset) + offset, bufPtr, remain);
cpCall(GetMMap(cache->offset) + offset, bufPtr, remain, userData);
len -= remain;
bufPtr += remain;
adjustAddr += HFLASH_BLOCK_SIZE;
@ -227,7 +278,7 @@ static uint8_t WriteData(uint32_t addr, const void *buf, uint32_t len)
}
cache->isDirty = 1;
memcpy(GetMMap(cache->offset), bufPtr, HFLASH_BLOCK_SIZE);
cpCall(GetMMap(cache->offset), bufPtr, HFLASH_BLOCK_SIZE, userData);
}
if (len) {
@ -238,7 +289,7 @@ static uint8_t WriteData(uint32_t addr, const void *buf, uint32_t len)
}
cache->isDirty = 1;
memcpy(GetMMap(cache->offset), bufPtr, len);
cpCall(GetMMap(cache->offset), bufPtr, len, userData);
}
return 1;
@ -269,6 +320,10 @@ uint8_t HFlashMemRead(uint32_t addr, void *buf, uint32_t len)
return 0;
}
if (buf == NULL || len == 0) {
return 1;
}
uint8_t *p = (uint8_t *)buf;
while (len > 0) {
const uint32_t pageAddr = Align4K(addr);
@ -294,13 +349,38 @@ uint8_t HFlashMemRead(uint32_t addr, void *buf, uint32_t len)
return 1;
}
static void _MemCpyHelper(void *dest, const void *src, uint32_t len, void *userData)
{
(void)userData;
memcpy(dest, src, len);
}
uint8_t HFlashMemWrite(uint32_t addr, const void *buf, uint32_t len)
{
if (sOpts == NULL) {
return 0;
}
return WriteData(addr, buf, len);
if (buf == NULL || len == 0) {
return 1;
}
return WriteData(addr, buf, len, _MemCpyHelper, NULL);
}
static void _MemSetValueHelper(void *dest, const void *src, uint32_t len, void *userData)
{
uint8_t value = *(uint8_t *)userData;
memset(dest, value, len);
}
uint8_t HFlashMemSetValue(uint32_t addr, uint8_t value, uint32_t len)
{
if (sOpts == NULL) {
return 0;
}
return WriteData(addr, NULL, len, _MemSetValueHelper, &value);
}
void HFlashMemSync()

View File

@ -7,6 +7,10 @@
#include "HShellLex.h"
#include <stdio.h>
#ifdef USE_FLASH_MEM
#include "HFlashMem.h"
#endif
#ifndef USE_STD_MEM
#include "HDSendBuffer.h"
#include "HSCrc32.h"
@ -261,7 +265,11 @@ 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
HFlashMemWrite(addr, data, size);
#else
return WriteData(addr, data, size, _WriteFlashHelper, NULL);
#endif
}
static void _WriteFalshValueHelper(void *dest, const void *src, uint16_t size, void *userData)