diff --git a/include/HFlashMem.h b/include/HFlashMem.h index 9bb1f91..923a5c5 100644 --- a/include/HFlashMem.h +++ b/include/HFlashMem.h @@ -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 */ diff --git a/include/HFlashServer.h b/include/HFlashServer.h index 85e42d8..7571492 100644 --- a/include/HFlashServer.h +++ b/include/HFlashServer.h @@ -16,6 +16,8 @@ #include "HDSendBuffer.h" #endif +///< 使用Flash内存映射功能 +// #define USE_FLASH_MEM ///< Flash块大小, 按块操作, 2的幂关系 #ifndef HFLASH_BLOCK_SIZE diff --git a/include/HProtocolBind.h b/include/HProtocolBind.h index ff1bc0f..1e72a42 100644 --- a/include/HProtocolBind.h +++ b/include/HProtocolBind.h @@ -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 diff --git a/src/HFlashMem.c b/src/HFlashMem.c index 8984656..c9a8b6c 100644 --- a/src/HFlashMem.c +++ b/src/HFlashMem.c @@ -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() diff --git a/src/HFlashServer.c b/src/HFlashServer.c index 14e7cad..27f9890 100644 --- a/src/HFlashServer.c +++ b/src/HFlashServer.c @@ -7,6 +7,10 @@ #include "HShellLex.h" #include +#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)