TinyFlashDB:一种超轻量的可纠错的通用单片机Flash存储方案

2023-05-16

文章目录

  • 一、TinyFlashDB设计理念
  • 二、TinyFlashDB使用示例
  • 三、TinyFlashDB API介绍
  • 四、TinyFlashDB设计原理
  • 五、TinyFlashDB移植和配置
  • 六、移植到STM32单片机

已剪辑自: https://mp.weixin.qq.com/s/jeUxw8pJCUZKNE92Rt5KPQ

摘要:在单片机日常开发中,总会需要存储一些信息,这时就需要使用单片机FLASH存储的方案,目前单片机存储的方案有很多如:EASYFLASHFLASHDBOSAL_NV等等方案,他们程序都非常大,在存储不多的变量时不值得。而且现有方案的代码中很少有考虑到flash写入出错的情况。

在实际产品中,嵌入式产品flash写入可能会受各种因素影响(电池供电、意外断电、气温等)从而并不是很稳定,一旦出现错误,会导致产品一系列问题。

一、TinyFlashDB设计理念

不同于其他很多的KV型数据库,TinyFlashDB每一个需要存储的变量都会分配一个单独的单片机flash扇区,变量长度不可变。

TinyFlashDB在设计时就考虑了写入错误的影响,追求力所能及的安全保障、资源占用方面尽可能的缩小(不到1kb代码占用)、尽可能的通用性(可以移植到51等8位机,无法逆序写入的stm32L4系列,某些flash加密的单片机和其他普通32位机上)。

二、TinyFlashDB使用示例

const tfdb_index_t test_index = {
    .end_byte = 0x00,
    .flash_addr = 0x4000,
    .flash_size = 256,
    .value_length = 2,

};
tfdb_addr_t addr = 0; /*addr cache*/

uint8_t test_buf[4]; /*aligned_value_size*/

uint16_t test_value;

void main()
{
    TFDB_Err_Code result;
    result = tfdb_set(&test_index, test_buf, &addr, &test_value);
    if(result == TFDB_NO_ERR)
    {
        printf("set ok, addr:%x\n", addr);
    }

    result = tfdb_get(&test_index, test_buf, &addr, &test_value);
    if(result == TFDB_NO_ERR)
    {
        printf("get ok, addr:%x, value:%x\n", addr, test_value);
    }
}

三、TinyFlashDB API介绍

typedef struct _tfdb_index_struct{
    tfdb_addr_t     flash_addr;/* the start address of the flash block */
    uint16_t        flash_size;/* the size of the flash block */
    uint8_t         value_length;/* the length of value that saved in this flash block */
    uint8_t         end_byte; /* must different to TFDB_VALUE_AFTER_ERASE */
    /* 0x00 is recommended for end_byte, because almost all flash is 0xff after erase. */
}tfdb_index_t;

结构体功能:在TinyFlashDB中,API的操作都需要指定的参数index,该index结构体中存储了flash的地址,flash的大小,存储的变量的长度,结束标志位。在读取flash扇区时会去校验此信息。

TFDB_Err_Code tfdb_get(const tfdb_index_t *index, uint8_t *rw_buffer, tfdb_addr_t *addr_cache, void* value_to);
  • 函数功能:从index指向的扇区中获取一个index中指定变量长度的变量,flash头部数据校验出错不会重新初始化flash。
  • 参数 index:tfdb操作的index指针。
  • 参数 rw_buffer:写入和读取的缓存,所有flash的操作最后都会将整理后的数据拷贝到该buffer中,再调用tfdb_port_write或者tfdb_port_read进行写入。当芯片对于写入的数据区缓存有特殊要求(例如4字节对齐,256字节对齐等),可以通过该参数将符合要求的变量指针传递给函数使用。至少为4字节长度。
  • 参数 addr_cache:可以是NULL,或者是地址缓存变量的指针,当addr_cache不为NULL,并且也不为0时,则认为addr_cache已经初始化成功,不再校验flash头部,直接从该addr_cache的地址读取数据。
  • 参数 value_to:要存储数据内容的地址。
  • 返回值:TFDB_NO_ERR成功,其他失败。
