libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
raw_sequential.cpp
1#include "raw_sequential.hpp"
2
3#include <cstddef>
4#include <cstdint>
5
6#include "libxr_def.hpp"
7#include "libxr_mem.hpp"
8
9using namespace LibXR;
10
12 : flash_(flash), max_buffer_size_(max_buffer_size)
13{
14 ASSERT(flash.MinEraseSize() * 2 <= flash.Size());
15 ASSERT(max_buffer_size <= flash.Size() / 2);
16 auto block_num = static_cast<size_t>(flash.Size() / flash.MinEraseSize());
17 block_size_ = block_num / 2 * flash.MinEraseSize();
18 buffer_ = new uint8_t[max_buffer_size];
19
20 Init();
21}
22
23DatabaseRawSequential::KeyInfo::KeyInfo() : raw_data(0xFFFFFFFF) {}
24
25DatabaseRawSequential::KeyInfo::KeyInfo(bool nextKey, uint8_t nameLength,
26 uint32_t dataSize)
27 : raw_data(0)
28{
29 SetNextKeyExist(nextKey);
30 SetNameLength(nameLength);
31 SetDataSize(dataSize);
32}
33
35{
36 raw_data = (raw_data & 0x7FFFFFFF) | (static_cast<uint32_t>(value & 0x1) << 31);
37}
38
40{
41 return (raw_data >> 31) & 0x1;
42}
43
45{
46 raw_data = (raw_data & 0x80FFFFFF) | (static_cast<uint32_t>(len & 0x7F) << 24);
47}
48
50{
51 return (raw_data >> 24) & 0x7F;
52}
53
55{
56 raw_data = (raw_data & 0xFF000000) | (size & 0x00FFFFFF);
57}
58
60{
61 return raw_data & 0x00FFFFFF;
62}
63
64void DatabaseRawSequential::ReadFlashOrExit(size_t offset, RawData data)
65{
66 REQUIRE(flash_.Read(offset, data) == ErrorCode::OK);
67}
68
69void DatabaseRawSequential::WriteFlashOrExit(size_t offset, ConstRawData data)
70{
71 REQUIRE(flash_.Write(offset, data) == ErrorCode::OK);
72}
73
74void DatabaseRawSequential::EraseFlashOrExit(size_t offset, size_t size)
75{
76 REQUIRE(flash_.Erase(offset, size) == ErrorCode::OK);
77}
78
80{
82 FlashInfo* flash_data_ = reinterpret_cast<FlashInfo*>(buffer_);
83 flash_data_->header = FLASH_HEADER;
84 flash_data_->key = {0, 0, 0};
86
88 {
89 InitBlock(BlockType::BACKUP);
90 }
91
93 {
95 {
96 InitBlock(BlockType::MAIN);
97 }
98 else
99 {
100 ReadFlashOrExit(block_size_, {buffer_, max_buffer_size_});
101 EraseFlashOrExit(0, block_size_);
102 WriteFlashOrExit(0, {buffer_, max_buffer_size_});
103 }
104 }
105
106 Load();
107}
108
110{
111 EraseFlashOrExit(block_size_, block_size_);
112 WriteFlashOrExit(block_size_, {buffer_, max_buffer_size_});
113
114 EraseFlashOrExit(0, block_size_);
115 WriteFlashOrExit(0, {buffer_, max_buffer_size_});
116}
117
118void DatabaseRawSequential::Load() { ReadFlashOrExit(0, {buffer_, max_buffer_size_}); }
119
121{
123 FlashInfo* flash_data_ = reinterpret_cast<FlashInfo*>(buffer_);
124 flash_data_->header = FLASH_HEADER;
125 flash_data_->key = {0, 0, 0};
127 EraseFlashOrExit(0, block_size_);
128 EraseFlashOrExit(block_size_, block_size_);
129 WriteFlashOrExit(0, {buffer_, max_buffer_size_});
130 WriteFlashOrExit(block_size_, {buffer_, max_buffer_size_});
131}
132
134{
135 auto ans = SearchKey(key.name_);
136 if (!ans)
137 {
139 }
140
141 KeyInfo key_buffer;
142 ReadFlashOrExit(ans, key_buffer);
143
144 if (key.raw_data_.size_ != key_buffer.GetDataSize())
145 {
146 return ErrorCode::FAILED;
147 }
148
149 GetKeyData(ans, key.raw_data_);
150
151 return ErrorCode::OK;
152}
153
154void DatabaseRawSequential::InitBlock(BlockType block)
155{
156 size_t offset = 0;
157 if (block == BlockType::BACKUP)
158 {
159 offset = block_size_;
160 }
161
162 EraseFlashOrExit(offset, block_size_);
163 WriteFlashOrExit(offset, {buffer_, max_buffer_size_});
164}
165
173{
174 size_t offset = 0;
175 if (block == BlockType::BACKUP)
176 {
177 offset = block_size_;
178 }
179 FlashInfo flash_data_;
180 ReadFlashOrExit(offset, flash_data_);
181 return flash_data_.header == FLASH_HEADER;
182}
183
190{
191 size_t offset = 0;
192 if (block == BlockType::BACKUP)
193 {
194 offset = block_size_;
195 }
196 FlashInfo flash_data_;
197 ReadFlashOrExit(offset, flash_data_);
198 return flash_data_.key.GetNameLength() == 0;
199}
200
207{
208 size_t offset = 0;
209 if (block == BlockType::BACKUP)
210 {
211 offset = block_size_;
212 }
213 uint8_t checksum_byte = 0;
214 ReadFlashOrExit(offset + max_buffer_size_ / sizeof(CHECKSUM_BYTE) - 1, checksum_byte);
215 return checksum_byte != CHECKSUM_BYTE;
216}
217
218bool DatabaseRawSequential::HasLastKey(size_t offset)
219{
220 KeyInfo key;
221 ReadFlashOrExit(offset, key);
222 return key.GetNextKeyExist();
223}
224
225size_t DatabaseRawSequential::GetKeySize(size_t offset)
226{
227 KeyInfo key;
228 ReadFlashOrExit(offset, key);
229 return sizeof(KeyInfo) + key.GetNameLength() + key.GetDataSize();
230}
231
232size_t DatabaseRawSequential::GetNextKey(size_t offset)
233{
234 return offset + GetKeySize(offset);
235}
236
237size_t DatabaseRawSequential::GetLastKey(BlockType block)
238{
239 if (IsBlockEmpty(block))
240 {
241 return 0;
242 }
243
244 size_t offset = LibXR::OffsetOf(&FlashInfo::key);
245 while (HasLastKey(offset))
246 {
247 offset = GetNextKey(offset);
248 }
249 return offset;
250}
251
252void DatabaseRawSequential::SetNestKeyExist(size_t offset, bool exist)
253{
254 KeyInfo key;
255 ReadFlashOrExit(offset, key);
256 key.SetNextKeyExist(exist);
257 LibXR::Memory::FastCopy(buffer_ + offset, &key, sizeof(KeyInfo));
258}
259
260bool DatabaseRawSequential::KeyDataCompare(size_t offset, const void* data, size_t size)
261{
262 KeyInfo key;
263 ReadFlashOrExit(offset, key);
264 size_t key_data_offset = offset + sizeof(KeyInfo) + key.GetNameLength();
265 uint8_t data_buffer;
266 for (size_t i = 0; i < size; i++)
267 {
268 ReadFlashOrExit(key_data_offset + i, data_buffer);
269 if (data_buffer != ((uint8_t*)data)[i])
270 {
271 return true;
272 }
273 }
274 return false;
275}
276
277bool DatabaseRawSequential::KeyNameCompare(size_t offset, const char* name)
278{
279 KeyInfo key;
280 ReadFlashOrExit(offset, key);
281 for (size_t i = 0; i < key.GetNameLength(); i++)
282 {
283 uint8_t data_buffer;
284 ReadFlashOrExit(offset + sizeof(KeyInfo) + i, data_buffer);
285 if (data_buffer != name[i])
286 {
287 return true;
288 }
289 }
290 return false;
291}
292
293ErrorCode DatabaseRawSequential::AddKey(const char* name, const void* data, size_t size)
294{
295 if (auto ans = SearchKey(name))
296 {
297 return SetKey(ans, data, size);
298 }
299
300 const uint32_t NAME_LEN = strlen(name) + 1;
301 size_t last_key_offset = GetLastKey(BlockType::MAIN);
302 size_t key_buf_offset =
303 last_key_offset ? GetNextKey(last_key_offset) : LibXR::OffsetOf(&FlashInfo::key);
304
305 size_t end_pos_offset = key_buf_offset + sizeof(KeyInfo) + NAME_LEN + size;
306 if (end_pos_offset > max_buffer_size_ - 1)
307 {
308 return ErrorCode::FULL;
309 }
310
311 size_t data_ptr_offset = key_buf_offset + sizeof(KeyInfo);
312 LibXR::Memory::FastCopy(buffer_ + data_ptr_offset, name, NAME_LEN);
313 LibXR::Memory::FastCopy(buffer_ + data_ptr_offset + NAME_LEN, data, size);
314
315 KeyInfo key_buf = {0, static_cast<uint8_t>(NAME_LEN), static_cast<uint32_t>(size)};
316 LibXR::Memory::FastCopy(buffer_ + key_buf_offset, &key_buf, sizeof(KeyInfo));
317 if (last_key_offset)
318 {
319 SetNestKeyExist(last_key_offset, 1);
320 }
321
322 Save();
323 return ErrorCode::OK;
324}
325
326ErrorCode DatabaseRawSequential::SetKey(const char* name, const void* data, size_t size)
327{
328 if (size_t key_offset = SearchKey(name))
329 {
330 return SetKey(key_offset, data, size);
331 }
332 return ErrorCode::FAILED;
333}
334
335ErrorCode DatabaseRawSequential::SetKey(size_t offset, const void* data, size_t size)
336{
337 ASSERT(offset != 0);
338
339 KeyInfo key;
340 ReadFlashOrExit(offset, key);
341
342 if (key.GetDataSize() == size)
343 {
344 if (KeyDataCompare(offset, data, size))
345 {
346 LibXR::Memory::FastCopy(buffer_ + offset + sizeof(KeyInfo) + key.GetNameLength(),
347 data, size);
348 Save();
349 }
350 return ErrorCode::OK;
351 }
352
353 return ErrorCode::FAILED;
354}
355
356ErrorCode DatabaseRawSequential::GetKeyData(size_t offset, RawData data)
357{
358 KeyInfo key;
359 ReadFlashOrExit(offset, key);
360 if (key.GetDataSize() > data.size_)
361 {
362 return ErrorCode::FAILED;
363 }
364 auto data_offset = offset + sizeof(KeyInfo) + key.GetNameLength();
365 ReadFlashOrExit(data_offset, {data.addr_, key.GetDataSize()});
366 return ErrorCode::OK;
367}
368
369size_t DatabaseRawSequential::SearchKey(const char* name)
370{
372 {
373 return 0;
374 }
375
376 size_t key_offset = LibXR::OffsetOf(&FlashInfo::key);
377 while (true)
378 {
379 if (KeyNameCompare(key_offset, name) == 0)
380 {
381 return key_offset;
382 }
383 if (!HasLastKey(key_offset))
384 {
385 break;
386 }
387 key_offset = GetNextKey(key_offset);
388 }
389 return 0;
390}
只读原始数据视图 / Immutable raw data view
键的基类,存储键名及其数据 (Base class for keys, storing key name and associated data).
Definition interface.hpp:31
RawData raw_data_
原始数据 (Raw data associated with the key).
Definition interface.hpp:34
const char * name_
键名 (Key name).
Definition interface.hpp:33
void Save()
保存当前缓冲区内容到 Flash (Save the current buffer content to Flash).
static constexpr uint8_t CHECKSUM_BYTE
校验字节 (Checksum byte).
uint32_t max_buffer_size_
最大缓冲区大小 (Maximum buffer size).
ErrorCode Get(Database::KeyBase &key) override
获取数据库中的键值 (Retrieve the key's value from the database).
void Init()
初始化数据库存储区,确保主备块正确 (Initialize database storage, ensuring main and backup blocks are valid).
uint8_t * buffer_
数据缓冲区 (Data buffer).
static constexpr uint32_t FLASH_HEADER
Flash 头部标识 (Flash header identifier).
void Restore()
还原存储数据,清空 Flash 区域 (Restore storage data, clearing Flash memory area).
bool IsBlockEmpty(BlockType block)
判断块是否为空 (Check if block is empty).
uint32_t block_size_
Flash 块大小 (Flash block size).
Flash & flash_
目标 Flash 存储设备 (Target Flash storage device).
void Load()
从 Flash 加载数据到缓冲区 (Load data from Flash into the buffer).
DatabaseRawSequential(Flash &flash, size_t max_buffer_size=256)
构造函数,初始化 Flash 存储和缓冲区 (Constructor initializing Flash storage and buffer).
bool IsBlockInited(BlockType block)
判断块是否已初始化 (Check if block is initialized).
BlockType
存储块类型 (Storage block type).
@ BACKUP
备份块 (Backup block).
bool IsBlockError(BlockType block)
判断块是否损坏 (Check if block has an error).
Abstract base class representing a flash memory interface. 抽象基类,表示闪存接口。
Definition flash.hpp:19
size_t Size() const
Returns the size of the flash memory area. 获取闪存存储区域的大小。
Definition flash.hpp:82
virtual ErrorCode Erase(size_t offset, size_t size)=0
Erases a section of the flash memory. 擦除闪存的指定区域。
virtual ErrorCode Write(size_t offset, ConstRawData data)=0
Writes data to the flash memory. 向闪存写入数据。
virtual ErrorCode Read(size_t offset, RawData data)
Reads data from the flash memory. 从闪存中读取数据。
Definition flash.cpp:14
size_t MinEraseSize() const
Returns the minimum erasable block size in bytes. 获取最小可擦除块大小(字节)。
Definition flash.hpp:64
static void FastSet(void *dst, uint8_t value, size_t size)
快速内存填充 / Fast memory fill
static void FastCopy(void *dst, const void *src, size_t size)
快速内存拷贝 / Fast memory copy
Definition libxr_mem.cpp:5
可写原始数据视图 / Mutable raw data view
size_t size_
数据字节数 / Data size in bytes
void * addr_
数据起始地址 / Data start address
LibXR 命名空间
Definition ch32_can.hpp:14
ErrorCode
定义错误码枚举
@ NOT_FOUND
未找到 | Not found
@ FAILED
操作失败 | Operation failed
@ FULL
已满 | Full
@ OK
操作成功 | Operation successful
size_t OffsetOf(MemberType OwnerType::*member) noexcept
计算成员在宿主对象中的偏移量
Definition libxr_def.hpp:88
Flash 存储的块信息结构 (Structure representing a Flash storage block).
Definition layout.hpp:163
键信息结构,存储键的元数据 (Structure containing key metadata).
Definition layout.hpp:106
uint32_t GetDataSize() const
获取数据字节数 (Get the payload size in bytes).
Definition layout.hpp:153
uint8_t GetNameLength() const
获取键名长度 (Get the key name length).
Definition layout.hpp:138
Flash 存储的块信息结构 (Structure representing a Flash storage block).
KeyInfo key
该块的键信息 (Key metadata in this block).
uint32_t header
Flash 块头标识 (Flash block header identifier).
键信息结构,存储键的元数据 (Structure containing key metadata).
uint8_t GetNameLength() const
获取键名长度 (Get the key name length).
void SetNameLength(uint8_t len)
设置键名长度 (Set the key name length).
uint32_t GetDataSize() const
获取数据字节数 (Get the payload size in bytes).
KeyInfo()
构造一个擦除态键头 (Construct one erased-state key header).
void SetNextKeyExist(bool value)
设置是否存在后继键 (Set whether another key follows).
bool GetNextKeyExist() const
获取是否存在后继键 (Get whether another key follows).
void SetDataSize(uint32_t size)
设置数据字节数 (Set the payload size in bytes).