1. 避免不间断不断执行问题
This commit is contained in:
parent
9cd7eb2499
commit
df494faf2d
@ -12,6 +12,15 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// 使用位图模块映射保护区
|
||||||
|
#ifndef HFLASH_USE_BITMAP
|
||||||
|
#define HFLASH_USE_BITMAP 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if HFLASH_USE_BITMAP
|
||||||
|
#include "HBitMap.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
// 使用HShell
|
// 使用HShell
|
||||||
#ifndef HFLASH_USE_HSHELL
|
#ifndef HFLASH_USE_HSHELL
|
||||||
#define HFLASH_USE_HSHELL 1
|
#define HFLASH_USE_HSHELL 1
|
||||||
@ -24,7 +33,7 @@
|
|||||||
|
|
||||||
#ifndef USE_STD_MEM
|
#ifndef USE_STD_MEM
|
||||||
#ifndef HFLASH_USE_FLASH_MEM
|
#ifndef HFLASH_USE_FLASH_MEM
|
||||||
#include "HDSendBuffer.h"
|
#include "HSendBuffer.h"
|
||||||
#endif // HFLASH_USE_FLASH_MEM
|
#endif // HFLASH_USE_FLASH_MEM
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -39,7 +48,7 @@
|
|||||||
#ifdef USE_STD_MEM
|
#ifdef USE_STD_MEM
|
||||||
#define HFLASH_MALLOC(size) malloc(size)
|
#define HFLASH_MALLOC(size) malloc(size)
|
||||||
#else
|
#else
|
||||||
#define HFLASH_MALLOC(size) HDSendBufferGet(size)
|
#define HFLASH_MALLOC(size) HSendBufferGet(size)
|
||||||
#endif // USE_STD_MEM
|
#endif // USE_STD_MEM
|
||||||
#endif // HFLASH_MALLOC
|
#endif // HFLASH_MALLOC
|
||||||
|
|
||||||
@ -48,7 +57,7 @@
|
|||||||
#ifdef USE_STD_MEM
|
#ifdef USE_STD_MEM
|
||||||
#define HFLASH_FREE(ptr) free(ptr)
|
#define HFLASH_FREE(ptr) free(ptr)
|
||||||
#else
|
#else
|
||||||
#define HFLASH_FREE(ptr) HDSendBufferFree(ptr)
|
#define HFLASH_FREE(ptr) HSendBufferFree(ptr)
|
||||||
#endif // USE_STD_MEM
|
#endif // USE_STD_MEM
|
||||||
#endif // HFLASH_FREE
|
#endif // HFLASH_FREE
|
||||||
#endif // HFLASH_USE_FLASH_MEM
|
#endif // HFLASH_USE_FLASH_MEM
|
||||||
@ -90,10 +99,34 @@ typedef union HFlashPageInfo {
|
|||||||
};
|
};
|
||||||
} HFlashPageInfo;
|
} HFlashPageInfo;
|
||||||
|
|
||||||
|
#if HFLASH_USE_BITMAP
|
||||||
|
///< 计算保护区备份跨度大小, 传入原始保护区 addr/size 即可
|
||||||
|
#define HFLASH_CALC_PROTECT_SPAN_SIZE(addr, size) \
|
||||||
|
((uint32_t)((((((uint64_t)(addr)) & ((uint64_t)HFLASH_BLOCK_SIZE - 1u)) + (uint64_t)(size)) + \
|
||||||
|
(uint64_t)HFLASH_BLOCK_SIZE - 1u) & ~((uint64_t)HFLASH_BLOCK_SIZE - 1u)))
|
||||||
|
|
||||||
|
///< 计算保护区位图大小数组, size 需要传保护区备份跨度大小
|
||||||
|
#define HFLASH_CALC_BITMAP_SIZE(size) \
|
||||||
|
(HBITMAP_CALC_LEN(((uint32_t)(size) + HFLASH_BLOCK_SIZE - 1u) / HFLASH_BLOCK_SIZE))
|
||||||
|
|
||||||
|
///< 直接通过保护区 addr/size 计算位图数组大小
|
||||||
|
#define HFLASH_CALC_PROTECT_BITMAP_SIZE(addr, size) \
|
||||||
|
HFLASH_CALC_BITMAP_SIZE(HFLASH_CALC_PROTECT_SPAN_SIZE((addr), (size)))
|
||||||
|
|
||||||
|
///< 便于静态定义保护区位图数组
|
||||||
|
#define HFLASH_PROTECT_BITMAP_DEFINE(name, addr, size) \
|
||||||
|
HBitMapType name[HFLASH_CALC_PROTECT_BITMAP_SIZE((addr), (size))]
|
||||||
|
#else
|
||||||
|
#define HFLASH_CALC_BITMAP_SIZE(size) 0
|
||||||
|
#define HFLASH_CALC_PROTECT_BITMAP_SIZE(addr, size) 0
|
||||||
|
#endif
|
||||||
typedef struct HFlashProtectInfo {
|
typedef struct HFlashProtectInfo {
|
||||||
HFlashAddr_t addr; ///< 保护区地址
|
HFlashAddr_t addr; ///< 保护区地址
|
||||||
uint32_t size; ///< 保护区大小
|
uint32_t size; ///< 保护区大小
|
||||||
HFlashAddr_t backupAddr; ///< 保护区备份地址
|
HFlashAddr_t backupAddr; ///< 保护区备份地址
|
||||||
|
#if HFLASH_USE_BITMAP
|
||||||
|
HBitMapType *bitMap; ///< 保护区需保存的位图, 4k基准
|
||||||
|
#endif
|
||||||
} HFlashProtectInfo;
|
} HFlashProtectInfo;
|
||||||
|
|
||||||
typedef struct HFlashCacheInfo {
|
typedef struct HFlashCacheInfo {
|
||||||
@ -160,6 +193,15 @@ uint16_t HFlashGetVersion(HFlashAddr_t addr, HFlashVersionInfo *info);
|
|||||||
*/
|
*/
|
||||||
void HFlashSetPageCache(HFlashCacheInfo *pageInfo, uint16_t size);
|
void HFlashSetPageCache(HFlashCacheInfo *pageInfo, uint16_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief HFlashInitProtectCache 初始化保护区缓存, 内部不构建内存, 由外部分配
|
||||||
|
* 需要在设置保护地址前调用, 会将内存清零
|
||||||
|
* @param protectInfo 保护区描述缓存
|
||||||
|
* @param bitMap 位图
|
||||||
|
* @param size 保护区备份跨度大小, 推荐使用 HFLASH_CALC_PROTECT_SPAN_SIZE(addr, size) 计算
|
||||||
|
*/
|
||||||
|
void HFlashInitProtectCache(HFlashProtectInfo *protectInfo, void *bitMap, uint32_t size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief HFlashSetProtectCache 设置保护区描述缓存, 内部不构建内存, 由外部分配
|
* @brief HFlashSetProtectCache 设置保护区描述缓存, 内部不构建内存, 由外部分配
|
||||||
* 需要在设置保护地址前调用
|
* 需要在设置保护地址前调用
|
||||||
|
|||||||
146
src/HFlashMem.c
146
src/HFlashMem.c
@ -23,8 +23,8 @@
|
|||||||
// 最大热度
|
// 最大热度
|
||||||
#define MAX_HEAT ((1 << 5) - 1)
|
#define MAX_HEAT ((1 << 5) - 1)
|
||||||
|
|
||||||
// 写转读增加热度
|
// 写回后保留的最低热度, 避免刚刷回立刻被淘汰
|
||||||
#define WRITE_CONV_READ_ADD_HEAT (2)
|
#define WRITE_BACK_KEEP_HEAT (2)
|
||||||
|
|
||||||
// 读最小热度
|
// 读最小热度
|
||||||
#define READ_MIN_HEAT (0)
|
#define READ_MIN_HEAT (0)
|
||||||
@ -100,8 +100,10 @@ static void SyncCache()
|
|||||||
sOpts->cache[i].isDirty = 0;
|
sOpts->cache[i].isDirty = 0;
|
||||||
sOpts->cache[i].eraseStatus = kEraseWait;
|
sOpts->cache[i].eraseStatus = kEraseWait;
|
||||||
|
|
||||||
// 写入页转换空闲页, 热度持续增加
|
// 写回后只保留一个基础热度, 避免被动刷回页持续虚高
|
||||||
sOpts->cache[i].heat = FAST_MIN(uint8_t, sOpts->cache[i].heat + WRITE_CONV_READ_ADD_HEAT, MAX_HEAT);
|
if (sOpts->cache[i].heat < WRITE_BACK_KEEP_HEAT) {
|
||||||
|
sOpts->cache[i].heat = WRITE_BACK_KEEP_HEAT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,8 +141,10 @@ static void FastSyncCache()
|
|||||||
sOpts->cache[i].isDirty = 0;
|
sOpts->cache[i].isDirty = 0;
|
||||||
sOpts->cache[i].eraseStatus = kEraseWait;
|
sOpts->cache[i].eraseStatus = kEraseWait;
|
||||||
|
|
||||||
// 写入页转换空闲页, 热度持续增加
|
// 写回后只保留一个基础热度, 避免被动刷回页持续虚高
|
||||||
sOpts->cache[i].heat = FAST_MIN(uint8_t, sOpts->cache[i].heat + WRITE_CONV_READ_ADD_HEAT, MAX_HEAT);
|
if (sOpts->cache[i].heat < WRITE_BACK_KEEP_HEAT) {
|
||||||
|
sOpts->cache[i].heat = WRITE_BACK_KEEP_HEAT;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,8 +208,10 @@ static void CheckSyncCache()
|
|||||||
sOpts->cache[i].isDirty = 0;
|
sOpts->cache[i].isDirty = 0;
|
||||||
sOpts->cache[i].eraseStatus = kEraseWait;
|
sOpts->cache[i].eraseStatus = kEraseWait;
|
||||||
|
|
||||||
// 写入页转换空闲页, 热度持续增加
|
// 写回后只保留一个基础热度, 避免被动刷回页持续虚高
|
||||||
sOpts->cache[i].heat = FAST_MIN(uint8_t, sOpts->cache[i].heat + WRITE_CONV_READ_ADD_HEAT, MAX_HEAT);
|
if (sOpts->cache[i].heat < WRITE_BACK_KEEP_HEAT) {
|
||||||
|
sOpts->cache[i].heat = WRITE_BACK_KEEP_HEAT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (needErase != sInfo.useNum) {
|
if (needErase != sInfo.useNum) {
|
||||||
@ -229,7 +235,7 @@ static void StartSyncCache()
|
|||||||
sCheckTimer = HTIMER_INVALID;
|
sCheckTimer = HTIMER_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
sCheckTimer = HTimerAdd(HFLASH_TIMER_ID, 0, CheckSyncCache, kHTimerLoop);
|
sCheckTimer = HTimerAdd(HFLASH_TIMER_ID, 1, CheckSyncCache, kHTimerLoop);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ScheduleHeat()
|
static void ScheduleHeat()
|
||||||
@ -250,6 +256,39 @@ static void ScheduleHeat()
|
|||||||
sInfo.currHeatTime = HDLogGetTime();
|
sInfo.currHeatTime = HDLogGetTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static HFlashMemCache *FindCacheByAddr(uint32_t addr)
|
||||||
|
{
|
||||||
|
for (uint16_t i = 0; i < sInfo.useNum; ++i) {
|
||||||
|
if (addr != sOpts->cache[i].addr) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sOpts->cache + i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ResetCache(HFlashMemCache *cache, uint32_t addr, uint16_t index)
|
||||||
|
{
|
||||||
|
memset(cache, 0, sizeof(HFlashMemCache));
|
||||||
|
cache->addr = addr;
|
||||||
|
cache->offset = index;
|
||||||
|
cache->heat = READ_MIN_HEAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HFlashMemCache *AllocCache(void)
|
||||||
|
{
|
||||||
|
if (sInfo.useNum >= sOpts->cacheSize) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint16_t index = sInfo.useNum;
|
||||||
|
++sInfo.useNum;
|
||||||
|
ResetCache(sOpts->cache + index, 0, index);
|
||||||
|
return sOpts->cache + index;
|
||||||
|
}
|
||||||
|
|
||||||
static HFlashMemCache *FindMinHeatCache()
|
static HFlashMemCache *FindMinHeatCache()
|
||||||
{
|
{
|
||||||
int16_t index = -1;
|
int16_t index = -1;
|
||||||
@ -290,45 +329,25 @@ static HFlashMemCache *FindReadCache(uint32_t addr, uint8_t needRead)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint16_t i = 0; i < sInfo.useNum; ++i) {
|
HFlashMemCache *cache = FindCacheByAddr(addr);
|
||||||
if (addr != sOpts->cache[i].addr) {
|
if (cache) {
|
||||||
continue;
|
cache->heat = FAST_MIN(uint8_t, cache->heat + 1, MAX_HEAT);
|
||||||
}
|
return cache;
|
||||||
|
|
||||||
sOpts->cache[i].heat = FAST_MIN(uint8_t, sOpts->cache[i].heat + 1, MAX_HEAT);
|
|
||||||
return sOpts->cache + i;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果缓存没有满, 直接增加
|
|
||||||
if (sInfo.useNum < sOpts->cacheSize) {
|
if (sInfo.useNum < sOpts->cacheSize) {
|
||||||
const uint16_t index = sInfo.useNum;
|
cache = AllocCache();
|
||||||
++sInfo.useNum;
|
}
|
||||||
if (needRead) {
|
if (cache == NULL) {
|
||||||
WatiErase();
|
cache = FindMinHeatCache();
|
||||||
if (sOpts->read(addr, GetMMap(index), HFLASH_BLOCK_SIZE) == 0) {
|
|
||||||
LogE("addr[0x%08x], read faild", addr);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查找空闲的最低热度页
|
if (cache == NULL) {
|
||||||
HFlashMemCache *cache = FindMinHeatCache();
|
|
||||||
if (cache == NULL || cache->heat > READ_MIN_HEAT) {
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint16_t index = cache->offset;
|
const uint16_t index = cache->offset;
|
||||||
memset(cache, 0, sizeof(HFlashMemCache));
|
ResetCache(cache, addr, index);
|
||||||
cache->addr = addr;
|
|
||||||
cache->offset = index;
|
|
||||||
cache->heat = READ_MIN_HEAT;
|
|
||||||
|
|
||||||
if (needRead) {
|
if (needRead) {
|
||||||
WatiErase();
|
WatiErase();
|
||||||
@ -338,6 +357,7 @@ static HFlashMemCache *FindReadCache(uint32_t addr, uint8_t needRead)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cache->heat = FAST_MIN(uint8_t, cache->heat + 1, MAX_HEAT);
|
||||||
return cache;
|
return cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -349,8 +369,29 @@ static HFlashMemCache *FindWriteCache(uint32_t addr, uint8_t needRead)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
HFlashMemCache *cache = FindReadCache(addr, needRead);
|
HFlashMemCache *cache = FindCacheByAddr(addr);
|
||||||
if (cache) {
|
if (cache) {
|
||||||
|
cache->heat = FAST_MIN(uint8_t, cache->heat + 1, MAX_HEAT);
|
||||||
|
return cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sInfo.useNum < sOpts->cacheSize) {
|
||||||
|
cache = AllocCache();
|
||||||
|
if (cache == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint16_t index = cache->offset;
|
||||||
|
ResetCache(cache, addr, index);
|
||||||
|
if (needRead) {
|
||||||
|
WatiErase();
|
||||||
|
if (sOpts->read(addr, GetMMap(index), HFLASH_BLOCK_SIZE) == 0) {
|
||||||
|
LogE("addr[0x%08x], read faild", addr);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cache->heat = FAST_MIN(uint8_t, cache->heat + 1, MAX_HEAT);
|
||||||
return cache;
|
return cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -364,10 +405,7 @@ static HFlashMemCache *FindWriteCache(uint32_t addr, uint8_t needRead)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const uint16_t index = cache->offset;
|
const uint16_t index = cache->offset;
|
||||||
memset(cache, 0, sizeof(HFlashMemCache));
|
ResetCache(cache, addr, index);
|
||||||
cache->addr = addr;
|
|
||||||
cache->offset = index;
|
|
||||||
cache->heat = READ_MIN_HEAT;
|
|
||||||
if (needRead) {
|
if (needRead) {
|
||||||
WatiErase();
|
WatiErase();
|
||||||
// 找到一个空闲且最低温度的
|
// 找到一个空闲且最低温度的
|
||||||
@ -377,6 +415,7 @@ static HFlashMemCache *FindWriteCache(uint32_t addr, uint8_t needRead)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cache->heat = FAST_MIN(uint8_t, cache->heat + 1, MAX_HEAT);
|
||||||
return cache;
|
return cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -501,6 +540,24 @@ void HFlashMemInit(HFlashMemOpts *opts)
|
|||||||
FATAL_ERROR("flash Size not 4k align");
|
FATAL_ERROR("flash Size not 4k align");
|
||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sCheckTimer != HTIMER_INVALID) {
|
||||||
|
HTimerRemove(sCheckTimer);
|
||||||
|
sCheckTimer = HTIMER_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
sInfo.currHeatTime = HDLogGetTime();
|
||||||
|
sInfo.needWaitErase = 0;
|
||||||
|
sInfo.useNum = 0;
|
||||||
|
for (uint16_t i = 0; i < sOpts->cacheSize; ++i) {
|
||||||
|
if (sOpts->cache[i].addr == 0 && sOpts->cache[i].eraseStatus == 0 &&
|
||||||
|
sOpts->cache[i].isDirty == 0 &&
|
||||||
|
sOpts->cache[i].heat == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
sInfo.useNum = i + 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const HFlashMemOpts *HFlashMemGetOpt()
|
const HFlashMemOpts *HFlashMemGetOpt()
|
||||||
@ -661,4 +718,3 @@ void HFlashMemFreeCache()
|
|||||||
sInfo.useNum = 0;
|
sInfo.useNum = 0;
|
||||||
sInfo.currHeatTime = HDLogGetTime();
|
sInfo.currHeatTime = HDLogGetTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
#include "HFlashServer.h"
|
#include "HFlashServer.h"
|
||||||
#include "HDLog.h"
|
#include "HDLog.h"
|
||||||
#include "HVector.h"
|
|
||||||
#include "HTimer.h"
|
#include "HTimer.h"
|
||||||
#if HFLASH_USE_HSHELL
|
#if HFLASH_USE_HSHELL
|
||||||
#include "HShellLex.h"
|
#include "HShellLex.h"
|
||||||
@ -20,6 +19,9 @@
|
|||||||
#include "HSCrc32.h"
|
#include "HSCrc32.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if !HFLASH_USE_BITMAP
|
||||||
|
#include "HVector.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef USE_STD_MEM
|
#ifdef USE_STD_MEM
|
||||||
#include <nmmintrin.h>
|
#include <nmmintrin.h>
|
||||||
@ -66,6 +68,11 @@ void HDMainLoopCallOverride(uint8_t event)
|
|||||||
#define IS_NOT_4K(size) ((size & (HFLASH_BLOCK_SIZE - 1)) != 0)
|
#define IS_NOT_4K(size) ((size & (HFLASH_BLOCK_SIZE - 1)) != 0)
|
||||||
#define ALIGN_4K(size) (((size) + HFLASH_BLOCK_SIZE - 1) & ~(HFLASH_BLOCK_SIZE - 1))
|
#define ALIGN_4K(size) (((size) + HFLASH_BLOCK_SIZE - 1) & ~(HFLASH_BLOCK_SIZE - 1))
|
||||||
|
|
||||||
|
// 计算bitMap地址
|
||||||
|
#define CALC_BITMAP_INDEX(addr) ((addr) >> 12)
|
||||||
|
// 从bitMap计算flash偏移地址
|
||||||
|
#define CALC_FLASH_BITMAP_OFFSET(index) ((index) << 12)
|
||||||
|
|
||||||
#if HFLASH_USE_HSHELL
|
#if HFLASH_USE_HSHELL
|
||||||
enum eShell
|
enum eShell
|
||||||
{
|
{
|
||||||
@ -133,8 +140,10 @@ static HTimer_t sSyncPageTimer = HTIMER_INVALID;
|
|||||||
// 同步页表缓存定时器
|
// 同步页表缓存定时器
|
||||||
static HTimer_t sSyncCacheTimer = HTIMER_INVALID;
|
static HTimer_t sSyncCacheTimer = HTIMER_INVALID;
|
||||||
|
|
||||||
|
#if !HFLASH_USE_BITMAP
|
||||||
// 存储需要备份的保护区地址页偏移
|
// 存储需要备份的保护区地址页偏移
|
||||||
static HVECTOR_DEFINE32(sNeedBackupOffset, 10);
|
static HVECTOR_DEFINE32(sNeedBackupOffset, 10);
|
||||||
|
#endif
|
||||||
|
|
||||||
static uint8_t RestoreBackup(HFlashAddr_t srcAddr, HFlashAddr_t dstAddr, uint32_t size);
|
static uint8_t RestoreBackup(HFlashAddr_t srcAddr, HFlashAddr_t dstAddr, uint32_t size);
|
||||||
static uint8_t RestoreBackupRange(HFlashAddr_t addr, uint32_t size);
|
static uint8_t RestoreBackupRange(HFlashAddr_t addr, uint32_t size);
|
||||||
@ -152,6 +161,7 @@ static uint32_t GetBackupCrc32(HFlashAddr_t addr, uint32_t size);
|
|||||||
static uint8_t GetBackupAddr(HFlashAddr_t addr, uint32_t size, HFlashAddr_t *backupAddr);
|
static uint8_t GetBackupAddr(HFlashAddr_t addr, uint32_t size, HFlashAddr_t *backupAddr);
|
||||||
static uint8_t GetProtectBackupRange(HFlashAddr_t addr, uint32_t size, HFlashAddr_t *backupStartAddr, uint32_t *backupSize);
|
static uint8_t GetProtectBackupRange(HFlashAddr_t addr, uint32_t size, HFlashAddr_t *backupStartAddr, uint32_t *backupSize);
|
||||||
static inline uint32_t AdjustProtectBackupSize(HFlashAddr_t addr, uint32_t size);
|
static inline uint32_t AdjustProtectBackupSize(HFlashAddr_t addr, uint32_t size);
|
||||||
|
static void ClearProtectInfoEntry(HFlashProtectInfo *info);
|
||||||
|
|
||||||
static void ResetRuntimeState()
|
static void ResetRuntimeState()
|
||||||
{
|
{
|
||||||
@ -172,7 +182,15 @@ static void ResetRuntimeState()
|
|||||||
sSyncCacheTimer = HTIMER_INVALID;
|
sSyncCacheTimer = HTIMER_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if HFLASH_USE_BITMAP
|
||||||
|
for (uint16_t i = 0; i < sInfo.protectCacheSize; ++i) {
|
||||||
|
if (sInfo.protectInfo[i].bitMap) {
|
||||||
|
HBitMapFill(sInfo.protectInfo[i].bitMap, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
HVectorClear(sNeedBackupOffset);
|
HVectorClear(sNeedBackupOffset);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
///< 检查地址是否在双备份保护区内
|
///< 检查地址是否在双备份保护区内
|
||||||
@ -513,6 +531,20 @@ static inline uint32_t AdjustProtectBackupSize(HFlashAddr_t addr, uint32_t size)
|
|||||||
return backupSize;
|
return backupSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ClearProtectInfoEntry(HFlashProtectInfo *info)
|
||||||
|
{
|
||||||
|
#if HFLASH_USE_BITMAP
|
||||||
|
HBitMapType *bitMap = info->bitMap;
|
||||||
|
memset(info, 0, sizeof(HFlashProtectInfo));
|
||||||
|
info->bitMap = bitMap;
|
||||||
|
if (bitMap != NULL) {
|
||||||
|
HBitMapFill(bitMap, 0);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
memset(info, 0, sizeof(HFlashProtectInfo));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static void SyncBackup()
|
static void SyncBackup()
|
||||||
{
|
{
|
||||||
LogD("Start sync Backup");
|
LogD("Start sync Backup");
|
||||||
@ -521,6 +553,34 @@ static void SyncBackup()
|
|||||||
sBackupTimer = HTIMER_INVALID;
|
sBackupTimer = HTIMER_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if HFLASH_USE_BITMAP
|
||||||
|
for (uint16_t i = 0; i < sInfo.protectUseNum; ++i) {
|
||||||
|
HFlashAddr_t protectStartAddr = 0;
|
||||||
|
uint32_t backupSize = 0;
|
||||||
|
if (GetProtectBackupRange(sInfo.protectInfo[i].addr, sInfo.protectInfo[i].size, &protectStartAddr, &backupSize) == 0) {
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
(void)backupSize;
|
||||||
|
HBitMapIndexType index = 0;
|
||||||
|
for (;;) {
|
||||||
|
index = HBitMapFindFirstSetBitIndex(sInfo.protectInfo[i].bitMap, index);
|
||||||
|
if (index == kHBitMapInvalidIndex) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint32_t addr = protectStartAddr + CALC_FLASH_BITMAP_OFFSET(index);
|
||||||
|
if (SyncBackupRange(addr, HFLASH_BLOCK_SIZE) == 0) {
|
||||||
|
LogE("RestorePage faild, addr[0x%08x]", addr);
|
||||||
|
StartSyncBackupTimer();
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
HBitMapSetBit(sInfo.protectInfo[i].bitMap, index, 0);
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
for (HVectorLenType remain = HVectorGetUseLen(sNeedBackupOffset); remain > 0; --remain) {
|
for (HVectorLenType remain = HVectorGetUseLen(sNeedBackupOffset); remain > 0; --remain) {
|
||||||
const uint32_t addr = HVectorGetData(sNeedBackupOffset, remain - 1);
|
const uint32_t addr = HVectorGetData(sNeedBackupOffset, remain - 1);
|
||||||
if (SyncBackupRange(addr, HFLASH_BLOCK_SIZE) == 0) {
|
if (SyncBackupRange(addr, HFLASH_BLOCK_SIZE) == 0) {
|
||||||
@ -531,6 +591,7 @@ static void SyncBackup()
|
|||||||
|
|
||||||
HVectorSetUseLen(sNeedBackupOffset, remain - 1);
|
HVectorSetUseLen(sNeedBackupOffset, remain - 1);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// 备份页表数据
|
// 备份页表数据
|
||||||
const uint32_t crcValue = GetBackupCrc32(AdjustPageAddr(sInfo.pageAddr), AdjustPageByte(sPageInfo.useNum));
|
const uint32_t crcValue = GetBackupCrc32(AdjustPageAddr(sInfo.pageAddr), AdjustPageByte(sPageInfo.useNum));
|
||||||
@ -550,8 +611,27 @@ static void StartSyncBackupTimer()
|
|||||||
sBackupTimer = HTimerAdd(HFLASH_TIMER_ID, HFLASH_SYNC_BACKUP_TIME, SyncBackup, kHTimerOnce);
|
sBackupTimer = HTimerAdd(HFLASH_TIMER_ID, HFLASH_SYNC_BACKUP_TIME, SyncBackup, kHTimerOnce);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _AddBackupAddr(uint32_t addr)
|
static void _AddBackupAddr(uint32_t addr, int16_t protecIndex)
|
||||||
{
|
{
|
||||||
|
#if HFLASH_USE_BITMAP
|
||||||
|
HFlashAddr_t protectStartAddr = 0;
|
||||||
|
uint32_t backupSize = 0;
|
||||||
|
HFlashProtectInfo *info = &sInfo.protectInfo[protecIndex];
|
||||||
|
if (GetProtectBackupRange(info->addr, info->size, &protectStartAddr, &backupSize) == 0) {
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addr < protectStartAddr || addr >= (protectStartAddr + backupSize)) {
|
||||||
|
LogE("protect bitmap addr[0x%08x] out of range[0x%08x][0x%08x]",
|
||||||
|
addr,
|
||||||
|
protectStartAddr,
|
||||||
|
protectStartAddr + backupSize);
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
HBitMapSetBit(info->bitMap, (addr - protectStartAddr) >> 12, 1);
|
||||||
|
LogD("Add wait sync addr[0x%08x]", addr);
|
||||||
|
#else
|
||||||
do {
|
do {
|
||||||
const HVectorLenType index = HVectorFindData(sNeedBackupOffset, addr);
|
const HVectorLenType index = HVectorFindData(sNeedBackupOffset, addr);
|
||||||
if (index != HVECTOR_ERROR) {
|
if (index != HVECTOR_ERROR) {
|
||||||
@ -571,12 +651,14 @@ static void _AddBackupAddr(uint32_t addr)
|
|||||||
} while (0);
|
} while (0);
|
||||||
|
|
||||||
LogD("Add wait sync addr[0x%08x], size[%d]", addr, HVectorGetUseLen(sNeedBackupOffset));
|
LogD("Add wait sync addr[0x%08x], size[%d]", addr, HVectorGetUseLen(sNeedBackupOffset));
|
||||||
|
#endif
|
||||||
StartSyncBackupTimer();
|
StartSyncBackupTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void AddBackupAddr(uint32_t addr, uint32_t size)
|
static void AddBackupAddr(uint32_t addr, uint32_t size)
|
||||||
{
|
{
|
||||||
if (IsProtect(addr, size) == 0) {
|
int16_t protectIndex = FindProtectIndex(addr, size);
|
||||||
|
if (protectIndex < 0) {
|
||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -585,24 +667,20 @@ static void AddBackupAddr(uint32_t addr, uint32_t size)
|
|||||||
const uint16_t offset = addr - adjustAddr;
|
const uint16_t offset = addr - adjustAddr;
|
||||||
uint32_t remain = offset + size > HFLASH_BLOCK_SIZE ? HFLASH_BLOCK_SIZE - offset : size;
|
uint32_t remain = offset + size > HFLASH_BLOCK_SIZE ? HFLASH_BLOCK_SIZE - offset : size;
|
||||||
|
|
||||||
_AddBackupAddr(adjustAddr);
|
_AddBackupAddr(adjustAddr, protectIndex);
|
||||||
size -= remain;
|
size -= remain;
|
||||||
adjustAddr += HFLASH_BLOCK_SIZE;
|
adjustAddr += HFLASH_BLOCK_SIZE;
|
||||||
for (; size >= HFLASH_BLOCK_SIZE; adjustAddr += HFLASH_BLOCK_SIZE, size -= HFLASH_BLOCK_SIZE) {
|
for (; size >= HFLASH_BLOCK_SIZE; adjustAddr += HFLASH_BLOCK_SIZE, size -= HFLASH_BLOCK_SIZE) {
|
||||||
_AddBackupAddr(adjustAddr);
|
_AddBackupAddr(adjustAddr, protectIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size) {
|
if (size) {
|
||||||
_AddBackupAddr(adjustAddr);
|
_AddBackupAddr(adjustAddr, protectIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void AddBackupOffsetAddr(uint32_t addr, uint32_t offset, uint32_t size)
|
static void AddBackupOffsetAddr(uint32_t addr, uint32_t offset, uint32_t size)
|
||||||
{
|
{
|
||||||
if (IsProtect(addr, size) == 0) {
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
|
|
||||||
AddBackupAddr(addr + offset, size);
|
AddBackupAddr(addr + offset, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1164,22 +1242,42 @@ void HFlashSetPageCache(HFlashCacheInfo *pageInfo, uint16_t size)
|
|||||||
sInfo.pageCacheSize = size;
|
sInfo.pageCacheSize = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HFlashInitProtectCache(HFlashProtectInfo *protectInfo, void *bitMap, uint32_t size)
|
||||||
|
{
|
||||||
|
memset(protectInfo, 0, sizeof(HFlashProtectInfo));
|
||||||
|
#if HFLASH_USE_BITMAP
|
||||||
|
if (HBitMapInit(bitMap, HFLASH_CALC_BITMAP_SIZE(size)) == 0) {
|
||||||
|
FATAL_ERROR("bitmap init fail");
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
protectInfo->bitMap = bitMap;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void HFlashSetProtectCache(HFlashProtectInfo *protectInfo, uint16_t size)
|
void HFlashSetProtectCache(HFlashProtectInfo *protectInfo, uint16_t size)
|
||||||
{
|
{
|
||||||
ResetRuntimeState();
|
ResetRuntimeState();
|
||||||
sInfo.protectInfo = protectInfo;
|
sInfo.protectInfo = protectInfo;
|
||||||
sInfo.protectCacheSize = size;
|
sInfo.protectCacheSize = size;
|
||||||
sInfo.protectUseNum = 0;
|
sInfo.protectUseNum = 0;
|
||||||
|
#if HFLASH_USE_BITMAP
|
||||||
|
for (uint16_t i = 0; i < size; ++i) {
|
||||||
|
if (sInfo.protectInfo[i].bitMap != NULL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (protectInfo != NULL && size) {
|
FATAL_ERROR("protect cache[0x%08x] not init", sInfo.protectInfo[i].addr);
|
||||||
memset(protectInfo, 0, size * sizeof(HFlashProtectInfo));
|
return ;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void HFlashSetPageAddr(HFlashAddr_t addr, uint32_t size)
|
void HFlashSetPageAddr(HFlashAddr_t addr, uint32_t size)
|
||||||
{
|
{
|
||||||
if (IS_NOT_4K(addr) || IS_NOT_4K(size)) {
|
if (IS_NOT_4K(addr) || IS_NOT_4K(size)) {
|
||||||
FATAL_ERROR("not align page size[0x%08x], size[%x]", addr, size);
|
FATAL_ERROR("not align page size[0x%08x], size[%x]", addr, size);
|
||||||
|
return ;
|
||||||
}
|
}
|
||||||
|
|
||||||
sInfo.pageAddr = addr;
|
sInfo.pageAddr = addr;
|
||||||
@ -1270,7 +1368,9 @@ void HFlashClearProtectAddr()
|
|||||||
ResetRuntimeState();
|
ResetRuntimeState();
|
||||||
sInfo.protectUseNum = 0;
|
sInfo.protectUseNum = 0;
|
||||||
if (sInfo.protectInfo != NULL && sInfo.protectCacheSize) {
|
if (sInfo.protectInfo != NULL && sInfo.protectCacheSize) {
|
||||||
memset(sInfo.protectInfo, 0, sInfo.protectCacheSize * sizeof(HFlashProtectInfo));
|
for (uint16_t i = 0; i < sInfo.protectCacheSize; ++i) {
|
||||||
|
ClearProtectInfoEntry(&sInfo.protectInfo[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1302,6 +1402,13 @@ void HFlashAddProtectAddr(HFlashAddr_t addr, uint32_t size, HFlashAddr_t backupA
|
|||||||
}
|
}
|
||||||
|
|
||||||
HFlashProtectInfo *info = &sInfo.protectInfo[sInfo.protectUseNum];
|
HFlashProtectInfo *info = &sInfo.protectInfo[sInfo.protectUseNum];
|
||||||
|
ClearProtectInfoEntry(info);
|
||||||
|
#if HFLASH_USE_BITMAP
|
||||||
|
if (HBitMapGetBitLen(info->bitMap) < (AdjustProtectBackupSize(addr, size) >> 12)) {
|
||||||
|
FATAL_ERROR("protect addr[0x%08x] bitmap too small", addr);
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
info->addr = addr;
|
info->addr = addr;
|
||||||
info->size = size;
|
info->size = size;
|
||||||
info->backupAddr = backupAddr;
|
info->backupAddr = backupAddr;
|
||||||
@ -1318,11 +1425,18 @@ void HFlashDelProtectAddr(HFlashAddr_t addr)
|
|||||||
|
|
||||||
ResetRuntimeState();
|
ResetRuntimeState();
|
||||||
for (uint16_t i = (uint16_t)index; i + 1 < sInfo.protectUseNum; ++i) {
|
for (uint16_t i = (uint16_t)index; i + 1 < sInfo.protectUseNum; ++i) {
|
||||||
|
#if HFLASH_USE_BITMAP
|
||||||
|
HBitMapType *currBitMap = sInfo.protectInfo[i].bitMap;
|
||||||
sInfo.protectInfo[i] = sInfo.protectInfo[i + 1];
|
sInfo.protectInfo[i] = sInfo.protectInfo[i + 1];
|
||||||
|
sInfo.protectInfo[i].bitMap = currBitMap;
|
||||||
|
HBitMapFill(sInfo.protectInfo[i].bitMap, 0);
|
||||||
|
#else
|
||||||
|
sInfo.protectInfo[i] = sInfo.protectInfo[i + 1];
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
--sInfo.protectUseNum;
|
--sInfo.protectUseNum;
|
||||||
memset(&sInfo.protectInfo[sInfo.protectUseNum], 0, sizeof(HFlashProtectInfo));
|
ClearProtectInfoEntry(&sInfo.protectInfo[sInfo.protectUseNum]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t CheckBackupArea()
|
static uint8_t CheckBackupArea()
|
||||||
@ -1537,6 +1651,18 @@ static uint8_t _CheckOverLap(uint32_t index, HFlashPageInfo *info, void *userDat
|
|||||||
|
|
||||||
return IsOverLap(info->addr, info->size, cache->info.addr, cache->info.size);
|
return IsOverLap(info->addr, info->size, cache->info.addr, cache->info.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint8_t HasProtectOverlap(HFlashAddr_t addr, uint32_t size)
|
||||||
|
{
|
||||||
|
for (uint16_t i = 0; i < sInfo.protectUseNum; ++i) {
|
||||||
|
if (IsOverLap(addr, size, sInfo.protectInfo[i].addr, sInfo.protectInfo[i].size)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void HFlashRegister(HFlashAddr_t addr, uint32_t size)
|
void HFlashRegister(HFlashAddr_t addr, uint32_t size)
|
||||||
{
|
{
|
||||||
if (IS_NOT_4(size)) {
|
if (IS_NOT_4(size)) {
|
||||||
@ -1544,6 +1670,11 @@ void HFlashRegister(HFlashAddr_t addr, uint32_t size)
|
|||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (HasProtectOverlap(addr, size) && IsProtect(addr, size) == 0) {
|
||||||
|
FATAL_ERROR("addr[0x%08x] size[%d] partial overlap protect range", addr, size);
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
HFlashCacheInfo *cache = FindCache(addr);
|
HFlashCacheInfo *cache = FindCache(addr);
|
||||||
if (cache == NULL) {
|
if (cache == NULL) {
|
||||||
// 首次创建页表, 不需要检查
|
// 首次创建页表, 不需要检查
|
||||||
@ -1646,12 +1777,10 @@ uint8_t HFlashWrite(HFlashAddr_t addr, const void *data, uint32_t size)
|
|||||||
cache->info.useSize = size;
|
cache->info.useSize = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新crc, 写入数据后再更新页表
|
|
||||||
HSCrc32Reset();
|
|
||||||
HSCrc32Update((uint8_t *)data, cache->info.useSize);
|
|
||||||
cache->info.crc32 = HSCrc32Get();
|
|
||||||
|
|
||||||
result = WriteFlash(addr, data, size);
|
result = WriteFlash(addr, data, size);
|
||||||
|
if (result) {
|
||||||
|
cache->info.crc32 = GetFlashCrc32(addr, cache->info.useSize);
|
||||||
|
}
|
||||||
WriteCachePage(cache);
|
WriteCachePage(cache);
|
||||||
|
|
||||||
// 检查是否在保护区域, 需要的话需要写入等待备份
|
// 检查是否在保护区域, 需要的话需要写入等待备份
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user