跳转至

键值对存储(nvm)

一、简介

nvm:非易失性存储器(英语:non-volatile memory,缩写为 NVM)是指当电流关掉后,所存储的数据不会消失的电脑存储器,利用文件系统实现的一种非易失性参数存储管理模块。

典型的应用场景为:小数据量的简单键值对参数。不适合大容量数据的存储管理,如果数据量超过 10K,建议直接使用 io 接口操作文件来管理。

二、演示功能概述

本教程教你如何用 Air724 开发板,用 nvm API 对小数据量的简单键值对参数读写,并通过日志观察实验结果。

三、准备硬件环境

3.1 开发板准备

使用 EVB_Air724 开发板,如下图所示:

淘宝购买链接:Air724UG-NFM 开发板淘宝购买链接

此开发板的详细使用说明参考:Air724UG 产品手册 中的《 EVB_Air724UG_AXX 开发板使用说明》,写这篇文章时最新版本的使用说明为:《EVB_Air724UG_A14 开发板使用说明》;开发板使用过程中遇到任何问题,可以直接参考这份使用说明文档。

api:https://doc.openluat.com/wiki/21?wiki_page_id=2068

3.2 数据通信线

USB 数据线一根(micro USB)。

3.3 PC 电脑

WIN7 以及以上版本的 WINDOWS 系统。

3.4 SIM 卡

中国大陆环境下,可以上网的 SIM 卡。一般来说,使用移动,电信,联通的物联网卡或者手机卡都行。

3.5 组装硬件环境

usb 数据线插入 USB 口,另一端与电脑相连,拨码开关全部拨到 ON,串口切换开关选择 UART1,USB 供电的 4V 对应开关拨至 ON 档,SIM 卡放到 SIM 卡槽中锁紧,如下图所示。

四、准备软件环境

4.1 下载调试工具

使用说明参考:Luatools 下载和详细使用

4.2 源码及固件

1.底层 core 下载

下载底层固件,并解压

链接:https://docs.openluat.com/air724ug/luatos/firmware/

如下图所示,红框的是我们要使用到的。

2.本教程使用的 demo:

https://gitee.com/openLuat/LuatOS-Air724UG/tree/master/script_LuaTask/demo/nvm

4.3 下载固件和脚本到开发板中

打开 Luatools,开发板上电开机,如开机成功 Luatools 会打印如下信息。

点击项目管理测试选项。

进入管理界面,如下图所示。

  • 点击选择文件,选择底层固件,我的文件放在 D:\luatOS\Air724 路径中

  • 点击增加脚本或资源文件,选择 之前下载的程序源码,如下图所示。

  • 点击下载底层和脚本,下载完成如下图所示。

五、代码示例介绍

5.1 API 说明

本文用到的接口函数不做详细介绍,可通过点击右侧链接查看具体介绍:nvm API

5.2 testNvm.lua 代码

系统启动后等待一定时间,确保异步操作有足够的时间完成。

nvm.sett() 用于将数据存储到非易失性存储器中,数据即使系统重启也能保存。

nvm.gett() 用于从非易失性存储器中读取数据。输出日志。

--- 模块功能:参数存储功能测试.
-- @author openLuat
-- @module nvm.testNvm
-- @license MIT
-- @copyright openLuat
-- @release 2018.03.27

module(...,package.seeall)

require"config"
require"nvm"

nvm.init("config.lua")

nvm.set("strPara","str2")
nvm.set("numPara",2)
nvm.set("boolPara",false)
nvm.set("tablePara",{"item2-1","item2-2","item2-3"})

log.info("testNvm.strPara",nvm.get("strPara"))
log.info("testNvm.numPara",nvm.get("numPara"))
log.info("testNvm.boolPara",nvm.get("boolPara"))
local tableValue = nvm.get("tablePara")
log.info("testNvm.tablePara",tableValue[1],tableValue[2],tableValue[3])

sys.taskInit(function()
    sys.wait(3000)
    nvm.sett("testtable","chinese",100)
    sys.wait(1000)
    log.info("testNvm.testtable",nvm.gett("testtable","chinese"))
end)

5.3 main.lua 代码

本代码为主程序脚本,系统启动后首先会对 4G 网络进行配置,等待网络连接成功,然后加载测试模块。

5.4 config.lua 代码

参数文件名为 config.lua,本地烧录时清除已有的参数。

六、开机调试

6.1 开发板开机

连接好硬件并下载固件后,启动 Luatools 软件,系统运行信息将显示在界面中。红框中为开发板连接到 PC 机后正常打印的信息,如下图所示。

6.2 功能调试

对出各种键,并且日志打印对应的数值。

七、常见问题

7.1 nvm 适用于什么场景?

nvm 每次更新参数,保存到参数文件中时,会把所有参数拼接在一起,然后执行一次全量写文件的动作;此拼接操作消耗内存较多,如果数据量很大,需要的内存就很大,在系统可用内存紧张的情况下,很容易出现内存不足,从而导致参数更新失败,严重情况下还会造成系统重启。 因此,nvm 仅适用于小数据量的简单键值对参数;不适用于大容量数据的存储管理,如果数据量超过 10KB【仅仅为经验值,实际能够存储的数据量和系统运行过程中的动态可用内存有关:可用内存越小,允许存储的数据量就越少;可用内存越大,允许存储的数据量就越多,但是也不建议超过 10KB】,建议参考 fs 的 demo 直接使用 io 接口操作文件来管理。

7.2 本地烧录时会清除原有的 para.lua 吗?

原有的 para.lua 是在 nvm.init(“config.lua”,true)时创建的,则不会清除,原有的 para.lua 是在 nvm.init(“config.lua”)时创建的,则会清除。

7.3 fota 远程升级时,会清除原有的 para.lua 吗?

默认不会 如果需要清除,根据产品的业务逻辑,在合适的时间点,调用 nvm.restore()恢复出厂设置即可。

7.4 软件版本升级时,可以在 config.lua 中增加新的参数吗?

可以,需要执行一次初始化动作才会生效,一般是直接重启执行初始化

7.5 软件版本升级时,可以在 config.lua 中删除旧的参数吗?

可以,但是操作起来比较复杂,不建议这样做 如果旧的参数没用了,可以在 config.lua 中一直保留;脚本代码不要再读写这些参数就行了。

7.6 程序运行过程中,可以使用 nvm.set 接口增加新的参数吗?

可以,新增的参数,在恢复出厂设置后会被清除,因为 config.lua 中没有此参数。

7.7 程序运行过程中,可以使用 nvm.set 接口删除已有的参数吗?

可以,将某个参数设置为 nil 就相当于删除。 删除的参数,在恢复出厂设置后会还原为 config.lua 中的默认值,因为 config.lua 中存在此参数。

7.8 读写操作过程中,掉电会丢失数据吗?

nvm 有备份机制,如果掉电时正在写参数,可能会造成正在写入的参数数据不生效,下次开机会恢复为上次正常写入的数据,不会导致数据内容出错 如果掉电时正在读参数,不会对参数数据造成任何影响;因为读取的是内存中的数据。

7.9 nvm.set 接口可以写多少次?

nvm 通过文件接口写 flash,具有擦写均衡机制 flash 可以完全擦写至少 10 万次 假设通过 rtos.get_fs_free_size()获取到的文件系统剩余空间为 512K 字节,nvm 参数文件总大小为 1K 字节,因为 nvm 参数文件还存在一个备份文件,所以写 256 次可以完全擦写一次文件系统剩余空间。允许擦写的总次数理论值就是 256*10 万次。