闪存中的键值对:无文件系统 minINI

  许多嵌入式系统应用需要以持久的方式存储某种数据:校准值、设置或日志信息。对于较少的数据量,使用外部存储器或文件系统是一种过度大材小用。在许多系统中,我使用minINI以“ini-file”的方式存储键值解析,但它需要使用某种文件系统。minINI很棒,效率很高,使获取和存储数据变得非常容易。但对于简单的情况,单个闪存页面或扇区正是我所需要的。相反,直接管理该页面,为什么不在没有文件系统的情况下使用minINI?

  例如,我使用上面的电路板驱动多达4个不同的步进电机和霍尔传感器。我需要存储校准偏移量和电机信息,并且每个电路板的信息可能不同。这些板通过RS-485总线连接,因此每个板都有一个唯一的地址。对于此应用程序,我需要存储键值对(例如,address=0x10)。为此,我使用minINI将数据存储在内部闪存的一页中,因此不需要文件系统。

1、概述

  因为 minINI 处理文件,所以它需要某种文件系统。对于较小的系统或较小的数据量,随着代码大小和数据需求的增加,这增加了复杂性。在本文中,我将介绍一种对 minINI 库进行无文件和无文件系统适配的方法,该方法只需要一个小型且可配置的 RAM 缓冲区以及单个 FLASH 页面或扇区。这样,一个非常通用和用户友好的键值存储可用于小型嵌入式系统,而无需文件系统。
  该实现可在 GitHub 上找到。

2、.ini文件

  .ini文件允许我将数据分组为“部分”和“键值”对。下面是一个示例:

[motor0]
name=split-flap 0
offset=30
x=0[motor1]
offset=32

  使用minINI,我可以读/写这样的值。它具有“只读”模式,在这种模式下,我只能读取数据。

3、minINI接口

  minINI 架构包括一个“粘合”接口。这样,它可以很容易地适应不同的文件系统。以下是 FatFS 的“粘合”实现:

#define INI_FILETYPE    FIL
#define ini_openread(filename,file)   (f_open((file), (filename), FA_READ+FA_OPEN_EXISTING) == FR_OK)
#define ini_openwrite(filename,file)  (f_open((file), (filename), FA_WRITE+FA_CREATE_ALWAYS) == FR_OK)
#define ini_close(file)               (f_close(file) == FR_OK)
#define ini_read(buffer,size,file)    f_gets((buffer), (size),(file))
#define ini_write(buffer,file)        f_puts((buffer), (file))
#define ini_remove(filename)          (f_unlink(filename) == FR_OK)#define INI_FILEPOS                   unsigned long//DWORD
#define ini_tell(file,pos)            (*(pos) = f_tell((file)))
#define ini_seek(file,pos)            (f_lseek((file), *(pos)) == FR_OK)

4、FLASH接口

  我们的想法是添加一个新的“粘合”,它不需要文件系统。相反,它直接读取和写入闪存,并模仿文件系统。
  这有一个限制:仅支持单个“ini文件”。该限制可以很容易地扩展到支持多个“文件”,但我真的没有看到这种需求,至少在我的应用程序中没有。

5、配置

  配置是使用配置宏(请参见软件配置的不同方式)。下面是一个示例配置:

  这样就可以配置闪存。数据大小宏用于限制数据大小,以减少用于写入闪存的内存缓冲区的数量。
需要从可用于链接器的闪存数量中减少/排除已使用的闪存,否则应用程序也可能使用它。以下是如何使用恩智浦MCUXpresso IDE从内存映射中减少内存:

6、命令行

  该实现包括一个命令行/shell 接口。
  低于只读配置的状态:

  “McuMinINI”显示minINI的“核心”信息,而“ini”组用于闪存实现它。
  使用命令行界面,可以检查或修改数据:

7、用法

  将键值对与 minINI 结合使用非常简单:我可以查询整数、布尔值、浮点值或字符串值。下面是获取设备存储地址的示例:

#define NVMC_MININI_FILE_NAME         "settings.ini" /* 'file' name used *//* RS-485 bus settings */
#define NVMC_MININI_SECTION_RS485     "rs485"
#define NVMC_MININI_KEY_RS485_ADDR    "addr" /* long value: RS-485 address */
...
*addr = McuMinINI_ini_getl(NVMC_MININI_SECTION_RS485, NVMC_MININI_KEY_RS485_ADDR, 0x1, NVMC_MININI_FILE_NAME);

  我真正喜欢minINI的是我可以提供默认值(在上面的示例中0x1):如果部分/键不存在,它将返回我指定的默认值:这样默认值就不需要配置区域中的任何空间。
存储值类似于下面的示例:

McuMinINI_ini_putl(NVMC_MININI_SECTION_RS485, NVMC_MININI_KEY_RS485_ADDR, addr, NVMC_MININI_FILE_NAME);

