找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

1563

积分

0

好友

231

主题
发表于 6 天前 | 查看: 20| 回复: 0

FlashDB 是一款面向嵌入式系统的超轻量级数据库,旨在为资源受限的嵌入式产品提供可靠、高效的数据存储方案。它不仅支持基于文件系统的数据库,还深度结合 Flash 存储器的物理特性,在保证极低资源占用的前提下,优化性能与可靠性,并尽可能延长 Flash 的使用寿命。

FlashDB 主要提供两种数据模型:

  1. 键值数据库 (KVDB):一种非关系型数据库,数据以键值对的形式存储,其中键作为唯一标识符。其特点是接口简洁、操作高效,易于扩展。
  2. 时序数据库 (TSDB):专门用于存储按时间顺序产生的数据。每条记录都包含时间戳,非常适合数据量大、插入和查询频繁的场景。

KVDB 典型应用场景

  • 产品参数存储
  • 用户配置信息管理
  • 小型文件管理

TSDB 典型应用场景

  • 存储动态产生的结构化数据,例如温湿度传感器采集的环境监测信息、智能手环记录的健康数据等。
  • 记录系统运行日志、历史告警信息等。

FlashDB 软件包架构图

FlashDB 数据模型示意图

与 EasyFlash 的对比

EasyFlash 和 FlashDB 均由开发者 armink 开源,同为轻量级嵌入式存储解决方案,但设计定位不同。FlashDB 可视为 EasyFlash 的功能增强与演进版本

EasyFlash与FlashDB对比图

对比维度 EasyFlash FlashDB
核心定位 轻量级 Flash 存储器库,侧重参数存储 超轻量级嵌入式数据库,提供结构化数据管理。
数据模型 键值对 (Key-Value),用于存储环境变量。 1. 键值对 (KVDB)<br>2. 时序数据 (TSDB)
关键功能 ENV(环境变量)、IAP、Log。 在KVDB基础上,新增时序数据库(TSDB),支持按时间序列高效存取。
性能与资源 资源占用极低。 功能更多,在保持低资源占用的同时优化了查询性能。
依赖关系 可独立使用,或依赖 RT-Thread 的FAL抽象层。 底层依赖于FAL(Flash Abstraction Layer),需先完成FAL移植。
版本关系 早期项目,其v5.0.0版本重命名为FlashDB 由EasyFlash发展而来,功能更全面。
  • 选择 EasyFlash:如果需求非常简单,仅需存储少量设备参数、配置,且对资源消耗极其敏感。
  • 选择 FlashDB:如果需要记录大量带时间戳的数据(如传感器历史、运行日志),或未来可能需要更复杂的数据查询与管理功能。

移植与配置(以STM32F407ZG为例)

FlashDB 底层的 Flash 操作依赖于 RT-Thread 的 FAL (Flash Abstraction Layer) 抽象层。该软件包同样支持裸机平台,因此移植工作的核心是将目标 Flash 设备对接到 FAL。

FlashDB 移植依赖关系图

FAL 的配置可参考相关文章。本文以使用 STM32 片内 Flash 为例,关键配置文件 fal_cfg.h 内容如下:

#ifndef _FAL_CFG_H_
#define _FAL_CFG_H_

#include <rtthread.h>
#include <board.h>

extern const struct fal_flash_dev stm32_onchip_flash_128k;

/* flash device table */
#define FAL_FLASH_DEV_TABLE                                          \
{                                                                    \
    &stm32_onchip_flash_128k,                                        \
}

/* ====================== Partition Configuration ========================== */
#ifdef FAL_PART_HAS_TABLE_CFG
/* partition table */
#define FAL_PART_TABLE                                                                                               \
{                                                                                                                    \
    {FAL_PART_MAGIC_WROD, "fdb_kvdb", "onchip_flash_128k", 1* 128 * 1024 , 2* 128 * 1024, 0}, \
    {FAL_PART_MAGIC_WROD, "fdb_tsdb", "onchip_flash_128k", 3* 128 * 1024 , 2* 128 * 1024, 0}, \
}
#endif /* FAL_PART_HAS_TABLE_CFG */

#endif /* _FAL_CFG_H_ */

此配置定义了两个分区:fdb_kvdbfdb_tsdb,分别用于存放键值数据库和时序数据库的数据。

在 RT-Thread 的 ENV 工具或 rtconfig.h 中启用 FlashDB 软件包:
开启FlashDB配置

若 TSDB 需要时间戳功能,还需确保 RTC 设备驱动已正确配置并启用。
编译时若遇到错误,需根据提示调整相关配置,例如确保 gettimeofday 等系统调用已适配:
编译报错及解决

功能测试

编写测试用例,对 KVDB 和 TSDB 的基本功能进行验证。以下为主函数 main.c 的核心示例代码:

#include <rtthread.h>
#include <flashdb.h>

/* KVDB 对象 */
static struct fdb_kvdb kvdb = { 0 };
/* TSDB 对象 */
struct fdb_tsdb tsdb = { 0 };

/* 模拟时间戳的计数器 */
static int counts = 0;

/* 声明测试函数 */
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);

/* 锁函数,用于保证操作原子性(裸机环境示例) */
static void lock(fdb_db_t db) {
    __disable_irq(); // 关中断
}
static void unlock(fdb_db_t db) {
    __enable_irq(); // 开中断
}
/* 获取时间函数(此处用计数器模拟,实际项目应替换为RTC时间) */
static fdb_time_t get_time(void) {
    return ++counts;
}

int main(void) {
    fdb_err_t result;

#ifdef FDB_USING_KVDB
    {
        /* 初始化 KVDB */
        fdb_kvdb_control(&kvdb, FDB_KVDB_CTRL_SET_LOCK, (void *)lock);
        fdb_kvdb_control(&kvdb, FDB_KVDB_CTRL_SET_UNLOCK, (void *)unlock);
        result = fdb_kvdb_init(&kvdb, "env", "fdb_kvdb", NULL, NULL);
        if (result != FDB_NO_ERR) return -1;

        /* 执行 KVDB 测试样例 */
        kvdb_basic_sample(&kvdb);
        kvdb_type_string_sample(&kvdb);
        kvdb_type_blob_sample(&kvdb);
    }
#endif

#ifdef FDB_USING_TSDB
    {
        /* 初始化 TSDB */
        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_tsdb", get_time, 128, NULL);
        fdb_tsdb_control(&tsdb, FDB_TSDB_CTRL_GET_LAST_TIME, &counts); // 读取上次保存的时间
        if (result != FDB_NO_ERR) return -1;

        /* 执行 TSDB 测试样例 */
        tsdb_sample(&tsdb);
    }
#endif

    while (1) {
        rt_thread_mdelay(1000);
    }
}

通过串口调试工具查看输出,可以验证 FlashDB 是否正常工作:
FlashDB 测试运行输出

参考资料




上一篇:C++学习难点解析与职业发展指南:从入门到进阶的系统性建议
下一篇:Kubernetes七层流量入口深度解析:Ingress与Gateway API架构对比与选型指南
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2025-12-24 21:10 , Processed in 0.227842 second(s), 40 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 云栈社区.

快速回复 返回顶部 返回列表