Coder Social home page Coder Social logo

armink / flashdb Goto Github PK

View Code? Open in Web Editor NEW
1.7K 58.0 406.0 4.71 MB

An ultra-lightweight database that supports key-value and time series data | 一款支持 KV 数据和时序数据的超轻量级数据库

License: Apache License 2.0

C 100.00%
database tsdb kvdb key-value embedded iot lightweight

flashdb's Issues

format string using <inttypes.h>

例:
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);

采用KV保存196bytes结构体,运行一段时间后结构体元素错误,请教问题

朱先生您好:
我在实际项目中使用了FlashDB,既使用了KV数据库也使用了tsl数据库,用KV数据库保存系统运行参数,用tsl数据库保存历史数据记录,很好用,谢谢您!
我的设备的存储介质是:W25Q256,容量为32M Bytes,采用QSPI接口与STM32F4连接,将32M空间中的一部分由FlashDB管理。

  但是在实际项目使用KV数据库中,也发现了一个问题:
 我的系统运行参数是一个大小为196 Bytes的结构体,采用一个Key-Value保存到KV数据库中,每间隔1分钟读取这个KV,并修改结构体中的某一个元素在进行保存,在运行一段时间后,再读取这个键值,发现有些字段的数值是错误的,分析在写入过程中,出现这个错误的概率很大。
我目前的解决方案是:再写入完成后,读取一次,进行对比,如果不一样,就再次重新写。

 问题:请问当采用KV数据库保存一个大数据结构体,出现这种错误的原因是什么?我该如何来做呢?

_fdb_write_status()函数执行前是否先擦除再写入?

由于最近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()函数没有考虑在写入前,擦除相应扇区的数据吗?
   是否需要在移植接口函数中特殊考虑?

KV数据库,写满如何处理

朱工,你好:
应用中常常需要保存参数到flash中,TS数据库有回滚的配置,但是KV数据库写满后,会返回FDB_SAVED_FULL,用户应该如何操作,是否需要手动调用fdb_kv_set_default清空数据库,然后重新写入?当前,每个flash扇区4K,配置分区起始地址0,大小为8K。

FlashDB Error 请教一下怎么回事?

\ | /

  • RT - Thread Operating System
    / | \ 3.1.3 build Sep 21 2020
    2006 - 2019 Copyright by rt-thread team
    SPI2 DWM1000 Attach Success!
    spi2 run success! can find spi20_dem1000 device!
    spi2 Configure Success!
    DeviceID = DECA0130
    DWM1000 Init Scccess!
    [SFUD] Find a Winbond flash chip. Size is 2097152 bytes.
    [SFUD] FLASH_W25Q16 flash device is initialize success.
    [D/FAL] (fal_flash_init:61) Flash device | stm32_onchip | addr: 0x08000000 | len: 0x00100000 | blk_size: 0x00020000 |initialized finish.
    [D/FAL] (fal_flash_init:61) Flash device | FLASH_W25Q16 | addr: 0x00000000 | len: 0x00200000 | blk_size: 0x00001000 |initialized finish.
    [I/FAL] ==================== FAL partition table ====================
    [I/FAL] | name | flash_dev | offset | length |
    [I/FAL] -------------------------------------------------------------
    [I/FAL] | app | stm32_onchip | 0x00000000 | 0x00100000 |
    [I/FAL] | fdb_tsdb1 | FLASH_W25Q16 | 0x00000000 | 0x00000400 |
    [I/FAL] | fdb_kvdb1 | FLASH_W25Q16 | 0x00000400 | 0x00000400 |
    [I/FAL] =============================================================
    [I/FAL] RT-Thread Flash Abstraction Layer (V0.5.0) initialize success.
    [FlashDB][kv][env] (packages\FlashDB-latest\src\fdb_kvdb.c:1583) ((FDB_GC_EMPTY_SEC_THRESHOLD > 0 && FDB_GC_EMPTY_SEC_THRESHOLD < SECTOR_NUM)) has assert failed at fdb_kvdb_init.

Are there any plans to develop a port/demo to ESP32 microcontroller?

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.

TSL数据库删除后再次追加遍历后发现部分数据有问题

根据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] ===========================================================

关于FlashDB 移植到Rtthread的问题。。。

朱工,您好,再次的打扰您一下!
我再移植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]

每次启动日志都提示 [FlashDB][kv][env] Found an KV (user_setting) which has changed value failed. Now will recovery it.

