2024年6月6日星期四
以写入一条boot_count为例。boot_count每次值累加1.KV名不变。相当于每次把上一次的状态置删除,然后写入新的一条。
整条KV长度56(0x38)字节。
为了方便查看,数据库开始地址修改为0x20000,分配4个扇区。
[D/FAL] (fal_flash_init:47) Flash device | stm32_onchip | addr: 0x08000000 | len: 0x00040000 | blk_size: 0x00000800 |initialized finish.
[32;22m[I/FAL] ==================== FAL partition table ====================[0m
[32;22m[I/FAL] | name | flash_dev | offset | length |[0m
[32;22m[I/FAL] -------------------------------------------------------------[0m
[32;22m[I/FAL] | fdb_tsdb1 | stm32_onchip | 0x0001a000 | 0x00002000 |[0m
[32;22m[I/FAL] | fdb_kvdb1 | stm32_onchip | 0x00020000 | 0x00002000 |[0m
[32;22m[I/FAL] =============================================================[0m
[32;22m[I/FAL] Flash Abstraction Layer (V0.5.99) initialize success.[0m
[FlashDB][kv][env][fdb_kvdb1] (..\..\..\src\fdb_kvdb.c:1777) The oldest addr is @0x00000000
[FlashDB][kv][env][fdb_kvdb1] (..\..\..\src\fdb_kvdb.c:1793) KVDB size is 8192 bytes.
[FlashDB][kv][env][fdb_kvdb1] Sector header info is incorrect. Auto format this sector (0x00000000).
[FlashDB][kv][env][fdb_kvdb1] Sector header info is incorrect. Auto format this sector (0x00000800).
[FlashDB][kv][env][fdb_kvdb1] Sector header info is incorrect. Auto format this sector (0x00001000).
[FlashDB][kv][env][fdb_kvdb1] Sector header info is incorrect. Auto format this sector (0x00001800).
[FlashDB][kv][env][fdb_kvdb1] All sector header is incorrect. Set it to default.
[FlashDB] FlashDB V2.1.0 is initialize success.
[FlashDB] You can get the latest version on https://github.com/armink/FlashDB .
empty_kV值为0x748。
0x2748位置写Val:28,此时还余0xB0字节。
0x38+0x24+0x40=0x9C。0xB0大于0x9C此次还能写入0扇区。写入后,empty_kV值为0x780。
0x2780位置写Val:29,此时还余0x80字节。
0x38+0x24+0x40=0x9C。0x80小于0x9C此时0扇区写不下。
//分配KV空间
static uint32_t alloc_kv(fdb_kvdb_t db, kv_sec_info_t sector, size_t kv_size)
{
uint32_t empty_kv = FAILED_ADDR;
size_t empty_sector = 0, using_sector = 0;
struct alloc_kv_cb_args arg = {db, kv_size, &empty_kv};
/* sector status statistics 扇区状态统计,统计使用的扇区和空扇区数量*/
if (using_sector > 0) {
/* alloc the KV from the using status sector first 首先从使用状态扇区分配KV*/
sector_iterator(db, sector, FDB_SECTOR_STORE_USING, &arg, NULL, alloc_kv_cb, true);
}
if (empty_sector > 0 && empty_kv == FAILED_ADDR) {
if (empty_sector > FDB_GC_EMPTY_SEC_THRESHOLD || db->gc_request) {//1个扇区写不下了,转下一个空扇区
sector_iterator(db, sector, FDB_SECTOR_STORE_EMPTY, &arg, NULL, alloc_kv_cb, true);
} else {
/* no space for new KV now will GC and retry 现在没有空间给新的KV,将GC并重试*/
FDB_DEBUG("Trigger a GC check after alloc KV failed.\n");
db->gc_request = true;
}
}
return empty_kv;
}
当一个扇区没空间了则执行
sector_iterator(db, sector, FDB_SECTOR_STORE_EMPTY, &arg, NULL, alloc_kv_cb, true);
查找到最近的一个空扇区。
并读取Flash下一扇区状态信息,计算出empty_kv,remain更新到扇区缓存表中。
[FlashDB][sample][kvdb][basic] ==================== kvdb_basic_sample ====================
[FlashDB][sample][kvdb][basic] get the 'boot_count' value is 96
[FlashDB][sample][kvdb][basic] set the 'boot_count' value to 97
[FlashDB][sample][kvdb][basic] ===========================================================
[FlashDB][sample][kvdb][basic] ==================== kvdb_basic_sample ====================
[FlashDB][sample][kvdb][basic] get the 'boot_count' value is 97
[FlashDB][kv][env][fdb_kvdb1] (..\..\..\src\fdb_kvdb.c:928) Trigger a GC check after alloc KV failed.
写到97后,触发GC回收。
#define FDB_GC_EMPTY_SEC_THRESHOLD 1
即保留了一个扇区不会写数据。
[FlashDB][kv][env][fdb_kvdb1] Warning: Alloc an KV (size 56) failed when new KV. Now will GC then retry.
[FlashDB][kv][env][fdb_kvdb1] (..\..\..\src\fdb_kvdb.c:1149) The remain empty sector is 1, GC threshold is 1.
LOG提示有一个空扇区。
GC先将扇区0的3条KV移到扇区3,然后删除扇区0。接着将要写的KV继续在扇区3内容后面写。
扇区3写满了,则删除1扇区。在第0扇区接着写数据。始终保持一个扇区空,用来GC。
第2轮时,出现一次写Flash错误。GC第0扇区(0x000000)没成功,再次GC了第1扇区。
后面就再也没有GC第0扇区。
再3轮后,GC第3扇区(0x00001800)时写出错。状态都为未使用了。
此时是在扇区2写数据,当写满后,就再也写不动了,写610写不进了。一直读出的是609.也没有报什么错误。
重开机再次测试到5000数,运行正常。可能是受干扰了。