嵌入式技术论坛
直播中

刘润生

7年用户 753经验值
私信 关注
[经验]

FlashDB嵌入式数据库软件移植

前言

FlashDB是一款超轻量级的嵌入式数据库,专注于提供嵌入式产品的数据存储方案。与传统的基于文件系统的数据库不同,FlashDB结合了 Flash 的特性,具有较强的性能及可靠性。并在保证极低的资源占用前提下,尽可能延长 Flash 使用寿命。

软件移植

1.闪存设备移植

(1)闪存设备表设置

目前只使用Norflash外部flash作为存储设备,所以只需要设置一个设备。设备表代码如下

/* flash device table */
#define FAL_FLASH_DEV_TABLE
{
&nor_flash0,
}
(2)闪存区块划分

目前闪存主要用于bsp数据、日志、文件系统存储,主要设置分区名称、关联的 Flash 设备名、偏移地址(相对 Flash 设备内部)、大小。

#define FAL_PART_TABLE
{
{FAL_PART_MAGIC_WROD, FAL_PART_TSDB_BSP_NAME , "norflash0", 910241024, 110241024, 0},
{FAL_PART_MAGIC_WROD, FAL_PART_LOG_NAME, "norflash0", 1110241024, 810241024, 0},
{FAL_PART_MAGIC_WROD, FAL_PART_FATFS_NAME , "norflash0", 3210241024, 3210241024, 0},
}
(3)闪存设备设置

norflash主要配置norflash的大小,名称,读写擦接口等。

struct fal_flash_dev nor_flash0 =
{
.name = FAL_USING_NOR_FLASH_DEV_NAME,
.addr = 0,
.len = 1 * 1024 * 1024,
.blk_size = 4096,
.ops = {init, read, write, erase},
.write_gran = 1
};

其中函数接口主要是实现对norflash的初始化、读、写、擦

初始化函数

#define SFUD_FLASH_DEVICE_TABLE
{
[SFUD_W25_DEVICE_INDEX] =
{.name = "W25Q512JV",
.spi.name = "SPI3",
.chip = {"W25Q512JV", SFUD_MF_ID_WINBOND, 0x40, 0x20, 64L1024L1024L, SFUD_WM_PAGE_256B, 4096, 0x20},
}
}

static int init(void)
{

sfud_dev = sfud_get_device_table();


if (NULL == sfud_dev)
{
    return -1;
}

/* update the flash chip information */
nor_flash0.blk_size = sfud_dev->chip.erase_gran;
nor_flash0.len = sfud_dev->chip.capacity;
lock_init();
return 0;

}

读函数

static int read(long offset, uint8_t *buf, size_t size)
{
assert(sfud_dev);
assert(sfud_dev->init_ok);
sfud_read(sfud_dev, nor_flash0.addr + offset, size, buf);

return size;

}

写函数

static int write(long offset, const uint8_t *buf, size_t size)
{
assert(sfud_dev);
assert(sfud_dev->init_ok);
if (sfud_write(sfud_dev, nor_flash0.addr + offset, size, buf) != SFUD_SUCCESS)
{
return -1;
}

return size;

}

擦除函数

static int erase(long offset, size_t size)
{
assert(sfud_dev);
assert(sfud_dev->init_ok);
if (sfud_erase(sfud_dev, nor_flash0.addr + offset, size) != SFUD_SUCCESS)
{
return -1;
}

return size;

}

2.FlashDB配置

在fdb_cfg.h文件中可以设置相关配置,详见如下

FDB_USING_KVDB
// 使能 KVDB 功能

FDB_KV_AUTO_UPDATE
// 使能 KV 自动升级功能。该功能使能后, fdb_kvdb.ver_num 存储了当前数据库的版本,如果版本发生变化时,会自动触发升级动作,将更新新的默认 KV 集合至当前数据库中。

FDB_USING_TSDB
// 使能 TSDB 功能

