diff --git a/include/HFlashServer.h b/include/HFlashServer.h index 967ccc2..ac18dcc 100644 --- a/include/HFlashServer.h +++ b/include/HFlashServer.h @@ -235,6 +235,16 @@ uint8_t HFlashWrite(HFlashAddr_t addr, const void *data, uint32_t size); */ uint8_t HFlashWriteOffset(HFlashAddr_t addr, uint32_t offset, const void *data, uint32_t size); +/** + * @brief HFlashWriteOffsetValue 写入从原始地址偏移后的地方写入相同值, 超出原未使用部分会自动写入0填充 + * @param addr 需要注册的地址 + * @param offset 地址偏移 + * @param value 写入值 + * @param size 写入数据大小 + * @return 1: 写入成功 0: 写入失败 + */ +uint8_t HFlashWriteOffsetValue(HFlashAddr_t addr, uint32_t offset, uint8_t value, uint32_t size); + /** * @brief HFlashWriteRawOffset 写入原始地址偏移后的位置写入Flash数据, 超出部分不自动填充, 仅提供给一些库使用, 正常情况请勿使用 * @param addr 需要注册的地址 @@ -322,6 +332,17 @@ typedef void (*HFlashUpdateVersionCallback)(HFlashAddr_t addr, uint16_t oldVersi */ void HFlashUpdateVersion(HFlashAddr_t addr, uint16_t newVersion, HFlashUpdateVersionCallback callback, void *userData); +/** + * @brief HFlashUpgradeVersion 升级版本号, 仅在版本升高时触发回调 + * 如果旧版本比新版本大或相同, 不处理 + * 如果旧版本比新版本小, 会更新记录版本并触发回调, 可用于把数据升级到新版本 + * @param addr 需要注册的地址 + * @param newVersion 新版本号 + * @param callback 回调函数 + * @param userData 用户数据 + */ +void HFlashUpgradeVersion(HFlashAddr_t addr, uint16_t newVersion, HFlashUpdateVersionCallback callback, void *userData); + /** * @brief HFlashDefaultUpdateVersion 默认更新版本号回调, 直接删除旧数据 * @param addr 需要注册的地址 @@ -344,6 +365,14 @@ void HFlashDeleteData(HFlashAddr_t addr); */ uint32_t HFlashGetUseSize(HFlashAddr_t addr); +/** + * @brief HFlashSetUseSize 设置Flash数据的使用大小 + * @param addr 需要注册的地址 + * @param size 使用大小 + * @return 1: 设置成功 0: 设置失败 + */ +uint8_t HFlashSetUseSize(HFlashAddr_t addr, uint32_t size); + /** * @brief HFlashGetSize 获取Flash数据的大小 * @param addr 需要注册的地址 diff --git a/src/HFlashServer.c b/src/HFlashServer.c index fa26d7e..9c81b3c 100644 --- a/src/HFlashServer.c +++ b/src/HFlashServer.c @@ -521,16 +521,16 @@ static void SyncBackup() sBackupTimer = HTIMER_INVALID; } - for (uint16_t i = 0; i < HVectorGetUseLen(sNeedBackupOffset); ++i) { - const uint32_t addr = HVectorGetData(sNeedBackupOffset, i); + for (HVectorLenType remain = HVectorGetUseLen(sNeedBackupOffset); remain > 0; --remain) { + const uint32_t addr = HVectorGetData(sNeedBackupOffset, remain - 1); if (SyncBackupRange(addr, HFLASH_BLOCK_SIZE) == 0) { LogE("RestorePage faild, addr[0x%08x]", addr); StartSyncBackupTimer(); return ; } - } - HVectorClear(sNeedBackupOffset); + HVectorSetUseLen(sNeedBackupOffset, remain - 1); + } // 备份页表数据 const uint32_t crcValue = GetBackupCrc32(AdjustPageAddr(sInfo.pageAddr), AdjustPageByte(sPageInfo.useNum)); @@ -1706,6 +1706,40 @@ uint8_t HFlashWriteOffset(HFlashAddr_t addr, uint32_t offset, const void *data, return WriteOffset(addr, offset, data, size, 1); } +uint8_t HFlashWriteOffsetValue(HFlashAddr_t addr, uint32_t offset, uint8_t value, uint32_t size) +{ + uint8_t result = 0; + HFlashCacheInfo *cache = FindCache(addr); + if (cache == NULL) { + FATAL_ERROR("addr[0x%08x] not register", addr); + return result; + } + + const uint32_t useSize = offset + size; + if (cache->info.size < useSize) { + FATAL_ERROR("addr[0x%08x] size[%d] overflow", addr, useSize); + return result; + } + + if (cache->info.useSize < useSize) { + if (cache->info.useSize < offset) { + WriteFlashValue(addr + cache->info.useSize, offset - cache->info.useSize, 0); + } + + cache->info.useSize = useSize; + } + + result = WriteFlashValue(addr + offset, size, value); + cache->waitCrc = 1; + WriteCachePage(cache); + + if (IsProtect(addr, size)) { + AddBackupOffsetAddr(addr, offset, size); + } + + return result; +} + uint8_t HFlashWriteRawOffset(HFlashAddr_t addr, uint32_t offset, const void *data, uint32_t size) { return WriteOffset(addr, offset, data, size, 0); @@ -1818,7 +1852,7 @@ uint8_t HFlashRawRead(HFlashAddr_t addr, void *data, uint32_t size) return ReadFlashCall(addr, data, size); } -void HFlashUpdateVersion(HFlashAddr_t addr, uint16_t newVersion, HFlashUpdateVersionCallback callback, void *userData) +static void UpdateVersionInner(HFlashAddr_t addr, uint16_t newVersion, HFlashUpdateVersionCallback callback, void *userData, uint8_t onlyUpgrade) { HFlashCacheInfo *cache = FindCache(addr); if (cache == NULL) { @@ -1830,6 +1864,10 @@ void HFlashUpdateVersion(HFlashAddr_t addr, uint16_t newVersion, HFlashUpdateVer return ; } + if (onlyUpgrade && (newVersion < cache->info.version)) { + return ; + } + const uint16_t oldVersion = cache->info.version; cache->info.version = newVersion; if (callback) { @@ -1839,6 +1877,16 @@ void HFlashUpdateVersion(HFlashAddr_t addr, uint16_t newVersion, HFlashUpdateVer WriteCachePage(cache); } +void HFlashUpdateVersion(HFlashAddr_t addr, uint16_t newVersion, HFlashUpdateVersionCallback callback, void *userData) +{ + UpdateVersionInner(addr, newVersion, callback, userData, 0); +} + +void HFlashUpgradeVersion(HFlashAddr_t addr, uint16_t newVersion, HFlashUpdateVersionCallback callback, void *userData) +{ + UpdateVersionInner(addr, newVersion, callback, userData, 1); +} + void HFlashDefaultUpdateVersion(HFlashAddr_t addr, uint16_t oldVersion, uint16_t newVersion, void *userData) { (void)(oldVersion); @@ -1850,14 +1898,7 @@ void HFlashDefaultUpdateVersion(HFlashAddr_t addr, uint16_t oldVersion, uint16_t void HFlashDeleteData(HFlashAddr_t addr) { - HFlashCacheInfo *cache = FindCache(addr); - if (cache == NULL) { - FATAL_ERROR("addr[0x%08x] not register", addr); - return ; - } - - cache->info.useSize = 0; - WriteCachePage(cache); + HFlashSetUseSize(addr, 0); } uint32_t HFlashGetUseSize(HFlashAddr_t addr) @@ -1871,6 +1912,28 @@ uint32_t HFlashGetUseSize(HFlashAddr_t addr) return cache->info.useSize; } +uint8_t HFlashSetUseSize(HFlashAddr_t addr, uint32_t size) +{ + HFlashCacheInfo *cache = FindCache(addr); + if (cache == NULL) { + LogE("addr[0x%08x] not register", addr); + return 0; + } + + if (size > cache->info.size) { + LogE("addr[0x%08x] useSize[%d] overflow size[%d]", addr, size, cache->info.size); + return 0; + } + + cache->info.useSize = size; + cache->info.crc32 = GetFlashCrc32(addr, size); + WriteCachePage(cache); + if (size) { + AddBackupAddr(addr, size); + } + return 1; +} + uint32_t HFlashGetSize(HFlashAddr_t addr) { HFlashCacheInfo *cache = FindCache(addr); diff --git a/src/HRingBuffer.c b/src/HRingBuffer.c index 4c39289..27c0683 100644 --- a/src/HRingBuffer.c +++ b/src/HRingBuffer.c @@ -54,6 +54,16 @@ static inline HRingBufferLenType GetRingBufferTypeSize(const HRingBufferType *ri return 0; } +static inline uint8_t GetRingBufferTypeShift(const HRingBufferType *ringBuffer) { + switch(GetRingBufferType(ringBuffer)) { + case kHRingBufferFlag8: return 0; + case kHRingBufferFlag16: return 1; + case kHRingBufferFlag32: return 2; + } + + return 0xFF; +} + static inline HRingBufferDataType GetRingBufferData(const HRingBufferType *ringBuffer, HRingBufferLenType pos) { switch(GetRingBufferType(ringBuffer)) { case kHRingBufferFlag8: return ((const _HRingBuffer8 *)ringBuffer)->data[pos]; break; @@ -199,29 +209,40 @@ HRingBufferDataType HRingBufferPopData(HRingBufferType* buffer) { // 获取环状缓冲区数据, 返回获取的数据长度 HRingBufferLenType HRingBufferGetByteDatas(HRingBufferType* buffer, uint8_t *data, HRingBufferLenType len) { - if (HRingBufferGetUseLen(buffer) == 0) { + const HRingBufferLenType useLen = HRingBufferGetUseLen(buffer); + if (useLen == 0) { return 0; } _HRingBufferBase *base = (_HRingBufferBase *)buffer; - const HRingBufferLenType typeSize = GetRingBufferTypeSize(buffer); - const HRingBufferLenType startPos = base->start; - const HRingBufferLenType endPos = base->end; - int copyLen = (endPos - startPos) * typeSize; - if (startPos >= endPos) { - copyLen = (base->len - startPos) * typeSize; - } - - if (copyLen > len) { - copyLen = len / typeSize * typeSize; - } - - if (copyLen == 0) { + const uint8_t typeShift = GetRingBufferTypeShift(buffer); + if (data == NULL || typeShift > 2) { return 0; } - memcpy(data, GetRingByteData(buffer, startPos), copyLen); - AdjustReadPos(buffer, copyLen / typeSize); + HRingBufferLenType copyElems = len >> typeShift; + if (copyElems > useLen) { + copyElems = useLen; + } + + if (copyElems == 0) { + return 0; + } + + const HRingBufferLenType startPos = base->start; + HRingBufferLenType firstCopyElems = base->len - startPos; + if (firstCopyElems > copyElems) { + firstCopyElems = copyElems; + } + + const HRingBufferLenType copyLen = copyElems << typeShift; + const HRingBufferLenType firstCopyLen = firstCopyElems << typeShift; + memcpy(data, GetRingByteData(buffer, startPos), firstCopyLen); + if (firstCopyLen < copyLen) { + memcpy(data + firstCopyLen, GetRingByteData(buffer, 0), copyLen - firstCopyLen); + } + + AdjustReadPos(buffer, copyElems); return copyLen; }