diff --git a/include/HFlashServer.h b/include/HFlashServer.h index 2cd1510..105149f 100644 --- a/include/HFlashServer.h +++ b/include/HFlashServer.h @@ -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 #include @@ -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__ diff --git a/src/HFlashServer.c b/src/HFlashServer.c index 865a011..9d2aca6 100644 --- a/src/HFlashServer.c +++ b/src/HFlashServer.c @@ -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; +}