1. 完成Flash服务
This commit is contained in:
parent
ea96363aff
commit
54c9dc52a7
@ -24,6 +24,16 @@
|
||||
#define HFLASH_FREE(ptr) free(ptr)
|
||||
#endif
|
||||
|
||||
///< 定时器ID
|
||||
#ifndef HFLASH_TIMER_ID
|
||||
#define HFLASH_TIMER_ID 0
|
||||
#endif
|
||||
|
||||
///< 同步时间ms
|
||||
#ifndef HFLASH_SYNC_TIME
|
||||
#define HFLASH_SYNC_TIME 2000
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
@ -131,11 +141,62 @@ void HFlashInitCheck();
|
||||
void HFlashRegister(HFlashAddr_t addr, uint32_t size);
|
||||
|
||||
/**
|
||||
* @brief HFlashWrite 写入Flash, 需要注册的地址
|
||||
* @param addr 地址
|
||||
* @brief HFlashWrite 写入Flash数据
|
||||
* @param addr 需要注册的地址
|
||||
* @param data 写入数据
|
||||
* @param size 写入数据大小
|
||||
*/
|
||||
void HFlashWrite(HFlashAddr_t addr, void *data, uint32_t size);
|
||||
|
||||
/**
|
||||
* @brief HFlashWriteOffset 写入从原始地址偏移后的地方写入数据, 如果偏移后的写入大小超过原未使用, 超出部分会自动写入0填充
|
||||
* @param addr 需要注册的地址
|
||||
* @param offset 地址偏移
|
||||
* @param data 写入数据
|
||||
* @param size 写入数据大小
|
||||
*/
|
||||
void HFlashWriteOffset(HFlashAddr_t addr, uint32_t offset, void *data, uint32_t size);
|
||||
|
||||
/**
|
||||
* @brief HFlashRawWrite 原始写入Flash数据, 不校验任何东西, 正常情况下不建议使用
|
||||
* @param addr 地址
|
||||
* @param data 写入数据
|
||||
* @param size 写入数据大小
|
||||
*/
|
||||
void HFlashRawWrite(HFlashAddr_t addr, void *data, uint32_t size);
|
||||
|
||||
/**
|
||||
* @brief HFlashRead 读取Flash数据
|
||||
* @param addr 需要注册的地址
|
||||
* @param data 读取数据写入的缓存内存
|
||||
* @param size 读取数据大小
|
||||
* @return 1: 读取成功 0: 读取失败
|
||||
*/
|
||||
void HFlashRead(HFlashAddr_t addr, void *data, uint32_t size);
|
||||
|
||||
/**
|
||||
* @brief HFlashReadOffset 读取从原始地址偏移后的地方的数据
|
||||
* @param addr 需要注册的地址
|
||||
* @param offset 地址偏移
|
||||
* @param data 读取数据写入的缓存内存
|
||||
* @param size 读取数据大小
|
||||
* @return 1: 读取成功 0: 读取失败
|
||||
*/
|
||||
void HFlashReadOffset(HFlashAddr_t addr, uint32_t offset, void *data, uint32_t size);
|
||||
|
||||
/**
|
||||
* @brief HFlashRawRead 原始读取Flash数据, 不校验任何东西, 正常情况下不建议使用
|
||||
* @param addr 地址
|
||||
* @param data 读取数据写入的缓存内存
|
||||
* @param size 读取数据大小
|
||||
*/
|
||||
void HFlashRawRead(HFlashAddr_t addr, void *data, uint32_t size);
|
||||
|
||||
/**
|
||||
* @brief HFlashGetCrc32 获取Flash数据的CRC32值
|
||||
* @param addr 需要注册的地址
|
||||
* @return CRC32
|
||||
*/
|
||||
uint32_t HFlashGetCrc32(HFlashAddr_t addr);
|
||||
|
||||
#endif // __H_FLASH_SERVER_H__
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
#include "HFlashServer.h"
|
||||
#include "HDLog.h"
|
||||
#include "HVector.h"
|
||||
#include "HTimer.h"
|
||||
|
||||
|
||||
#if 1
|
||||
@ -60,6 +61,9 @@ struct Info {
|
||||
static struct Info sInfo;
|
||||
static union PageInfo sPageInfo;
|
||||
|
||||
// 备份定时器
|
||||
static HTimer_t sBackupTimer = HTIMER_INVALID;
|
||||
|
||||
// 需要备份的保护区地址页偏移
|
||||
static HVECTOR_DEFINE32(sNeedBackupOffset, 10);
|
||||
|
||||
@ -108,6 +112,14 @@ static uint8_t EraseFlash(HFlashAddr_t addr)
|
||||
return sInfo.erase(addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 写入数据到Flash
|
||||
* @param addr 写入的Flash地址
|
||||
* @param data 写入的数据
|
||||
* @param size 写入的数据大小
|
||||
* @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)
|
||||
{
|
||||
if (sInfo.write == NULL) {
|
||||
@ -138,7 +150,6 @@ static uint8_t WriteData(HFlashAddr_t addr, void *data, uint32_t size, void(*cal
|
||||
}
|
||||
|
||||
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;
|
||||
@ -155,7 +166,6 @@ static uint8_t WriteData(HFlashAddr_t addr, void *data, uint32_t size, void(*cal
|
||||
}
|
||||
|
||||
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;
|
||||
@ -175,7 +185,6 @@ static uint8_t WriteData(HFlashAddr_t addr, void *data, uint32_t size, void(*cal
|
||||
}
|
||||
|
||||
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;
|
||||
@ -198,82 +207,6 @@ static void _WriteFlashHelper(void *dest, const void *src, uint16_t buffSize, vo
|
||||
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)
|
||||
@ -289,6 +222,11 @@ static uint8_t WriteFlashValue(uint32_t addr, uint32_t size, uint8_t value)
|
||||
|
||||
static void SyncBackup()
|
||||
{
|
||||
if (sBackupTimer != HTIMER_INVALID) {
|
||||
HTimerRemove(sBackupTimer);
|
||||
sBackupTimer = HTIMER_INVALID;
|
||||
}
|
||||
|
||||
// 需要备份的数据为空, 说明是二次调用, 上次已经同步了
|
||||
if (HVectorEmpty(sNeedBackupOffset) && sPageInfo.needBackupPage == 0) {
|
||||
return ;
|
||||
@ -309,6 +247,12 @@ static void SyncBackup()
|
||||
|
||||
static void _AddBackupAddr(uint32_t addr)
|
||||
{
|
||||
if (sBackupTimer != HTIMER_INVALID) {
|
||||
HTimerRemove(sBackupTimer);
|
||||
sBackupTimer = HTIMER_INVALID;
|
||||
}
|
||||
|
||||
sBackupTimer = HTimerAdd(HFLASH_TIMER_ID, HFLASH_SYNC_TIME, SyncBackup, kHTimerOnce);
|
||||
const HVectorLenType index = HVectorFindData(sNeedBackupOffset, addr);
|
||||
if (index == HVECTOR_ERROR) {
|
||||
return ;
|
||||
@ -586,6 +530,7 @@ static uint8_t _FindCacheHelper(uint32_t index, HFlashPageInfo *info, void *user
|
||||
static HFlashCacheInfo *FindCache(HFlashAddr_t addr)
|
||||
{
|
||||
uint8_t currMin = 0xFF;
|
||||
HFlashCacheInfo cache;
|
||||
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) {
|
||||
@ -593,6 +538,19 @@ static HFlashCacheInfo *FindCache(HFlashAddr_t addr)
|
||||
}
|
||||
|
||||
sInfo.pageCache[i].heat = FLASH_MIN(uint8_t, sInfo.pageCache[i].heat + 1, ((1 << 5) - 1));
|
||||
|
||||
if (i == 0) {
|
||||
return &sInfo.pageCache[i];
|
||||
}
|
||||
|
||||
// 这里需要根据热度交换缓存位置
|
||||
if (sInfo.pageCache[i].heat > sInfo.pageCache[i - 1].heat) {
|
||||
cache = sInfo.pageCache[i];
|
||||
sInfo.pageCache[i] = sInfo.pageCache[i - 1];
|
||||
sInfo.pageCache[i - 1] = cache;
|
||||
--i;
|
||||
}
|
||||
|
||||
return &sInfo.pageCache[i];
|
||||
}
|
||||
|
||||
@ -604,7 +562,6 @@ static HFlashCacheInfo *FindCache(HFlashAddr_t addr)
|
||||
}
|
||||
|
||||
// 查找到了就直接替换最后面的就行
|
||||
HFlashCacheInfo cache;
|
||||
memset(&cache, 0, sizeof(HFlashCacheInfo));
|
||||
cache.info.addr = addr;
|
||||
if (ScanPage(_FindCacheHelper, &cache)) {
|
||||
@ -795,6 +752,8 @@ void HFlashWrite(HFlashAddr_t addr, void *data, uint32_t size)
|
||||
return ;
|
||||
}
|
||||
|
||||
++cache->info.modifyCount;
|
||||
|
||||
// 更新使用长度
|
||||
if (cache->info.useSize < size) {
|
||||
cache->info.useSize = size;
|
||||
@ -804,14 +763,112 @@ void HFlashWrite(HFlashAddr_t addr, void *data, uint32_t size)
|
||||
HSCrc32Reset();
|
||||
HSCrc32Update((uint8_t *)data, size);
|
||||
cache->info.crc32 = HSCrc32Get();
|
||||
++cache->info.modifyCount;
|
||||
|
||||
WriteFlash(addr, data, size);
|
||||
WritePage(cache->pos, &cache->info);
|
||||
|
||||
// 检查是否在保护区域, 需要的话需要写入等待备份
|
||||
if (IsProtect(addr, size)) {
|
||||
AddBackupAddr(addr, size);
|
||||
}
|
||||
|
||||
WriteFlash(addr, data, size);
|
||||
WritePage(cache->pos, &cache->info);
|
||||
}
|
||||
|
||||
void HFlashWriteOffset(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);
|
||||
return ;
|
||||
}
|
||||
|
||||
const uint32_t useSize = offset + size;
|
||||
// 检查写入数据大小是否超出注册提供的大小范围
|
||||
if (cache->info.size < useSize) {
|
||||
FATAL_ERROR("addr[0x%08x] size[%d] overflow", addr, useSize);
|
||||
return ;
|
||||
}
|
||||
|
||||
++cache->info.modifyCount;
|
||||
|
||||
// 更新使用长度, 将跨越的部分填充0
|
||||
if (cache->info.useSize < useSize) {
|
||||
if (cache->info.useSize < offset) {
|
||||
WriteFlashValue(addr + cache->info.useSize, offset - cache->info.useSize, 0);
|
||||
}
|
||||
|
||||
cache->info.useSize = useSize;
|
||||
}
|
||||
|
||||
cache->info.crc32 = GetFlashCrc32(addr, useSize);
|
||||
WriteFlash(addr + offset, data, size);
|
||||
WritePage(cache->pos, &cache->info);
|
||||
|
||||
// 检查是否在保护区域, 需要的话需要写入等待备份
|
||||
if (IsProtect(addr, size)) {
|
||||
AddBackupAddr(addr, useSize);
|
||||
}
|
||||
}
|
||||
|
||||
void HFlashRawWrite(HFlashAddr_t addr, void *data, uint32_t size)
|
||||
{
|
||||
WriteFlash(addr, data, size);
|
||||
}
|
||||
|
||||
void 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 ;
|
||||
}
|
||||
|
||||
// 超出部分填充0
|
||||
if (cache->info.useSize < size) {
|
||||
memset((uint8_t *)data + cache->info.useSize, 0, size - cache->info.useSize);
|
||||
}
|
||||
|
||||
const uint32_t readSize = FLASH_MIN(uint32_t, size, cache->info.useSize);
|
||||
ReadFlash(addr, data, readSize);
|
||||
}
|
||||
|
||||
void 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 ;
|
||||
}
|
||||
|
||||
// 读取的偏移量超出使用长度
|
||||
if (cache->info.useSize < offset) {
|
||||
memset(data, 0, size);
|
||||
return ;
|
||||
}
|
||||
|
||||
// 读取的数据超出使用长度, 将使用长度后面填充0
|
||||
const uint32_t useSize = offset + size;
|
||||
const uint32_t remain = useSize - cache->info.useSize;
|
||||
if (cache->info.useSize < useSize) {
|
||||
memset((uint8_t *)data + size - remain, 0, remain);
|
||||
}
|
||||
|
||||
ReadFlash(addr, data, size - remain);
|
||||
}
|
||||
|
||||
void HFlashRawRead(HFlashAddr_t addr, void *data, uint32_t size)
|
||||
{
|
||||
ReadFlash(addr, data, size);
|
||||
}
|
||||
|
||||
uint32_t HFlashGetCrc32(HFlashAddr_t addr)
|
||||
{
|
||||
HFlashCacheInfo *cache = FindCache(addr);
|
||||
if (cache == NULL) {
|
||||
FATAL_ERROR("addr[0x%08x] not register", addr);
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
return cache->info.crc32;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user