TFDB_Err_Code tfdb_set(const tfdb_index_t *index, uint8_t *rw_buffer, tfdb_addr_t *addr_cache, void* value_from);
  • 函数功能:在index指向的扇区中写入一个index中指定变量长度的变量,flash头部数据校验出错重新初始化flash。
  • 参数 index:tfdb操作的index指针。
  • 参数 rw_buffer:写入和读取的缓存,所有flash的操作最后都会将整理后的数据拷贝到该buffer中,再调用tfdb_port_write或者tfdb_port_read进行写入。当芯片对于写入的数据区缓存有特殊要求(例如4字节对齐,256字节对齐等),可以通过该参数将符合要求的变量指针传递给函数使用。至少为4字节长度。
  • 参数 addr_cache:可以是NULL,或者是地址缓存变量的指针,当addr_cache不为NULL,并且也不为0时,则认为addr_cache已经初始化成功,不再校验flash头部,直接从该addr_cache的地址读取数据。
  • 参数 value_from:要存储的数据内容。
  • 返回值:TFDB_NO_ERR成功,其他失败。

四、TinyFlashDB设计原理

观察上方代码,可以发现TinyFlashDB的操作都需要tfdb_index_t定义的index参数。

Flash初始化后头部信息为4字节,所以只支持1、2、4、8字节操作的flash:头部初始化时会读取头部,所以函数中rw_buffer指向的数据第一要求至少为4字节,如果最小写入单位是8字节,则为第一要求最少为8字节。

第一字节第二字节第三字节第四字节和其他对齐字节

flash_size高8位字节flash_size低8位字节value_lengthend_byte

数据存储时,会根据flash支持的字节操作进行对齐,所以函数中rw_buffer指向的数据第二要求至少为下面函数中计算得出的aligned_value_size个字节:

    aligned_value_size  = index->value_length + 2;/* data + verify + end_byte */
 
#if (TFDB_WRITE_UNIT_BYTES==2)
    /* aligned with TFDB_WRITE_UNIT_BYTES */
    aligned_value_size = ((aligned_value_size + 1) & 0xfe);
#elif (TFDB_WRITE_UNIT_BYTES==4)
    /* aligned with TFDB_WRITE_UNIT_BYTES */
    aligned_value_size = ((aligned_value_size + 3) & 0xfc);
#elif (TFDB_WRITE_UNIT_BYTES==8)
    /* aligned with TFDB_WRITE_UNIT_BYTES */
    aligned_value_size = ((aligned_value_size + 7) & 0xf8);
#endif

前value_length个字节第value_length+1字节第value_length+2字节其他对齐字节

value_from数据内容value_from的和校验end_byteend_byte

每次写入后都会再读取出来进行校验,如果校验不通过,就会继续在下一个地址写入。指导达到最大写入次数(TFDB_WRITE_MAX_RETRY)或者头部校验错误。

读取数据时也会计算和校验,不通过的话继续读取,直到返回校验通过的最新数据,或者读取失败。

五、TinyFlashDB移植和配置

移植使用只需要在tfdb_port.c中,编写完成三个接口函数,也要在tfdb_port.h中添加相应的头文件和根据不同芯片修改宏定义

TFDB_Err_Code tfdb_port_read(tfdb_addr_t addr, uint8_t *buf, size_t size);

TFDB_Err_Code tfdb_port_erase(tfdb_addr_t addr, size_t size);

TFDB_Err_Code tfdb_port_write(tfdb_addr_t addr, const uint8_t *buf, size_t size);

所有的配置项都在tfdb_port.h中

/* use string.h or self functions */
#define TFDB_USE_STRING_H               1

#if TFDB_USE_STRING_H
    #include "string.h"
    #define tfdb_memcpy memcpy
    #define tfdb_memcmp memcmp
    #define TFDB_MEMCMP_SAME 0
#else
    #define tfdb_memcpy
    #define tfdb_memcmp
    #define TFDB_MEMCMP_SAME
#endif

#define TFDB_DEBUG                          printf

/* The data value in flash after erased, most are 0xff, some flash maybe different. */
#define TFDB_VALUE_AFTER_ERASE              0xff

/* the flash write granularity, unit: byte
 * only support 1(stm32f4)/ 2(CH559)/ 4(stm32f1)/ 8(stm32L4) */
#define TFDB_WRITE_UNIT_BYTES               8 /* @note you must define it for a value */

/* @note the max retry times when flash is error ,set 0 will disable retry count */
#define TFDB_WRITE_MAX_RETRY                32

/* must not use pointer type. Please use uint32_t, uint16_t or uint8_t. */
typedef uint32_t    tfdb_addr_t;

六、移植到STM32单片机

项目地址:`https://github.com/smartmx/TFDB/tree/main```