FDB_USING_FAL_MODE
// 使能 FAL 模式,FAL 里的分区用于存储数据库。该模式下,FlashDB 直接操作 Flash,所以性能较好

// FDB_USING_FILE_LIBC_MODE 与 FDB_USING_FILE_POSIX_MODE 模式只能二选一。相比 FAL 模式,文件模式下数据库的存储位置、大小及数量没有限制。
FDB_USING_FILE_POSIX_MODE
// 使用 POSIX 的文件模式,需要系统提供 open/read/write/close 相关文件访问接口。
FDB_USING_FILE_LIBC_MODE
// 使用 C 标准库的文件模式,需要系统提供 fopen/fread/fwrite/fclose 相关文件访问接口。

FDB_WRITE_GRAN
// Flash 写粒度,单位为 bit。目前支持
// 1: nor flash
// 8: stm32f2/f4 片上 Flash
// 32: stm32f1 片上 Flash
// 如果数据库中使用了多种 Flash 规格,例如:既有 nor flash,也有 stm32f4 片上 Flash ,此时取最大值作为配置项,即:8 bit

FDB_BIG_ENDIAN
// MCU 大小端配置,默认不配置时,系统自动使用小端配置

FDB_PRINT(...)
// 打印函数宏定义配置,默认不配置时,使用 printf 作为打印日志是输出函数。用户也可以自定义新的打印函数宏定义,例如:

#define FDB_PRINT(...) my_printf(VA_ARGS)
FDB_DEBUG_ENABLE
// 使能调试信息输出。关闭该配置时,系统将不会输出用于调试的日志。

3.FlashDB API接口

(1)首先初始化flashdb数据库

fdb_tsdb_control(&tsdb, FDB_TSDB_CTRL_SET_LOCK, (void *)lock);
    fdb_tsdb_control(&tsdb, FDB_TSDB_CTRL_SET_UNLOCK, (void *)unlock);
    result = fdb_tsdb_init(&tsdb, "log", "fdb_tsdb1", get_time, 128, NULL);

(2)写入flashdb数据库

先将数据存放到自定义结构体中,制作blob包并将数据写入(追加写入)数据库中

{ /* APPEND new TSL (time series log) */
    struct env_status status;

    /* append new log to TSDB */
    status.temp = 36;
    status.humi = 85;
    fdb_tsl_append(tsdb, fdb_blob_make(&blob, &status, sizeof(status)));


    status.temp = 38;
    status.humi = 90;
    fdb_tsl_append(tsdb, fdb_blob_make(&blob, &status, sizeof(status)));

}

(3)读取flashdb数据库

通过起始时间和结束时间将数据库中数据读到结构体中,同时可以读取这个时间段的TSL数据量

{ /* QUERY the TSDB by time */
    /* prepare query time (from 1970-01-01 00:00:00 to 2020-05-05 00:00:00) */
    struct tm tm_from = { .tm_year = 1970 - 1900, .tm_mon = 0, .tm_mday = 1, .tm_hour = 0, .tm_min = 0, .tm_sec = 0 };
    struct tm tm_to = { .tm_year = 2020 - 1900, .tm_mon = 4, .tm_mday = 5, .tm_hour = 0, .tm_min = 0, .tm_sec = 0 };
    time_t from_time = mktime(&tm_from), to_time = mktime(&tm_to);
    size_t count;
    /* query all TSL in TSDB by time */
    fdb_tsl_iter_by_time(tsdb, from_time, to_time, query_by_time_cb, tsdb);
    /* query all FDB_TSL_WRITE status TSL's count in TSDB by time */
    count = fdb_tsl_query_count(tsdb, from_time, to_time, FDB_TSL_WRITE);
    FDB_INFO("query count is: %zu\n", count);
}

(4)清空flashdb数据库

{
struct fdb_blob;
gType_TSDBInfo_st *p_ts_info = NULL;
fdb_tsl_clean(p_ts_info->p_tsdb);
}

原作者:阿拉斯加的小野牛

更多回帖

发帖
×
20
完善资料,
赚取积分