前言
FlashDB是一款超轻量级的嵌入式数据库,专注于提供嵌入式产品的数据存储方案。与传统的基于文件系统的数据库不同,FlashDB结合了 Flash 的特性,具有较强的性能及可靠性。并在保证极低的资源占用前提下,尽可能延长 Flash 使用寿命。
固件下载
github下载地址:https://github.com/armink/FlashDB
gitee下载地址:https://gitee.com/Armink/FlashDB
软件移植
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", 9*1024*1024, 1*1024*1024, 0}, \
{FAL_PART_MAGIC_WROD, FAL_PART_LOG_NAME, "norflash0", 11*1024*1024, 8*1024*1024, 0}, \
{FAL_PART_MAGIC_WROD, FAL_PART_FATFS_NAME , "norflash0", 32*1024*1024, 32*1024*1024, 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, 64L*1024L*1024L, 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);
}
4.参考文档
文档路径: