armink / FlashDB

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

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

Open Samwuzhitao opened 3 years ago

Samwuzhitao commented 3 years ago

// 回收扇区将数据存放在 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!

armink commented 3 years ago
Samwuzhitao commented 3 years ago

芯片:stm32103RC 写粒度:32 出错的条件直接执行这个 HAL_FLASH_Program 函数直接报错

armink commented 3 years ago

执行这个 HAL_FLASH_Program 函数直接报错

这个条件是什么,比如不支持再次写入,所以报错?

Samwuzhitao commented 3 years ago

image 这个没有继续追踪这个数据写出错的问题,只是我发现,在GC过程中,不停的按复位键,这个错误信息会不停的出现 [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!, 我这边复现这个问题,增加部分调试信息,

armink commented 3 years ago

嗯,这块建议也咨询一下 ST ,深入确认一下,目前来看,这种情况,既然写对了,上不应该提示错误