1. 完善初版HFlashServer

This commit is contained in:
coffee 2025-12-01 16:51:13 +08:00
parent 019a0604d0
commit ea96363aff
3 changed files with 961 additions and 6 deletions

141
include/HFlashServer.h Normal file
View File

@ -0,0 +1,141 @@
/**
* : 2025-11-27
* : coffee
* : Flash通用服务模块, Flash操作
*/
#ifndef __H_FLASH_SERVER_H__
#define __H_FLASH_SERVER_H__
///< Flash块大小, 按块操作, 2的幂关系
#ifndef HFLASH_BLOCK_SIZE
#define HFLASH_BLOCK_SIZE (4096)
#endif
///< 获取缓存内存, 需要大于Flash一块大小
#ifndef HFLASH_MALLOC
#define HFLASH_MALLOC(size) malloc(size)
#endif
///< 释放缓存
#ifndef HFLASH_FREE
#define HFLASH_FREE(ptr) free(ptr)
#endif
#include <stdint.h>
#include <stdlib.h>
///< Flash地址类型
typedef uint32_t HFlashAddr_t;
///< Flash页表信息
typedef union HFlashPageInfo {
uint8_t reverse[32]; ///< 每页的信息占用32字节
struct __attribute__((packed)) {
HFlashAddr_t addr; ///< 地址
uint32_t crc32; ///< 使用大小内容的CRC32
uint32_t size : 24; ///< 大小
uint32_t useSize : 24; ///< 使用大小
uint16_t version; ///< 当前页数据的版本
uint32_t modifyCount; ///< 修改次数
};
} HFlashPageInfo;
typedef struct HFlashCacheInfo {
HFlashPageInfo info; ///< 页表信息
uint32_t pos : 19; ///< 存储页表信息的位置
uint32_t heat : 4; ///< 热度优先级
} HFlashCacheInfo;
/**
* @brief HFlashEraseCallback
* @param addr Flash地址
* @return 1: 0:
*/
typedef uint8_t (*HFlashEraseCallback)(HFlashAddr_t addr);
/**
* @brief HFlashReadCallback
* @param addr Flash地址
* @param data Flash读取写入的缓存数据内存
* @param size
* @return 1: 0:
*/
typedef uint8_t (*HFlashReadCallback)(HFlashAddr_t addr, uint8_t *data, uint32_t size);
/**
* @brief HFlashWriteCallback
* @param addr Flash地址
* @param data Flash读取写入的缓存数据内存
* @param size
* @return 1: 0:
*/
typedef uint8_t (*HFlashWriteCallback)(HFlashAddr_t addr, uint8_t *data, uint32_t size);
/**
* @brief HFlashInitCallback Flash初始化回调
* @param read
* @param write
* @param erase
*/
void HFlashInitCallback(HFlashReadCallback read, HFlashWriteCallback write, HFlashEraseCallback erase);
/**
* @brief HFlashSetPageCache , ,
* @param pageInfo
* @param size
*/
void HFlashSetPageCache(HFlashCacheInfo *pageInfo, uint16_t size);
/**
* @brief HFlashSetPageAddr
* @param addr
* @param size
*/
void HFlashSetPageAddr(HFlashAddr_t addr, uint32_t size);
/**
* @brief HFlashSetPageBackupAddr
* @param addr
* @param size ,
*/
void HFlashSetPageBackupAddr(HFlashAddr_t addr, uint32_t size);
/**
* @brief HFlashProtectAddr , 使
* @param addr
* @param size
*/
void HFlashProtectAddr(HFlashAddr_t addr, uint32_t size);
/**
* @brief HFlashProtectBackupAddr
* @param addr
* @param size ,
*/
void HFlashProtectBackupAddr(HFlashAddr_t addr, uint32_t size);
/**
* @brief HFlashInitCheck HFlashRegister前需要初始化检查, ,
*/
void HFlashInitCheck();
/**
* @brief HFlashRegister
* @param addr
* @param size
*/
void HFlashRegister(HFlashAddr_t addr, uint32_t size);
/**
* @brief HFlashWrite Flash,
* @param addr
* @param data
* @param size
*/
void HFlashWrite(HFlashAddr_t addr, void *data, uint32_t size);
#endif // __H_FLASH_SERVER_H__