使用一下命令克隆Demo,裸机移植例程

git clone -b raw https://github.com/smartmx/TFDB.git
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

TinyFlashDB:一种超轻量的可纠错的通用单片机Flash存储方案 的相关文章

  • Qt自定义信号和槽函数

    文章目录 自定义信号函数自定义槽函数自定义信号和槽的完整实例 已剪辑自 http c biancheng net view vip 9662 html 实际开发中 xff0c 如果仅使用 Qt 提供的信号函数和槽函数 xff0c 会经常遇到
  • QT中信号和槽之间的参数传递和参数匹配

    已剪辑自 https blog csdn net lyc daniel article details 12047819 信号槽如何传递参数 xff08 或带参数的信号槽 xff09 利用Qt进行程序开发时 xff0c 有时需要信号槽来完成
  • QT使用信号与槽时编译错误“no matching function for call to connect“

    转转于 xff1a http t csdn cn K3aYh 初学QT xff0c 在尝试用connect手动关联一个按钮和QlineEdit的时候编译报错 xff0c 如下 xff1a 然后贴上主要代码块 xff1a span class
  • QT-QTableWidget中的cell和item的区别

    文章目录 QTableWidget中单击一个单元格响应不同的函数 xff1a cell和item的区别 xff1a 单击单元格响应自定义函数我的错误思路 xff1a 已剪辑自 https blog csdn net CCLasdfg art
  • QT开发网络调试助手项目总结

    之前整理了一些使用QT开发串口调试助手的项目 博客地址 xff1a 上位机总结 这次继续整理一些使用QT开发网络调试助手的项目 Qt开源作品41 网络调试助手增强版V2022 我的QT学习之路 xff0c 编写UDP 43 tcp网络调试助
  • QT开源项目总结-总有一款适合你

    Qt Open Source Project 开源项目推荐 xff1a 本人收集的有关Qt的GitHub Gitee开源项目 精品收藏 我的Qt作品 Github上的一些高分Qt开源项目 Qt编写项目作品大全 Qt 开源作品
  • Qt 打印调试信息-怎样获取QTableWidget的行数和列数-读取QTableWidget表格中的数据

    文章目录 Qt 打印调试信息怎样获取QTableWidget的行数和列数Qt怎么把QTableWidget表格中的数据读取出来 Qt 打印调试信息 打印当前目录代码如下 xff0c 别忘了头文件 include include lt QtD
  • VR游戏交互开发的一些体验

    VR游戏交互开发的一些体验 本文主要写Unity开发手游过程中VR交互输入控制的一些浅薄的经验交互方面 xff0c 头控和视线按钮依然较为主流 xff0c 可以获得传感器数据来获得输入除了实体按钮输入之外还可以探索其他交互方式 xff0c
  • 一篇文章快速搞懂Qt文件读写操作

    已剪辑自 https www cnblogs com jfzhu p 13546886 html 导读 xff1a Qt当中使用QFile类对文件进行读写操作 xff0c 对文本文件也可以与QTextStream一起使用 xff0c 这样读
  • 完整的PRD文档包含哪些内容?

    完整的PRD文档包含哪些内容 xff1f 千万 xff0c 千万 xff0c 千万别再套模板写需求文档了 xff0c 要想写好需求文档重要的不是包含哪些内容 xff0c 而是为什么包含这些内容 xff01 话不多说 xff0c 直接上干货
  • 分享一个开源的QT的串口示波器

    已剪辑自 https mp weixin qq com s XHELtvZ Wk2hNzsWD52D1w 直接来源 果果小师弟 逛github时看到这个QT的串口示波器 xff0c 完全开源 xff0c 支持串口 TCP 波形显示 通信协议
  • C 语言函数返回值,竟也有潜规则~

    已剪辑自 https mp weixin qq com s WNHx1zhna8iGaYIj6 3 fg 基本上 xff0c 没有人会将大段的C语言代码全部塞入 main 函数 更好的做法是按照复用率高 耦合性低的原则 xff0c 尽可能的
  • 模型在物理学发展中的作用

    已剪辑自 https mp weixin qq com s txS CQAIXPtY6kb2tHukUQ 模型是物理学认识由唯象理论过渡到动力学理论重要的环节 开普勒的行星运行模型 气体的分子运动模型 爱因斯坦的光子模型 卢瑟福 玻尔的原子
  • 第一性原理谈安全性和可靠性

    已剪辑自 https mp weixin qq com s jttd dhv9PmNu25Z zyd5Q 最近从各个行业对系统的安全性的关注度越来越高 xff0c 10月28日 xff0c 工信部公开征求的 道路机动车辆生产准入许可管理条例
  • 在浏览器地址栏输入一个URL后回车,背后会进行哪些技术步骤?

    转载于 xff1a 小林的图解网络系列 关键是要有个上帝视角 xff0c 先要有个网络模型的概念 xff0c 也就是TCP IP 四层网络模型 xff0c 然后针对每一层的协议进行深入 学习计算机网络一定要抓主一个点 xff0c 就是 输入
  • 在MacOS上实现两个网络调试助手的UDP通信测试

    文章目录 一 背景二 网络调试助手软件三 UDP通信过程 一 背景 因为有一个项目要中会使用本机中两个应用程序之间的UDP通信 因此本文记录一下怎么在MacOS上实现两个网络调试助手的UDP通信测试 二 网络调试助手软件 我使用的网络调试助
  • QT和网络调试助手之间的UDP通信

    文章目录 一 背景二 实现过程简述UDP协议工作原理及编程模型UDP 接收端UDP 发送端运行UDP接收端和发送端运行UDP发送端发送数据给网络调试助手 一 背景 之前一篇博客实现了两个网络调试助手之间的UDP通信 文章链接 xff1a 在
  • 一个开源且完全自主开发的国产网络协议栈

    已剪辑自 https mp weixin qq com s 1LE7mGc9mRuajRgNsyirQ onps是一个开源且完全自主开发的国产网络协议栈 xff0c 适用于资源受限的单片机系统 xff0c 提供完整地ethernet ppp
  • PyQt的使用

    使用conda切换到python3 如果不会使用conda xff0c 那么安装anaconda后打开navigator xff0c 再environments中选择创建好的python3环境 xff0c 右键打开terminal即可 安装
  • 前后台系统及嵌入式前后台模式实时性优化

    一 前后台系统 前后台系统 xff0c 即计算机前后台系统 xff0c 早期的嵌入式系统中没有操作系统的概念 xff0c 程序员编写嵌入式程序通常直接面对裸机及裸设备 xff0c 在这种情况下 xff0c 通常把嵌入式程序分成两部分 xff

