Compare commits

..

5 Commits

Author SHA1 Message Date
coffee
176709e37d 1. 修改使用延迟写入缓存, 写入页, 写入备份 2025-12-06 09:54:51 +08:00
coffee
247e211168 1. 还需要优化一版, 先备份 2025-12-06 09:53:23 +08:00
coffee
150d642f22 1. 增加操作日志
2. 优化Flash备份策略
2025-12-05 11:19:08 +08:00
coffee
a902eb38c8 1. 修复偏移读取的问题 2025-12-03 16:51:27 +08:00
coffee
276218d3e0 1. 修复一些使用长度问题 2025-12-03 10:31:36 +08:00
4 changed files with 486 additions and 114 deletions

View File

@ -5,6 +5,7 @@
#include <stdint.h>
#include <string.h>
#include <stdarg.h>
// 使用宏开关管理日志
#ifndef LOG_CLOSE_OUT
@ -13,6 +14,7 @@
#define USE_HD_LOG_DATA (1)
#define USE_HD_TRACE (1)
#define USE_HD_FPGA_CHECK (1)
#define USE_HD_OPT_LOG (1)
#endif
// 当前检查栈数量的线程总数
@ -89,6 +91,13 @@
#endif
#define InitLogData() HDLogInit(NULL)
// 操作日志
#if USE_HD_OPT_LOG
#define LogOpt(format, ...) HDLogOptOut(format, ##__VA_ARGS__)
#else
#define LogOpt(...)
#endif
typedef enum eLogLevel {
kLogLevelSwitch = 0, ///< 日志开关
kLogLevelColor, ///< 彩色日志
@ -120,17 +129,27 @@ void HDLogOptFlashInit();
void HDLogInit(uint32_t (*getTime)());
/**
* @brief
* @return
* @brief
* @param call
*/
void HDLogSetOptCall(void (*call)(const char *format, va_list args));
/**
* @brief
* @return
*/
uint32_t HDLogGetTime();
/**
* @brief
**/
__attribute__ ((format(printf, 6, 7)))
void HDLogOut(uint8_t ext, uint8_t level, const char *fileName, const char *funcName, int line, const char *format, ...);
/**
* @brief
*/
void HDLogOptOut(const char *format, ...);
/**
* @brief FPGA
* @param data FPGA数据

View File

@ -1,7 +1,7 @@
/**
* : 2025-11-27
* : coffee
* : Flash通用服务模块, Flash操作的完备性,
* : Flash通用服务模块, Flash操作的完备性, , 使,
*/
@ -22,7 +22,7 @@
#define HFLASH_BLOCK_SIZE (4096)
#endif
///< 获取缓存内存, 需要能申请到大于等于Flash一块大小
///< 获取缓存内存, 需要能申请到大于等于(Flash一块大小)
#ifndef HFLASH_MALLOC
#ifdef USE_STD_MEM
#define HFLASH_MALLOC(size) malloc(size)
@ -45,9 +45,19 @@
#define HFLASH_TIMER_ID 0
#endif
///< 同步时间ms
#ifndef HFLASH_SYNC_TIME
#define HFLASH_SYNC_TIME 2000
///< 同步缓存页时间ms
#ifndef HFLASH_SYNC_CACHE_PAGE_TIME
#define HFLASH_SYNC_CACHE_PAGE_TIME 600
#endif
///< 同步页表信息时间ms
#ifndef HFLASH_SYNC_PAGE_INFO_TIME
#define HFLASH_SYNC_PAGE_INFO_TIME 800
#endif
///< 同步备份页表信息时间ms
#ifndef HFLASH_SYNC_BACKUP_TIME
#define HFLASH_SYNC_BACKUP_TIME 1000
#endif
///< Flash地址类型
@ -63,6 +73,7 @@ typedef union HFlashPageInfo {
uint32_t useSize : 24; ///< 使用大小
uint16_t version; ///< 当前页数据的版本
uint32_t modifyCount; ///< 修改次数
uint8_t invalid : 1; ///< 无效标志
};
} HFlashPageInfo;
@ -71,6 +82,7 @@ typedef struct HFlashCacheInfo {
uint32_t pos : 19; ///< 存储页表信息的位置
uint32_t heat : 4; ///< 热度优先级
uint32_t waitWrite : 1; ///< 延后写入, 一般适用于流式操作或者延后复写
uint32_t waitCrc : 1; ///< 延后CRC
} HFlashCacheInfo;
@ -162,7 +174,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 +184,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数据, , 使, 使
* @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 +209,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 +224,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数据
@ -272,10 +294,22 @@ uint32_t HFlashGetUseSize(HFlashAddr_t addr);
uint32_t HFlashGetSize(HFlashAddr_t addr);
/**
* @brief HFlashGetCrc32 Flash数据的CRC32值
* @brief HFlashGetCrc32 CRC32值
* @param addr
* @return CRC32
*/
uint32_t HFlashGetCrc32(HFlashAddr_t addr);
/**
* @brief HFlashCalcCrc32 Flash数据的CRC32值
* @param addr
* @return CRC32
*/
uint32_t HFlashCalcCrc32(HFlashAddr_t addr);
/**
* @brief HFlashSync Flash数据,
*/
void HFlashSync();
#endif // __H_FLASH_SERVER_H__

