LPC5500系列Flash变身微型数据库-移植FlashDB组件
LPC5500系列是NXP推出的基于Arm® Cortex® -M33的全新系列MCU,内嵌最高可达640KB的Flash存储空间,其内部Flash由多个页组成,每页大小为512字节,可以单独擦除/编程。用户的可执行程序从FLASH的起始地址0x0000_0000开始存放,其擦写寿命可达10W次。
闪存控制器在读数据的时候,支持预取缓冲器加速。
如果用户的程序代码没有占满全部Flash空间,那我们可以利用剩下的Flash空间来当数据存储器使用,这些空间可以存储一些用户配置,运行记录等,同时对于存储数据量不大的情况,可以省去外部存储芯片,节约成本。
但是这类应用却暗藏小玄机:Flash不比EEPROM,它的擦写寿命有限,即使是LPC5500系列的可以达到擦写10W次的Flash,还是比不过EEPROM的擦写寿命,所以这就需要磨损平衡算法。
同时,如果用户正在调用Flash函数进行擦写时掉电,则还需要额外的软件逻辑来进行掉电保护。这些问题其实是非常通用的需求,所以必然就会有通用的开源解决方案。
这篇文章就为大家介绍一个网上很流行的,适用于MCU的Flash微型数据库软件—FlashDB。
LPC5500系列Flash介绍
所有LPC5500系列的Flash的扇区(Sector)大小为32KB(可一次擦除32KB)
所有LPC5500系列的Flash的页(Page)大小为512字节(一次擦除/编程的最小单位)
下面这张表是数据手册中的Flash重要性能参数:
从表中可以看到,LPC55S69的Flash擦写寿命均可达到10W次,尤其出色的是Flash擦写时间,写一个页(512字节)的时间只有1ms。擦一个页(512)字节的时间只有2ms。这两项指标超过市面大部分同类产品。
LPC5500系列的SDK API设计非常统一,型号间的迁移成本基本为零。所以这篇文章不再区分LPC5500系列中的具体型号,并以最早的LPC55S69作为实验平台。
如果您想迁移到LPC5500的其他系列上,只要更换SDK即可,SDK中的API函数几乎都是一样的。
FlashDB介绍
FlashDB是网友Armink,针对小型嵌入式设备开发的一款超轻量级的嵌入式数据库,专注于提供嵌入式产品的数据存储方案。
与传统的基于文件系统的数据库不同,FlashDB 结合了Flash的特性,具有较强的性能及可靠性。并在保证极低的资源占用前提下,尽可能延长Flash使用寿命。它是之前的开源项目EasyFlash的全新升级版本。
地址:https://github.com/armink/FlashDB
文档:https://armink.github.io/FlashDB/#/
FlashDB 提供两种数据库模式:
键值数据库 :是一种非关系数据库,它将数据存储为键值(Key-Value)对集合,其中键作为唯一标识符。KVDB 操作简洁,可扩展性强。
时序数据库 :时间序列数据库(Time Series Database, 简称 TSDB),它将数据按照时间顺序存储 。TSDB具有时间戳,数据存储量大,插入及查询性能高。
关于FlashDB的介绍在FlashDB的中文文档页上有非常全面的描述,本文就不再赘述了。下面我们正式开始移植工作。
FlashDB移植
准备工作
硬件:LPCXpresso55S69EVK
软件:Keil IDE
SDK:从NXP官网 (https://mcuxpresso.nxp.com/en/dashboard)下载LPC55S69的SDK 包:SDK_2.9.0_LPCXpresso55S69
下载FlashDB,添加源码到工程树
在https://github.com/armink/FlashDB上下载FlashDB 源代码。
FlashDB的源代码结构很简单,只需要把src/port添加到工程路径中,把inc头文件添加到IDE搜索路径中即可。
如下图所示添加源文件(和 example例程):
其中fal_flash_lpc55s69.c是自己创建的文件,负责对接FlashDB的底层Flash接口。
这里提一下,FlashDB底层Flash对接依赖另一个叫做fal的中间件。也就是薄薄的一层,把Flash抽象封装一下,关于fal的介绍在这里:
http://packages.rt-thread.org/detail.html?package=fal
对接底层Flash操作接口
FlashDB(fal)的底层Flash对接接口非常简单。用户只需要根据自己的Flash情况分别实现 init, read, write, erase这些操作函数即可,API说明如下图:
对于LPC5500系列Flash操作不熟悉的朋友可以参见SDK中的Flash操作example:
\lpcxpresso55s69\driver_examples\flashiap
1,Init 函数
定义全局的Flash操作句柄,并在init中调用flash初始化函数FLASH_Init。
2,read函数
注意这里是使用专门的API: FLASH_Read函数来读取Flash数据,没有用CPU直接寻址访问。这样可避免CPU直接读取空Flash造成HardFault的问题。
3,Erase函数
没啥可说的,常规操作:
4,Write函数
写函数稍微有点复杂,因为LPC的写入最小单位和擦除最小单位同为页(512字节)。所以写之前要先判断需要写的页是不是已经被擦除的,如果不是的话,需要先把原来的数据读到RAM中,然后修改数据,然后擦除这个页再写入:
以上就是Flash底层对接的全部内容了。
测试
将底层对接好后,在main中编写一些简单的测试例程,可以参见FlashDB中的example目录中的文件。
这里我们只测试KV(key-value)型数据库的功能。
在main中,我们定义了boot_count作为每次启动的计数器,每次复位后,该值从数据库中读取,然后自加1,并存入数据库。
在main中,我们初始化FlashDB组件,对接底层Flash并且运行FlashDB自带的KV测试测试例程:
加入这些代码后,重新编译工程,并且下载运行:
每次复位后,串口都会打印FlashDB example的log信息。可以看到boot_count的值随着每次复位都递增,验证了FlashDB移植是没有问题的。
总结
这篇小文介绍了LPC5500系列Flash的参数性能以及如何移植开源嵌入式数据库软件FlashDB,希望对大家有所帮助。
|