FDS,全称闪存数据存储器,用于访问芯片内部的闪存。当您需要在闪存中存储数据,或在闪存中读取用户数据,或在闪存中更新或删除数据时,FDS模块是您的最佳选择。FDS通过文件和记录的方式组织Flash数据,也就是说真实数据放在一个记录中,多个记录组成一个文件。根据应用需要,整个系统可以只有一个文件,也可以包含多个文件。文件用文件ID标记,2字节(注意:不能取0xFFFF)。一个或多个记录可以放在一个文件下。记录由记录键标记,记录键也是2字节长(注意:值不能是0x0000)。这里需要注意的是,同一个文件下的两个或多个记录的关键字可以是相同的。例如,我们可以建立以下文件系统:文件1包含两个记录,文件2包含三个记录,文件2包含两个关键字为0x0003的记录。
注意:如果能保证一个文件下所有记录的键都不一样,文件系统会变得更加简洁,尤其是查找记录时,只返回一条记录,可以简化很多应用逻辑。如前所述,这不是强制要求:记录在同一文件中的密钥可以是相同的。
FDS用法
一般来说,FDS模块的使用如下:
1)要修改FDS的默认配置参数,如总共分配多少个Flash空房间(默认只为用户分配8kB Flash空房间),请修改sdk_config.h文件中的以下默认配置项:
2)通过fds_register注册fds事件回调函数,通过fds_init初始化FDS模块。FDS模块的初始化、记录写入、记录更新、记录删除和垃圾收集是异步的。也就是说,调用这些FDS操作的API只是将相应的操作放入队列中,并立即返回(队列大小由上面提到的FDS_OP_QUEUE_SIZE控制),真实的Flash操作结果通过事件回调函数通知给你。注意:FDS模块可以初始化几次。示例代码如下:
3)通过fds_record_write新建一条记录,即写一条记录。请注意,在写入记录时,您必须确保输入参数是全局变量或静态的局部变量。建议使用全局变量!记录关键字可以重复,因此连续调用同一个fds_record_write两次将生成两个具有相同关键字的记录。如前所述,fds_record_write是异步的,所以它的返回值是success,只表示操作排队成功,真实的flash操作结果由前面注册的fds_evt_handler通知。示例代码如下:
4)通过fds_record_open读取记录。读取前必须找到记录,这是通过fds_record_find实现的。由于同一个文件可以包含多个具有相同关键字的记录,所以可以通过多次调用同一个fds_record_find来找到所有相关的记录。示例代码如下:
5)操作记录,如fds_record_update、fds_record_delete等。,对于更新和删除操作,在更新或删除之前必须先找到相应的记录。fds_record_delete并不真正删除该记录,而是将该记录标记为无效。fds_record_update实际上包括两个步骤:首先找到以前的记录,然后将其标记为无效(即删除操作),然后写入新的记录。请记住:删除不会回收闪存空,但无效记录仍会占用闪存空,这些无效记录占用的闪存空只能在垃圾收集(fds_gc)后重新用于新记录。请注意,fds_record_find只会查找有效记录,不会向用户返回无效记录。另外,fds_record_ update和fds_record_delete是异步的,所以它们的返回值是success,只表示操作排队成功,真实的flash操作结果由之前注册的fds_evt_handler通知。示例代码如下:
6)当Flash不够用,即FDS写记录或更新记录并返回错误FDS_ERR_NO_SPACE_IN_FLASH时,请调用垃圾收集函数fds_gc进行垃圾收集。Fds_gc是一个非常耗时的操作过程(请确保操作过程中没有断电,否则闪存行为未知)。它会逐页操作,然后将该页中的有效记录复制到交换页,然后擦除该页,标记为交换页,上一个交换页变成数据页,以此类推,直到所有页都被回收。只有在fds_gc之后,才会释放之前无效记录占用的Flash空,然后会有额外的Flash空供用户操作。
建议您直接参考SDK附带的fds示例来编写自己的fds应用程序代码。SDK附带的fds示例的目录是:SDK安装目录examplesperipheralflash _ fds(注意:SDK14之后还有fds示例)
了解FDS
作为上层模块,FDS通过调用fstorage API实现其功能,fsstorage通过调用NVMC外设驱动或软设备Flash访问API实现操作Flash的目的。呼叫图如下所示:
当softdevice存在时,建议使用nrf_fstorage_sd后端;没有softdevice时使用nrf _ fstorage _ nvmc后端。
根据是否有引导程序,FDS将操作不同的闪存空房间,如下所示:
当您通过FDS将数据写入闪存时,除了数据本身,FDS还会向该记录添加额外的信息:标题,闪存中记录的完整格式如下:
因此,在计算记录占用的总闪存空时,请记住添加每条记录的标题(3个字)。
关于FDS使用的常见问题
使用FDS模块时,您经常会遇到以下问题:
FDS不支持掉电保护,所以在Flash操作过程中出现了掉电,FDS行为将未知OTA的时候,新固件的FDS page数目一定要等于老固件的FDS page数,否则将出现不可知行为fds_record_write或者fds_record_update后,强烈建议回读该记录,以确保记录的确write或者update成功忘了给参数清0。Nordic提供的API输入参数很多都是结构体变量,这些变量使用之前,记得一定要通过memset先清0。如果忘了清0,就会出现一些匪夷所思的现象。 fds_record_desc_t desc; //= {0}; //错误,忘了清0 fds_find_token_t tok; //= {0}; //错误,忘了清0忘了使用全局变量或者静态局部变量。因为write和update操作都是异步的,所以record.data.p_data必须指向全局变量或者静态局部变量,以保证Flash操作过程中p_data指向的内容不会更改。变量起始地址必须字对齐。Flash操作是以word为单位的,所以要求write和update操作的p_data指向的变量的起始地址必须word对齐,大家可以使用伪汇编指令“__ALIGN(sizeof(uint32_t))”来保证该变量起始地址是word对齐的。Update或者delete之前必须先find。fds_record_update或者fds_record_delete会用到参数deor,这个deor必须是通过fds_record_find返回的。忘了使用fds_gc导致Flash fatal error或者其他奇奇怪怪的问题。当write或者update报FDS_ERR_NO_SPACE_IN_FLASH错误时,记得一定要调用fds_gc。或者当delete record或者update record达到一定次数后,主动调用fds_gc。或者通过查看fds_stat得到dirty record数目达到某个值后,主动调用fds_gc。SDK已知问题。每个版本SDK都有或多或少的问题,这些问题都可以在Nordic devzone上查到。比如SDK12.2.0 fds_gc在某些情况下,就会有问题,请参考: https://devzone.nordicsemi.com/question/93241/what-are-sdk-12x0-known-issues/,所以,一般建议大家使用最新版SDK,最新版SDK会把之前发现的问题都修复掉,它的稳定性和可靠性都是最高的。FDS不支持掉电保护,所以在FDS操作过程中,尤其是垃圾回收过程中,发生了掉电,那么Flash内容将变得不可靠。所以强烈建议大家:在每一次write或者update之后,都把相应记录读出来,跟原始内容进行比对,以确保记录真的写成功或者更新成功了。有关FDS用法的更多信息,请点击阅读原文。
1.《fds文件 【Nordic 博文分享系列】 FDS用法及常见问题 - nRF5 SDK模块系列一》援引自互联网,旨在传递更多网络信息知识,仅代表作者本人观点,与本网站无关,侵删请联系页脚下方联系方式。
2.《fds文件 【Nordic 博文分享系列】 FDS用法及常见问题 - nRF5 SDK模块系列一》仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证。
3.文章转载时请保留本站内容来源地址,https://www.lu-xu.com/yule/1065390.html