\ | /

  • RT - Thread Operating System
    / | \ 4.0.3 build Dec 18 2020
    2006 - 2020 Copyright by rt-thread team
    spi1 GPIO_PinsRemapConfig = AFIO_MAP5_SPI1_0001
    [I/SFUD] Find a Winbond flash chip. Size is 4194304 bytes.
    [I/SFUD] sf_cmd flash device is initialize success.
    [I/SFUD] Probe SPI flash sf_cmd by SPI device SPI_flash success.
    4 MB sf_cmd is current selected device.
    [I/FAL] Flash Abstraction Layer (V0.5.0) initialize success.
    [FlashDB][kv][env] (../../../components/FlashDB/src/fdb_kvdb.c:1599) KVDB in partition fdb_kvdb1, size is 32768 bytes.
    [FlashDB][kv][env] Found an KV (user_setting) which has changed value failed. Now will recovery it.
    msh >msh >

\ | /

  • RT - Thread Operating System
    / | \ 4.0.3 build Dec 18 2020
    2006 - 2020 Copyright by rt-thread team
    spi1 GPIO_PinsRemapConfig = AFIO_MAP5_SPI1_0001
    [I/SFUD] Find a Winbond flash chip. Size is 4194304 bytes.
    [I/SFUD] sf_cmd flash device is initialize success.
    [I/SFUD] Probe SPI flash sf_cmd by SPI device SPI_flash success.
    4 MB sf_cmd is current selected device.
    [I/FAL] Flash Abstraction Layer (V0.5.0) initialize success.
    [FlashDB][kv][env] (../../../components/FlashDB/src/fdb_kvdb.c:1599) KVDB in partition fdb_kvdb1, size is 32768 bytes.
    [FlashDB][kv][env] Found an KV (user_setting) which has changed value failed. Now will recovery it.
    msh >msh >psr: 0x21000053
    r00: 0x50001000
    r01: 0x20000102
    r02: 0x00000001
    r03: 0x00000004
    r04: 0x20001a68
    r05: 0x00000004
    r06: 0x00000001
    r07: 0x00000000
    r08: 0x20001b9c
    r09: 0x20001b90
    r10: 0x20001b98
    r11: 0x20001a80
    r12: 0x00000000
    lr: 0x08008e85
    pc: 0x0800a03a
    hard fault on handler

usage fault:
SCB_CFSR_UFSR:0x100 UNALIGNED

测试用例 fdb_tsdb_init 报错!求教大神

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提示信息如下:

\ | /

  • RT - Thread Operating System
    / | \ 4.0.2 build Oct 29 2020
    2006 - 2019 Copyright by rt-thread team
    lwIP-2.0.2 initialized!
    the rtc of rx8025 init succeed!
    [SFUD] Find a Winbond flash chip. Size is 1048576 bytes.
    [SFUD] nor_flash0 flash device is initialize success.
    [2071] I/ppp.dev: ppp_device(pp) register successfully.
    [2077] I/sal.skt: Socket Abstraction Layer initialize success.
    [I/FAL] RT-Thread Flash Abstraction Layer (V0.5.99) initialize success
    fal_init Ok
    [I/FAL] The FAL MTD NOR device (filesystem) created successfully
    [2109] I/main: Filesystem initialized!
    msh />[FlashDB][kv][env] (packages\FlashDB-latest\src\fdb_kvdb.c:1599) KVDB in partition fdb_kvdb1, size is 131072 bytes.
    [FlashDB] FlashDB V1.0.99 is initialize success.
    [FlashDB] You can get the latest version on https://github.com/armink/FlashDB .
    [FlashDB][sample][kvdb][basic] ==================== kvdb_basic_sample ====================
    [FlashDB][sample][kvdb][basic] get the 'boot_count' value is 19
    [FlashDB][sample][kvdb][basic] set the 'boot_count' value to 20
    [FlashDB][sample][kvdb][basic] ===========================================================
    [FlashDB][sample][kvdb][string] ==================== kvdb_type_string_sample ====================
    [FlashDB][sample][kvdb][string] create the 'temp' string KV, value is: 36C
    [FlashDB][sample][kvdb][string] get the 'temp' value is: 36C
    [FlashDB][sample][kvdb][string] set 'temp' value to 38C
    [FlashDB][sample][kvdb][string] delete the 'temp' finish
    [FlashDB][sample][kvdb][string] ===========================================================
    [FlashDB][sample][kvdb][blob] ==================== kvdb_type_blob_sample ====================
    [FlashDB][sample][kvdb][blob] create the 'temp' blob KV, value is: 36
    [FlashDB][sample][kvdb][blob] get the 'temp' value is: 36
    [FlashDB][sample][kvdb][blob] set 'temp' value to 38
    [FlashDB][sample][kvdb][blob] delete the 'temp' finish
    [FlashDB][sample][kvdb][blob] ===========================================================
    [FlashDB][tsl][log] Sector (0x00176128) header info is incorrect.
    psr: 0x40000000
    r00: 0x20015070
    r01: 0x65757177
    r02: 0x20015070
    r03: 0x00800000
    r04: 0x20015070
    r05: 0x20015070
    r06: 0x00000000
    r07: 0x00000000
    r08: 0xdeadbeef
    r09: 0xdeadbeef
    r10: 0xdeadbeef
    r11: 0xdeadbeef
    r12: 0x0000ffc4
    lr: 0x08007ddb
    pc: 0x20015070
    hard fault on thread: sys_

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

