1. 避免不间断不断执行问题
This commit is contained in:
parent
9cd7eb2499
commit
df494faf2d
@ -12,6 +12,15 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// 使用位图模块映射保护区
|
||||
#ifndef HFLASH_USE_BITMAP
|
||||
#define HFLASH_USE_BITMAP 1
|
||||
#endif
|
||||
|
||||
#if HFLASH_USE_BITMAP
|
||||
#include "HBitMap.h"
|
||||
#endif
|
||||
|
||||
// 使用HShell
|
||||
#ifndef HFLASH_USE_HSHELL
|
||||
#define HFLASH_USE_HSHELL 1
|
||||
@ -24,7 +33,7 @@
|
||||
|
||||
#ifndef USE_STD_MEM
|
||||
#ifndef HFLASH_USE_FLASH_MEM
|
||||
#include "HDSendBuffer.h"
|
||||
#include "HSendBuffer.h"
|
||||
#endif // HFLASH_USE_FLASH_MEM
|
||||
#endif
|
||||
|
||||
@ -39,7 +48,7 @@
|
||||
#ifdef USE_STD_MEM
|
||||
#define HFLASH_MALLOC(size) malloc(size)
|
||||
#else
|
||||
#define HFLASH_MALLOC(size) HDSendBufferGet(size)
|
||||
#define HFLASH_MALLOC(size) HSendBufferGet(size)
|
||||
#endif // USE_STD_MEM
|
||||
#endif // HFLASH_MALLOC
|
||||
|
||||
@ -48,7 +57,7 @@
|
||||
#ifdef USE_STD_MEM
|
||||
#define HFLASH_FREE(ptr) free(ptr)
|
||||
#else
|
||||
#define HFLASH_FREE(ptr) HDSendBufferFree(ptr)
|
||||
#define HFLASH_FREE(ptr) HSendBufferFree(ptr)
|
||||
#endif // USE_STD_MEM
|
||||
#endif // HFLASH_FREE
|
||||
#endif // HFLASH_USE_FLASH_MEM
|
||||
@ -90,10 +99,34 @@ typedef union 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 {
|
||||
HFlashAddr_t addr; ///< 保护区地址
|
||||
uint32_t size; ///< 保护区大小
|
||||
HFlashAddr_t backupAddr; ///< 保护区备份地址
|
||||
#if HFLASH_USE_BITMAP
|
||||
HBitMapType *bitMap; ///< 保护区需保存的位图, 4k基准
|
||||
#endif
|
||||
} HFlashProtectInfo;
|
||||
|
||||
typedef struct HFlashCacheInfo {
|
||||
@ -160,6 +193,15 @@ uint16_t HFlashGetVersion(HFlashAddr_t addr, HFlashVersionInfo *info);
|
||||
*/
|
||||
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 设置保护区描述缓存, 内部不构建内存, 由外部分配
|
||||
* 需要在设置保护地址前调用
|
||||
|
||||
146
src/HFlashMem.c
146
src/HFlashMem.c
@ -23,8 +23,8 @@
|
||||
// 最大热度
|
||||
#define MAX_HEAT ((1 << 5) - 1)
|
||||
|
||||
// 写转读增加热度
|
||||
#define WRITE_CONV_READ_ADD_HEAT (2)
|
||||
// 写回后保留的最低热度, 避免刚刷回立刻被淘汰
|
||||
#define WRITE_BACK_KEEP_HEAT (2)
|
||||
|
||||
// 读最小热度
|
||||
#define READ_MIN_HEAT (0)
|
||||
@ -100,8 +100,10 @@ static void SyncCache()
|
||||
sOpts->cache[i].isDirty = 0;
|
||||
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].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;
|
||||
}
|
||||
|
||||
@ -204,8 +208,10 @@ static void CheckSyncCache()
|
||||
sOpts->cache[i].isDirty = 0;
|
||||
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) {
|
||||
@ -229,7 +235,7 @@ static void StartSyncCache()
|
||||
sCheckTimer = HTIMER_INVALID;
|
||||
}
|
||||
|
||||
sCheckTimer = HTimerAdd(HFLASH_TIMER_ID, 0, CheckSyncCache, kHTimerLoop);
|
||||
sCheckTimer = HTimerAdd(HFLASH_TIMER_ID, 1, CheckSyncCache, kHTimerLoop);
|
||||
}
|
||||
|
||||
static void ScheduleHeat()
|
||||
@ -250,6 +256,39 @@ static void ScheduleHeat()
|
||||
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()
|
||||
{
|
||||
int16_t index = -1;
|
||||
@ -290,45 +329,25 @@ static HFlashMemCache *FindReadCache(uint32_t addr, uint8_t needRead)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (uint16_t i = 0; i < sInfo.useNum; ++i) {
|
||||
if (addr != sOpts->cache[i].addr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
sOpts->cache[i].heat = FAST_MIN(uint8_t, sOpts->cache[i].heat + 1, MAX_HEAT);
|
||||
return sOpts->cache + i;
|
||||
HFlashMemCache *cache = FindCacheByAddr(addr);
|
||||
if (cache) {
|
||||
cache->heat = FAST_MIN(uint8_t, cache->heat + 1, MAX_HEAT);
|
||||
return cache;
|
||||
}
|
||||
|
||||
// 如果缓存没有满, 直接增加
|
||||
if (sInfo.useNum < sOpts->cacheSize) {
|
||||
const uint16_t index = sInfo.useNum;
|
||||
++sInfo.useNum;
|
||||
if (needRead) {
|
||||
WatiErase();
|
||||
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;
|
||||
cache = AllocCache();
|
||||
}
|
||||
if (cache == NULL) {
|
||||
cache = FindMinHeatCache();
|
||||
}
|
||||
|
||||
// 查找空闲的最低热度页
|
||||
HFlashMemCache *cache = FindMinHeatCache();
|
||||
if (cache == NULL || cache->heat > READ_MIN_HEAT) {
|
||||
if (cache == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const uint16_t index = cache->offset;
|
||||
memset(cache, 0, sizeof(HFlashMemCache));
|
||||
cache->addr = addr;
|
||||
cache->offset = index;
|
||||
cache->heat = READ_MIN_HEAT;
|
||||
ResetCache(cache, addr, index);
|
||||
|
||||
if (needRead) {
|
||||
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;
|
||||
}
|
||||
|
||||
@ -349,8 +369,29 @@ static HFlashMemCache *FindWriteCache(uint32_t addr, uint8_t needRead)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HFlashMemCache *cache = FindReadCache(addr, needRead);
|
||||
HFlashMemCache *cache = FindCacheByAddr(addr);
|
||||
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;
|
||||
}
|
||||
|
||||
@ -364,10 +405,7 @@ static HFlashMemCache *FindWriteCache(uint32_t addr, uint8_t needRead)
|
||||
}
|
||||
|
||||
const uint16_t index = cache->offset;
|
||||
memset(cache, 0, sizeof(HFlashMemCache));
|
||||
cache->addr = addr;
|
||||
cache->offset = index;
|
||||
cache->heat = READ_MIN_HEAT;
|
||||
ResetCache(cache, addr, index);
|
||||
if (needRead) {
|
||||
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;
|
||||
}
|
||||
|
||||
@ -501,6 +540,24 @@ void HFlashMemInit(HFlashMemOpts *opts)
|
||||
FATAL_ERROR("flash Size not 4k align");
|
||||
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()
|
||||
@ -661,4 +718,3 @@ void HFlashMemFreeCache()
|
||||
sInfo.useNum = 0;
|
||||
sInfo.currHeatTime = HDLogGetTime();
|
||||
}
|
||||
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
|
||||
#include "HFlashServer.h"
|
||||
#include "HDLog.h"
|
||||
#include "HVector.h"
|
||||
#include "HTimer.h"
|
||||
#if HFLASH_USE_HSHELL
|
||||
#include "HShellLex.h"
|
||||
@ -20,6 +19,9 @@
|
||||
#include "HSCrc32.h"
|
||||
#endif
|
||||
|
||||
#if !HFLASH_USE_BITMAP
|
||||
#include "HVector.h"
|
||||
#endif
|
||||
|
||||
#ifdef USE_STD_MEM
|
||||
#include <nmmintrin.h>
|
||||
@ -66,6 +68,11 @@ void HDMainLoopCallOverride(uint8_t event)
|
||||
#define IS_NOT_4K(size) ((size & (HFLASH_BLOCK_SIZE - 1)) != 0)
|
||||
#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
|
||||
enum eShell
|
||||
{
|
||||
@ -133,8 +140,10 @@ static HTimer_t sSyncPageTimer = HTIMER_INVALID;
|
||||
// 同步页表缓存定时器
|
||||
static HTimer_t sSyncCacheTimer = HTIMER_INVALID;
|
||||
|
||||
#if !HFLASH_USE_BITMAP
|
||||
// 存储需要备份的保护区地址页偏移
|
||||
static HVECTOR_DEFINE32(sNeedBackupOffset, 10);
|
||||
#endif
|
||||
|
||||
static uint8_t RestoreBackup(HFlashAddr_t srcAddr, HFlashAddr_t dstAddr, 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 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 void ClearProtectInfoEntry(HFlashProtectInfo *info);
|
||||
|
||||
static void ResetRuntimeState()
|
||||
{
|
||||
@ -172,7 +182,15 @@ static void ResetRuntimeState()
|
||||
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);
|
||||
#endif
|
||||
}
|
||||
|
||||
///< 检查地址是否在双备份保护区内
|
||||
@ -513,6 +531,20 @@ static inline uint32_t AdjustProtectBackupSize(HFlashAddr_t addr, uint32_t size)
|
||||
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()
|
||||
{
|
||||
LogD("Start sync Backup");
|
||||
@ -521,6 +553,34 @@ static void SyncBackup()
|
||||
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) {
|
||||
const uint32_t addr = HVectorGetData(sNeedBackupOffset, remain - 1);
|
||||
if (SyncBackupRange(addr, HFLASH_BLOCK_SIZE) == 0) {
|
||||
@ -531,6 +591,7 @@ static void SyncBackup()
|
||||
|
||||
HVectorSetUseLen(sNeedBackupOffset, remain - 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
// 备份页表数据
|
||||
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);
|
||||
}
|
||||
|
||||
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 {
|
||||
const HVectorLenType index = HVectorFindData(sNeedBackupOffset, addr);
|
||||
if (index != HVECTOR_ERROR) {
|
||||
@ -571,12 +651,14 @@ static void _AddBackupAddr(uint32_t addr)
|
||||
} while (0);
|
||||
|
||||
LogD("Add wait sync addr[0x%08x], size[%d]", addr, HVectorGetUseLen(sNeedBackupOffset));
|
||||
#endif
|
||||
StartSyncBackupTimer();
|
||||
}
|
||||
|
||||
static void AddBackupAddr(uint32_t addr, uint32_t size)
|
||||
{
|
||||
if (IsProtect(addr, size) == 0) {
|
||||
int16_t protectIndex = FindProtectIndex(addr, size);
|
||||
if (protectIndex < 0) {
|
||||
return ;
|
||||
}
|
||||
|
||||
@ -585,24 +667,20 @@ static void AddBackupAddr(uint32_t addr, uint32_t size)
|
||||
const uint16_t offset = addr - adjustAddr;
|
||||
uint32_t remain = offset + size > HFLASH_BLOCK_SIZE ? HFLASH_BLOCK_SIZE - offset : size;
|
||||
|
||||
_AddBackupAddr(adjustAddr);
|
||||
_AddBackupAddr(adjustAddr, protectIndex);
|
||||
size -= remain;
|
||||
adjustAddr += HFLASH_BLOCK_SIZE;
|
||||
for (; size >= HFLASH_BLOCK_SIZE; adjustAddr += HFLASH_BLOCK_SIZE, size -= HFLASH_BLOCK_SIZE) {
|
||||
_AddBackupAddr(adjustAddr);
|
||||
_AddBackupAddr(adjustAddr, protectIndex);
|
||||
}
|
||||
|
||||
if (size) {
|
||||
_AddBackupAddr(adjustAddr);
|
||||
_AddBackupAddr(adjustAddr, protectIndex);
|
||||
}
|
||||
}
|
||||
|
||||
static void AddBackupOffsetAddr(uint32_t addr, uint32_t offset, uint32_t size)
|
||||
{
|
||||
if (IsProtect(addr, size) == 0) {
|
||||
return ;
|
||||
}
|
||||
|
||||
AddBackupAddr(addr + offset, size);
|
||||
}
|
||||
|
||||
@ -1164,22 +1242,42 @@ void HFlashSetPageCache(HFlashCacheInfo *pageInfo, uint16_t 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)
|
||||
{
|
||||
ResetRuntimeState();
|
||||
sInfo.protectInfo = protectInfo;
|
||||
sInfo.protectCacheSize = size;
|
||||
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) {
|
||||
memset(protectInfo, 0, size * sizeof(HFlashProtectInfo));
|
||||
FATAL_ERROR("protect cache[0x%08x] not init", sInfo.protectInfo[i].addr);
|
||||
return ;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void HFlashSetPageAddr(HFlashAddr_t addr, uint32_t size)
|
||||
{
|
||||
if (IS_NOT_4K(addr) || IS_NOT_4K(size)) {
|
||||
FATAL_ERROR("not align page size[0x%08x], size[%x]", addr, size);
|
||||
return ;
|
||||
}
|
||||
|
||||
sInfo.pageAddr = addr;
|
||||
@ -1270,7 +1368,9 @@ void HFlashClearProtectAddr()
|
||||
ResetRuntimeState();
|
||||
sInfo.protectUseNum = 0;
|
||||
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];
|
||||
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->size = size;
|
||||
info->backupAddr = backupAddr;
|
||||
@ -1318,11 +1425,18 @@ void HFlashDelProtectAddr(HFlashAddr_t addr)
|
||||
|
||||
ResetRuntimeState();
|
||||
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].bitMap = currBitMap;
|
||||
HBitMapFill(sInfo.protectInfo[i].bitMap, 0);
|
||||
#else
|
||||
sInfo.protectInfo[i] = sInfo.protectInfo[i + 1];
|
||||
#endif
|
||||
}
|
||||
|
||||
--sInfo.protectUseNum;
|
||||
memset(&sInfo.protectInfo[sInfo.protectUseNum], 0, sizeof(HFlashProtectInfo));
|
||||
ClearProtectInfoEntry(&sInfo.protectInfo[sInfo.protectUseNum]);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (IS_NOT_4(size)) {
|
||||
@ -1544,6 +1670,11 @@ void HFlashRegister(HFlashAddr_t addr, uint32_t size)
|
||||
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);
|
||||
if (cache == NULL) {
|
||||
// 首次创建页表, 不需要检查
|
||||
@ -1646,12 +1777,10 @@ uint8_t HFlashWrite(HFlashAddr_t addr, const void *data, uint32_t size)
|
||||
cache->info.useSize = size;
|
||||
}
|
||||
|
||||
// 更新crc, 写入数据后再更新页表
|
||||
HSCrc32Reset();
|
||||
HSCrc32Update((uint8_t *)data, cache->info.useSize);
|
||||
cache->info.crc32 = HSCrc32Get();
|
||||
|
||||
result = WriteFlash(addr, data, size);
|
||||
if (result) {
|
||||
cache->info.crc32 = GetFlashCrc32(addr, cache->info.useSize);
|
||||
}
|
||||
WriteCachePage(cache);
|
||||
|
||||
// 检查是否在保护区域, 需要的话需要写入等待备份
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user