1. 修复偏移读取的问题

This commit is contained in:
coffee 2025-12-03 16:51:27 +08:00
parent 276218d3e0
commit a902eb38c8
2 changed files with 167 additions and 24 deletions

View File

@ -63,6 +63,7 @@ typedef union HFlashPageInfo {
uint32_t useSize : 24; ///< 使用大小
uint16_t version; ///< 当前页数据的版本
uint32_t modifyCount; ///< 修改次数
uint8_t invalid : 1; ///< 无效标志
};
} HFlashPageInfo;
@ -162,7 +163,7 @@ void HFlashRegister(HFlashAddr_t addr, uint32_t size);
* @param size
* @return 1: 0:
*/
uint8_t HFlashWrite(HFlashAddr_t addr, void *data, uint32_t size);
uint8_t HFlashWrite(HFlashAddr_t addr, const void *data, uint32_t size);
/**
* @brief HFlashWriteOffset , 使, 0
@ -172,7 +173,17 @@ uint8_t HFlashWrite(HFlashAddr_t addr, void *data, uint32_t size);
* @param size
* @return 1: 0:
*/
uint8_t HFlashWriteOffset(HFlashAddr_t addr, uint32_t offset, void *data, uint32_t size);
uint8_t HFlashWriteOffset(HFlashAddr_t addr, uint32_t offset, const void *data, uint32_t size);
/**
* @brief HFlashWriteRawOffset Flash数据, , CRC, 使, 使
* @param addr
* @param offset
* @param data
* @param size
* @return 1: 0:
*/
uint8_t HFlashWriteRawOffset(HFlashAddr_t addr, uint32_t offset, const void *data, uint32_t size);
/**
* @brief HFlashStreamBegin , 使
@ -187,7 +198,7 @@ void HFlashStreamBegin(HFlashAddr_t addr);
* @param size
* @return 1: 0:
*/
uint8_t HFlashStreamWrite(HFlashAddr_t addr, void *data, uint32_t size);
uint8_t HFlashStreamWrite(HFlashAddr_t addr, const void *data, uint32_t size);
/**
* @brief HFlashStreamEnd , CRC
@ -202,7 +213,7 @@ void HFlashStreamEnd(HFlashAddr_t addr);
* @param size
* @return 1: 0:
*/
uint8_t HFlashRawWrite(HFlashAddr_t addr, void *data, uint32_t size);
uint8_t HFlashRawWrite(HFlashAddr_t addr, const void *data, uint32_t size);
/**
* @brief HFlashRead Flash数据

View File

@ -39,7 +39,7 @@ uint32_t HSCrc32Get()
#ifdef USE_STD_MEM
#define FATAL_ERROR(format, ...) LogE(format, ##__VA_ARGS__);
#else
#define FATAL_ERROR(format, ...) LogE(format, ##__VA_ARGS__); while(1);
#define FATAL_ERROR(format, ...) while (1) { LogE(format, ##__VA_ARGS__); HShellRun(); };
#endif
// 最大热度
@ -50,12 +50,16 @@ uint32_t HSCrc32Get()
enum eShell
{
kShellPageInfo, ///< 查看页表信息
kShellPageInfo, ///< 查看页表信息
kShellDelUseDataPage, ///< 删除页表使用数据
kShellDelPage, ///< 删除页
kShellMax,
};
static HShellMatch sShellMatch[] = {
HSHELL_MATCH_ITEM(kShellPageInfo, "pageInfo"),
HSHELL_MATCH_ITEM(kShellDelUseDataPage, "pagedelUseData"),
HSHELL_MATCH_ITEM(kShellDelPage, "pageDel"),
};
@ -90,12 +94,19 @@ static union PageInfo sPageInfo;
// 备份定时器
static HTimer_t sBackupTimer = HTIMER_INVALID;
// 需要备份的保护区地址页偏移
// 延后计算CRC定时器
static HTimer_t sDelayCrc32Timer = HTIMER_INVALID;
// 存储需要备份的保护区地址页偏移
static HVECTOR_DEFINE32(sNeedBackupOffset, 10);
// 存储需要延后计算CRC的记录地址
static HVECTOR_DEFINE32(sDelayCalcCrc32, 3);
static uint8_t RestoreBackup(HFlashAddr_t srcAddr, HFlashAddr_t dstAddr, uint32_t size);
static void StartBackupTimer();
static HFlashCacheInfo *FindCache(HFlashAddr_t addr);
static void WriteCachePage(HFlashCacheInfo *info);
///< 检查地址是否在双备份保护区内
static uint8_t IsProtect(HFlashAddr_t addr, uint32_t size)
@ -147,7 +158,7 @@ static uint8_t EraseFlash(HFlashAddr_t addr)
* @param call , dest缓存, src已经调整好位置的指针, buffSize需要拷贝的数据大小, userData用户数据
* @return
*/
static uint8_t WriteData(HFlashAddr_t addr, void *data, uint32_t size, void(*call)(void *dest, const void *src, uint16_t buffSize, void *userData), void *userData)
static uint8_t WriteData(HFlashAddr_t addr, const void *data, uint32_t size, void(*call)(void *dest, const void *src, uint16_t buffSize, void *userData), void *userData)
{
if (sInfo.write == NULL) {
FATAL_ERROR("write is null");
@ -231,7 +242,7 @@ static void _WriteFlashHelper(void *dest, const void *src, uint16_t buffSize, vo
memcpy(dest, src, buffSize);
}
static uint8_t WriteFlash(HFlashAddr_t addr, void *data, uint32_t size)
static uint8_t WriteFlash(HFlashAddr_t addr, const void *data, uint32_t size)
{
return WriteData(addr, data, size, _WriteFlashHelper, NULL);
}
@ -334,7 +345,6 @@ static void AddBackupAddr(uint32_t addr, uint32_t size)
}
}
static uint32_t GetFlashCrc32(HFlashAddr_t addr, uint32_t size)
{
if (size == 0) {
@ -362,6 +372,57 @@ static uint32_t GetFlashCrc32(HFlashAddr_t addr, uint32_t size)
return HSCrc32Get();
}
static void SyncDelayCrc32()
{
LogD("Start sync DelayCrc32");
if (sDelayCrc32Timer != HTIMER_INVALID) {
HTimerRemove(sDelayCrc32Timer);
sDelayCrc32Timer = HTIMER_INVALID;
}
for (uint16_t i = 0; i < HVectorGetUseLen(sDelayCalcCrc32); ++i) {
const uint32_t addr = HVectorGetData(sDelayCalcCrc32, i);
HFlashCacheInfo *cache = FindCache(addr);
if (cache == NULL) {
LogE("addr[0x%08x], cache not found", addr);
continue;
}
cache->info.crc32 = GetFlashCrc32(addr, cache->info.useSize);
WriteCachePage(cache);
}
HVectorClear(sDelayCalcCrc32);
}
static void StartDelayCrc32Timer()
{
if (sDelayCrc32Timer != HTIMER_INVALID) {
HTimerRemove(sDelayCrc32Timer);
sDelayCrc32Timer = HTIMER_INVALID;
}
sDelayCrc32Timer = HTimerAdd(HFLASH_TIMER_ID, HFLASH_SYNC_TIME, SyncDelayCrc32, kHTimerOnce);
}
static void AddDelayCrc32(HFlashAddr_t addr)
{
do {
const HVectorLenType index = HVectorFindData(sDelayCalcCrc32, addr);
if (index != HVECTOR_ERROR) {
break;
}
if (HVectorAddData(sDelayCalcCrc32, addr)) {
break;
}
SyncDelayCrc32();
} while (0);
StartDelayCrc32Timer();
}
static uint8_t RestoreBackup(HFlashAddr_t srcAddr, HFlashAddr_t dstAddr, uint32_t size)
{
const uint16_t mallocSize = 1024;
@ -534,10 +595,25 @@ static uint8_t ScanPage(uint8_t (*call)(uint32_t index, HFlashPageInfo *info, vo
///< 检查是否重叠, 重叠返回1
static uint8_t _CreatePageInfoHelper(uint32_t index, HFlashPageInfo *info, void *userData)
{
if (info->invalid) {
return 0;
}
HFlashPageInfo *cache = (HFlashPageInfo *)userData;
return IsOverLap(info->addr, info->size, cache->addr, cache->size);
}
static uint8_t ScanAvailablePage(uint32_t index, HFlashPageInfo *info, void *userData)
{
uint32_t *result = (uint32_t *)userData;
if (info->invalid == 0) {
return 0;
}
*result = index;
return 1;
}
static uint8_t CreatePageInfo(HFlashAddr_t addr, uint32_t size)
{
HFlashPageInfo info;
@ -550,13 +626,21 @@ static uint8_t CreatePageInfo(HFlashAddr_t addr, uint32_t size)
return 0;
}
uint32_t index = 0;
if (ScanPage(ScanAvailablePage, &index)) {
// 如果找到空闲页, 覆盖之前的页
info.crc32 = GetFlashCrc32(info.addr, info.useSize);
WritePage(index, &info);
return 1;
}
if (sPageInfo.useNum >= sPageInfo.pageNum) {
FATAL_ERROR("page table is full");
return 0;
}
// 写入新页表
const uint32_t index = sPageInfo.useNum++;
index = sPageInfo.useNum++;
info.crc32 = GetFlashCrc32(info.addr, info.useSize);
WritePage(index, &info);
@ -565,6 +649,10 @@ static uint8_t CreatePageInfo(HFlashAddr_t addr, uint32_t size)
static uint8_t _FindCacheHelper(uint32_t index, HFlashPageInfo *info, void *userData)
{
if (info->invalid) {
return 0;
}
HFlashCacheInfo *cache = (HFlashCacheInfo *)userData;
if (info->addr != cache->info.addr) {
return 0;
@ -689,12 +777,12 @@ static uint8_t _Print(uint32_t index, HFlashPageInfo *info, void *userData)
{
uint32_t *arg1 = (uint32_t *)userData;
if (*arg1 == -1) {
HSHELL_PRINTFL("page[%d], addr[0x%08x], useSize[0x%x], size[0x%x], modifyCount[%d], crc32[0x%x], version[%d]", index, info->addr, info->useSize, info->size, info->modifyCount, info->crc32, info->version);
HSHELL_PRINTFL("page[%d], invalid[%d], addr[0x%08x][%u], useSize[0x%x][%d], size[0x%x][%d], modifyCount[%d], crc32[0x%x], version[%d]", index, info->invalid, info->addr, info->addr, info->useSize, info->useSize, info->size, info->size, info->modifyCount, info->crc32, info->version);
return 0;
}
if (index == *arg1) {
HSHELL_PRINTFL("page[%d], addr[0x%08x], useSize[0x%x], size[0x%x], modifyCount[%d], crc32[0x%x], version[%d]", index, info->addr, info->useSize, info->size, info->modifyCount, info->crc32, info->version);
HSHELL_PRINTFL("page[%d], invalid[%d], addr[0x%08x][%u], useSize[0x%x][%d], size[0x%x][%d], modifyCount[%d], crc32[0x%x], version[%d]", index, info->invalid, info->addr, info->addr, info->useSize, info->useSize, info->size, info->size, info->modifyCount, info->crc32, info->version);
return 1;
}
@ -704,13 +792,36 @@ static uint8_t _Print(uint32_t index, HFlashPageInfo *info, void *userData)
static void Shell(HSHELL_FUNC_ARGS)
{
uint32_t arg1 = 0;
if (HSHellToUint32(tokens, tokensLen, 0, &arg1) == 0) {
if (HSHellToUint32(tokens, tokensLen, 1, &arg1) == 0) {
arg1 = -1;
}
switch (key) {
case kShellPageInfo: {
ScanPage(_Print, &arg1);
for (uint16_t i = 0; i < sInfo.pageCacheUseNum; ++i) {
HSHELL_PRINTFL("Cache index[%d], addr[0x%08x], useSize[0x%x][%d], size[0x%x][%d], modifyCount[%d], crc32[0x%x], version[%d]", i, sInfo.pageCache[i].info.addr, sInfo.pageCache[i].info.useSize, sInfo.pageCache[i].info.useSize, sInfo.pageCache[i].info.size, sInfo.pageCache[i].info.size, sInfo.pageCache[i].info.modifyCount, sInfo.pageCache[i].info.crc32, sInfo.pageCache[i].info.version);
}
} break;
case kShellDelUseDataPage: {
HFlashCacheInfo *cache = FindCache(arg1);
if (cache == NULL) {
HSHELL_PRINTFL("addr[0x%08x] not register", arg1);
return ;
}
cache->info.useSize = 0;
WriteCachePage(cache);
} break;
case kShellDelPage: {
HFlashCacheInfo *cache = FindCache(arg1);
if (cache == NULL) {
HSHELL_PRINTFL("addr[0x%08x] not register", arg1);
return ;
}
cache->info.invalid = 1;
WriteCachePage(cache);
} break;
default:
break;
@ -778,6 +889,10 @@ void HFlashInitCheck()
///< 检查是否重叠, 重叠返回1
static uint8_t _CheckOverLap(uint32_t index, HFlashPageInfo *info, void *userData)
{
if (info->invalid) {
return 0;
}
HFlashCacheInfo *cache = (HFlashCacheInfo *)userData;
if (cache->pos == index) {
return 0;
@ -823,6 +938,7 @@ void HFlashRegister(HFlashAddr_t addr, uint32_t size)
if (cache->info.useSize > size) {
LogE("addr[0x%08x] useSize[%d] > size[%d]", addr, cache->info.useSize, size);
cache->info.useSize = 0;
cache->waitWrite = 1;
}
// 检查是否在保护区域, 不是保护区域不需要检查crc校验
@ -873,7 +989,7 @@ void HFlashRegister(HFlashAddr_t addr, uint32_t size)
WriteCachePage(cache);
}
uint8_t HFlashWrite(HFlashAddr_t addr, void *data, uint32_t size)
uint8_t HFlashWrite(HFlashAddr_t addr, const void *data, uint32_t size)
{
// 检查是否存在致命性错误, 使用的地址不在注册页表中
uint8_t result = 0;
@ -910,7 +1026,7 @@ uint8_t HFlashWrite(HFlashAddr_t addr, void *data, uint32_t size)
return result;
}
uint8_t HFlashWriteOffset(HFlashAddr_t addr, uint32_t offset, void *data, uint32_t size)
static uint8_t WriteOffset(HFlashAddr_t addr, uint32_t offset, const void *data, uint32_t size, uint8_t needSetZero)
{
uint8_t result = 0;
HFlashCacheInfo *cache = FindCache(addr);
@ -928,7 +1044,7 @@ uint8_t HFlashWriteOffset(HFlashAddr_t addr, uint32_t offset, void *data, uint32
// 更新使用长度, 将跨越的部分填充0
if (cache->info.useSize < useSize) {
if (cache->info.useSize < offset) {
if (needSetZero && cache->info.useSize < offset) {
WriteFlashValue(addr + cache->info.useSize, offset - cache->info.useSize, 0);
}
@ -936,8 +1052,13 @@ uint8_t HFlashWriteOffset(HFlashAddr_t addr, uint32_t offset, void *data, uint32
}
result = WriteFlash(addr + offset, data, size);
cache->info.crc32 = GetFlashCrc32(addr, cache->info.useSize);
WriteCachePage(cache);
if (needSetZero) {
cache->info.crc32 = GetFlashCrc32(addr, cache->info.useSize);
WriteCachePage(cache);
} else {
cache->waitWrite = 1;
AddDelayCrc32(addr);
}
// 检查是否在保护区域, 需要的话需要写入等待备份
if (IsProtect(addr, size)) {
@ -947,6 +1068,16 @@ uint8_t HFlashWriteOffset(HFlashAddr_t addr, uint32_t offset, void *data, uint32
return result;
}
uint8_t HFlashWriteOffset(HFlashAddr_t addr, uint32_t offset, const void *data, uint32_t size)
{
return WriteOffset(addr, offset, data, size, 1);
}
uint8_t HFlashWriteRawOffset(HFlashAddr_t addr, uint32_t offset, const void *data, uint32_t size)
{
return WriteOffset(addr, offset, data, size, 0);
}
void HFlashStreamBegin(HFlashAddr_t addr)
{
HFlashCacheInfo *cache = FindCache(addr);
@ -960,7 +1091,7 @@ void HFlashStreamBegin(HFlashAddr_t addr)
cache->info.useSize = 0;
}
uint8_t HFlashStreamWrite(HFlashAddr_t addr, void *data, uint32_t size)
uint8_t HFlashStreamWrite(HFlashAddr_t addr, const void *data, uint32_t size)
{
uint8_t result = 0;
HFlashCacheInfo *cache = FindCache(addr);
@ -998,7 +1129,7 @@ void HFlashStreamEnd(HFlashAddr_t addr)
WriteCachePage(cache);
}
uint8_t HFlashRawWrite(HFlashAddr_t addr, void *data, uint32_t size)
uint8_t HFlashRawWrite(HFlashAddr_t addr, const void *data, uint32_t size)
{
return WriteFlash(addr, data, size);
}
@ -1038,12 +1169,13 @@ uint8_t HFlashReadOffset(HFlashAddr_t addr, uint32_t offset, void *data, uint32_
// 读取的数据超出使用长度, 将使用长度后面填充0
const uint32_t useSize = offset + size;
const uint32_t remain = useSize - cache->info.useSize;
if (cache->info.useSize < useSize) {
if (useSize > cache->info.useSize) {
const uint32_t remain = useSize - cache->info.useSize;
memset((uint8_t *)data + size - remain, 0, remain);
size -= remain;
}
return ReadFlash(addr + offset, data, size - remain);
return ReadFlash(addr + offset, data, size);
}
uint8_t HFlashRawRead(HFlashAddr_t addr, void *data, uint32_t size)