FlashDB 初始化时出现 Warning: Sector header check failed

使用 M4 挂载 SPI W25Q128 ,也就是16M Byte 程序初始化已经成功。
通过 Fal,挂载了 两个分区在上面,
使用 fal bench 测试也正常。
初始化 flash db 时 出现如下问题,麻烦天龙哥 指点一下 谢谢!!!

image

default kv中怎么加入结构体呢?

具体的应用如下:
初始化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中加入结构体呢?

ts数据库存满后如何处理?

你好,请问,对于一个ts数据库,如果数据存满空间后,会如何处理?删除最早的数据而插入最新的数据吗

扇区是否存在重复擦除的bug?

阅读源码的时候, 发现了一个问题:
就是的当sector_iterator(db, &sector, 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);
    }

不就重复的对各扇区多擦除了一次吗?

1.png

其中

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

KVDB在FILE_MODE下的事务操作支持

KVDB的一个重要应用场景是嵌入式系统的参数存储,通常这种场景下会有多个参数批量设置的操作。
在多个参数同时修改期间如果操作中断或断电,会出现一半新参数、一半旧参数的问题。在关键设备中可能会引起严重问题,参考事务型文件系统,操作中断后可以自动回滚到上一个版本,保证数据一致性。
针对这个,目前是否有好的解决方法么?

目前在做的FILE_MODE功能中,是否可以考虑简单的设置AB两份数据库文件先后写入的方式来实现回滚操作?

Error: this TSL (0x00000570) size (16) is out of bound

朱工,您好:

第一次使用您的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

麻烦帮忙看下什么原因,谢谢!

