armink / FlashDB

An ultra-lightweight database that supports key-value and time series data | 一款支持 KV 数据和时序数据的超轻量级数据库
Apache License 2.0
1.84k stars 426 forks source link

flashdb调用_fdb_write_status写状态前未擦除,片上flash无法写入 #198

Closed eternal-echo closed 1 year ago

eternal-echo commented 1 year ago

硬件环境

TC397 片内的DFLASH0 写粒度为64 扇区大小为4096

问题描述

更新扇区状态时,重复向未擦除的地址写入数据,写入失败。

具体描述

初始化时格式化扇区,使用时创建kv,需要调用update_sec_status更新扇区状态,会在写入的情况下再次调用_fdb_write_status函数写扇区的状态数据,片上flash只支持先擦除后写,格式化的时候已经擦除,但后面会重复在扇区头部写状态数据,导致写kv失败。 set kv时,flashdb试图向0xaf00 0000 0000 0008地址写入00 ff ff ff ff ff ff ff,原先0xaf00 0000 0000 0000存的是ff ff ff ff ff ff ff ff0xaf00 0000 0000 0008存的是ff ff ff ff ff ff ff ff

fdb_err_t _fdb_write_status(fdb_db_t db, uint32_t addr, uint8_t status_table[], size_t status_num, size_t status_index, bool sync)
{
    fdb_err_t result = FDB_NO_ERR;
    size_t byte_index;

    FDB_ASSERT(status_index < status_num);
    FDB_ASSERT(status_table);

    /* set the status first */
    byte_index = _fdb_set_status(status_table, status_num, status_index);

    /* the first status table value is all 1, so no need to write flash */
    if (byte_index == ~0UL) {
        return FDB_NO_ERR;
    }
#if (FDB_WRITE_GRAN == 1)
    result = _fdb_flash_write(db, addr + byte_index, (uint32_t *)&status_table[byte_index], 1, sync);
#else /*  (FDB_WRITE_GRAN == 8) ||  (FDB_WRITE_GRAN == 32) ||  (FDB_WRITE_GRAN == 64) */
    /* write the status by write granularity
     * some flash (like stm32 onchip) NOT supported repeated write before erase */
    result = _fdb_flash_write(db, addr + byte_index, (uint32_t *) &status_table[byte_index], FDB_WRITE_GRAN / 8, sync);
#endif /* FDB_WRITE_GRAN == 1 */

    return result;
}

目前,我的write接口里读取当前要写的区域未被擦除,就返回-1,如果擦除了才会写数据。 我也尝试了在write接口里自己调用erase函数,但是会导致set的key丢失。 想请教下龙哥,flashdb有考虑状态更新时重复写操作失败的问题吗?又是如何解决状态位重复写的问题的呢?

armink commented 1 year ago

你的意思是,如果 TC397 的 Flash 刚刚擦除过,如果第一次写入过 FF 后,再次写入其他的数据就没法写入了吗?

eternal-echo commented 1 year ago

你的意思是,如果 TC397 的 Flash 刚刚擦除过,如果第一次写入过 FF 后,再次写入其他的数据就没法写入了吗?

对,TC397的dflash擦除后状态是0,一般的flash擦除后是1,我通过fal命令行观察到扇区头部的数据都是ff。
写粒度为64位时,状态数据占24个字节,flashdb是通过不断的将原先全为ff ff ff ff ff ff ff ff的数据写为00 ff ff ff ff ff ff ff来记录当前扇区的状态,但TC397比较特殊,只能从0写到1,是不是应该在_fdb_set_status_fdb_get_status里取个反?才能正常使用?
flashdb里感觉可以加一个擦除状态是0还是1的宏定义来自行选择是哪种flash。

armink commented 1 year ago

TC397的dflash擦除后状态是0

这有点尴尬了,完全超出了我原有设计,除非重新设计

flashdb里感觉可以加一个擦除状态是0还是1的宏定义来自行选择是哪种flash。

这个要统筹考虑一下,毕竟你这个 Flash 太特殊了。除非改动非常小