19size_t AvailableSize() {
return GetChecksumOffset() - GetUsedBlockSize(BlockType::MAIN); }
26size_t GetBlockOffset(BlockType block)
28 return block == BlockType::BACKUP ? block_size_ : 0;
35size_t GetChecksumOffset() {
return block_size_ - GetChecksumSize(); }
41size_t GetChecksumSize() {
return AlignSize(
sizeof(CHECKSUM_BYTE)); }
50void WriteEmptyBlockPrefix(BlockType block)
52 const size_t offset = GetBlockOffset(block);
53 EraseFlashOrExit(offset, block_size_);
56 info.
header = FLASH_HEADER;
63 WriteFlashOrExit(offset, {
reinterpret_cast<uint8_t*
>(&info),
sizeof(
FlashInfo)});
70void WriteBlockChecksum(BlockType block)
72 WriteFlashOrExit(GetBlockOffset(block) + GetChecksumOffset(),
73 {&CHECKSUM_BYTE,
sizeof(CHECKSUM_BYTE)});
84void InitBlock(BlockType block)
86 WriteEmptyBlockPrefix(block);
87 WriteBlockChecksum(block);
97void PrepareBackup() { WriteEmptyBlockPrefix(BlockType::BACKUP); }
111bool IsBackupPrepared()
113 const size_t sentinel_offset = GetSentinelOffset(BlockType::BACKUP);
115 ReadFlashOrExit(GetBlockOffset(BlockType::BACKUP), info);
116 if (info.
header != FLASH_HEADER ||
123 return IsErased(sentinel_offset + AlignSize(
sizeof(
KeyInfo)),
124 GetBlockOffset(BlockType::BACKUP) + block_size_);
131size_t GetCrcSize() {
return AlignSize(
sizeof(uint32_t)); }
138uint32_t GetBackupCrc(
size_t used_size)
140 uint32_t crc = 0xFFFFFFFFU;
142 const size_t offset = GetBlockOffset(BlockType::BACKUP);
143 for (
size_t done = 0; done < used_size;)
146 ReadFlashOrExit(offset + done, RawData(buffer, size));
147 for (
size_t i = 0; i < size; ++i)
150 for (
int bit = 0; bit < 8; ++bit)
152 crc = (crc >> 1) ^ (0xEDB88320U & (0U - (crc & 1U)));
175bool IsBackupRestorable(
size_t& used_size)
177 return IsBlockValid(BlockType::BACKUP) && !IsBlockEmpty(BlockType::BACKUP) &&
178 TryGetUsedBlockSize(BlockType::BACKUP, used_size);
196bool IsBackupComplete(
size_t& used_size)
198 if (!IsBackupRestorable(used_size) || used_size + GetCrcSize() > GetChecksumOffset())
202 uint32_t stored_crc = 0;
203 ReadFlashOrExit(GetBlockOffset(BlockType::BACKUP) + used_size, stored_crc);
204 return stored_crc == GetBackupCrc(used_size);
212bool IsBlockInited(BlockType block)
214 const size_t offset = GetBlockOffset(block);
216 ReadFlashOrExit(offset, flash_data);
217 return flash_data.
header == FLASH_HEADER;
229bool IsBlockEmpty(BlockType block)
231 const size_t offset = GetBlockOffset(block);
233 ReadFlashOrExit(offset, flash_data);
243bool IsBlockError(BlockType block)
245 const size_t offset = GetBlockOffset(block);
246 uint32_t checksum = 0;
247 ReadFlashOrExit(offset + GetChecksumOffset(), checksum);
248 return checksum != CHECKSUM_BYTE;
262bool IsBlockValid(BlockType block)
264 if (!IsBlockInited(block) || IsBlockError(block))
269 ReadFlashOrExit(GetSentinelOffset(block), sentinel);
279size_t GetSentinelOffset(BlockType block)
291bool IsErased(
size_t offset,
size_t end)
297 ReadFlashOrExit(offset, RawData(buffer, size));
298 for (
size_t i = 0; i < size; ++i)
300 if (buffer[i] != 0xFF)
323bool TryGetUsedBlockSize(BlockType block,
size_t& used_size)
325 const size_t block_offset = GetBlockOffset(block);
326 const size_t checksum_offset = block_offset + GetChecksumOffset();
331 if (key_offset + AlignSize(
sizeof(
KeyInfo)) > checksum_offset)
337 ReadFlashOrExit(key_offset, key);
347 const size_t next_key_offset = key_offset + AlignSize(
sizeof(
KeyInfo)) +
350 if (next_key_offset > checksum_offset)
357 used_size = next_key_offset - block_offset;
361 key_offset = next_key_offset;
371size_t GetUsedBlockSize(BlockType block)
373 return GetNextKey(GetLastKey(block)) - GetBlockOffset(block);
385void CopyBlockPrefixAndChecksum(BlockType dst_block, BlockType src_block,
388 const size_t dst_offset = GetBlockOffset(dst_block);
389 const size_t src_offset = GetBlockOffset(src_block);
390 const size_t checksum_offset = GetChecksumOffset();
392 DEV_ASSERT(used_size <= checksum_offset);
394 CopyFlashData(dst_offset, src_offset, used_size);
395 CopyFlashData(dst_offset + checksum_offset, src_offset + checksum_offset,
读写对齐布尔位图块的工具 Helpers for reading and writing aligned boolean flag blocks.
static void SetFlag(BlockBoolData< BlockSize > &obj, bool value)
把一个布尔值编码进位图块 / Encode one boolean value into a flag block.
static bool ReadFlag(const BlockBoolData< BlockSize > &obj)
从位图块读取布尔值 / Decode one boolean value from a flag block.
constexpr auto min(LeftType a, RightType b) -> std::common_type_t< LeftType, RightType >
计算两个数的最小值 / Computes the minimum of two numbers
size_t OffsetOf(MemberType OwnerType::*member) noexcept
计算成员在宿主对象中的偏移量 Computes the offset of a member within the owning object
Flash 存储的块信息结构 Structure representing a Flash storage block.
uint32_t header
Flash 块头签名 / Flash block-header signature.
键信息结构,存储键的元数据 Structure containing key metadata.
BlockBoolData< MinWriteSize > uninit
该键是否未初始化
BlockBoolData< MinWriteSize > available_flag
该键是否有效
uint32_t GetDataSize() const
获取数据字节数 / Get the payload size in bytes.
void SetNameLength(uint8_t len)
设置键名长度 / Set the key name length.
BlockBoolData< MinWriteSize > no_next_key
是否是最后一个键
void SetDataSize(uint32_t size)
设置数据字节数 / Set the payload size in bytes.
uint8_t GetNameLength() const
获取键名长度 / Get the key name length.