817
src/HFlashServer.c Normal file
View File

@ -0,0 +1,817 @@
#include "HFlashServer.h"
#include "HDLog.h"
#include "HVector.h"
#if 1
#include <nmmintrin.h>
static uint32_t sCrcValue;
void HSCrc32Reset()
{
sCrcValue = 0xFFFFFFFF;
}
void HSCrc32Update(const uint8_t *data, size_t len)
{
for (size_t i = 0; i < len; i++) {
sCrcValue = _mm_crc32_u8(sCrcValue, data[i]);
}
}
uint32_t HSCrc32Get()
{
return sCrcValue ^ 0xFFFFFFFF;
}
#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 IS_NOT_4(size) ((size & (4 - 1)) != 0)
union PageInfo {
uint8_t reverse[32]; ///< 每页的信息占用32字节
struct __attribute__((packed)) {
uint32_t crc32; ///< 页表内容的CRC32校验值
uint32_t pageNum : 19; ///< 可用页数量
uint32_t useNum : 19; ///< 已使用页数量
uint32_t needBackupPage : 1; ///< 是否需要备份页表
};
};
struct Info {
HFlashReadCallback read; ///< 读取回调
HFlashWriteCallback write; ///< 写入回调
HFlashEraseCallback erase; ///< 擦除回调
HFlashAddr_t pageAddr; ///< 页表地址
HFlashAddr_t pageBackupAddr; ///< 页表备份地址
uint32_t pageSize; ///< 页大小
HFlashAddr_t protectAddr; ///< 保护区地址
HFlashAddr_t protectBackupAddr; ///< 保护区备份地址
uint32_t protectSize; ///< 保护区大小
HFlashCacheInfo *pageCache; ///< 页表缓存
uint16_t pageCacheSize; ///< 页表缓存大小
uint16_t pageCacheUseNum; ///< 页表缓存使用页
};
static struct Info sInfo;
static union PageInfo sPageInfo;
// 需要备份的保护区地址页偏移
static HVECTOR_DEFINE32(sNeedBackupOffset, 10);
static uint8_t RestoreBackup(HFlashAddr_t srcAddr, HFlashAddr_t dstAddr, uint32_t size);
///< 检查地址是否在双备份保护区内
static uint8_t IsProtect(HFlashAddr_t addr, uint32_t size)
{
const HFlashAddr_t addrEnd = addr + size;
if (addrEnd < addr) {
FATAL_ERROR("addr[0x%08x] size[%d] overflow", addr, size);
return 0;
}
if (addr < sInfo.protectAddr || addr >= sInfo.protectAddr + sInfo.protectSize) {
return 0;
}
if (addrEnd > sInfo.protectAddr + sInfo.protectSize) {
FATAL_ERROR("addr[0x%08x] size[%d] overflow protect", addr, size);
return 0;
}
return 1;
}
static uint8_t ReadFlash(HFlashAddr_t addr, void *data, uint32_t size)
{
if (sInfo.read == NULL) {
FATAL_ERROR("read is null");
return 0;
}
uint8_t *dataPtr = (uint8_t *)data;
return sInfo.read(addr, dataPtr, size);
}
static uint8_t EraseFlash(HFlashAddr_t addr)
{
if (sInfo.erase == NULL) {
FATAL_ERROR("erase is null");
return 0;
}
return sInfo.erase(addr);
}
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)
{
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;
uint32_t remain = offset + size > HFLASH_BLOCK_SIZE ? HFLASH_BLOCK_SIZE - offset : size;
uint8_t *buff = (uint8_t *)HFLASH_MALLOC(HFLASH_BLOCK_SIZE);
uint8_t result = 0;
if (buff == NULL) {
LogE("addr[0x%08x], write size[%d] malloc faild", addr, size);
return 0;
}
// 先写入首个未对齐的块
if (ReadFlash(adjustAddr, buff, HFLASH_BLOCK_SIZE) == 0) {
LogE("addr[0x%08x], read faild", adjustAddr);
goto _flashError;
}
if (EraseFlash(adjustAddr) == 0) {
LogE("addr[0x%08x], erase faild", adjustAddr);
goto _flashError;
}
call(buff + offset, dataPtr, remain, userData);
// memcpy(buff + offset, dataPtr, remain);
if (sInfo.write(adjustAddr, buff, HFLASH_BLOCK_SIZE) == 0) {
LogE("addr[0x%08x], write faild", adjustAddr);
goto _flashError;
}
// 操作块读写
size -= remain;
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) {
LogE("addr[0x%08x], erase faild", adjustAddr);
goto _flashError;
}
call(buff, dataPtr, HFLASH_BLOCK_SIZE, userData);
// memcpy(buff, dataPtr, HFLASH_BLOCK_SIZE);
if (sInfo.write(adjustAddr, buff, HFLASH_BLOCK_SIZE) == 0) {
LogE("addr[0x%08x], write faild", adjustAddr);
goto _flashError;
}
}
// 操作最后一个未对齐的块
if (size) {
if (ReadFlash(adjustAddr, buff, HFLASH_BLOCK_SIZE) == 0) {
LogE("addr[0x%08x], read faild", adjustAddr);
goto _flashError;
}
if (EraseFlash(adjustAddr) == 0) {
LogE("addr[0x%08x], erase faild", adjustAddr);
goto _flashError;
}
call(buff, dataPtr, size, userData);
// memcpy(buff, dataPtr, size);
if (sInfo.write(adjustAddr, buff, HFLASH_BLOCK_SIZE) == 0) {
LogE("addr[0x%08x], write faild", adjustAddr);
goto _flashError;
}
}
result = 1;
_flashError:
HFLASH_FREE(buff);
return result;
}
static void _WriteFlashHelper(void *dest, const void *src, uint16_t buffSize, void *userData)
{
(void)userData;
memcpy(dest, src, buffSize);
}
static uint8_t WriteFlash(HFlashAddr_t addr, void *data, uint32_t size)
{
return WriteData(addr, data, size, _WriteFlashHelper, NULL);
#if 0
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;
uint32_t remain = offset + size > HFLASH_BLOCK_SIZE ? HFLASH_BLOCK_SIZE - offset : size;
uint8_t *buff = (uint8_t *)HFLASH_MALLOC(HFLASH_BLOCK_SIZE);
uint8_t result = 0;
if (buff == NULL) {
LogE("addr[0x%08x], write size[%d] malloc faild", addr, size);
return 0;
}
// 先写入首个未对齐的块
if (ReadFlash(adjustAddr, buff, HFLASH_BLOCK_SIZE) == 0) {
LogE("addr[0x%08x], read faild", adjustAddr);
goto _flashError;
}
if (EraseFlash(adjustAddr) == 0) {
LogE("addr[0x%08x], erase faild", adjustAddr);
goto _flashError;
}
memcpy(buff + offset, dataPtr, remain);
if (sInfo.write(adjustAddr, buff, HFLASH_BLOCK_SIZE) == 0) {
LogE("addr[0x%08x], write faild", adjustAddr);
goto _flashError;
}
// 操作块读写
size -= remain;
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) {
LogE("addr[0x%08x], erase faild", adjustAddr);
goto _flashError;
}
memcpy(buff, dataPtr, HFLASH_BLOCK_SIZE);
if (sInfo.write(adjustAddr, buff, HFLASH_BLOCK_SIZE) == 0) {
LogE("addr[0x%08x], write faild", adjustAddr);
goto _flashError;
}
}
// 操作最后一个未对齐的块
if (size) {
if (ReadFlash(adjustAddr, buff, HFLASH_BLOCK_SIZE) == 0) {
LogE("addr[0x%08x], read faild", adjustAddr);
goto _flashError;
}
if (EraseFlash(adjustAddr) == 0) {
LogE("addr[0x%08x], erase faild", adjustAddr);
goto _flashError;
}
memcpy(buff, dataPtr, size);
if (sInfo.write(adjustAddr, buff, HFLASH_BLOCK_SIZE) == 0) {
LogE("addr[0x%08x], write faild", adjustAddr);
goto _flashError;
}
}
result = 1;
_flashError:
HFLASH_FREE(buff);
return result;
#endif
}
static void _WriteFalshValueHelper(void *dest, const void *src, uint16_t size, void *userData)
{
uint8_t *value = (uint8_t *)userData;
memset(dest, *value, size);
}
static uint8_t WriteFlashValue(uint32_t addr, uint32_t size, uint8_t value)
{
return WriteData(addr, NULL, size, _WriteFalshValueHelper, &value);
}
static void SyncBackup()
{
// 需要备份的数据为空, 说明是二次调用, 上次已经同步了
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.protectAddr + (addr - sInfo.pageAddr);
RestoreBackup(addr, destAddr, HFLASH_BLOCK_SIZE);
}
HVectorClear(sNeedBackupOffset);
// 备份页表数据
RestoreBackup(sInfo.pageAddr, sInfo.pageBackupAddr, sInfo.pageSize);
sPageInfo.needBackupPage = 0;
}
static void _AddBackupAddr(uint32_t addr)
{
const HVectorLenType index = HVectorFindData(sNeedBackupOffset, addr);
if (index == HVECTOR_ERROR) {
return ;
}
if (HVectorAddData(sNeedBackupOffset, addr)) {
return ;
}
// 添加数据失败, 缓存已满, 需要先同步再添加
SyncBackup();
if (HVectorAddData(sNeedBackupOffset, addr) == 0) {
LogE("add wait sync addr[0x%08x], faild", addr);
}
}
static void AddBackupAddr(uint32_t addr, uint32_t size)
{
if (IsProtect(addr, size) == 0) {
return ;
}
// 只需要存储对应页位置, 整个页拷贝, 需要判断是不是需要超越页边界
uint32_t adjustAddr = addr & ~(HFLASH_BLOCK_SIZE - 1);
const uint16_t offset = addr - adjustAddr;
uint32_t remain = offset + size > HFLASH_BLOCK_SIZE ? HFLASH_BLOCK_SIZE - offset : size;
_AddBackupAddr(adjustAddr);
size -= remain;
adjustAddr += HFLASH_BLOCK_SIZE;
for (; size >= HFLASH_BLOCK_SIZE; adjustAddr += HFLASH_BLOCK_SIZE, size -= HFLASH_BLOCK_SIZE) {
_AddBackupAddr(adjustAddr);
}
if (size) {
_AddBackupAddr(adjustAddr);
}
}
static uint32_t GetFlashCrc32(HFlashAddr_t addr, uint32_t size)
{
if (size == 0) {
return 0xFFFFFFFF;
}
HSCrc32Reset();
uint8_t *buff = (uint8_t *)HFLASH_MALLOC(HFLASH_BLOCK_SIZE);
if (buff == NULL) {
LogE("addr[0x%08x], write size[%d] malloc faild", addr, size);
return 0xFFFFFFFF;
}
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) {
LogE("addr[0x%08x][0x%08x], size[%d] read faild", addr, addr + i, remain);
break;
}
HSCrc32Update(buff, remain);
}
HFLASH_FREE(buff);
return HSCrc32Get();
}
static uint8_t RestoreBackup(HFlashAddr_t srcAddr, HFlashAddr_t dstAddr, uint32_t size)
{
uint8_t *buff = (uint8_t *)HFLASH_MALLOC(HFLASH_BLOCK_SIZE);
if (buff == NULL) {
LogE("addr[0x%08x], write size[%d] malloc faild", srcAddr, size);
return 0;
}
uint8_t result = 0;
uint32_t i = 0;
uint32_t remain = 0;
for (; i < size; i += HFLASH_BLOCK_SIZE) {
remain = FLASH_MIN(uint32_t, size - i, HFLASH_BLOCK_SIZE);
result = result || ReadFlash(srcAddr + i, buff, remain) == 0;
result = result || WriteFlash(dstAddr + i, buff, remain) == 0;
if (result) {
LogE("read addr[0x%08x], write addr[0x%08x], write size[%d] faild", srcAddr + i, dstAddr + i, remain);
result = 0;
goto _FlashError;
}
}
result = 1;
_FlashError:
HFLASH_FREE(buff);
LogD("Restore srcAddr[0x%08x], dstAddr[0x%08x], size[%d], result[%d]", srcAddr, dstAddr, size, !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)
{
if (index >= sPageInfo.useNum) {
LogE("index[%d][%d] overflow", index, sPageInfo.useNum);
return 0;
}
const HFlashAddr_t srcAddr = AdjustPageAddrOffset(sInfo.pageBackupAddr, index);
const HFlashAddr_t dstAddr = AdjustPageAddrOffset(sInfo.pageAddr, index);
return RestoreBackup(srcAddr, dstAddr, sizeof(HFlashPageInfo));
}
static void UpdatePageInfo()
{
sPageInfo.crc32 = GetFlashCrc32(AdjustPageAddr(sInfo.pageAddr), AdjustPageByte(sPageInfo.useNum));
WriteFlash(sInfo.pageAddr, &sPageInfo, sizeof(sPageInfo));
sPageInfo.needBackupPage = 1;
}
static void ReadPage(uint32_t index, HFlashPageInfo *info)
{
if (index >= sPageInfo.useNum || info == NULL) {
LogE("index[%d][%d] overflow", index, sPageInfo.useNum);
return;
}
const HFlashAddr_t addr = AdjustPageAddrOffset(sInfo.pageAddr, index);
ReadFlash(addr, info, sizeof(HFlashPageInfo));
}
static void WritePage(uint32_t index, HFlashPageInfo *info)
{
if (index >= sPageInfo.useNum || info == NULL) {
LogE("index[%d][%d] overflow", index, sPageInfo.useNum);
return;
}
const HFlashAddr_t addr = AdjustPageAddrOffset(sInfo.pageAddr, index);
WriteFlash(addr, info, sizeof(HFlashPageInfo));
UpdatePageInfo();
}
/// 检查是否重叠, 重叠返回1, 非重叠返回0
static uint8_t IsOverLap(HFlashAddr_t srcAddr, uint32_t size, HFlashAddr_t dstAddr, uint32_t dstSize)
{
if (size == 0 || dstSize == 0) {
return 0;
}
const HFlashAddr_t srcEnd = srcAddr + size;
const HFlashAddr_t dstEnd = dstAddr + dstSize;
if (srcEnd < srcAddr) {
FATAL_ERROR("addr[0x%08x] size[%d] overflow", srcAddr, size);
return 1;
}
if (dstEnd < dstAddr) {
FATAL_ERROR("addr[0x%08x] size[%d] overflow", dstAddr, dstSize);
return 1;
}
// 非重叠
if (srcEnd <= dstAddr || dstEnd <= srcAddr) {
return 0;
}
return 1;
}
/**
* @brief
* @param call , index , info , userData , 0
* @param userData
* @return uint8_t 0,
*/
static uint8_t ScanPage(uint8_t (*call)(uint32_t index, HFlashPageInfo *info, void *userData), void *userData)
{
if (call == NULL) {
return 0;
}
const uint32_t pageNum = FLASH_MIN(uint32_t, sPageInfo.useNum, (HFLASH_BLOCK_SIZE / sizeof(HFlashPageInfo)));
HFlashPageInfo *buff = (HFlashPageInfo *)HFLASH_MALLOC(pageNum * sizeof(HFlashPageInfo));
if (buff == NULL) {
LogE("malloc faild");
return 0;
}
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) {
LogE("read page table[0x%08x] faild", AdjustPageAddrOffset(sInfo.pageAddr, i));
break;
}
for (uint32_t j = 0; j < num; ++j) {
result = call(i + j, buff + j, userData);
if (result) {
break;
}
}
if (result) {
break;
}
}
HFLASH_FREE(buff);
return result;
}
static uint8_t _CreatePageInfoHelper(uint32_t index, HFlashPageInfo *info, void *userData)
{
HFlashPageInfo *cache = (HFlashPageInfo *)userData;
return IsOverLap(info->addr, info->size, cache->addr, cache->size);
}
static uint8_t CreatePageInfo(HFlashAddr_t addr, uint32_t size)
{
HFlashPageInfo info;
memset(&info, 0, sizeof(HFlashPageInfo));
info.addr = addr;
info.size = size;
// 检查页表地址是否和当前页表地址范围内存在重叠
if (ScanPage(_CreatePageInfoHelper, &info)) {
FATAL_ERROR("addr[0x%08x] size[%d] exist range Error", addr, size);
return 0;
}
if (sPageInfo.useNum >= sPageInfo.pageNum) {
FATAL_ERROR("page table is full");
return 0;
}
// 写入新页表
const uint32_t index = sPageInfo.useNum++;
info.crc32 = GetFlashCrc32(info.addr, info.useSize);
WritePage(index, &info);
return 1;
}
static uint8_t _FindCacheHelper(uint32_t index, HFlashPageInfo *info, void *userData)
{
HFlashCacheInfo *cache = (HFlashCacheInfo *)userData;
if (info->addr != cache->info.addr) {
return 0;
}
memset(cache, 0, sizeof(HFlashCacheInfo));
memcpy(cache->info.reverse, info->reverse, sizeof(HFlashPageInfo));
cache->pos = index;
return 1;
}
///< 查找缓存, 不存在就去查表, 表也不存在就去创建
static HFlashCacheInfo *FindCache(HFlashAddr_t addr)
{
uint8_t currMin = 0xFF;
for (uint16_t i = 0; i < sInfo.pageCacheUseNum; ++i) {
currMin = FLASH_MIN(uint8_t, currMin, sInfo.pageCache[i].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));
return &sInfo.pageCache[i];
}
// 没有找到, 先降低温度
if (sInfo.pageCacheUseNum && currMin > 0) {
for (uint16_t i = 0; i < sInfo.pageCacheUseNum; ++i) {
sInfo.pageCache[i].heat -= currMin;
}
}
// 查找到了就直接替换最后面的就行
HFlashCacheInfo cache;
memset(&cache, 0, sizeof(HFlashCacheInfo));
cache.info.addr = addr;
if (ScanPage(_FindCacheHelper, &cache)) {
const uint16_t index = sInfo.pageCacheUseNum;
if (sInfo.pageCacheUseNum < sInfo.pageCacheSize) {
++sInfo.pageCacheUseNum;
}
memcpy(&sInfo.pageCache[index], &cache, sizeof(HFlashCacheInfo));
return &sInfo.pageCache[index];
}
return NULL;
}
void HFlashInitCallback(HFlashReadCallback read, HFlashWriteCallback write, HFlashEraseCallback erase)
{
sInfo.read = read;
sInfo.write = write;
sInfo.erase = erase;
}
void HFlashSetPageCache(HFlashCacheInfo *pageInfo, uint16_t size)
{
sInfo.pageCache = pageInfo;
sInfo.pageCacheSize = size;
}
void HFlashSetPageAddr(HFlashAddr_t addr, uint32_t size)
{
sInfo.pageAddr = addr;
sInfo.pageSize = size;
}
void HFlashSetPageBackupAddr(HFlashAddr_t addr, uint32_t size)
{
if (sInfo.pageSize != size) {
FATAL_ERROR("page size not match[%d][%d]", sInfo.pageSize, size);
return ;
}
sInfo.pageBackupAddr = addr;
sInfo.pageSize = size;
}
void HFlashProtectAddr(HFlashAddr_t addr, uint32_t size)
{
sInfo.protectAddr = addr;
sInfo.protectSize = size;
}
void HFlashProtectBackupAddr(HFlashAddr_t addr, uint32_t size)
{
if (sInfo.protectSize != size) {
FATAL_ERROR("protect size not match[%d][%d]", sInfo.protectSize, size);
return ;
}
sInfo.protectBackupAddr = addr;
sInfo.protectSize = size;
}
void HFlashInitCheck()
{
if (sInfo.pageCache == NULL || sInfo.pageCacheSize == 0) {
FATAL_ERROR("pageCache is null");
return ;
}
// 检查页表地址有没有和备份地址重叠问题
if (IsOverLap(sInfo.pageAddr, sInfo.pageSize, sInfo.pageBackupAddr, sInfo.pageSize)) {
FATAL_ERROR("page table and backup table is overlap");
return ;
}
const uint32_t num = sInfo.pageSize / sizeof(HFlashPageInfo);
do {
if (ReadFlash(sInfo.pageAddr, sPageInfo.reverse, sizeof(sPageInfo)) == 0) {
LogE("Read page table[0x%08x] faild", sInfo.pageAddr);
break;
}
LogD("num[%d], useNum[%d], pageNum[%d]", num, sPageInfo.useNum, sPageInfo.pageNum);
// 检查是不是无效页表, 如果是就去检查备份, 如果备份也是无效的, 说明是首次初始化
uint8_t invalid = sPageInfo.pageNum > num;
invalid = invalid || sPageInfo.useNum > num;
invalid = invalid || sPageInfo.useNum > sPageInfo.pageNum;
invalid = invalid || GetFlashCrc32(AdjustPageAddr(sInfo.pageAddr), AdjustPageByte(sPageInfo.useNum)) != sPageInfo.crc32;
if (invalid == 0) {
// 检查通过
return ;
}
LogD("page table is invalid, check backup table");
// 备份校验
if (ReadFlash(sInfo.pageBackupAddr, sPageInfo.reverse, sizeof(sPageInfo)) == 0) {
LogE("Read backup page table[0x%08x] faild", sInfo.pageBackupAddr);
break;
}
invalid = sPageInfo.pageNum > num;
invalid = invalid || sPageInfo.useNum > num;
invalid = invalid || sPageInfo.useNum > sPageInfo.pageNum;
invalid = invalid || GetFlashCrc32(AdjustPageAddr(sInfo.pageBackupAddr), AdjustPageByte(sPageInfo.useNum)) != sPageInfo.crc32;
if (invalid) {
// 备份也无效, 首次创建, 去初始化数据
LogD("backup page table is invalid, init data");
break;
}
// 备份校验通过, 恢复备份数据
RestoreBackup(sInfo.pageBackupAddr, sInfo.pageAddr, sPageInfo.useNum);
return ;
} while (0);
memset(sPageInfo.reverse, 0, sizeof(sPageInfo));
sPageInfo.pageNum = num;
}
void HFlashRegister(HFlashAddr_t addr, uint32_t size)
{
if (IS_NOT_4(size)) {
FATAL_ERROR("size[%d] not align 4", size);
return ;
}
HFlashCacheInfo *cache = FindCache(addr);
if (cache == NULL) {
// 首次创建页表, 不需要检查
LogD("create addr[0x%08x] size[%d]", addr, size);
if (CreatePageInfo(addr, size) == 0) {
LogE("Create addr[0x%08x] size[%d] faild", addr, size);
}
sPageInfo.needBackupPage = 1;
cache = FindCache(addr);
RestoreBackup(sInfo.protectAddr, sInfo.protectBackupAddr, sInfo.protectSize);
return ;
}
// 检查是否在保护区域, 不是保护区域不需要检查crc校验
if (IsProtect(addr, size) == 0) {
return ;
}
// 检查保护区域的crc是否相同
if (GetFlashCrc32(addr, size) == cache->info.crc32) {
return ;
}
// 先恢复内容区域
LogD("addr[0x%08x] size[%d] crc32 not match, start restore", addr, size);
RestoreBackup(sInfo.protectBackupAddr + (cache->info.addr - sInfo.protectAddr), cache->info.addr, cache->info.size);
// 如果恢复后还校验失败, 那就恢复对应页表
const uint32_t contentCrc = GetFlashCrc32(cache->info.addr, cache->info.size);
if (contentCrc == cache->info.crc32) {
return ;
}
// 恢复页表后重新读取
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) {
return ;
}
// 恢复后数据还是错误的, 需要将页表数据使用长度修正0, 避免异常数据导致程序异常
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);
}
void HFlashWrite(HFlashAddr_t addr, void *data, uint32_t size)
{
// 检查是否存在致命性错误, 使用的地址不在注册页表中
HFlashCacheInfo *cache = FindCache(addr);
if (cache == NULL) {
FATAL_ERROR("addr[0x%08x] not register", addr);
return ;
}
// 检查写入数据大小是否超出注册提供的大小范围
if (cache->info.size < size) {
FATAL_ERROR("addr[0x%08x] size[%d] overflow", addr, size);
return ;
}
// 更新使用长度
if (cache->info.useSize < size) {
cache->info.useSize = size;
}
// 更新crc, 写入数据后再更新页表
HSCrc32Reset();
HSCrc32Update((uint8_t *)data, size);
cache->info.crc32 = HSCrc32Get();
++cache->info.modifyCount;
// 检查是否在保护区域, 需要的话需要写入等待备份
if (IsProtect(addr, size)) {
AddBackupAddr(addr, size);
}
WriteFlash(addr, data, size);
WritePage(cache->pos, &cache->info);
}

