教程较长,按需阅读
前言
FlashDB 是一款超轻量级的嵌入式数据库。它结合了 Flash 的特性,具有较强的性能及可靠性。
FlashDB提供了键值数据库和时序数据库两种数据库模式,不仅资源占用极低,内存占用几乎为 0,而且存储容量大,非常适合用于物联网产品。
移植
根据 FlashDB开发文档,FlashDB 底层的 Flash 管理及操作依赖于 RT-Thread 的 FAL (Flash Abstraction Layer) Flash 抽象层开源软件包,所以将所用到的 Flash 对接到 FAL ,即可完成整个移植工作。
FlashDB移植的关键是FAL的移植。本文在片外flash上搭建FAL,并移植FlashDB。
下面我们就开始实际操作,从将flash挂载到spi总线上开始,最终完成FlashDB数据库的搭建。新手可以跟着一步一步做,有一些开发经验的朋友可以选择性地阅读。
1.开启SPI总线
新建一个空白的RT-Thread项目,本文基于STM32F103芯片。
首先在drivers目录下打开board.h
文件,找到SPI对应部分。根据指导,一步一步做下去。
操作步骤
step1:打开RT-Thread Settings,点击更多配置来到组件一栏,勾选如下。
step2:board.h
文件中,打开SPI宏定义。
step3:使用stm32cubemx产生初始化函数,将其粘贴于board.c
文件末尾。
然后选择芯片型号——>填写项目名称,双击IOC文件后如图操作。
复制初始化函数到board.c
文件。(ps:初始化函数在哪个文件中,名字叫什么,在board.h文件对应部分都是可以找到的哦)
step4:在drivers目录下的stm32f1xx_hal_conf.h
文件中打开SPI驱动。
验证
配置完成,让我们编译下载一下,看看有没有成功。
使用list_device
指令查看设备,可以看到SPI总线已经存在了。
2.挂载片外flash
接下来,我们将片外flash(W25Q128)挂到SPI总线上。
代码
此处,参考RT-Thread官方开发文档,在application目录下,新增flash.c
文件。
#include <rtthread.h>
#include <board.h>
#include <rtdevice.h>
#include "drv_spi.h"
#include "spi_flash.h"
#include "spi_flash_sfud.h"
#define DBG_TAG "flash"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
#define W25Q_SPI_BUS_NAME "spi1" /* 上一步骤 打开的是SPI1,这里也写1,一定要对应*/
#define W25Q_SPI_DEVICE_NAME "spi10" /* SPI1总线上0号设备*/
/*原理见官方文档*/
static int rt_hw_spi_flash_init(void)
{
rt_hw_spi_device_attach(W25Q_SPI_BUS_NAME, W25Q_SPI_DEVICE_NAME, GPIOA, GPIO_PIN_4);
//这提醒我们,一定要从原理图上看清楚自己的flash名
if (RT_NULL == rt_sfud_flash_probe("W25Q128", W25Q_SPI_DEVICE_NAME))
{
return -RT_ERROR;
};
return RT_EOK;
}
/* 导出到自动初始化 */
INIT_COMPONENT_EXPORT(rt_hw_spi_flash_init);
验证
经过验证,flash已经挂载成功了,下面开始搭建FAL。
3.搭建FAL抽象层
FAL是RT-Thread的一个软件包,主要是用于Flash 抽象层的实现,负责管理 Flash 设备和 Flash 分区。关于FAL的详细功能,大家可以参考RT-Thread软件包友情链接。文档非常详细,这里也参考了文档中的内容。
3.1添加FAL
打开RT-Thread Settings点击立即添加,然后搜索FAL。
3.2配置FAL
因为我们只用到了片外flash,所以可以将fal_cfg.h
中关于片外flash的部分删除,并且定义自己的分区表。
最终修改fal_cfg.h
文件如下:
#ifndef _FAL_CFG_H_
#define _FAL_CFG_H_
#include <rtconfig.h>
#include <board.h>
#define NOR_FLASH_DEV_NAME "W25Q128" /*一定要改为自己的flash名称*/
/* ===================== Flash device Configuration ========================= */
extern struct fal_flash_dev nor_flash0;
/* flash device table(定义设备表,我删掉了片上flash) */
#define FAL_FLASH_DEV_TABLE \
{ \
&nor_flash0, \
}
/* ====================== Partition Configuration ========================== */
#ifdef FAL_PART_HAS_TABLE_CFG
/* partition table ps:可根据需要自行分区*/
#define FAL_PART_TABLE \
{ \
{FAL_PART_MAGIC_WORD, "easyflash", NOR_FLASH_DEV_NAME, 0, 1024*1024, 0}, \
{FAL_PART_MAGIC_WORD, "download", NOR_FLASH_DEV_NAME, 1024*1024, 1024*1024, 0}, \
}
#endif /* FAL_PART_HAS_TABLE_CFG */
#endif /* _FAL_CFG_H_ */
其实我并没有做太大改动,只是删掉了片上flash相关部分,大家可以根据需要自行分区、命名。
当出现错误时,建议仔细阅读FlashDB开发文档当中的注意事项,讲得非常详细。
3.3初始化FAL
在main.c
文件中,包含fal.h
并调用fal_init()
初始化程序。
3.4验证
做到这里已经比较累了,我们来编译下载,感受一下成功的喜悦。
4.移植FlashDB
FlashDB官方有在F103上运行的demo,也为键值数据库、时序数据库提供了相应的示例,这里我们通过运行kvdb基础示例(位于samples/kvdb_basic_sample.c
)来验证是否移植成功。
4.1添加flashDB软件包
添加方法同FAL包,这里不复述了。添加后右击flashdb,选择详细配置,勾选如下:
4.2配置FlashDB
在packages——>FlashDB——>inc
目录下通过 fdb_cfg.h
对其进行功能配置,这里参考官方demo,修改 fdb_cfg.h
文件如下:
#ifndef _FDB_CFG_H_
#define _FDB_CFG_H_
/* using KVDB feature */
#define FDB_USING_KVDB
#ifdef FDB_USING_KVDB
/* Auto update KV to latest default when current KVDB version number is changed. @see fdb_kvdb.ver_num */
/* #define FDB_KV_AUTO_UPDATE */
#endif
/* using TSDB (Time series database) feature */
#define FDB_USING_TSDB
/* the flash write granularity, unit: bit
* only support 1(nor flash)/ 8(stm32f2/f4)/ 32(stm32f1) */
//#define FDB_WRITE_GRAN /* @note you must define it for a value */
//注意,上一步我们已经勾选了,这里不要重复配置
/* MCU Endian Configuration, default is Little Endian Order. */
/* #define FDB_BIG_ENDIAN */
/* log print macro. default EF_PRINT macro is printf() */
/* #define FDB_PRINT(...) my_printf(__VA_ARGS__) */
/* print debug information */
#define FDB_DEBUG_ENABLE
#endif /* _FDB_CFG_H_ */
//以上所有来源于官方demo
4.3验证
配置好之后,我们通过调用官方例程来验证是否移植成功。
KVDB基础示例代码位于 samples/kvdb_basic_sample.c
,在 main.c
有定义默认的 KV 集合表,在里面有 boot_count KV。通过该 KV 来记录当前系统的启动次数。每次掉电再启动时,该 KV 会自动加一,并保存至 KVDB 中。
简言之就是,能存储、更新启动次数。
step1:在application目录下,新增flashdb.c
文件,代码如下:
#include <stdio.h>
#include <board.h>
#include <flashdb.h>
#include <stm32f1xx_hal.h>
#define FDB_LOG_TAG "flashdb"
static uint32_t boot_count = 0;
struct fdb_kvdb _global_kvdb = {0};
struct fdb_tsdb _global_tsdb = {0};
extern void kvdb_basic_sample(fdb_kvdb_t kvdb);
static struct fdb_default_kv_node default_kv_table[] = {{"boot_count", &boot_count, sizeof(boot_count)}}; /* int type KV */
static int flashdb(void)
{
fdb_err_t result;
struct fdb_default_kv default_kv;
default_kv.kvs = default_kv_table;
default_kv.num = sizeof(default_kv_table) / sizeof(default_kv_table[0]);
result = fdb_kvdb_init(&_global_kvdb, "env", "download", &default_kv, NULL);
//init函数的第三个参数,是用于存储数据的fal分区,大家根据自己的情况选择
if (result != FDB_NO_ERR)
{
return -1;
}
else
{
kvdb_basic_sample(&_global_kvdb);
}
return RT_EOK;
}
INIT_ENV_EXPORT(flashdb);
step2:开启libc,我也不知道为何,不开就会报莫名其妙错误,暂时先不深究。
step3:编译下载
下载后可以看到,已经成功读取、设置启动次数(如果大家是第一次下载,则启动次数会设置为1)。按下复位键,可以看到次数加一。
总结
这篇文章着重介绍操作,几乎不涉及原理的讲解,所以一些理论知识还需要大家仔细阅读官方文档。我也是初学这些知识,水平有限,若有错误,还望大家批评指正。