1. 增加完备Flash服务

This commit is contained in:
coffee 2025-12-02 01:09:13 +08:00
parent 54c9dc52a7
commit e1d52c26de
2 changed files with 219 additions and 68 deletions

View File

@ -1,20 +1,21 @@
/**
* : 2025-11-27
* : coffee
* : Flash通用服务模块, Flash操作
* : Flash通用服务模块, Flash操作的完备性,
*/
#ifndef __H_FLASH_SERVER_H__
#define __H_FLASH_SERVER_H__
#include <stdint.h>
///< Flash块大小, 按块操作, 2的幂关系
#ifndef HFLASH_BLOCK_SIZE
#define HFLASH_BLOCK_SIZE (4096)
#endif
///< 获取缓存内存, 需要大于Flash一块大小
///< 获取缓存内存, 需要能申请到于等于Flash一块大小
#ifndef HFLASH_MALLOC
#define HFLASH_MALLOC(size) malloc(size)
#endif
@ -34,9 +35,6 @@
#define HFLASH_SYNC_TIME 2000
#endif
#include <stdint.h>
#include <stdlib.h>
///< Flash地址类型
typedef uint32_t HFlashAddr_t;
@ -57,6 +55,7 @@ typedef struct HFlashCacheInfo {
HFlashPageInfo info; ///< 页表信息
uint32_t pos : 19; ///< 存储页表信息的位置
uint32_t heat : 4; ///< 热度优先级
uint32_t waitWrite : 1; ///< 延后写入, 一般适用于流式操作或者延后复写
} HFlashCacheInfo;
@ -115,18 +114,18 @@ void HFlashSetPageAddr(HFlashAddr_t addr, uint32_t size);
void HFlashSetPageBackupAddr(HFlashAddr_t addr, uint32_t size);
/**
* @brief HFlashProtectAddr , 使
* @brief HFlashSetProtectAddr , 使
* @param addr
* @param size
*/
void HFlashProtectAddr(HFlashAddr_t addr, uint32_t size);
void HFlashSetProtectAddr(HFlashAddr_t addr, uint32_t size);
/**
* @brief HFlashProtectBackupAddr
* @brief HFlashSetProtectBackupAddr
* @param addr
* @param size ,
*/
void HFlashProtectBackupAddr(HFlashAddr_t addr, uint32_t size);
void HFlashSetProtectBackupAddr(HFlashAddr_t addr, uint32_t size);
/**
* @brief HFlashInitCheck HFlashRegister前需要初始化检查, ,
@ -145,8 +144,9 @@ void HFlashRegister(HFlashAddr_t addr, uint32_t size);
* @param addr
* @param data
* @param size
* @return 1: 0:
*/
void HFlashWrite(HFlashAddr_t addr, void *data, uint32_t size);
uint8_t HFlashWrite(HFlashAddr_t addr, void *data, uint32_t size);
/**
* @brief HFlashWriteOffset , 使, 0
@ -154,16 +154,39 @@ void HFlashWrite(HFlashAddr_t addr, void *data, uint32_t size);
* @param offset
* @param data
* @param size
* @return 1: 0:
*/
void HFlashWriteOffset(HFlashAddr_t addr, uint32_t offset, void *data, uint32_t size);
uint8_t HFlashWriteOffset(HFlashAddr_t addr, uint32_t offset, void *data, uint32_t size);
/**
* @brief HFlashStreamBegin , 使
* @param addr
*/
void HFlashStreamBegin(HFlashAddr_t addr);
/**
* @brief HFlashStreamWrite , CRC, Flash数据即可
* @param addr
* @param data
* @param size
* @return 1: 0:
*/
uint8_t HFlashStreamWrite(HFlashAddr_t addr, void *data, uint32_t size);
/**
* @brief HFlashStreamEnd , CRC
* @param addr
*/
void HFlashStreamEnd(HFlashAddr_t addr);
/**
* @brief HFlashRawWrite Flash数据, 西, 使
* @param addr
* @param data
* @param size
* @return 1: 0:
*/
void HFlashRawWrite(HFlashAddr_t addr, void *data, uint32_t size);
uint8_t HFlashRawWrite(HFlashAddr_t addr, void *data, uint32_t size);
/**
* @brief HFlashRead Flash数据
@ -172,7 +195,7 @@ void HFlashRawWrite(HFlashAddr_t addr, void *data, uint32_t size);
* @param size
* @return 1: 0:
*/
void HFlashRead(HFlashAddr_t addr, void *data, uint32_t size);
uint8_t HFlashRead(HFlashAddr_t addr, void *data, uint32_t size);
/**
* @brief HFlashReadOffset
@ -182,15 +205,35 @@ void HFlashRead(HFlashAddr_t addr, void *data, uint32_t size);
* @param size
* @return 1: 0:
*/
void HFlashReadOffset(HFlashAddr_t addr, uint32_t offset, void *data, uint32_t size);
uint8_t HFlashReadOffset(HFlashAddr_t addr, uint32_t offset, void *data, uint32_t size);
/**
* @brief HFlashRawRead Flash数据, 西, 使
* @param addr
* @param data
* @param size
* @return 1: 0:
*/
void HFlashRawRead(HFlashAddr_t addr, void *data, uint32_t size);
uint8_t HFlashRawRead(HFlashAddr_t addr, void *data, uint32_t size);
/**
* @brief HFlashUpdateVersionCallback
* @param addr
* @param oldVersion
* @param newVersion
* @param userData
*/
typedef void (*HFlashUpdateVersionCallback)(HFlashAddr_t addr, uint16_t oldVersion, uint16_t newVersion, void *userData);
/**
* @brief HFlashUpdateVersion ,
* , 使
* , 使
* @param addr
* @param newVersion
* @param callback
* @param userData
*/
void HFlashUpdateVersion(HFlashAddr_t addr, uint16_t newVersion, HFlashUpdateVersionCallback callback, void *userData);
/**
* @brief HFlashGetCrc32 Flash数据的CRC32值

View File

@ -26,11 +26,16 @@ uint32_t HSCrc32Get()
}
#endif
// 计算最小值
#define FLASH_MIN(type, a, b) ((b) ^ (((a) ^ (b)) & (-(type)((a) < (b)))))
// #define FATAL_ERROR(format, ...) LogE(format, ##__VA_ARGS__); while(1);
#define FATAL_ERROR(format, ...) LogE(format, ##__VA_ARGS__);
// 最大热度
#define MAX_HEAT ((1 << 4) - 1)
// 检查是不是4对齐
#define IS_NOT_4(size) ((size & (4 - 1)) != 0)
union PageInfo {
@ -84,7 +89,7 @@ static uint8_t IsProtect(HFlashAddr_t addr, uint32_t size)
}
if (addrEnd > sInfo.protectAddr + sInfo.protectSize) {
FATAL_ERROR("addr[0x%08x] size[%d] overflow protect", addr, size);
FATAL_ERROR("addr[0x%08x][0x%08x] size[%d][%d] overflow protect", addr, sInfo.protectAddr, size, sInfo.protectSize);
return 0;
}
@ -222,6 +227,7 @@ static uint8_t WriteFlashValue(uint32_t addr, uint32_t size, uint8_t value)
static void SyncBackup()
{
LogD("Start sync Backup");
if (sBackupTimer != HTIMER_INVALID) {
HTimerRemove(sBackupTimer);
sBackupTimer = HTIMER_INVALID;
@ -234,7 +240,7 @@ static void SyncBackup()
for (uint16_t i = 0; i < HVectorGetUseLen(sNeedBackupOffset); ++i) {
const uint32_t addr = HVectorGetData(sNeedBackupOffset, i);
const uint32_t destAddr = sInfo.protectAddr + (addr - sInfo.pageAddr);
const uint32_t destAddr = sInfo.protectBackupAddr + (addr - sInfo.protectAddr);
RestoreBackup(addr, destAddr, HFLASH_BLOCK_SIZE);
}
@ -245,7 +251,7 @@ static void SyncBackup()
sPageInfo.needBackupPage = 0;
}
static void _AddBackupAddr(uint32_t addr)
static void StartBackupTimer()
{
if (sBackupTimer != HTIMER_INVALID) {
HTimerRemove(sBackupTimer);
@ -253,20 +259,30 @@ static void _AddBackupAddr(uint32_t addr)
}
sBackupTimer = HTimerAdd(HFLASH_TIMER_ID, HFLASH_SYNC_TIME, SyncBackup, kHTimerOnce);
}
static void _AddBackupAddr(uint32_t addr)
{
do {
const HVectorLenType index = HVectorFindData(sNeedBackupOffset, addr);
if (index == HVECTOR_ERROR) {
return ;
if (index != HVECTOR_ERROR) {
break;
}
if (HVectorAddData(sNeedBackupOffset, addr)) {
return ;
break;
}
// 添加数据失败, 缓存已满, 需要先同步再添加
SyncBackup();
if (HVectorAddData(sNeedBackupOffset, addr) == 0) {
LogE("add wait sync addr[0x%08x], faild", addr);
break;
}
} while (0);
LogD("Add wait sync addr[0x%08x], size[%d]", addr, HVectorGetUseLen(sNeedBackupOffset));
StartBackupTimer();
}
static void AddBackupAddr(uint32_t addr, uint32_t size)
@ -346,7 +362,7 @@ static uint8_t RestoreBackup(HFlashAddr_t srcAddr, HFlashAddr_t dstAddr, uint32_
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], result[%d]", srcAddr, dstAddr, size, result);
return result;
}
@ -410,6 +426,13 @@ static void WritePage(uint32_t index, HFlashPageInfo *info)
UpdatePageInfo();
}
static void WriteCachePage(HFlashCacheInfo *info)
{
++info->info.modifyCount;
info->waitWrite = 0;
WritePage(info->pos, &info->info);
}
/// 检查是否重叠, 重叠返回1, 非重叠返回0
static uint8_t IsOverLap(HFlashAddr_t srcAddr, uint32_t size, HFlashAddr_t dstAddr, uint32_t dstSize)
{
@ -530,15 +553,16 @@ static uint8_t _FindCacheHelper(uint32_t index, HFlashPageInfo *info, void *user
static HFlashCacheInfo *FindCache(HFlashAddr_t addr)
{
uint8_t currMin = 0xFF;
uint8_t fastCoolDown = 0;
HFlashCacheInfo cache;
for (uint16_t i = 0; i < sInfo.pageCacheUseNum; ++i) {
currMin = FLASH_MIN(uint8_t, currMin, sInfo.pageCache[i].heat);
fastCoolDown = fastCoolDown || sInfo.pageCache[i].heat >= MAX_HEAT;
if (sInfo.pageCache[i].info.addr != addr) {
continue;
}
sInfo.pageCache[i].heat = FLASH_MIN(uint8_t, sInfo.pageCache[i].heat + 1, ((1 << 5) - 1));
sInfo.pageCache[i].heat = FLASH_MIN(uint8_t, sInfo.pageCache[i].heat + 1, MAX_HEAT);
if (i == 0) {
return &sInfo.pageCache[i];
}
@ -555,9 +579,11 @@ static HFlashCacheInfo *FindCache(HFlashAddr_t addr)
}
// 没有找到, 先降低温度
if (sInfo.pageCacheUseNum && currMin > 0) {
if (sInfo.pageCacheUseNum && (currMin > 0 || fastCoolDown)) {
// 达到最大热度, 需要快速降温
const uint16_t mask = -((uint16_t)fastCoolDown);
for (uint16_t i = 0; i < sInfo.pageCacheUseNum; ++i) {
sInfo.pageCache[i].heat -= currMin;
sInfo.pageCache[i].heat = ((sInfo.pageCache[i].heat >> 1) & mask) | ((sInfo.pageCache[i].heat - currMin) & ~mask);
}
}
@ -570,6 +596,11 @@ static HFlashCacheInfo *FindCache(HFlashAddr_t addr)
++sInfo.pageCacheUseNum;
}
// 如果是延迟写入的, 需要先写入再替换
if (sInfo.pageCache[index].waitWrite) {
WriteCachePage(&sInfo.pageCache[index]);
}
memcpy(&sInfo.pageCache[index], &cache, sizeof(HFlashCacheInfo));
return &sInfo.pageCache[index];
}
@ -607,13 +638,13 @@ void HFlashSetPageBackupAddr(HFlashAddr_t addr, uint32_t size)
sInfo.pageSize = size;
}
void HFlashProtectAddr(HFlashAddr_t addr, uint32_t size)
void HFlashSetProtectAddr(HFlashAddr_t addr, uint32_t size)
{
sInfo.protectAddr = addr;
sInfo.protectSize = size;
}
void HFlashProtectBackupAddr(HFlashAddr_t addr, uint32_t size)
void HFlashSetProtectBackupAddr(HFlashAddr_t addr, uint32_t size)
{
if (sInfo.protectSize != size) {
FATAL_ERROR("protect size not match[%d][%d]", sInfo.protectSize, size);
@ -697,8 +728,8 @@ void HFlashRegister(HFlashAddr_t addr, uint32_t size)
}
sPageInfo.needBackupPage = 1;
cache = FindCache(addr);
RestoreBackup(sInfo.protectAddr, sInfo.protectBackupAddr, sInfo.protectSize);
StartBackupTimer();
// RestoreBackup(sInfo.protectAddr, sInfo.protectBackupAddr, sInfo.protectSize);
return ;
}
@ -734,26 +765,25 @@ void HFlashRegister(HFlashAddr_t addr, uint32_t size)
LogE("addr[0x%08x] size[%d] crc32 not match", cache->info.addr, cache->info.size);
cache->info.useSize = 0;
cache->info.crc32 = GetFlashCrc32(cache->info.addr, cache->info.useSize);
WritePage(cache->pos, &cache->info);
WriteCachePage(cache);
}
void HFlashWrite(HFlashAddr_t addr, void *data, uint32_t size)
uint8_t HFlashWrite(HFlashAddr_t addr, void *data, uint32_t size)
{
// 检查是否存在致命性错误, 使用的地址不在注册页表中
uint8_t result = 0;
HFlashCacheInfo *cache = FindCache(addr);
if (cache == NULL) {
FATAL_ERROR("addr[0x%08x] not register", addr);
return ;
return result;
}
// 检查写入数据大小是否超出注册提供的大小范围
if (cache->info.size < size) {
FATAL_ERROR("addr[0x%08x] size[%d] overflow", addr, size);
return ;
return result;
}
++cache->info.modifyCount;
// 更新使用长度
if (cache->info.useSize < size) {
cache->info.useSize = size;
@ -764,32 +794,33 @@ void HFlashWrite(HFlashAddr_t addr, void *data, uint32_t size)
HSCrc32Update((uint8_t *)data, size);
cache->info.crc32 = HSCrc32Get();
WriteFlash(addr, data, size);
WritePage(cache->pos, &cache->info);
result = WriteFlash(addr, data, size);
WriteCachePage(cache);
// 检查是否在保护区域, 需要的话需要写入等待备份
if (IsProtect(addr, size)) {
AddBackupAddr(addr, size);
}
return result;
}
void HFlashWriteOffset(HFlashAddr_t addr, uint32_t offset, void *data, uint32_t size)
uint8_t HFlashWriteOffset(HFlashAddr_t addr, uint32_t offset, void *data, uint32_t size)
{
uint8_t result = 0;
HFlashCacheInfo *cache = FindCache(addr);
if (cache == NULL) {
FATAL_ERROR("addr[0x%08x] not register", addr);
return ;
return result;
}
const uint32_t useSize = offset + size;
// 检查写入数据大小是否超出注册提供的大小范围
if (cache->info.size < useSize) {
FATAL_ERROR("addr[0x%08x] size[%d] overflow", addr, useSize);
return ;
return result;
}
++cache->info.modifyCount;
// 更新使用长度, 将跨越的部分填充0
if (cache->info.useSize < useSize) {
if (cache->info.useSize < offset) {
@ -800,27 +831,79 @@ void HFlashWriteOffset(HFlashAddr_t addr, uint32_t offset, void *data, uint32_t
}
cache->info.crc32 = GetFlashCrc32(addr, useSize);
WriteFlash(addr + offset, data, size);
WritePage(cache->pos, &cache->info);
result = WriteFlash(addr + offset, data, size);
WriteCachePage(cache);
// 检查是否在保护区域, 需要的话需要写入等待备份
if (IsProtect(addr, size)) {
AddBackupAddr(addr, useSize);
}
return result;
}
void HFlashRawWrite(HFlashAddr_t addr, void *data, uint32_t size)
void HFlashStreamBegin(HFlashAddr_t addr)
{
WriteFlash(addr, data, size);
HFlashCacheInfo *cache = FindCache(addr);
if (cache == NULL) {
FATAL_ERROR("addr[0x%08x] not register", addr);
return ;
}
void HFlashRead(HFlashAddr_t addr, void *data, uint32_t size)
cache->waitWrite = 1;
cache->info.crc32 = 0xFFFFFFFF;
cache->info.useSize = 0;
}
uint8_t HFlashStreamWrite(HFlashAddr_t addr, void *data, uint32_t size)
{
uint8_t result = 0;
HFlashCacheInfo *cache = FindCache(addr);
if (cache == NULL) {
FATAL_ERROR("addr[0x%08x] not register", addr);
return result;
}
if (cache->info.useSize + size > cache->info.size) {
LogE("addr[0x%08x] size[%d][%d] overflow", addr, cache->info.useSize + size, cache->info.size);
return result;
}
WriteFlash(addr + cache->info.useSize, data, size);
cache->info.useSize += size;
++cache->info.modifyCount;
return result;
}
void HFlashStreamEnd(HFlashAddr_t addr)
{
HFlashCacheInfo *cache = FindCache(addr);
if (cache == NULL) {
FATAL_ERROR("addr[0x%08x] not register", addr);
return ;
}
cache->waitWrite = 0;
cache->info.crc32 = GetFlashCrc32(addr, cache->info.useSize);
if (IsProtect(addr, cache->info.useSize)) {
AddBackupAddr(addr, cache->info.useSize);
}
WriteCachePage(cache);
}
uint8_t HFlashRawWrite(HFlashAddr_t addr, void *data, uint32_t size)
{
return WriteFlash(addr, data, size);
}
uint8_t HFlashRead(HFlashAddr_t addr, void *data, uint32_t size)
{
HFlashCacheInfo *cache = FindCache(addr);
if (cache == NULL) {
FATAL_ERROR("addr[0x%08x] not register", addr);
memset(data, 0, size);
return ;
return 0;
}
// 超出部分填充0
@ -829,22 +912,22 @@ void HFlashRead(HFlashAddr_t addr, void *data, uint32_t size)
}
const uint32_t readSize = FLASH_MIN(uint32_t, size, cache->info.useSize);
ReadFlash(addr, data, readSize);
return ReadFlash(addr, data, readSize);
}
void HFlashReadOffset(HFlashAddr_t addr, uint32_t offset, void *data, uint32_t size)
uint8_t HFlashReadOffset(HFlashAddr_t addr, uint32_t offset, void *data, uint32_t size)
{
HFlashCacheInfo *cache = FindCache(addr);
if (cache == NULL) {
FATAL_ERROR("addr[0x%08x] not register", addr);
memset(data, 0, size);
return ;
return 0;
}
// 读取的偏移量超出使用长度
if (cache->info.useSize < offset) {
memset(data, 0, size);
return ;
return 0;
}
// 读取的数据超出使用长度, 将使用长度后面填充0
@ -854,12 +937,36 @@ void HFlashReadOffset(HFlashAddr_t addr, uint32_t offset, void *data, uint32_t s
memset((uint8_t *)data + size - remain, 0, remain);
}
ReadFlash(addr, data, size - remain);
return ReadFlash(addr + offset, data, size - remain);
}
void HFlashRawRead(HFlashAddr_t addr, void *data, uint32_t size)
uint8_t HFlashRawRead(HFlashAddr_t addr, void *data, uint32_t size)
{
ReadFlash(addr, data, size);
return ReadFlash(addr, data, size);
}
void HFlashUpdateVersion(HFlashAddr_t addr, uint16_t newVersion, HFlashUpdateVersionCallback callback, void *userData)
{
HFlashCacheInfo *cache = FindCache(addr);
if (cache == NULL) {
FATAL_ERROR("addr[0x%08x] not register", addr);
return ;
}
if (cache->info.version == newVersion) {
return ;
}
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);
}
}
uint32_t HFlashGetCrc32(HFlashAddr_t addr)
@ -872,3 +979,4 @@ uint32_t HFlashGetCrc32(HFlashAddr_t addr)
return cache->info.crc32;
}