armink / flashdb Goto Github PK
View Code? Open in Web Editor NEWAn ultra-lightweight database that supports key-value and time series data | 一款支持 KV 数据和时序数据的超轻量级数据库
License: Apache License 2.0
An ultra-lightweight database that supports key-value and time series data | 一款支持 KV 数据和时序数据的超轻量级数据库
License: Apache License 2.0
如何保证数据没有被异常篡改
朱先生你好,感谢您的FlashDB!
接上一条问题继续,我找到问题的根本原因,在于我的驱动中读取延时时间太短导致读取数据不全而出现读取错误。
但是我在排查故障的过程中发现FlashDB的实现程序中,从上层调用下一层函数的过程中,很多不判断函数返回值,而是直接返回,比如:
1、fdb_kvdb.c源文件get_kv函数中,第588行_fdb_flash_read((fdb_db_t)db, kv.addr.value, (uint32_t *) value_buf, read_len)语句,没有判断是否读取正确,而是直接返回。
2、fdb_utils.c源文件中_fdb_flash_read函数中,第256行fal_partition_read(db->storage.part, addr, (uint8_t *) buf, size)也没有判断返回,而是直接返回FDB_NO_ERR。
3、fdb_kvdb.c文件中,第530行find_kv(fdb_kvdb_t db, const char *key, fdb_kv_t kv)函数中调用read_kv(db, kv)也没有判断返回,而是直接返回true。
4、例程中FlashDB移植的read(long offset, uint8_t *buf, size_t size)函数,也没有判断返回数值,而是直接返回四则。
还有很多处,没有判断函数执行返回数值。
这样带来的问题是,当底层一个函数执行出现错误时,但是仍然是按照正确时返回,最终会出现读取或者写入的数据是错误的,而且程序健壮性不够强,排查故障很不方便。
朱先生是嵌入式行业大牛,请问,您这么做的原因是什么?有什么特殊考虑吗?
阅读源码的时候, 发现了一个问题:
就是的当sector_iterator(db, §or, FDB_SECTOR_STORE_UNUSED, &check_failed_count, db, check_sec_hdr_cb, false);
函数检测到所有的扇区的头部都出问题的时候, 这个时候check_failed_count
的值应该和该FAL分区中总的扇区数相等, 那么执行
if (check_failed_count == SECTOR_NUM) {
FDB_INFO("Warning: All sector header check failed. Set it to default.\n");
fdb_kv_set_default(db);
}
不就重复的对各扇区多擦除了一次吗?
其中
static bool check_sec_hdr_cb(kv_sec_info_t sector, void *arg1, void *arg2)
{
if (!sector->check_ok) {
size_t *failed_count = arg1;
fdb_kvdb_t db = arg2;
FDB_INFO("Warning: Sector header check failed. Format this sector (0x%08lX).\n", sector->addr);
(*failed_count) ++;
format_sector(db, sector->addr, SECTOR_NOT_COMBINED);
}
return false;
}
这个函数擦除了一次
上面的函数是在初始化是被 fdb_kvdb_init
调用, 调用关系大致为fdb_kvdb_init -> _fdb_kv_load
TSDB一直追加到分区满,会有什么动作
函数get_next_kv_addr中,发现pre_kv的crc校验失败,会触发find_next_kv_addr来尝试发现下一个kv_node。
但是在传递参数的的时候终止地址似乎有些问题。
终止地址传递的是sector结束地址减去sector_hdr的长度,但是sector_hdr是放在sector的头部的,这样看起来会导致find的时候没有对sector最后一部分地址进行检查。
劳烦作者看一下我的理解是否有问题
由于最近github间歇性被墙,我代 @xql923 提问:
硬件环境:
MCU:STM32F413;SPI Flash:W25Q256
配置FlashDB参数:FDB_WRITE_GRAN == 1
W25Q256每次按照一个扇区擦除4096字节,一个扇区只有在擦除后才能再次写入,如果扇区内数据没有擦除而直接写入,会写入失败。
问题描述:
移植FlashDB保存参数和数据,但是在实际仿真调试时,fdb_utils.c文件中_fdb_write_status()函数总是执行失败,仿真发现,_fdb_write_status()函数每次值写入一个字节,写入前FlashDB并没有考虑擦除所在扇区数据,而是直接写入,这样会导致写入失败。
请问,_fdb_write_status()函数没有考虑在写入前,擦除相应扇区的数据吗?
是否需要在移植接口函数中特殊考虑?
场景:多核处理器,有多个kvdb实例和多个cpu,每个cpu独占使用自己的kvdb实例。
目前kvdb的set_kv()
,del_kv()
等函数使用了static变量,无法支持重入,需要在调用时加全局锁。
如果暂不打算支持,建议在api文档中说明哪些接口无法重入。
朱工你好,请问,我通过时间查询ts数据库记录,有时能查询到记录,有时候查询不到记录,返回记录数为0,请问,根据时间查询ts数据库记录时,是否有特殊需要注意的地方?
芯片cm-4
系统4.0.2
调度器不调度
朱工,您好,再次的打扰您一下!
我再移植FlashDB的时候发现一个问题,您看看 是不是真正存在。
1、我在Env 环境中加载Flash DB 组件;然后需要定义两个全局变量,直接定义就好了。
2、但是在git hub 上提交的例程是 基于裸机的,Lock 和 unlock 是关闭和打开中断。这时候就有两个问题
(1)我再写的过程中发现,SPI TX RX DMA 开启,是无法运行的程序会执行不下去。将SPI DMA 关闭之后,程序可以运行,但是关闭之后又出现如下(2)问题。
(2)在shell中出现了,thread:heap stack overflow,程序无法继续运行。
(3)我是在main函数中,第一个线程之前 创建的,顺序是
<1>led
<2>SPIflash
<3>wdt
<4>fal
<5>falsh db
<6>通过rt_thread_create 创建第一个 LED 闪烁线程。
(4)这时候我将Lock 和 unlock 中的 两个函数__disable_irq(); __enable_irq();屏蔽掉,留下空的函数体,程序可以执行。
公司刚刚有个项目,选一个实时操作系统,可能我理解的还不够,有问题麻烦您指点一下。
谢谢
Email: [email protected]
1、系统信息
1.1 rt-thread stm32-207spi-nor_flash
1.2 fal信息
No flash device or partition was probed.
Usage: fal probe [dev_name|part_name] - probe flash device o[I/FAL] ==================== FAL partition table ====================
[I/FAL] | name | flash_dev | offset | length |
[I/FAL] -------------------------------------------------------------
[I/FAL] | onchip_flash | onchip_flash_16k | 0x00000000 | 0x00040000 |
[I/FAL] | bootloader | nor_flash0 | 0x00000000 | 0x00020000 |
[I/FAL] | filesystem | nor_flash0 | 0x00020000 | 0x00020000 |
[I/FAL] | fdb_tsdb1 | nor_flash0 | 0x00040000 | 0x000a0000 |
[I/FAL] | fdb_kvdb1 | nor_flash0 | 0x000e0000 | 0x00020000 |
[I/FAL] =============================================================
1.3 fal 测试信息
fal probe fdb_tsdb1
Probed a flash partition | fdb_tsdb1 | flash_dev: nor_flash0 |msh />
msh />fal bench 4096 yes
Erasing 655360 bytes data, waiting...
Erase benchmark success, total time: 0.828S.
Writing 655360 bytes data, waiting...
Write benchmark success, total time: 2.564S.
Reading 655360 bytes data, waiting...
Read benchmark success, total time: 2.010S.
1.4 fal 擦除写入读取测试针对 tsbd的 最后8byte进行
bench测试后第一次读取
msh />fal read 655352 8
Read data success. Start from 0x0009FFF8, size is 8. The data Offset (h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[0009FFF8] F8 F9 FA FB FC FD FE FF ........
擦除测试
msh />fal read 655352 8
Read data success. Start from 0x0009FFF8, size is 8. The data Offset (h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[0009FFF8] F8 F9 FA FB FC FD FE FF ........
写入测试
fal write 655352 1 2 3 4 5 6 7
Write data success. Start from 0x0009FFF8, size is 7.
Write data: 1 2 3 4 5 6 7 .
msh />fal read 655352 8
Read data success. Start from 0x0009FFF8, size is 8. The data Offset (h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[0009FFF8] 01 02 03 04 05 06 07 FF ........
2、调试断点:
main 函数增加测试代码 运行到这句出错 result = fdb_tsdb_init(&tsdb, "log", "fdb_tsdb1", get_time, 128, NULL);
3、shell提示信息如下:
\ | /
thread pri status sp stack size max used left tick-------- --- ------- ---------- ---------- ------ ---------- ---
dl645_th 20 init 0x00000044 0x00000800 03% 0x00000014 000
key_thre 20 suspend 0x00000044 0x00000200 13% 0x0000000a 000
rx8025_t 20 init 0x00000044 0x00000400 06% 0x00000014 000
led_thre 20 suspend 0x00000044 0x00000200 13% 0x00000014 000
tshell 20 suspend 0x00000110 0x00001000 06% 0x0000000a 000
ppp_recv 9 suspend 0x000000b8 0x00000800 08% 0x00000014 000
sys_ 23 suspend 0x00000188 0x00000800 19% 0x0000000a -01
tcpip 10 suspend 0x000000c0 0x00001000 15% 0x00000014 000
etx 12 suspend 0x0000009c 0x00000400 15% 0x00000010 000
erx 12 suspend 0x00000084 0x00000400 42% 0x0000000f 000
tidle0 31 suspend 0x00000040 0x00000100 31% 0x0000001f -01
main 10 suspend 0x00000248 0x00000800 42% 0x00000011 -02
usage fault:
SCB_CFSR_UFSR:0x02 INVSTATE
在使用SPI FLASH情况下啊,已经存在多个分区,怎样区别操作不同分区?
在fal_flash_sfud_port.c 文件中,
···
struct fal_flash_dev nor_flash0 =
{
.name = FAL_USING_NOR_FLASH_DEV_NAME,
.addr = 0,
.len = 410241024,
.blk_size = 4096,
.ops = {init, read, write, erase},
.write_gran = 1
};
···
中的 addr 和 len 修改后可否限制操作到其他位置,例如 addr = 10240; len = 10240, 是否说明 地址0-10239 和 20480之后的空间是绝对不会用到的。
分区表中的地址是在此定义空间中相对划分的吗?
根据tsdb_sample.c修改测试程序
1、首先append10条数据,然后遍历一遍数据是没有问题
2、再次重复上述动作
3、调用删除接口,删除数据库中数据【将状态修改为delete】
4、再次重复1、2动作,发现遍历后数据出现问题
代码:
写入数据
{ /* APPEND new TSL (time series log) */
struct env_status status;
for (int i = 0; i < 10; i++)
{
status.temp = 48 + i;
status.humi = 100 + i;
fdb_tsl_append(tsdb, fdb_blob_make(&blob, &status, sizeof(status)));
FDB_INFO("append the new status.temp (%d) and status.humi (%d)\n", status.temp, status.humi);
}
}
遍历数据库数据
fdb_tsl_iter(tsdb, query_cb, tsdb);
static bool query_cb(fdb_tsl_t tsl, void *arg)
{
struct fdb_blob blob;
struct env_status status;
fdb_tsdb_t db = arg;
fdb_blob_read((fdb_db_t) db, fdb_tsl_to_blob(tsl, fdb_blob_make(&blob, &status, sizeof(status))));
FDB_INFO("[query_cb] queried a TSL: time: %ld, status: %d, temp: %d, humi: %d\n", tsl->time, tsl->status, status.temp, status.humi);
return false;
}
删除数据库数据,将状态修改为delete:
fdb_tsl_clean(tsdb);
fdb_tsl_iter(tsdb, set_status_delete_cb, tsdb);
fdb_tsl_iter(tsdb, query_cb, tsdb);
日志:
[FlashDB][sample][tsdb] [query_cb] queried a TSL: time: 21, status: 4, temp: 58, humi: 110
[FlashDB][sample][tsdb] [query_cb] queried a TSL: time: 22, status: 4, temp: 59, humi: 111
[FlashDB][sample][tsdb] [query_cb] queried a TSL: time: 23, status: 4, temp: 60, humi: 112
[FlashDB][sample][tsdb] [query_cb] queried a TSL: time: 24, status: 4, temp: 61, humi: 113
[FlashDB][sample][tsdb] [query_cb] queried a TSL: time: 25, status: 4, temp: 62, humi: 114
[FlashDB][sample][tsdb] [query_cb] queried a TSL: time: 26, status: 4, temp: 63, humi: 115
[FlashDB][sample][tsdb] [query_cb] queried a TSL: time: 27, status: 4, temp: 64, humi: 116
[FlashDB][sample][tsdb] [query_cb] queried a TSL: time: 28, status: 4, temp: 65, humi: 117
[FlashDB][sample][tsdb] [query_cb] queried a TSL: time: 29, status: 4, temp: 8, humi: 352
[FlashDB][sample][tsdb] [query_cb] queried a TSL: time: 30, status: 4, temp: 67, humi: 40
[FlashDB][sample][tsdb] [query_cb] queried a TSL: time: 31, status: 4, temp: 360, humi: 0
[FlashDB][sample][tsdb] [query_cb] queried a TSL: time: 32, status: 4, temp: 39, humi: 8
[FlashDB][sample][tsdb] [query_cb] queried a TSL: time: 33, status: 4, temp: 0, humi: 122
[FlashDB][sample][tsdb] [query_cb] queried a TSL: time: 34, status: 4, temp: 8, humi: 368
[FlashDB][sample][tsdb] [query_cb] queried a TSL: time: 35, status: 4, temp: 72, humi: 38
[FlashDB][sample][tsdb] [query_cb] queried a TSL: time: 129, status: 4, temp: 0, humi: -1
[FlashDB][sample][tsdb] [query_cb] queried a TSL: time: 74, status: 4, temp: 74, humi: 126
[FlashDB][sample][tsdb] [query_cb] queried a TSL: time: 38, status: 4, temp: 75, humi: 127
[FlashDB][sample][tsdb] [query_cb] queried a TSL: time: 39, status: 4, temp: 76, humi: 128
[FlashDB][sample][tsdb] [query_cb] queried a TSL: time: 40, status: 4, temp: 77, humi: 129
[FlashDB][sample][tsdb] ===========================================================
朱总,好!
又打扰您了,想问下env增量升级的逻辑,比如default kv node中有2个结构体,如果结构体中的元素增加或减少后,改变KVDB_VERSION,会更新对于的数据吗?还是说default kv node中有2个结构体,如果再增加一个node后,改变KVDB_VERSION,数据会更新。
我测试修改结构体中的元素,改变KVDB_VERSION,读出的数据不对,所以想请教下env增量升级的逻辑,谢谢您!
例:
FDB_PRINT("blob @0x%08lX %lubytes", kv->addr.value, kv->value_len);
kv->addr.value和kv->value_len是uint32_t类型的变量,则格式化字符串应该用<inttypes.h>定义的格式:
FDB_PRINT("blob @0x%08" PRIX32 " %" PRIu32 "bytes", kv->addr.value, kv->value_len);
// 回收扇区将数据存放在 FDB_SECTOR_STORE_UNUSED 未使用的扇区
sector_iterator(db, §or, FDB_SECTOR_STORE_UNUSED, db, NULL, do_gc, false);
// 且存储状态为 FDB_SECTOR_STORE_EMPTY FDB_SECTOR_STORE_UNUSED 的扇区总和
// arg1 = db 数据库指针
// arg2 = NULL
static bool do_gc(kv_sec_info_t sector, void *arg1, void *arg2)
{
struct fdb_kv kv;
fdb_kvdb_t db = arg1;
/* s0: 回收扇区必须是校验OK且,扇区的脏状态为 FDB_SECTOR_DIRTY_TRUE FDB_SECTOR_DIRTY_GC*/
if (sector->check_ok &&
(sector->status.dirty == FDB_SECTOR_DIRTY_TRUE ||
sector->status.dirty == FDB_SECTOR_DIRTY_GC))
{
uint8_t status_table[FDB_DIRTY_STATUS_TABLE_SIZE];
/* s1: 将状态设置为GC状态 */
/************************************************************************************
疑问: 我知道FLASH写入数据是需要先擦后写的,此处的设置状态也是将每个状态错开在不同字节中实现
修改状态,实际是修改的不同位置的字节,如果上次写入数据在GC状态下断电,下次开机操作的
时候继续回收,重复写入这个GC在片上FLASH上会出现FLASH写数据出错的异常,再下次开机是否会
丢失数据?
*************************************************************************************/
/* change the sector status to GC */
if (sector->status.dirty == FDB_SECTOR_DIRTY_TRUE) // 增加此句更合理,如果是GC状态,就不用再次写入
_fdb_write_status((fdb_db_t)db, sector->addr + SECTOR_DIRTY_OFFSET, status_table,
FDB_SECTOR_DIRTY_STATUS_NUM, FDB_SECTOR_DIRTY_GC);
/* s2: 转移数据 */
/* search all KV */
kv.addr.start = sector->addr + SECTOR_HDR_DATA_SIZE;
do
{
/* s20: 根据 kv.addr.start 读取当前的 kv 数据 */
read_kv(db, &kv);
if (kv.crc_is_ok && (kv.status == FDB_KV_WRITE || kv.status == FDB_KV_PRE_DELETE))
{
/* move the KV to new space */
/* s21: 转移KV数据 */
if (move_kv(db, &kv) != FDB_NO_ERR)
{
FDB_DEBUG("Error: Moved the KV (%.*s) for GC failed.\n", kv.name_len, kv.name);
}
}
} while ((kv.addr.start = get_next_kv_addr(db, sector, &kv)) != FAILED_ADDR);
/* s3: 格式化当前扇区 */
format_sector(db, sector->addr, SECTOR_NOT_COMBINED);
FDB_DEBUG("Collect a sector @0x%08' PRIX32 '\n", sector->addr);
}
return false;
}
之前一直遇到的问题,添加这个限制条件后就没有再出现过报错信息
[FlashDB][kv][env] (../packages/FlashDB-v1.0.0/src/fdb_kvdb.c:1043) The remain empty sector is 3, GC threshold is 4.
[E/drv.flash] HAL_FLASH_Program 写数据出错
[E/FAL] (fal_partition_write:437) Partition write error! Flash device(onchip_flash) write error!
具体的应用如下:
初始化KVDB
static struct fdb_default_kv_node default_kv_table[] = {
{"boot_count", &boot_count, sizeof(boot_count)},
{"boot_time", &boot_time, sizeof(boot_time)},
}
// 初始化函数
void flash_kv_init(void)
{
struct fdb_default_kv default_kv;
default_kv.kvs = default_kv_table;
default_kv.num = sizeof(default_kv_table) / sizeof(default_kv_table[0]);
fdb_kvdb_init(&kvdb, "env", "fdb_kvdb", &default_kv, NULL);
}
初始化完成后,程序开始运行,运行过程中加入一个kv。
struct test {
uint8_t a;
uint8_t b;
};
struct fdb_blob blob;
struct test p_test;
p_test.a = 1u;
p_test.b = 2u;
fdb_kv_set_blob(&kvdb, "test", fdb_blob_make(&blob, &p_test, sizeof(struct test)));
通过以上方式kvdb中增加了test kv,如果在随后升级程序,struct test 改变,会造成test kv读取数据错误。
比如:
struct test {
uint8_t a;
uint8_t b;
uint8_t c;
};
struct fdb_blob blob;
struct test p_test;
fdb_kv_get_blob(&kvdb, "test", fdb_blob_make(&blob, &p_test, sizeof(struct test)));
这原因是不是因为在改变struct test后没有set test kv 直接get test kv造成的?
怎么在default kv中加入结构体呢?
\ | /
Hardware
MCU: STM32F103VC
norflash:W25Q128
Software
IDE:MDK 5.30.0.0
C-Complier: ArmClang V6.14
RTOS: FreeRTOS V10.3.1
static void kv_iterator(fdb_kvdb_t db, fdb_kv_t kv, void *arg1, void *arg2,
bool (*callback)(fdb_kv_t kv, void *arg1, void *arg2))
{
struct kvdb_sec_info sector;
uint32_t sec_addr;
// sec_addr = 0;
sec_addr = (uint32_t)((fdb_db_t)db)->part->offset;
static void sector_iterator(fdb_kvdb_t db, kv_sec_info_t sector, fdb_sector_store_status_t status, void *arg1, void *arg2,
bool (*callback)(kv_sec_info_t sector, void *arg1, void *arg2), bool traversal_kv)
{
uint32_t sec_addr;
/* search all sectors */
// sec_addr = 0;
sec_addr = (uint32_t)((fdb_db_t)db)->part->offset;
能否添加一个公开的KV的iterator api?
目前需要手动暴露内部的kv_iterator()接口来遍历整个db,比较麻烦而且需要暴露库的内部实现
可以考虑添加一个迭代器结构体,用迭代器结构体来存储状态,然后api每次返回一个迭代结果,这样用起来更方便一些
我的设备启动后,分别读取三个分区中存储的KV内容,读到第三个时出现地址错误,然后设备就hardfault复位了,这时什么奇怪的事情?
[ 0][fal_flash.c: 65]Flash device | P25Q32H | addr: 0x00000000 | len: 0x00400000 | blk_size: 0x00001000 |initialized finish.
[ 0][fal_partition.c: 102]==================== FAL partition table ====================
[ 0][fal_partition.c: 104]| name | flash_dev | offset | length |
[ 0][fal_partition.c: 105]-------------------------------------------------------------
[ 0][fal_partition.c: 116]| pt_bcfg | P25Q32H | 0x000c0000 | 0x00010000 |
[ 0][fal_partition.c: 116]| pt_ucfg | P25Q32H | 0x000d0000 | 0x00010000 |
[ 0][fal_partition.c: 116]| pt_data | P25Q32H | 0x000e0000 | 0x00020000 |
[ 0][fal_partition.c: 118]=============================================================
[ 0][fal.c: 57]Flash Abstraction Layer (V0.5.0) initialize success.
[ 0][fdb_kvdb.c:1596]KVDB in partition pt_bcfg, size is 65536 bytes.
[ 0][fdb.c: 59]FlashDB V1.0.0 beta is initialize success.
[ 0][fdb.c: 60]You can get the latest version on https://github.com/armink/FlashDB .
[ 0][fdb_kvdb.c:1319]type=
[ 0][fdb_kvdb.c:1334]bcfg
[ 0][fdb_kvdb.c:1349]
[ 0][fdb_kvdb.c:1377]
mode: next generation
[ 0][fdb_kvdb.c:1379]size: 272/61440 bytes.
[ 0][fdb_kvdb.c:1596]KVDB in partition pt_ucfg, size is 65536 bytes.
[ 0][fdb_kvdb.c:1319]type=
[ 0][fdb_kvdb.c:1334]ucfg
[ 0][fdb_kvdb.c:1349]
[ 0][fdb_kvdb.c:1377]
mode: next generation
[ 0][fdb_kvdb.c:1379]size: 7188/61440 bytes.
[ 0][fdb_kvdb.c:1596]KVDB in partition pt_data, size is 131072 bytes.
[ 3][fal_partition.c: 382]Partition read error! Partition address out of bound.
[ 3][fal_partition.c: 382]Partition read error! Partition address out of bound.
[ 3][fal_partition.c: 382]Partition read error! Partition address out of bound.
[ 3][fal_partition.c: 382]Partition read error! Partition address out of bound.
[ 3][fal_partition.c: 382]Partition read error! Partition address out of bound.
[ 3][fal_partition.c: 382]Partition read error! Partition address out of bound.
[ 3][fal_partition.c: 382]Partition read error! Partition address out of bound.
[ 3][fal_partition.c: 382]Partition read error! Partition address out of bound.
[ 3][fal_partition.c: 382]Partition read error! Partition address out of bound.
[ 3][fal_partition.c: 382]Partition read error! Partition address out of bound.
[ 3][fal_partition.c: 382]Partition read error! Partition address out of bound.
[ 3][fal_partition.c: 382]Partition read error! Partition address out of bound.
[ 3][fal_partition.c: 382]Partition read error! Partition address out of bound.
。。。。
。。。。
很多
tsdb数据库初始化时,会指定max_len参数,限制是比扇区大小小即可。
但是tsl_append()中,有以下语句:
db->cur_sec.remain -= LOG_IDX_DATA_SIZE + FDB_WG_ALIGN(blob->size);
例如设置扇区大小为4096,max_len为4095,最终可能导致remain为负数,最终导致数据混乱,fal write partition地址为负数。
你好,我的是nrf52832 + SPI flash 的低功耗产品。每次按键开机,实际上就是一次硬复位。fdb_kvdb_init() 实测每次运行大概1秒多时间,按键开机的体验很不顺畅。 请问,修改什么参数 可以缩短fdb_kvdb_init()的运行时间吗?
朱工你好,请问,对于键值KV型数据库,每个键值支持最大的字符数目是多少?
如果我想从easyflash切换到flashDB,那么原来的easylog,OTA功能是否需要另外实现?
In fdb_kvdb.c::del_kv()
function, FDB_SECTOR_STORE_STATUS_NUM
and FDB_SECTOR_DIRTY_STATUS_NUM
is an enum constant, if used in #if statement, the preprocessor will assume they are undefined macros, and evaluate to 0, so the #if statement will always be true.
Suggest use:
uint8_t status_table[KV_STATUS_TABLE_SIZE >= FDB_DIRTY_STATUS_TABLE_SIZE ? KV_STATUS_TABLE_SIZE : DIRTY_STATUS_TABLE_SIZE];
在fdb_kvdb.c::del_kv()
函数中,FDB_SECTOR_STORE_STATUS_NUM
和FDB_SECTOR_DIRTY_STATUS_NUM
是枚举常量,在#if条件编译语句中,预处理器将它们看作是未定义的宏,求值为0,#if语句永远为真。
建议使用:
uint8_t status_table[KV_STATUS_TABLE_SIZE >= FDB_DIRTY_STATUS_TABLE_SIZE ? KV_STATUS_TABLE_SIZE : DIRTY_STATUS_TABLE_SIZE];
FDB_STR_KV_VALUE_MAX_SIZE 1024*100 为获取的最大数 存储的最大数在哪里配置
朱工,您好:
第一次使用您的flashdb用在项目上存储数据,kvdb存储参数非常好用,感谢您的开源;
不过在使用tsdb存储数据时,日志打印报错,具体如下:
00> [FlashDB][kv][env] (../../FlashDB/src/fdb_kvdb.c:1599) KVDB in partition fdb_kvdb1, size is 8192 bytes.
00> [FlashDB] FlashDB V1.0.0 is initialize success.
00> [FlashDB] You can get the latest version on https://github.com/armink/FlashDB .
00> [FlashDB][main] get the 'system_par' succeed
00> [FlashDB][tsl][log] Error: this TSL (0x00000570) size (16) is out of bound.
00> [FlashDB][tsl][log] (../../FlashDB/src/fdb_tsdb.c:759) TSDB (log) oldest sectors is 0x00000000, current using sector is 0x00000000.
00> [FlashDB][tsl][log] Error: this TSL (0x00000570) size (16) is out of bound.
00> [FlashDB][kv][env] (../../FlashDB/src/fdb_kvdb.c:1146) Trigger a GC check after created KV.
00> [FlashDB][kv][env] (../../FlashDB/src/fdb_kvdb.c:1042) The remain empty sector is 2, GC threshold is 1.
00> [FlashDB][kv][env] (../../FlashDB/src/fdb_kvdb.c:1146) Trigger a GC check after created KV.
00> [FlashDB][kv][env] (../../FlashDB/src/fdb_kvdb.c:1042) The remain empty sector is 1, GC threshold is 1.
00> [FlashDB][kv][env] (../../FlashDB/src/fdb_kvdb.c:1022) Collect a sector @0x00000000
麻烦帮忙看下什么原因,谢谢!
使用环境:
朱先生您好:
我在实际项目中使用了FlashDB,既使用了KV数据库也使用了tsl数据库,用KV数据库保存系统运行参数,用tsl数据库保存历史数据记录,很好用,谢谢您!
我的设备的存储介质是:W25Q256,容量为32M Bytes,采用QSPI接口与STM32F4连接,将32M空间中的一部分由FlashDB管理。
但是在实际项目使用KV数据库中,也发现了一个问题:
我的系统运行参数是一个大小为196 Bytes的结构体,采用一个Key-Value保存到KV数据库中,每间隔1分钟读取这个KV,并修改结构体中的某一个元素在进行保存,在运行一段时间后,再读取这个键值,发现有些字段的数值是错误的,分析在写入过程中,出现这个错误的概率很大。
我目前的解决方案是:再写入完成后,读取一次,进行对比,如果不一样,就再次重新写。
问题:请问当采用KV数据库保存一个大数据结构体,出现这种错误的原因是什么?我该如何来做呢?
朱工您好,这个软件非常好用,谢谢!
请问,该软件的掉电保存是如何考虑的?如果在写入的时候掉电,该软件如何处理呢?
RT
你好,请问,对于一个ts数据库,如果数据存满空间后,会如何处理?删除最早的数据而插入最新的数据吗
朱工您好,按照你的提示:就是入库记录时间不能比上一个记录的时间小,那如果系统时钟错误,就必须向前调整,比如当前是10:00,调整到9:00,那么就会出现当前的记录时间比上一个记录的时间小,请问,程序应该如何处理呢?
如题
KVDB的一个重要应用场景是嵌入式系统的参数存储,通常这种场景下会有多个参数批量设置的操作。
在多个参数同时修改期间如果操作中断或断电,会出现一半新参数、一半旧参数的问题。在关键设备中可能会引起严重问题,参考事务型文件系统,操作中断后可以自动回滚到上一个版本,保证数据一致性。
针对这个,目前是否有好的解决方法么?
目前在做的FILE_MODE功能中,是否可以考虑简单的设置AB两份数据库文件先后写入的方式来实现回滚操作?
朱工,你好,
问下后续是否有计划支持带Offset方式对某个kv对进行读取和写入。
谢谢。
如题,我使用裸机系统移植FlashDB 主要使用了TSDB功能,我的SPIFLASH比较大 32MB,扇区4K共8192个扇区,我发现在第一次初始化的时候似乎FlashDB会擦写每一个扇区,相当的耗时。当存储了一部分数据想要清除数据库记录时,又会重复上述过程。请问有没有办法缩短初始化的格式化时间?
在格式化时(特别是第一次运行),会进入一个耗时的过程,FlashDB 程序不能喂狗,导致看门狗复位。
建议增加 hook,以便喂狗或是其他操作。
朱工,你好:
应用中常常需要保存参数到flash中,TS数据库有回滚的配置,但是KV数据库写满后,会返回FDB_SAVED_FULL,用户应该如何操作,是否需要手动调用fdb_kv_set_default清空数据库,然后重新写入?当前,每个flash扇区4K,配置分区起始地址0,大小为8K。
数据库的修改删除如何操作
还有fdb_tsl_query_count(tsdb, from_time, to_time,FDB_TSL_USER_STATUS1); 这个函数返回的数据也是错的
Hello guys,
I've just found this project and I was wondering if you guys have any plans to be porting the project to ESP32(espidf) platform.
If you guys want I can try to do my own port and PR the changes.
Finally but not least I want to congratulate you all for this amazing project.
我改了系统时钟频率。可是总是卡在
/* Wait till PLL is ready */
\ | /
\ | /
usage fault:
SCB_CFSR_UFSR:0x100 UNALIGNED
依赖于 RT-Thread 的 FAL (Flash Abstraction Layer) Flash 抽象层开源软件包???
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.