随机推荐

  • 又一嵌入式开源仿真器

    已剪辑自 https mp weixin qq com s X0I3EotJ8TRqLK8vb8iQvA 同QEMU类似 xff0c Renode也是嵌入式相关的一个模拟器 Renode 针对物联网应用 xff0c QEMU 针对 PC 模
  • SkyEye天目全数字实时仿真软件功能介绍

    文章目录 SkyEye的概念和应用 SkyEye的优势 SkyEye可与第三方语言或者模型集成 基于可视化图形的硬件建模 容器化的仿真平台 FPGA协同仿真 SkyEye的应用案例 SkyEye大规模航电系统仿真案例 SkyEye 飞行器显
  • SkyEye——如何实现1553B总线仿真?

    已剪辑自 https www digiproto com news 204 html 1553B最初是美国军方专为飞机上设备制定的一种信息传输总线标准 xff0c 具有双向传输的特性 xff0c 实时性和可靠性高 xff0c 现已广泛应用于
  • 细数SkyEye异构仿真的5大特色

    已剪辑自 https www digiproto com news 65 html 航天飞行器使用仿真器的重要性 航天飞行器如卫星 载人飞船等需要在空中运行很长的时间 xff0c 如果出现问题回收再调试可能要历时几个月 xff0c 而且不得
  • SkyEye:航空发动机控制系统仿真

    已剪辑自 https www digiproto com news 212 html 航空发动机 xff08 aero engine xff09 是一种高度复杂和精密的热力机械 xff0c 作为飞机的心脏 xff0c 不仅是飞机飞行的动力
  • 基于功能安全的车载计算平台开发:软件层面

    已剪辑自 https mp weixin qq com s SIBvH8u vCk6W28KrPBmA 车载智能计算平台作为智能汽车的安全关键系统 xff0c 软件层面的安全性至关重要 由于车载智能计算平台功能丰富 xff0c 应用场景复杂
  • 软件和硬件中的调用

    文章目录 1 概述 2 1 程序进程内的调用 xff1a 函数调用 2 2 程序进程间的调用 xff1a IPC 2 3 远程程序调用 xff1a RPC 2 4 远程调用REST 3 硬件 调用 3 1 综述 总线模型 3 2 片内的总线
  • 软件和硬件之间的数据交互接口

    已剪辑自 链接 编者按 软件和硬件 xff0c 既相互依存又需要某种程度上的相互独立 通过软件和硬件之间的接口把两者连接在一起 软硬件接口 xff0c 有很多含义 xff1a 比如指令集是CPU软件和硬件之间的接口 xff1b 比如一些硬件
  • 硬件定义软件?还是,软件定义硬件?

    文章目录 1 软件和硬件 1 1 软件和硬件的定义 1 2 硬件定义软件 和 软件定义硬件 的定义 1 3 CPU xff0c 软件和硬件解耦 1 4 CPU的软硬件定义 2 硬件定义软件 2 1 系统从软件逐步到硬件 2 2 硬件架构决定
  • Matlab下多径衰落信道的仿真

    衰落信道参数包括多径扩展和多普勒扩展 时不变的多径扩展相当于一个延时抽头滤波器 xff0c 而多普勒扩展要注意多普勒功率谱密度 xff0c 通常使用Jakes功率谱 高斯 均匀功率谱 多径衰落信道由单径信道叠加而成 xff0c 而单径信道中
  • 硬件接口和软件接口

    文章目录 硬件接口IDESCSISATA光纤通道游戏设备RAID卡USBMD设备MP3视频音频 软件接口Java里的接口面向对象的接口 聊聊软件接口1 什么是接口2 诞生3 早期 xff08 1950 1970 xff09 4 快速发展 x
  • 有关C语言,定时器,周期任务的一些文章汇总

    测试C语言中打印一句 hello world需要耗费多少时间 C C 43 43 开源库 适合嵌入式的定时器调度器 C语言实现的多线程定时器 C语言操作时间函数 xff0c 实现定时执行某个任务小程序 C语言实现任务调度与定时器 Linux
  • SCADE简单了解

    随着新能源三电 智能驾驶等新技术的应用 xff0c 汽车中衍生出很多的安全零部件 xff0c 如BMS VCU MCU ADAS等 xff0c 相应的软件在汽车中的比重越来越大 xff0c 随之而来的安全性 可靠性要求也越来越高 ANSYS
  • 冯诺依曼体系结构与操作系统

    文章目录 详解冯诺依曼体系结构与操作系统前言1 简要背景介绍2 五大部件介绍3 细节解释4 举例理解冯诺依曼机中数据走向 二 全面认识操作系统1 操作系统的概念2 计算机系统 比对 银行系统3 深入认识 管理 xff1a 5 操作系统存在的
  • ADAS系统安全架构设计及安全等级的分解

    已剪辑自 https mp weixin qq com s PaFQDUR iOnEeueYQ82m w 笔者从事功能安全领域工作八年有余 xff0c 结合个人经验分享一下对系统安全架构设计的理解 xff0c 希望能够解决部分同行对于安全架
  • 汽车电子电气架构演进驱动主机厂多重变化

    已剪辑自 https mp weixin qq com s P56MaFODVc eZ4JEOVJvfA 汽车电子电气架构 xff08 EEA xff0c Electrical Electronic Architecture xff09 把
  • 编写可移植C/C++程序的要点

    以前做过两年C C 43 43 程序移植工作 xff0c 从Win32平台移植到Linux平台 大约有上百万行C C 43 43 代码 xff0c 历时一年多 在开发Win32版本时 xff0c 已经强调了程序的可植性 xff0c 无奈Wi
  • 智能座舱域控制器技术发展趋势分析

    已剪辑自 https mp weixin qq com s ajmpg7ThTUBerLvb2Bng9g 提到座舱域控制器用的主控SoC芯片 xff0c 大家第一个会想到应该就是高通的SA8155P 目前 xff0c 在主机厂新上市的中高端
  • 一个单片机驱动LCD编程思路

    文章目录 LCD种类概述TFT lcdCOG lcdOLED lcd 硬件场景预备知识面向对象驱动与设备分离 LCD到底是什么LCD驱动框架代码分析GUI和LCD层驱动IC层接口层总体流程 用法和好处字库声明 已剪辑自 https mp w
  • TinyFlashDB:一种超轻量的可纠错的通用单片机Flash存储方案

    文章目录 一 TinyFlashDB设计理念二 TinyFlashDB使用示例三 TinyFlashDB API介绍四 TinyFlashDB设计原理五 TinyFlashDB移植和配置六 移植到STM32单片机 已剪辑自 https mp