View File

@ -55,11 +55,24 @@ static HShellMatch sLogMatch[] = {
#endif
};
///< 日志级别
static HBIT_DEFINE(sLogItem, kLogLevelMax);
///< 获取运行时间回调
static uint32_t (*sGetTime)() = NULL;
///< 日志操作回调
static void (*sOperateCall)(const char *format, va_list args) = NULL;
///< 获取当前任务回调
static HDLogGetTaskType_t sGetCurrTask = NULL;
///< 获取当前任务栈回调
static HDLogGetStackSizeType_t sGetCurrStackSize = NULL;
///< 获取Flash配置回调
static HDLogFlashOpt_t sFlashCall = NULL;
#if USE_SYS_CHECK_HEAP
static HDLogGetStackSizeType_t sGetCurrHeapSize = NULL;
#endif
@ -252,6 +265,11 @@ void HDLogInit(uint32_t (*getTime)())
#endif
}
void HDLogSetOptCall(void (*call)(const char *format, va_list args))
{
sOperateCall = call;
}
uint32_t HDLogGetTime()
{
if (sGetTime)
@ -351,6 +369,18 @@ void HDLogOut(uint8_t ext, uint8_t level, const char *fileName, const char *func
LOG_UNLOCK();
}
void HDLogOptOut(const char *format, ...)
{
va_list args;
va_start(args, format);
if (sOperateCall)
{
sOperateCall(format, args);
}
va_end(args);
}
static void HDLogFpgaError(const uint8_t *data, int len, uint8_t isWrite, uint8_t checkFpga)
{
if (checkFpga == 0)

View File

@ -4,6 +4,8 @@
#include "HDLog.h"
#include "HVector.h"
#include "HTimer.h"
#include "HShellLex.h"
#include <stdio.h>
#ifndef USE_STD_MEM
#include "HDSendBuffer.h"
@ -37,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
// 最大热度
@ -45,6 +47,24 @@ uint32_t HSCrc32Get()
// 检查是不是4对齐
#define IS_NOT_4(size) ((size & (4 - 1)) != 0)
#define IS_NOT_4K(size) ((size & (HFLASH_BLOCK_SIZE - 1)) != 0)
enum eShell
{
kShellPageInfo, ///< 查看页表信息
kShellDelUseDataPage, ///< 删除页表使用数据
kShellDelPage, ///< 删除页
kShellResetPage, ///< 重置页
kShellMax,
};
static HShellMatch sShellMatch[] = {
HSHELL_MATCH_ITEM(kShellPageInfo, "pageInfo"),
HSHELL_MATCH_ITEM(kShellDelUseDataPage, "pageDelUseData"),
HSHELL_MATCH_ITEM(kShellDelPage, "pageDel"),
HSHELL_MATCH_ITEM(kShellResetPage, "pageReset"),
};
union PageInfo {
uint8_t reverse[32]; ///< 每页的信息占用32字节
@ -52,7 +72,6 @@ union PageInfo {
uint32_t crc32; ///< 页表内容的CRC32校验值
uint32_t pageNum : 19; ///< 可用页数量
uint32_t useNum : 19; ///< 已使用页数量
uint32_t needBackupPage : 1; ///< 是否需要备份页表
};
};
@ -77,12 +96,20 @@ static union PageInfo sPageInfo;
// 备份定时器
static HTimer_t sBackupTimer = HTIMER_INVALID;
// 需要备份的保护区地址页偏移
// 同步页定时器
static HTimer_t sSyncPageTimer = HTIMER_INVALID;
// 同步定时器
static HTimer_t sSyncCacheTimer = HTIMER_INVALID;
// 存储需要备份的保护区地址页偏移
static HVECTOR_DEFINE32(sNeedBackupOffset, 10);
static uint8_t RestoreBackup(HFlashAddr_t srcAddr, HFlashAddr_t dstAddr, uint32_t size);
static void StartBackupTimer();
static void StartSyncBackupTimer();
static HFlashCacheInfo *FindCache(HFlashAddr_t addr);
static void WriteCachePage(HFlashCacheInfo *info);
static uint32_t GetFlashCrc32(HFlashAddr_t addr, uint32_t size);
///< 检查地址是否在双备份保护区内
static uint8_t IsProtect(HFlashAddr_t addr, uint32_t size)
@ -105,8 +132,12 @@ static uint8_t IsProtect(HFlashAddr_t addr, uint32_t size)
return 1;
}
static uint8_t ReadFlash(HFlashAddr_t addr, void *data, uint32_t size)
static uint8_t ReadFlashCall(HFlashAddr_t addr, void *data, uint32_t size)
{
if (size == 0) {
return 1;
}
if (sInfo.read == NULL) {
FATAL_ERROR("read is null");
return 0;
@ -116,7 +147,7 @@ static uint8_t ReadFlash(HFlashAddr_t addr, void *data, uint32_t size)
return sInfo.read(addr, dataPtr, size);
}
static uint8_t EraseFlash(HFlashAddr_t addr)
static uint8_t EraseFlashCall(HFlashAddr_t addr)
{
if (sInfo.erase == NULL) {
FATAL_ERROR("erase is null");
@ -126,6 +157,21 @@ static uint8_t EraseFlash(HFlashAddr_t addr)
return sInfo.erase(addr);
}
static uint8_t WriteFlashCall(HFlashAddr_t addr, const void *data, uint32_t size)
{
if (size == 0) {
return 1;
}
if (sInfo.write == NULL) {
FATAL_ERROR("write is null");
return 0;
}
uint8_t *dataPtr = (uint8_t *)data;
return sInfo.write(addr, dataPtr, size);
}
/**
* @brief Flash
* @param addr Flash地址
@ -134,13 +180,8 @@ 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");
return 0;
}
uint8_t *dataPtr = (uint8_t *)data;
uint32_t adjustAddr = addr & ~(HFLASH_BLOCK_SIZE - 1);
const uint16_t offset = addr - adjustAddr;
@ -153,18 +194,18 @@ static uint8_t WriteData(HFlashAddr_t addr, void *data, uint32_t size, void(*cal
}
// 先写入首个未对齐的块
if (ReadFlash(adjustAddr, buff, HFLASH_BLOCK_SIZE) == 0) {
if (ReadFlashCall(adjustAddr, buff, HFLASH_BLOCK_SIZE) == 0) {
LogE("addr[0x%08x], read faild", adjustAddr);
goto _flashError;
}
if (EraseFlash(adjustAddr) == 0) {
if (EraseFlashCall(adjustAddr) == 0) {
LogE("addr[0x%08x], erase faild", adjustAddr);
goto _flashError;
}
call(buff + offset, dataPtr, remain, userData);
if (sInfo.write(adjustAddr, buff, HFLASH_BLOCK_SIZE) == 0) {
if (WriteFlashCall(adjustAddr, buff, HFLASH_BLOCK_SIZE) == 0) {
LogE("addr[0x%08x], write faild", adjustAddr);
goto _flashError;
}
@ -174,13 +215,13 @@ static uint8_t WriteData(HFlashAddr_t addr, void *data, uint32_t size, void(*cal
adjustAddr += HFLASH_BLOCK_SIZE;
dataPtr += remain;
for (; size >= HFLASH_BLOCK_SIZE; adjustAddr += HFLASH_BLOCK_SIZE, size -= HFLASH_BLOCK_SIZE, dataPtr += HFLASH_BLOCK_SIZE) {
if (EraseFlash(adjustAddr) == 0) {
if (EraseFlashCall(adjustAddr) == 0) {
LogE("addr[0x%08x], erase faild", adjustAddr);
goto _flashError;
}
call(buff, dataPtr, HFLASH_BLOCK_SIZE, userData);
if (sInfo.write(adjustAddr, buff, HFLASH_BLOCK_SIZE) == 0) {
if (WriteFlashCall(adjustAddr, buff, HFLASH_BLOCK_SIZE) == 0) {
LogE("addr[0x%08x], write faild", adjustAddr);
goto _flashError;
}
@ -188,18 +229,18 @@ static uint8_t WriteData(HFlashAddr_t addr, void *data, uint32_t size, void(*cal
// 操作最后一个未对齐的块
if (size) {
if (ReadFlash(adjustAddr, buff, HFLASH_BLOCK_SIZE) == 0) {
if (ReadFlashCall(adjustAddr, buff, HFLASH_BLOCK_SIZE) == 0) {
LogE("addr[0x%08x], read faild", adjustAddr);
goto _flashError;
}
if (EraseFlash(adjustAddr) == 0) {
if (EraseFlashCall(adjustAddr) == 0) {
LogE("addr[0x%08x], erase faild", adjustAddr);
goto _flashError;
}
call(buff, dataPtr, size, userData);
if (sInfo.write(adjustAddr, buff, HFLASH_BLOCK_SIZE) == 0) {
if (WriteFlashCall(adjustAddr, buff, HFLASH_BLOCK_SIZE) == 0) {
LogE("addr[0x%08x], write faild", adjustAddr);
goto _flashError;
}
@ -218,7 +259,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);
}
@ -234,6 +275,21 @@ static uint8_t WriteFlashValue(uint32_t addr, uint32_t size, uint8_t value)
return WriteData(addr, NULL, size, _WriteFalshValueHelper, &value);
}
static inline uint32_t AdjustPageAddr(uint32_t addr)
{
return addr + sizeof(sPageInfo);
}
static inline uint32_t AdjustPageAddrOffset(uint32_t addr, uint32_t offset)
{
return addr + sizeof(sPageInfo) + offset * sizeof(HFlashPageInfo);
}
static inline uint32_t AdjustPageByte(uint32_t index)
{
return index * sizeof(HFlashPageInfo);
}
static void SyncBackup()
{
LogD("Start sync Backup");
@ -242,17 +298,12 @@ static void SyncBackup()
sBackupTimer = HTIMER_INVALID;
}
// 需要备份的数据为空, 说明是二次调用, 上次已经同步了
if (HVectorEmpty(sNeedBackupOffset) && sPageInfo.needBackupPage == 0) {
return ;
}
for (uint16_t i = 0; i < HVectorGetUseLen(sNeedBackupOffset); ++i) {
const uint32_t addr = HVectorGetData(sNeedBackupOffset, i);
const uint32_t destAddr = sInfo.protectBackupAddr + (addr - sInfo.protectAddr);
if (RestoreBackup(addr, destAddr, HFLASH_BLOCK_SIZE) == 0) {
LogE("RestorePage faild, addr[0x%08x]", addr);
StartBackupTimer();
StartSyncBackupTimer();
return ;
}
}
@ -260,18 +311,21 @@ static void SyncBackup()
HVectorClear(sNeedBackupOffset);
// 备份页表数据
RestoreBackup(sInfo.pageAddr, sInfo.pageBackupAddr, sInfo.pageSize);
sPageInfo.needBackupPage = 0;
const uint32_t crcValue = GetFlashCrc32(AdjustPageAddr(sInfo.pageBackupAddr), AdjustPageByte(sPageInfo.useNum));
if (crcValue != sPageInfo.crc32) {
RestoreBackup(sInfo.pageAddr, sInfo.pageBackupAddr, AdjustPageByte(sPageInfo.useNum + 1));
}
LogD("Sync Backup End");
}
static void StartBackupTimer()
static void StartSyncBackupTimer()
{
if (sBackupTimer != HTIMER_INVALID) {
HTimerRemove(sBackupTimer);
sBackupTimer = HTIMER_INVALID;
}
sBackupTimer = HTimerAdd(HFLASH_TIMER_ID, HFLASH_SYNC_TIME, SyncBackup, kHTimerOnce);
sBackupTimer = HTimerAdd(HFLASH_TIMER_ID, HFLASH_SYNC_BACKUP_TIME, SyncBackup, kHTimerOnce);
}
static void _AddBackupAddr(uint32_t addr)
@ -295,7 +349,7 @@ static void _AddBackupAddr(uint32_t addr)
} while (0);
LogD("Add wait sync addr[0x%08x], size[%d]", addr, HVectorGetUseLen(sNeedBackupOffset));
StartBackupTimer();
StartSyncBackupTimer();
}
static void AddBackupAddr(uint32_t addr, uint32_t size)
@ -321,7 +375,6 @@ static void AddBackupAddr(uint32_t addr, uint32_t size)
}
}
static uint32_t GetFlashCrc32(HFlashAddr_t addr, uint32_t size)
{
if (size == 0) {
@ -337,7 +390,7 @@ static uint32_t GetFlashCrc32(HFlashAddr_t addr, uint32_t size)
for (uint32_t i = 0; i < size; i += HFLASH_BLOCK_SIZE) {
const uint32_t remain = FLASH_MIN(uint32_t, size - i, HFLASH_BLOCK_SIZE);
if (ReadFlash(addr + i, buff, remain) == 0) {
if (ReadFlashCall(addr + i, buff, remain) == 0) {
LogE("addr[0x%08x][0x%08x], size[%d] read faild", addr, addr + i, remain);
break;
}
@ -349,52 +402,78 @@ static uint32_t GetFlashCrc32(HFlashAddr_t addr, uint32_t size)
return HSCrc32Get();
}
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 copySize)
{
const uint16_t mallocSize = 1024;
uint8_t *buff = (uint8_t *)HFLASH_MALLOC(mallocSize);
if (copySize == 0) {
LogD("addr[0x%08x], write size[%d] is 0", srcAddr, copySize);
return 1;
}
uint8_t *buff = (uint8_t *)HFLASH_MALLOC(HFLASH_BLOCK_SIZE);
if (buff == NULL) {
LogE("addr[0x%08x], write size[%d] malloc faild", srcAddr, size);
LogE("addr[0x%08x], write size[%d] malloc faild", srcAddr, copySize);
return 0;
}
uint8_t result = 0;
uint32_t i = 0;
uint32_t remain = 0;
for (; i < size; i += mallocSize) {
remain = FLASH_MIN(uint32_t, size - i, mallocSize);
result = result || ReadFlash(srcAddr + i, buff, remain) == 0;
result = result || WriteFlash(dstAddr + i, buff, remain) == 0;
uint32_t adjustAddr = dstAddr & ~(HFLASH_BLOCK_SIZE - 1);
uint32_t size = copySize;
uint32_t srcOffset = 0;
// 如果地址不是对齐页的, 先处理残余数据到对齐页
if (adjustAddr != dstAddr) {
const uint16_t offset = dstAddr - adjustAddr;
const uint32_t remain = offset + size > HFLASH_BLOCK_SIZE ? HFLASH_BLOCK_SIZE - offset : size;
// 先读取到对齐页, 然后将未对齐的数据重写
result = ReadFlashCall(adjustAddr, buff, HFLASH_BLOCK_SIZE) == 0;
result = result || ReadFlashCall(srcAddr + srcOffset, buff + offset, remain) == 0;
result = result || EraseFlashCall(adjustAddr) == 0;
result = result || WriteFlashCall(adjustAddr, buff, HFLASH_BLOCK_SIZE) == 0;
if (result) {
LogE("read addr[0x%08x], write addr[0x%08x], write size[%d] faild", srcAddr + i, dstAddr + i, remain);
result = 0;
LogE("addr[0x%08x], write size[%d] faild", srcAddr, size);
goto _FlashError;
}
size -= remain;
adjustAddr += HFLASH_BLOCK_SIZE;
srcOffset += remain;
}
// 中间对齐页直接读原地址页, 擦写目标页
for (; size >= HFLASH_BLOCK_SIZE; adjustAddr += HFLASH_BLOCK_SIZE, size -= HFLASH_BLOCK_SIZE, srcOffset += HFLASH_BLOCK_SIZE) {
result = result || ReadFlashCall(srcAddr + srcOffset, buff, HFLASH_BLOCK_SIZE) == 0;
result = result || EraseFlashCall(adjustAddr) == 0;
result = result || WriteFlashCall(adjustAddr, buff, HFLASH_BLOCK_SIZE) == 0;
if (result) {
result = 0;
LogE("addr[0x%08x], write size[%d] faild", srcAddr, size);
goto _FlashError;
}
}
// 最后不对齐的数据
if (size) {
result = result || ReadFlashCall(adjustAddr, buff, HFLASH_BLOCK_SIZE) == 0;
result = result || ReadFlashCall(srcAddr + srcOffset, buff, size) == 0;
result = result || EraseFlashCall(adjustAddr) == 0;
result = result || WriteFlashCall(adjustAddr, buff, HFLASH_BLOCK_SIZE) == 0;
if (result) {
result = 0;
LogE("addr[0x%08x], write size[%d] faild", srcAddr, size);
goto _FlashError;
}
size = 0;
}
result = 1;
_FlashError:
HFLASH_FREE(buff);
LogD("Restore srcAddr[0x%08x], dstAddr[0x%08x], size[%d], result[%d]", srcAddr, dstAddr, size, result);
LogD("Restore srcAddr[0x%08x], dstAddr[0x%08x], size[%d][%d], result[%d]", srcAddr, dstAddr, size, copySize, result);
return result;
}
static inline uint32_t AdjustPageAddr(uint32_t addr)
{
return addr + sizeof(sPageInfo);
}
static inline uint32_t AdjustPageAddrOffset(uint32_t addr, uint32_t offset)
{
return addr + sizeof(sPageInfo) + offset * sizeof(HFlashPageInfo);
}
static inline uint32_t AdjustPageByte(uint32_t index)
{
return index * sizeof(HFlashPageInfo);
}
///< 恢复指定页表
static uint8_t RestorePage(uint32_t index)
{
@ -408,12 +487,32 @@ static uint8_t RestorePage(uint32_t index)
return RestoreBackup(srcAddr, dstAddr, sizeof(HFlashPageInfo));
}
static void UpdatePageInfo()
static void SyncPageInfo()
{
sPageInfo.crc32 = GetFlashCrc32(AdjustPageAddr(sInfo.pageAddr), AdjustPageByte(sPageInfo.useNum));
WriteFlash(sInfo.pageAddr, &sPageInfo, sizeof(sPageInfo));
if (sSyncPageTimer != HTIMER_INVALID) {
HTimerRemove(sSyncPageTimer);
sSyncPageTimer = HTIMER_INVALID;
}
sPageInfo.needBackupPage = 1;
const uint32_t crcValue = GetFlashCrc32(AdjustPageAddr(sInfo.pageAddr), AdjustPageByte(sPageInfo.useNum));
if (crcValue == sPageInfo.crc32) {
return;
}
sPageInfo.crc32 = crcValue;;
WriteFlash(sInfo.pageAddr, &sPageInfo, sizeof(sPageInfo));
StartSyncBackupTimer();
}
static void StartSyncPageInfo()
{
if (sSyncPageTimer != HTIMER_INVALID) {
HTimerRemove(sSyncPageTimer);
sSyncPageTimer = HTIMER_INVALID;
}
sSyncPageTimer = HTimerAdd(HFLASH_TIMER_ID, HFLASH_SYNC_PAGE_INFO_TIME, SyncPageInfo, kHTimerOnce);
StartSyncBackupTimer();
}
static void ReadPage(uint32_t index, HFlashPageInfo *info)
@ -424,7 +523,7 @@ static void ReadPage(uint32_t index, HFlashPageInfo *info)
}
const HFlashAddr_t addr = AdjustPageAddrOffset(sInfo.pageAddr, index);
ReadFlash(addr, info, sizeof(HFlashPageInfo));
ReadFlashCall(addr, info, sizeof(HFlashPageInfo));
}
static void WritePage(uint32_t index, HFlashPageInfo *info)
@ -436,15 +535,50 @@ static void WritePage(uint32_t index, HFlashPageInfo *info)
const HFlashAddr_t addr = AdjustPageAddrOffset(sInfo.pageAddr, index);
WriteFlash(addr, info, sizeof(HFlashPageInfo));
StartSyncPageInfo();
}
UpdatePageInfo();
static void SyncCachePage()
{
if (sSyncCacheTimer != HTIMER_INVALID) {
HTimerRemove(sSyncCacheTimer);
sSyncCacheTimer = HTIMER_INVALID;
}
for (uint32_t i = 0; i < sInfo.pageCacheUseNum; ++i) {
// 更新Crc32
if (sInfo.pageCache[i].waitCrc) {
sInfo.pageCache[i].waitCrc = 0;
sInfo.pageCache[i].info.crc32 = GetFlashCrc32(sInfo.pageCache[i].info.addr, sInfo.pageCache[i].info.useSize);
sInfo.pageCache[i].waitWrite = 1;
}
// 写入页表
if (sInfo.pageCache[i].waitWrite) {
WritePage(sInfo.pageCache[i].pos, &sInfo.pageCache[i].info);
}
}
StartSyncPageInfo();
}
static void StartSyncCachePage()
{
if (sSyncCacheTimer != HTIMER_INVALID) {
HTimerRemove(sSyncCacheTimer);
sSyncCacheTimer = HTIMER_INVALID;
}
sSyncCacheTimer = HTimerAdd(HFLASH_TIMER_ID, HFLASH_SYNC_CACHE_PAGE_TIME, SyncCachePage, kHTimerOnce);
StartSyncPageInfo();
}
static void WriteCachePage(HFlashCacheInfo *info)
{
++info->info.modifyCount;
info->waitWrite = 0;
WritePage(info->pos, &info->info);
info->waitWrite = 1;
StartSyncCachePage();
}
/// 检查是否重叠, 重叠返回1, 非重叠返回0
@ -496,7 +630,7 @@ static uint8_t ScanPage(uint8_t (*call)(uint32_t index, HFlashPageInfo *info, vo
uint8_t result = 0;
for (uint32_t i = 0; i < sPageInfo.useNum; i += pageNum) {
const uint32_t num = FLASH_MIN(uint32_t, sPageInfo.useNum - i, pageNum);
if (ReadFlash(AdjustPageAddrOffset(sInfo.pageAddr, i), buff, AdjustPageByte(num)) == 0) {
if (ReadFlashCall(AdjustPageAddrOffset(sInfo.pageAddr, i), buff, AdjustPageByte(num)) == 0) {
LogE("read page table[0x%08x] faild", AdjustPageAddrOffset(sInfo.pageAddr, i));
break;
}
@ -521,10 +655,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;
@ -537,13 +686,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);
@ -552,6 +709,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;
@ -611,9 +772,16 @@ static HFlashCacheInfo *FindCache(HFlashAddr_t addr)
++sInfo.pageCacheUseNum;
}
// 更新Crc32
if (sInfo.pageCache[index].waitCrc) {
sInfo.pageCache[index].info.crc32 = GetFlashCrc32(sInfo.pageCache[index].info.addr, sInfo.pageCache[index].info.useSize);
sInfo.pageCache[index].waitWrite = 1;
}
// 如果是延迟写入的, 需要先写入再替换
if (sInfo.pageCache[index].waitWrite) {
WriteCachePage(&sInfo.pageCache[index]);
WritePage(sInfo.pageCache[index].pos, &sInfo.pageCache[index].info);
sInfo.pageCache[index].waitWrite = 0;
}
memcpy(&sInfo.pageCache[index], &cache, sizeof(HFlashCacheInfo));
@ -640,12 +808,20 @@ void HFlashSetPageCache(HFlashCacheInfo *pageInfo, uint16_t size)
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);
}
sInfo.pageAddr = addr;
sInfo.pageSize = size;
}
void HFlashSetPageBackupAddr(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);
}
if (sInfo.pageSize != size) {
FATAL_ERROR("page size not match[%d][%d]", sInfo.pageSize, size);
return ;
@ -657,12 +833,20 @@ void HFlashSetPageBackupAddr(HFlashAddr_t addr, uint32_t size)
void HFlashSetProtectAddr(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);
}
sInfo.protectAddr = addr;
sInfo.protectSize = size;
}
void HFlashSetProtectBackupAddr(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);
}
if (sInfo.protectSize != size) {
FATAL_ERROR("protect size not match[%d][%d]", sInfo.protectSize, size);
return ;
@ -672,8 +856,73 @@ void HFlashSetProtectBackupAddr(HFlashAddr_t addr, uint32_t size)
sInfo.protectSize = size;
}
static uint8_t _Print(uint32_t index, HFlashPageInfo *info, void *userData)
{
uint32_t *arg1 = (uint32_t *)userData;
if (*arg1 == -1) {
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], 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;
}
return 0;
}
static void Shell(HSHELL_FUNC_ARGS)
{
uint32_t 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;
case kShellResetPage: {
if (arg1 >= sPageInfo.pageNum) {
HSHELL_PRINTFL("index[%d] over max[%d]", arg1, sPageInfo.pageNum);
return ;
}
sPageInfo.useNum = arg1;
SyncPageInfo();
} break;
default:
break;
}
}
void HFlashInitCheck()
{
HSHellRegister(sShellMatch, sizeof(sShellMatch) / sizeof(HShellMatch), Shell, 0);
if (sInfo.pageCache == NULL || sInfo.pageCacheSize == 0) {
FATAL_ERROR("pageCache is null");
return ;
@ -687,7 +936,7 @@ void HFlashInitCheck()
const uint32_t num = sInfo.pageSize / sizeof(HFlashPageInfo);
do {
if (ReadFlash(sInfo.pageAddr, sPageInfo.reverse, sizeof(sPageInfo)) == 0) {
if (ReadFlashCall(sInfo.pageAddr, sPageInfo.reverse, sizeof(sPageInfo)) == 0) {
LogE("Read page table[0x%08x] faild", sInfo.pageAddr);
break;
}
@ -705,7 +954,7 @@ void HFlashInitCheck()
LogD("page table is invalid, check backup table");
// 备份校验
if (ReadFlash(sInfo.pageBackupAddr, sPageInfo.reverse, sizeof(sPageInfo)) == 0) {
if (ReadFlashCall(sInfo.pageBackupAddr, sPageInfo.reverse, sizeof(sPageInfo)) == 0) {
LogE("Read backup page table[0x%08x] faild", sInfo.pageBackupAddr);
break;
}
@ -720,8 +969,8 @@ void HFlashInitCheck()
break;
}
// 备份校验通过, 恢复备份数据
RestoreBackup(sInfo.pageBackupAddr, sInfo.pageAddr, sPageInfo.useNum);
// 备份校验通过, 恢复备份数据
RestoreBackup(sInfo.pageBackupAddr, sInfo.pageAddr, sInfo.pageSize);
return ;
} while (0);
@ -732,6 +981,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;
@ -754,8 +1007,7 @@ void HFlashRegister(HFlashAddr_t addr, uint32_t size)
LogE("Create addr[0x%08x] size[%d] faild", addr, size);
}
sPageInfo.needBackupPage = 1;
StartBackupTimer();
StartSyncBackupTimer();
return ;
}
@ -777,6 +1029,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校验
@ -803,12 +1056,22 @@ void HFlashRegister(HFlashAddr_t addr, uint32_t size)
LogE("addr[0x%08x] size[%d] crc32 not match, restore faild", cache->info.addr, cache->info.size);
RestorePage(cache->pos);
ReadPage(cache->pos, &cache->info);
if (contentCrc == cache->info.crc32) {
do {
// 如果恢复页表数据后, 大小不一致, 说明用户在调整大小, 放弃数据, 不恢复
if (cache->info.size != size) {
break;
}
// 恢复后数据校验不一致, 需要重置
if (contentCrc != cache->info.crc32) {
break;
}
return ;
}
} while (0);
// 恢复后数据还是错误的, 需要将该页表数据重新初始化
LogE("addr[0x%08x] size[%d] crc32 not match", cache->info.addr, cache->info.size);
LogE("addr[0x%08x] size[%d] newSize[%d] crc32 not match", cache->info.addr, cache->info.size, size);
memset(cache->info.reverse, 0, sizeof(cache->info));
cache->info.addr = addr;
cache->info.useSize = 0;
@ -817,7 +1080,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;
@ -833,14 +1096,14 @@ uint8_t HFlashWrite(HFlashAddr_t addr, void *data, uint32_t size)
return result;
}
// 更新使用长度
// 更新使用长度, 直接重写比较短的数据不要影响使用长度
if (cache->info.useSize < size) {
cache->info.useSize = size;
}
// 更新crc, 写入数据后再更新页表
HSCrc32Reset();
HSCrc32Update((uint8_t *)data, size);
HSCrc32Update((uint8_t *)data, cache->info.useSize);
cache->info.crc32 = HSCrc32Get();
result = WriteFlash(addr, data, size);
@ -854,7 +1117,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);
@ -872,15 +1135,15 @@ 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);
}
cache->info.useSize = useSize;
}
cache->info.crc32 = GetFlashCrc32(addr, useSize);
result = WriteFlash(addr + offset, data, size);
cache->waitCrc = 1;
WriteCachePage(cache);
// 检查是否在保护区域, 需要的话需要写入等待备份
@ -891,6 +1154,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);
@ -900,11 +1173,12 @@ void HFlashStreamBegin(HFlashAddr_t addr)
}
cache->waitWrite = 1;
cache->waitCrc = 1;
cache->info.crc32 = 0xFFFFFFFF;
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);
@ -920,6 +1194,7 @@ uint8_t HFlashStreamWrite(HFlashAddr_t addr, void *data, uint32_t size)
result = WriteFlash(addr + cache->info.useSize, data, size);
cache->waitWrite = 1;
cache->waitCrc = 1;
cache->info.useSize += size;
++cache->info.modifyCount;
return result;
@ -933,8 +1208,8 @@ void HFlashStreamEnd(HFlashAddr_t addr)
return ;
}
cache->waitWrite = 0;
cache->info.crc32 = GetFlashCrc32(addr, cache->info.useSize);
cache->waitCrc = 0;
if (IsProtect(addr, cache->info.useSize)) {
AddBackupAddr(addr, cache->info.useSize);
}
@ -942,7 +1217,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);
}
@ -962,7 +1237,7 @@ uint8_t HFlashRead(HFlashAddr_t addr, void *data, uint32_t size)
}
const uint32_t readSize = FLASH_MIN(uint32_t, size, cache->info.useSize);
return ReadFlash(addr, data, readSize);
return ReadFlashCall(addr, data, readSize);
}
uint8_t HFlashReadOffset(HFlashAddr_t addr, uint32_t offset, void *data, uint32_t size)
@ -982,17 +1257,18 @@ 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 ReadFlashCall(addr + offset, data, size);
}
uint8_t HFlashRawRead(HFlashAddr_t addr, void *data, uint32_t size)
{
return ReadFlash(addr, data, size);
return ReadFlashCall(addr, data, size);
}
void HFlashUpdateVersion(HFlashAddr_t addr, uint16_t newVersion, HFlashUpdateVersionCallback callback, void *userData)
@ -1008,16 +1284,12 @@ void HFlashUpdateVersion(HFlashAddr_t addr, uint16_t newVersion, HFlashUpdateVer
}
const uint16_t oldVersion = cache->info.version;
cache->waitWrite = 1;
cache->info.version = newVersion;
if (callback) {
callback(addr, oldVersion, newVersion, userData);
}
// 如果回调没有进行页写入, 需要进行页写入
if (cache->waitWrite) {
WriteCachePage(cache);
}
WriteCachePage(cache);
}
void HFlashDeleteData(HFlashAddr_t addr)
@ -1065,3 +1337,20 @@ uint32_t HFlashGetCrc32(HFlashAddr_t addr)
return cache->info.crc32;
}
uint32_t HFlashCalcCrc32(HFlashAddr_t addr)
{
HFlashCacheInfo *cache = FindCache(addr);
if (cache == NULL) {
FATAL_ERROR("addr[0x%08x] not register", addr);
return 0xFFFFFFFF;
}
return GetFlashCrc32(addr, cache->info.useSize);
}
void HFlashSync()
{
SyncCachePage();
SyncPageInfo();
SyncBackup();
}