1. 完成FlashMem
This commit is contained in:
parent
151d1565d6
commit
6663ede808
@ -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
|
||||
*/
|
||||
|
||||
@ -16,6 +16,8 @@
|
||||
#include "HDSendBuffer.h"
|
||||
#endif
|
||||
|
||||
///< 使用Flash内存映射功能
|
||||
// #define USE_FLASH_MEM
|
||||
|
||||
///< Flash块大小, 按块操作, 2的幂关系
|
||||
#ifndef HFLASH_BLOCK_SIZE
|
||||
|
||||
@ -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
|
||||
|
||||
104
src/HFlashMem.c
104
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()
|
||||
|
||||
@ -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)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user