View File

@ -90,17 +90,14 @@ static inline uint8_t IsRingBufferFull(const HRingBufferType *ringBuffer) {
InitRingBuffer((HRingBufferType *)ringBuffer); InitRingBuffer((HRingBufferType *)ringBuffer);
const _HRingBufferBase *base = (const _HRingBufferBase *)ringBuffer; const _HRingBufferBase *base = (const _HRingBufferBase *)ringBuffer;
return (base->flag & kHRingBufferFull) == kHRingBufferFull; return !!(base->flag & kHRingBufferFull);
} }
static inline void SetRingBufferFull(HRingBufferType *ringBuffer, uint8_t full) { static inline void SetRingBufferFull(HRingBufferType *ringBuffer, uint8_t full) {
InitRingBuffer((HRingBufferType *)ringBuffer); InitRingBuffer((HRingBufferType *)ringBuffer);
_HRingBufferBase *base = (_HRingBufferBase *)ringBuffer; _HRingBufferBase *base = (_HRingBufferBase *)ringBuffer;
if (full) { const uint8_t f = -(uint8_t)(!!full);
base->flag |= kHRingBufferFull; base->flag = (base->flag & ~kHRingBufferFull) | (f & kHRingBufferFull);
} else {
base->flag &= ~kHRingBufferFull;
}
} }
static void AdjustReadPos(HRingBufferType *ringBuffer, HRingBufferLenType pos) { static void AdjustReadPos(HRingBufferType *ringBuffer, HRingBufferLenType pos) {