1. 完成FlashMem
This commit is contained in:
parent
151d1565d6
commit
6663ede808
@ -36,6 +36,7 @@ typedef struct HFlashMemCache
|
|||||||
uint16_t offset; ///< 内存偏移
|
uint16_t offset; ///< 内存偏移
|
||||||
uint16_t eraseStatus : 2; ///< 擦除状态
|
uint16_t eraseStatus : 2; ///< 擦除状态
|
||||||
uint16_t isDirty : 1; ///< 是否脏页
|
uint16_t isDirty : 1; ///< 是否脏页
|
||||||
|
uint16_t heat : 4; ///< 热度优先级
|
||||||
} HFlashMemCache;
|
} HFlashMemCache;
|
||||||
|
|
||||||
///< 内存操作, 回调返回0表示失败
|
///< 内存操作, 回调返回0表示失败
|
||||||
@ -61,6 +62,7 @@ void HFlashMemInit(HFlashMemOpts *opts);
|
|||||||
* @param addr 读取地址
|
* @param addr 读取地址
|
||||||
* @param buf 读取数据写入缓存的内存
|
* @param buf 读取数据写入缓存的内存
|
||||||
* @param len 读取长度
|
* @param len 读取长度
|
||||||
|
* @return 成功返回1, 失败返回0
|
||||||
*/
|
*/
|
||||||
uint8_t HFlashMemRead(uint32_t addr, void *buf, uint32_t len);
|
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 addr 写入地址
|
||||||
* @param buf 写入数据
|
* @param buf 写入数据
|
||||||
* @param len 写入长度
|
* @param len 写入长度
|
||||||
|
* @return 成功返回1, 失败返回0
|
||||||
*/
|
*/
|
||||||
uint8_t HFlashMemWrite(uint32_t addr, const void *buf, uint32_t len);
|
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
|
* @brief 同步脏页写入Flash
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -16,6 +16,8 @@
|
|||||||
#include "HDSendBuffer.h"
|
#include "HDSendBuffer.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
///< 使用Flash内存映射功能
|
||||||
|
// #define USE_FLASH_MEM
|
||||||
|
|
||||||
///< Flash块大小, 按块操作, 2的幂关系
|
///< Flash块大小, 按块操作, 2的幂关系
|
||||||
#ifndef HFLASH_BLOCK_SIZE
|
#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);
|
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_BIND_CALL_ARGS HProtocolBind_t _index, uint8_t* _data, uint16_t _len
|
||||||
#define HPROTOCOL_IS_TIMEOUT() (data == NULL && len == 0)
|
#define HPROTOCOL_IS_TIMEOUT() (_data == NULL && _len == 0)
|
||||||
|
|
||||||
///< 协议会话
|
///< 协议会话
|
||||||
typedef struct HProtocolBindInfo
|
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 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
|
enum eErase
|
||||||
{
|
{
|
||||||
kEraseWait, ///< 等待擦除
|
kEraseWait, ///< 等待擦除
|
||||||
@ -140,6 +146,28 @@ static void StartSyncCache()
|
|||||||
}
|
}
|
||||||
|
|
||||||
sCheckTimer = HTimerAdd(HFLASH_TIMER_ID, 1, CheckSyncCache, kHTimerLoop);
|
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)
|
static HFlashMemCache *FindCache(uint32_t addr, uint8_t create)
|
||||||
@ -150,6 +178,7 @@ static HFlashMemCache *FindCache(uint32_t addr, uint8_t create)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sOpts->cache[i].heat = FAST_MIN(uint8_t, sOpts->cache[i].heat + 1, MAX_HEAT);
|
||||||
return sOpts->cache + i;
|
return sOpts->cache + i;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,24 +198,46 @@ static HFlashMemCache *FindCache(uint32_t addr, uint8_t create)
|
|||||||
memset(sOpts->cache + index, 0, sizeof(HFlashMemCache));
|
memset(sOpts->cache + index, 0, sizeof(HFlashMemCache));
|
||||||
sOpts->cache[index].addr = addr;
|
sOpts->cache[index].addr = addr;
|
||||||
sOpts->cache[index].offset = index;
|
sOpts->cache[index].offset = index;
|
||||||
|
sOpts->cache[index].heat = FAST_MIN(uint8_t, sOpts->cache[index].heat + 1, MAX_HEAT);
|
||||||
return sOpts->cache + index;
|
return sOpts->cache + index;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 从尾巴开始找旧的并且已经不是脏页的
|
int16_t index = -1;
|
||||||
for (int32_t i = sInfo.useNum - 1; i > 0; --i) {
|
uint8_t minHeat = MAX_HEAT;
|
||||||
|
for (uint16_t i = 0; i < sInfo.useNum; ++i) {
|
||||||
if (sOpts->cache[i].eraseStatus || sOpts->cache[i].isDirty) {
|
if (sOpts->cache[i].eraseStatus || sOpts->cache[i].isDirty) {
|
||||||
continue;
|
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);
|
LogE("addr[0x%08x], read faild", addr);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(sOpts->cache + i, 0, sizeof(HFlashMemCache));
|
memset(sOpts->cache + index, 0, sizeof(HFlashMemCache));
|
||||||
sOpts->cache[i].addr = addr;
|
sOpts->cache[index].addr = addr;
|
||||||
sOpts->cache[i].offset = i;
|
sOpts->cache[index].offset = index;
|
||||||
return sOpts->cache + i;
|
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);
|
uint32_t adjustAddr = Align4K(addr);
|
||||||
HFlashMemCache *cache = FindCache(adjustAddr, 1);
|
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;
|
cache->isDirty = 1;
|
||||||
memcpy(GetMMap(cache->offset) + offset, bufPtr, remain);
|
cpCall(GetMMap(cache->offset) + offset, bufPtr, remain, userData);
|
||||||
len -= remain;
|
len -= remain;
|
||||||
bufPtr += remain;
|
bufPtr += remain;
|
||||||
adjustAddr += HFLASH_BLOCK_SIZE;
|
adjustAddr += HFLASH_BLOCK_SIZE;
|
||||||
@ -227,7 +278,7 @@ static uint8_t WriteData(uint32_t addr, const void *buf, uint32_t len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
cache->isDirty = 1;
|
cache->isDirty = 1;
|
||||||
memcpy(GetMMap(cache->offset), bufPtr, HFLASH_BLOCK_SIZE);
|
cpCall(GetMMap(cache->offset), bufPtr, HFLASH_BLOCK_SIZE, userData);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len) {
|
if (len) {
|
||||||
@ -238,7 +289,7 @@ static uint8_t WriteData(uint32_t addr, const void *buf, uint32_t len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
cache->isDirty = 1;
|
cache->isDirty = 1;
|
||||||
memcpy(GetMMap(cache->offset), bufPtr, len);
|
cpCall(GetMMap(cache->offset), bufPtr, len, userData);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@ -269,6 +320,10 @@ uint8_t HFlashMemRead(uint32_t addr, void *buf, uint32_t len)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (buf == NULL || len == 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t *p = (uint8_t *)buf;
|
uint8_t *p = (uint8_t *)buf;
|
||||||
while (len > 0) {
|
while (len > 0) {
|
||||||
const uint32_t pageAddr = Align4K(addr);
|
const uint32_t pageAddr = Align4K(addr);
|
||||||
@ -294,13 +349,38 @@ uint8_t HFlashMemRead(uint32_t addr, void *buf, uint32_t len)
|
|||||||
return 1;
|
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)
|
uint8_t HFlashMemWrite(uint32_t addr, const void *buf, uint32_t len)
|
||||||
{
|
{
|
||||||
if (sOpts == NULL) {
|
if (sOpts == NULL) {
|
||||||
return 0;
|
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()
|
void HFlashMemSync()
|
||||||
|
|||||||
@ -7,6 +7,10 @@
|
|||||||
#include "HShellLex.h"
|
#include "HShellLex.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifdef USE_FLASH_MEM
|
||||||
|
#include "HFlashMem.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef USE_STD_MEM
|
#ifndef USE_STD_MEM
|
||||||
#include "HDSendBuffer.h"
|
#include "HDSendBuffer.h"
|
||||||
#include "HSCrc32.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)
|
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);
|
return WriteData(addr, data, size, _WriteFlashHelper, NULL);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _WriteFalshValueHelper(void *dest, const void *src, uint16_t size, void *userData)
|
static void _WriteFalshValueHelper(void *dest, const void *src, uint16_t size, void *userData)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user