8、内存要求

  当然,每个功能都会带来一些成本。但在这种情况下,我认为它真的是最小的。
  为了在闪存中存储数据,它至少需要一个扇区或闪存页。其大小取决于所使用的系统,例如1 kByte(LPC845)或2 KByte(Kinetis K22),具体取决于微控制器。大小配置为McuMinINI_CONFIG_FLASH_NVM_BLOCK_SIZE。
  对于写入访问,它需要一个RAM缓冲区来备份和存储来自FLASH的数据。该金额McuMinINI_CONFIG_FLASH_NVM_MAX_DATA_SIZE配置。最小值为 64 个字节。根据要存储的数据量,128 或 256 可能更合理。对于只读访问,缓冲区量为零。根据所使用的微控制器和SDK,需要闪存驱动程序的设备句柄:例如,在Kinetis上,这需要额外的100字节。对于像LP845这样的其他产品,不需要手柄,因为ROM例程用于闪存编程。
  在 Kinetis 上,只读配置会增加大约 6 KB 的代码大小(-O0,无优化),而使其读写会增加额外的 3 KB (-O0)。添加shell支持会增加额外的1 KB:因此这意味着最多需要10 KB的闪存,在启用优化后降至约6 KB。到目前为止,还不到完整的文件系统支持,很容易是30-50 KB的闪存。

9、总结

  有了这个用于minINI的附加粘合端口,可以在没有文件系统的情况下使用它。这使得它适用于较小的嵌入式系统。它支持只读和读写数据存储。它使用直接闪存读/写,只有在读写配置中,它才需要一个可配置的RAM缓冲区来写入或扩展数据。这样,就可以轻松地将“键值”对存储添加到任何嵌入式系统,而闪存的成本不到10 KB。
  您可以在GitHub上的McuLib中找到该实现。

链接

  • minINI by Compuphase: https://github.com/compuphase/minIni
  • minINI: https://www.compuphase.com/minini.htm
  • Using FatFS and MinINI with the NXP LPC55S16 EVK
  • FatFS, MinIni, Shell and FreeRTOS for the NXP K22FN512
  • Different Ways of Software Configuration
  • Configuration Data: Using the Internal FLASH instead of an external EEPROM
  • McuOnEclipse Library on GitHub: https://github.com/ErichStyger/McuOnEclipseLibrary

英文原文​:Key-Value pairs in FLASH Memory: file-system-less minINI | MCU on Eclipse

欢迎关注:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/499302.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

外设驱动库开发笔记41:ADS1256 ADC驱动

我们经常会碰到多通道AD采集的需求,有时候甚至需要高精度的ADC器件。本篇我们将来设计并实现ADS1256模数转换器的驱动。并简单讨论该驱动使用方式。 1、功能概述 ADS1256是TI公司推出的一款低噪声高分辨率的24位Sigma-Delta(E-v)模数转换器(ADC)。E-vADC与传统的逐…

PID参数自整定库之一:继电反馈整定算法

在前述的篇章中,我们实现了PID控制器并在后续对其进行了改进。但作为经典PID控制器还存在PID参数整定的问题。通常我们可以采取人工整定的办法,但人工整定涉及到比较专业的知识,而且找到合适的参数本身也不是一件容易的事,所以人们…

外设驱动库开发笔记42:DAC8552 DAC驱动

模拟信号输出是经常会遇到的应用需求,解决的办法应多种,但我们使用最多的还是数模转换。对于不同的数模转换器我们需要为其编写适用的驱动程序,在这一篇中我们就来考虑如何实现DAC8552高精度模数转换器的驱动程序。 1、功能概述 该DAC8552是…

软件设计开发笔记2:基于QT设计串口调试工具

串口通信是我们经常会遇到的问题。很多时候当我们设计一个串口应用时,我们希望有一个简便的、可视的方式来验证它。这一篇中我们就来基于QT设计一个串口调试工具。 1、概述 在开始软件设计之前,我们来简略地分析一下这样一个小软件其要包含的主要内容有…

外设驱动库开发笔记43:GPIO模拟SPI驱动

SPI总线是我们常用的串行设备接口,一般情况下我们都会适应硬件SPI接口,但有些时候当硬件端口不足时,我们也希望可以使用软件来模拟SPI硬件接口,特别是要求不是很高的时候。在这一篇中我们将来讨论如何使用GPIO和软件来模拟SPI通讯…

外设驱动库开发笔记44:DDC114 ADC驱动

在产品设计过程中,很多时候都会用到ADC器件,而在一些特殊场合还需要一些特别的ADC器件。我们在这篇中将讨论常用于医疗器件方面的,DDC114这款电流输入ADC,并为其设计一个驱动程序。 1、功能概述 模数转换器DDC114是一款电流输入型…

PID控制器改进笔记之七:改进PID控制器之防超调设定