使用环境:

  • mcu: stm32f103ve 内部 flash 存储 , 使用标准库读写内部flash
  • flash设备定义
    const struct fal_flash_dev stm32_onchip_flash =
    {
    .name = "stm32_onchip",
    .addr = 0x08000000,
    .len = 5121024,
    .blk_size = 2
    1024,
    .ops = {init, read, write, erase},
    .write_gran = 32
    };
  • 分区表配置信息:
    /* partition table /
    #define FAL_PART_TABLE
    {
    {FAL_PART_MAGIC_WORD, "fdb_kvdb1", "stm32_onchip", 400
    1024, 81024, 0},
    {FAL_PART_MAGIC_WORD, "fdb_tsdb1", "stm32_onchip", 408
    1024, 60*1024, 0},
    }

kv对校验失败后尝试发现下一个节点时,检索范围的问题

函数get_next_kv_addr中,发现pre_kv的crc校验失败,会触发find_next_kv_addr来尝试发现下一个kv_node。
但是在传递参数的的时候终止地址似乎有些问题。
终止地址传递的是sector结束地址减去sector_hdr的长度,但是sector_hdr是放在sector的头部的,这样看起来会导致find的时候没有对sector最后一部分地址进行检查。
劳烦作者看一下我的理解是否有问题

FlashDB的源程序中,为什么很多语句不判断下一层函数的返回数值,而是直接返回?

朱先生你好,感谢您的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)函数,也没有判断返回数值,而是直接返回四则。

   还有很多处,没有判断函数执行返回数值。
   这样带来的问题是,当底层一个函数执行出现错误时,但是仍然是按照正确时返回,最终会出现读取或者写入的数据是错误的,而且程序健壮性不够强,排查故障很不方便。

  朱先生是嵌入式行业大牛,请问,您这么做的原因是什么?有什么特殊考虑吗?

分区地址会丢失吗?

我的设备启动后,分别读取三个分区中存储的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.
。。。。
。。。。
很多

#if (KV_STATUS_TABLE_SIZE >= FDB_DIRTY_STATUS_TABLE_SIZE) may not work as expected

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_NUMFDB_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];

tsdb的max_len参数问题

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地址为负数。

关于分区起始地址错误问题

硬件软件环境

  1. Hardware
    MCU: STM32F103VC
    norflash:W25Q128

  2. Software
    IDE:MDK 5.30.0.0
    C-Complier: ArmClang V6.14
    RTOS: FreeRTOS V10.3.1

问题

  1. 关于kvdb测试发现,kvdb分区最好小于1M,不然初始化会使CPU 100%运行500ms以上(如下图),主要是由于迭代器函数sector_iterator()导致的,这部分可能需要算法优化吧。

  1. 关于kvdb和tsdb分区问题,测试发现,kvdb(一般比较小)最好放在tsdb的前面,这样kvdb的初始化耗时少,通过打印迭代器函数的addr发现了一些端倪,比如测试分区如下:

    kvdb的起始地址是0x00200000,但打印迭代器的初始化地址是0x00000000;也就是说迭代器是从tsdb的起始地址查询到kvdb的结束地址0x00202000;我通过修改以下代码(注释部分为原始代码),可以较少迭代次数,但flash重新格式化后会有“Partition read error! Partition address out of bound.”错误,因为对flashDB的逻辑不清楚,所以又将代码还原。
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;

能否添加SPI FLASH 多分区同时操作的样例

在使用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之后的空间是绝对不会用到的。
分区表中的地址是在此定义空间中相对划分的吗?

关于env 增量升级的逻辑

朱总,好!
又打扰您了,想问下env增量升级的逻辑,比如default kv node中有2个结构体,如果结构体中的元素增加或减少后,改变KVDB_VERSION,会更新对于的数据吗?还是说default kv node中有2个结构体,如果再增加一个node后,改变KVDB_VERSION,数据会更新。

我测试修改结构体中的元素,改变KVDB_VERSION,读出的数据不对,所以想请教下env增量升级的逻辑,谢谢您!

KV iterator export to API

能否添加一个公开的KV的iterator api?
目前需要手动暴露内部的kv_iterator()接口来遍历整个db,比较麻烦而且需要暴露库的内部实现

可以考虑添加一个迭代器结构体,用迭代器结构体来存储状态,然后api每次返回一个迭代结果,这样用起来更方便一些

TSDB ,SPI FLASH W25Q256,TSDB 首次格式化时间过长,调用fdb_tsl_clean() 耗时过长

如题,我使用裸机系统移植FlashDB 主要使用了TSDB功能,我的SPIFLASH比较大 32MB,扇区4K共8192个扇区,我发现在第一次初始化的时候似乎FlashDB会擦写每一个扇区,相当的耗时。当存储了一部分数据想要清除数据库记录时,又会重复上述过程。请问有没有办法缩短初始化的格式化时间?

请问如何可以缩短fdb_kvdb_init()的运行时间

你好,我的是nrf52832 + SPI flash 的低功耗产品。每次按键开机,实际上就是一次硬复位。fdb_kvdb_init() 实测每次运行大概1秒多时间,按键开机的体验很不顺畅。 请问,修改什么参数 可以缩短fdb_kvdb_init()的运行时间吗?

flashdb 如何修改删除

数据库的修改删除如何操作

还有fdb_tsl_query_count(tsdb, from_time, to_time,FDB_TSL_USER_STATUS1); 这个函数返回的数据也是错的

关于片上flash写数据出错的问题?

// 回收扇区将数据存放在 FDB_SECTOR_STORE_UNUSED 未使用的扇区
sector_iterator(db, &sector, 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实例和多个cpu,每个cpu独占使用自己的kvdb实例。
目前kvdb的set_kv()del_kv()等函数使用了static变量,无法支持重入,需要在调用时加全局锁。
如果暂不打算支持,建议在api文档中说明哪些接口无法重入。

easylog,OTA

如果我想从easyflash切换到flashDB,那么原来的easylog,OTA功能是否需要另外实现?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.