基于全志XR872sdk上面移植FlashDB
移植FlashDB
·
FlashDB介绍
基本概念
- 键值数据库(KVDB):是一种非关系数据库,它将数据存储为键值(Key-Value)对集合,其中键作为唯一标识符。KVDB 操作简洁,可扩展性强。
- 时序数据(TSDB) :时间序列数据库 (Time Series Database , 简称 TSDB),它将数据按照 时间顺序存储 。TSDB 数据具有时间戳,数据存储量大,插入及查询性能高。
- 时序记录(TSL) :TSL (Time series log),是 TSDB 中每条记录的简称。
- Blob :在计算机中,blob 常常是数据库中用来存储二进制文件的字段类型。在 FlashDB 中, KV 和 TSL 都使用 blob 类型来存储,该类型可以兼容任意变量类型。
- 迭代器(iterator):它可以让用户透过特定的接口巡访容器中的每一个元素,而不用了解底层的实现。 TSDB 和 KVDB 都支持通过迭代器对数据库进行遍历访问。
FlashDB官网:FlashDB官网
首先从GitHub上面拉取FlashDB源码:Releases · armink/FlashDB · GitHub
其中src文件夹是FlashDB的源码、inc是FlashDB的头文件。
将src和inc的文件分别拷贝到自己工程中
注意需要将拷贝过来的文件链接到自己的工程中,我这里是通过Makefile来链接的
FlashDB 底层的 Flash 管理及操作依赖于 RT-Thread 的 FAL (Flash Abstraction Layer) Flash 抽象层开源软件包。我这里用的是freertos,所以需要先移植FAL到工程中。
移植前建议先了解下 FAL 功能介绍,详见:软件包 - RT-Thread物联网操作系统
FlashDB源码目录下有fal的文件。将这里的src和inc拷贝到我们自己的工程中
同样也需要将拷贝进来的文件链接到自己的工程中
首先需要定义FLASH设备,提供flash读写等操作
/*
* Copyright (c) 2020, Armink, <armink.ztl@gmail.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <fal.h>
#include "sys/fdcm.h"
#include "sys/image.h"
#include "image/flash.h"
#define FLASH_ERASE_MIN_SIZE (4 * 1024)
#define LOCKER_ENABLE
#ifdef LOCKER_ENABLE
#include "kernel/os/os.h"
static OS_Semaphore_t s_lock;
#define LOCK() \
do { \
OS_SemaphoreWait(&s_lock, OS_WAIT_FOREVER); \
} while(0)
#define UNLOCK() \
do { \
OS_SemaphoreRelease(&s_lock); \
} while(0)
#else
#define LOCK()
#define UNLOCK()
#endif
static int init(void)
{
#ifdef LOCKER_ENABLE
if (0 == OS_SemaphoreIsValid(&s_lock)) {
if (OS_OK != OS_SemaphoreCreateBinary(&s_lock)) {
printf("fal semaphore create fail!!!!!!!!!!!!!.\n");
return -1;
} else {
printf("fal semaphore create suc.\n");
OS_SemaphoreRelease(&s_lock);
}
}
#endif
return 1;
}
static int read(long offset, uint8_t *buf, size_t size)
{
//Xassert(size % 4 == 0);
/* You can add your code under here. */
int32_t ret;
uint32_t addr = nor_flash0.addr + offset;
LOCK();
ret = flash_read(0, addr, buf, size);
UNLOCK();
return ret;
}
static int write(long offset, const uint8_t *buf, size_t size)
{
int32_t ret;
uint32_t addr = nor_flash0.addr + offset;
LOCK();
ret = flash_write(0, addr, buf, size);
UNLOCK();
return ret;
}
static int erase(long offset, size_t size)
{
int32_t ret;
uint32_t addr = nor_flash0.addr + offset;
int32_t erase_size = ((size - 1) / FLASH_ERASE_MIN_SIZE) + 1;
LOCK();
ret = flash_erase(0, addr, erase_size * FLASH_ERASE_MIN_SIZE);
UNLOCK();
return ret;
}
//1.定义 flash 设备
struct fal_flash_dev nor_flash0 =
{
.name = "norflash0",
.addr = 0x0,
.len = 4*1024*1024,
.blk_size = FLASH_ERASE_MIN_SIZE,
.ops = {init, read, write, erase},
.write_gran = 1
};
然后是定义Flash设备表和分区表
Flash 设备表定义在 fal_cfg.h
头文件中,定义分区表前需 新建 fal_cfg.h
文件 ,请将该文件统一放在对应 BSP 或工程目录的 port 文件夹下,并将该头文件路径加入到工程。
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-05-17 armink the first version
*/
#ifndef _FAL_CFG_H_
#define _FAL_CFG_H_
//#include <rtconfig.h>
//#include <board.h>
#define NOR_FLASH_DEV_NAME "norflash0"
#define FAL_PART_HAS_TABLE_CFG
/* ===================== Flash device Configuration ========================= */
//extern const struct fal_flash_dev stm32f2_onchip_flash;
extern struct fal_flash_dev nor_flash0;
/* flash device table */
#define FAL_FLASH_DEV_TABLE \
{ \
&nor_flash0, \
}
/* ====================== Partition Configuration ========================== */
#ifdef FAL_PART_HAS_TABLE_CFG
/* partition table */
#define FAL_PART_TABLE \
{ \
{FAL_PART_MAGIC_WORD, "fdb_kvdb1", NOR_FLASH_DEV_NAME, 0x37C000, 48*1024, 0}, \
}
#endif /* FAL_PART_HAS_TABLE_CFG */
#endif /* _FAL_CFG_H_ */
我这里不需要完整使用FAL层来抽象flash。只需要对特定的地址分区使用FlashDB。所以只定义了flash中0x37c000地址开始的48K数据来使用
此时移植工作已经基本完毕。可以写demo来测试
#include <stdio.h>
//#include "freertos/FreeRTOS.h"
//#include "freertos/task.h"
//#include "semphr.h"
//#include "esp_system.h"
//#include "esp_spi_flash.h"
#include <flashdb.h>
//#include "os_util.h"
#include "kernel/os/os.h"
#define FDB_LOG_TAG "[main]"
static uint32_t boot_count = 0;
static time_t boot_time[10] = {0, 1, 2, 3};
/* default KV nodes */
static struct fdb_default_kv_node default_kv_table[] = {
{"username", "armink", 0}, /* string KV */
{"password", "123456", 0}, /* string KV */
{"boot_count", &boot_count, sizeof(boot_count)}, /* int type KV */
{"boot_time", &boot_time, sizeof(boot_time)}, /* int array type KV */
};
#if 0
static struct fdb_default_kv_node default_file_kv_table[] = {
{"abc", "123", 0}, /* string KV */
{"qwe", "456", 0}, /* string KV */
{"f_boot_cnt", &boot_count, sizeof(boot_count)}, /* int type KV */
{"f_boot_time", &boot_time, sizeof(boot_time)}, /* int array type KV */
};
#endif
//static struct fdb_kvdb file_kvdb = {{ 0 }};
/* KVDB object */
static struct fdb_kvdb kvdb = {{ 0 }};
static OS_Mutex_t s_lock;
extern void kvdb_basic_sample(fdb_kvdb_t kvdb);
extern void kvdb_type_string_sample(fdb_kvdb_t kvdb);
extern void kvdb_type_blob_sample(fdb_kvdb_t kvdb);
extern void tsdb_sample(fdb_tsdb_t tsdb);
extern void kvdb_type_string_sample_mytest(fdb_kvdb_t kvdb);
static void lock(fdb_db_t db)
{
//xSemaphoreTake(s_lock, portMAX_DELAY);
if (OS_OK != (OS_MutexLock(&s_lock, OS_WAIT_FOREVER))) {
printf("[%s][%d]OS_MutexLock error.\n", __func__, __LINE__);
}
}
static void unlock(fdb_db_t db)
{
//xSemaphoreGive(s_lock);
if (OS_OK != (OS_MutexUnlock(&s_lock))) {
printf("[%s][%d]OS_MutexUnlock error.\n", __func__, __LINE__);
}
}
#ifdef FDB_USING_TSDB
/* TSDB object */
struct fdb_tsdb tsdb = {{ 0 }};
/* counts for simulated timestamp */
static int counts = 0;
static fdb_time_t get_time(void)
{
/* Using the counts instead of timestamp.
* Please change this function to return RTC time.
*/
return ++counts;
}
#endif
int flashdb_demo(void)
{
fdb_err_t result;
//if (s_lock == NULL) {
// s_lock = xSemaphoreCreateCounting(1, 1);
// assert(s_lock != NULL);
//}
if (OS_OK != (OS_MutexCreate(&s_lock))) {
printf("[%s][%d]MutexCreate error.\n", __func__, __LINE__);
return -1;
}
#ifdef FDB_USING_KVDB
{ /* KVDB Sample */
struct fdb_default_kv default_kv;
default_kv.kvs = default_kv_table;
default_kv.num = sizeof(default_kv_table) / sizeof(default_kv_table[0]);
/* set the lock and unlock function if you want */
fdb_kvdb_control(&kvdb, FDB_KVDB_CTRL_SET_LOCK, lock);
fdb_kvdb_control(&kvdb, FDB_KVDB_CTRL_SET_UNLOCK, unlock);
/* Key-Value database initialization
*
* &kvdb: database object
* "env": database name
* "fdb_kvdb1": The flash partition name base on FAL. Please make sure it's in FAL partition table.
* Please change to YOUR partition name.
* &default_kv: The default KV nodes. It will auto add to KVDB when first initialize successfully.
* NULL: The user data if you need, now is empty.
*/
result = fdb_kvdb_init(&kvdb, "env", "fdb_kvdb1", &default_kv, NULL);
if (result != FDB_NO_ERR) {
printf("err!!!!!!!!!!!!!!!!!!\n");
return -1;
}
printf("fdb_kv_set_default-------------------------\n");
fdb_kv_set_default(&kvdb);
printf("0000-------------------------\n");
fdb_kv_print(&kvdb);
printf("0000-------------------------\n");
/* run basic KV samples */
kvdb_basic_sample(&kvdb);
/* run string KV samples */
kvdb_type_string_sample(&kvdb);
/* run blob KV samples */
kvdb_type_blob_sample(&kvdb);
printf("-------------------------\n");
kvdb_type_string_sample_mytest(&kvdb);
// fdb_kv_print(&kvdb);
}
#endif /* FDB_USING_KVDB */
#if 1
#ifdef FDB_USING_TSDB
{ /* TSDB Sample */
/* set the lock and unlock function if you want */
fdb_tsdb_control(&tsdb, FDB_TSDB_CTRL_SET_LOCK, lock);
fdb_tsdb_control(&tsdb, FDB_TSDB_CTRL_SET_UNLOCK, unlock);
/* Time series database initialization
*
* &tsdb: database object
* "log": database name
* "fdb_tsdb1": The flash partition name base on FAL. Please make sure it's in FAL partition table.
* Please change to YOUR partition name.
* get_time: The get current timestamp function.
* 128: maximum length of each log
* NULL: The user data if you need, now is empty.
*/
result = fdb_tsdb_init(&tsdb, "log", "fdb_tsdb1", get_time, 128, NULL);
/* read last saved time for simulated timestamp */
fdb_tsdb_control(&tsdb, FDB_TSDB_CTRL_GET_LAST_TIME, &counts);
if (result != FDB_NO_ERR) {
return -1;
}
/* run TSDB sample */
tsdb_sample(&tsdb);
}
#endif /* FDB_USING_TSDB */
#ifdef FDB_USING_FILE_MODE
{
//struct fdb_default_kv default_kv;
//default_kv.kvs = default_file_kv_table;
//default_kv.num = sizeof(default_file_kv_table) / sizeof(default_file_kv_table[0]);
/* set the lock and unlock function if you want */
fdb_kvdb_control(&file_kvdb, FDB_KVDB_CTRL_SET_LOCK, lock);
fdb_kvdb_control(&file_kvdb, FDB_KVDB_CTRL_SET_UNLOCK, unlock);
bool file_mode = true;
//bool not_formatable = true;
uint32_t sec_size = 4096, db_size = PRJCONF_LITTLE_FS_SIZE-(4*4096);
/* set the sector and database max size */
fdb_kvdb_control(&file_kvdb, FDB_KVDB_CTRL_SET_SEC_SIZE, &sec_size);
fdb_kvdb_control(&file_kvdb, FDB_KVDB_CTRL_SET_MAX_SIZE, &db_size);
//fdb_kvdb_control(&kvdb, FDB_KVDB_CTRL_SET_NOT_FORMAT, ¬_formatable);
/* enable file mode */
fdb_kvdb_control(&file_kvdb, FDB_KVDB_CTRL_SET_FILE_MODE, &file_mode);
uint32_t lfs_free_spcae_size = 0;
lfs_free_spcae(&lfs_free_spcae_size);
printf("lfs free spce = %d LINE %d\n",lfs_free_spcae_size, __LINE__);
/*struct lfs_info info;
if (LFS_ERR_OK != lfs_stat(app_lfs_flash_get_handle(), "fdb_lfs", &info)) {
if (LFS_ERR_OK != lfs_mkdir(app_lfs_flash_get_handle(), "fdb_lfs")) {
printf("lfs_mkdir error.\n");
return -1;
}
} else {
printf("fdb_lfs dir exist.\n");
}
lfs_free_spcae(&lfs_free_spcae_size);
printf("lfs free spce = %d LINE %d\n",lfs_free_spcae_size, __LINE__);*/
/* Key-Value database initialization
*
* &kvdb: database object
* "env": database name
* "fdb_kvdb1": The flash partition name base on FAL. Please make sure it's in FAL partition table.
* Please change to YOUR partition name.
* &default_kv: The default KV nodes. It will auto add to KVDB when first initialize successfully.
* NULL: The user data if you need, now is empty.
*/
//result = fdb_kvdb_init(&file_kvdb, "lfs", "fdb_lfs", &default_kv, NULL);
result = fdb_kvdb_init(&file_kvdb, "lfs", "/", NULL, NULL);
if (result != FDB_NO_ERR) {
return -1;
}
/* run basic KV samples */
kvdb_basic_sample(&file_kvdb);
/* run string KV samples */
kvdb_type_string_sample(&file_kvdb);
/* run blob KV samples */
kvdb_type_blob_sample(&file_kvdb);
}
#endif
#endif
return 0;
}
编译烧录到板子上面运行结果:
更多推荐
已为社区贡献1条内容
所有评论(0)