我们已经设计了PID控制器,并根据实际使用的情况对器进行了诸多的改进。在这一篇中我们将讨论如何改进PID控制器超调的问题。 1、问题提出 在前面的文章中,我们曾推导过增量式PID控制器的公式,并且对其进行了离散化以适用于程序实现&#xff…

软件设计开发笔记3:基于QT的Modbus RTU主站

Modbus是一种常见的工业系统通讯协议。在我们的设计开发工作中经常使用到它。在这一篇中我们将简单实现一个基于QT的Modbus RTU主站上位工具。 1、概述 Modbus RTU主站应用很常见,有一些是通用的,有一些是专用的。而这里我们希望实现一个主要针对我们的…

外设驱动库开发笔记45:MS4515DO压力传感器驱动

很多时候我们需要检测流量和压力这些参数,比如我们要检测大气压,或者通过测量差压来获得输送流体的流量等,都需要用到压力传感器。这一篇我们就来讨论MS4515DO压力传感器的数据获取。 1、功能概述 MS4515DO是TE公司推出的一款基于PCB安装的小…

外设驱动库开发笔记48:MCP4725单通道DAC驱动

在产品设计过程中,我们经常会遇到数模转换的应用需求。在本篇种我们就来讨论一下MCP4725单通道数模转换器的驱动设计与实现。 1、功能概述 MCP4725是一个低功耗,高精度,单通道,12位缓冲电压输出数字到模拟转换器(DAC)与非易失性存…

如何确保不使用动态内存

在许多嵌入式应用程序中,内存分配必须是静态的,而不是动态的。意味着在应用程序中不应使用对malloc()或free()等内容的调用,因为它们可能会在运行时失败(内存不足、堆碎片)。 但是,当与第三方库甚至 C/C 标…

go 单元测试 testing 打印输出_2020,你需掌握go 单元测试进阶篇

本文说明go语言自带的测试框架未提供或者未方便地提供的测试方案,主要是用于解决写单元测试中比较头痛的依赖问题。也就是伪造模式,经典的伪造模式有桩对象(stub),模拟对象(mock)和伪对象(fake)。比较幸运的是,社区有丰富的第三方测试框架支持…

一文读懂Git工作流

Git是目前最流行的代码管理工具,相信大家也都是在用Git来管理自己团队的源代码。 团队一般为了规范开发,保持良好的代码提交记录以及维护 Git 分支结构清晰,方便后续维护等,都会迫切需要一个比较规范的 Git 工作流。 本文就是在…

xbox360fsd更新游戏封面_游戏类短视频创作指南

一.起步阶段1.内容发布垂直,整体风格一致,选定一个品类的游戏内容风格持续更新注意:冷启动时期不要频繁更换游戏类型2.账号IP化 根据自身风格特色打造独特的风格账号。有利延长账号生命周期,提升粉丝转化率。搞笑、中二…

开发者们都在关注的网站

开发者们都在关注的网站 😉 综合类(5个) 1、GitHub 全球最大的编程开源社区,很多优秀的开源项目都在上边,不知道这个都不要说自己是程序员😂 访问地址:https://github.com 2、CSDN 全球最大中…

ios framework 调用第三方 framework_Python基础:标准库和常用的第三方库

Python的标准库有:名称作用datetime为日期和时间处理同时提供了简单和复杂的方法。zlib直接支持通用的数据打包和压缩格式:zlib,gzip,bz2,zipfile,以及 tarfile。random提供了生成随机数的工具。math为浮点…

作图神器ProcessOn - 免费好用

因工作需要,我经常需要花一些流程图,时序图,架构图什么的,之前使用的Windows系统,大部分情况下就用的Visio来画图。后来为了工作方便,换成了Mac电脑,结果发现Mac上没有Visio,然后就在…

三电平igbt死区时间计算_基于大功率三电平IGBT模块并联的参考设计

当前的可再生能源行业中,光伏和风力发电均面临着补贴逐步退坡,平价上网时代即将到来的挑战。为应对这一挑战,光伏逆变器和风力变流器厂家研发的新品单机功率越来越高,以取得更低的单位功率成本。市场上1.5MW的集中式光伏逆变器和3…

手把手教你搭建开发环境之Java开发

大家好呀,从今天开始,我们的手把手系列教程就正式开始啦。 如果你觉得本文对你有一些帮助,欢迎大家关注、点赞、分享给需要的小伙伴们,谢谢大家啦。 前言 Java虽然是一个比较老的语言,但到现在依然充满了活力&#x…

opc服务器组态文件已写保护_远程组态软件不仅方便了PLC无线远程监控,也大大降低了工程成本...

远程组态软件不仅方便了PLC无线远程监控,也大大降低了工程成本组态软件远程监控1.本地上位SCADA系统采集分布各地现场PLC等设备运行的数据,并可以下发控制指令;2.提供稳定的OPC接口服务,常年稳定运行,规模可达10万数据…