项目中使用到了flash,而Nordic为操作flash准备了很丰富的工具,包括fstorage 和fds,两者都是异步返回真实操作结果的,其中fds依赖于fstorage,是一个简单易用的文件系统。
使用fds之前一般都需要初始化一下,包括使用 fds_register 函数来注册一个事件回调,用来获得异步操作的结果。然后还需要使用 fds_init 函数进行初始化,完了之后就可以进行各种文件操作了。
为了与物理地址隔离,fds使用了虚拟页的概念。使用fds之前需要配置好一个虚拟页分配多大空间,必须是物理页的空间(一般是4096 byte)的整数倍。然后还需要设置总共使用多少个虚拟页,可用的虚拟页是分配的数量减一,因为其中有一页被用作GC的缓存。
这里从fds_init 开始追溯。
为了防止反复初始化,fds_init 会首先检查是否已经初始化过了,如果已经做过初始化操作,则直接返回FDS_SUCCESS。从这里可以看出,fds_init函数可以反复调用,来确保自己的模块在使用fds的时候将其正确的初始化。
fds依赖于fstorage,任意的fds操作最终都会转化为fstorage操作,这里首先需要有一个fstorage的句柄。
NRF_FSTORAGE_DEF(nrf_fstorage_t m_fs) =
{
// The flash area boundaries are set in fds_init().
.evt_handler = fs_event_handler,
};
其中,fs_event_handler为fstorage的异步回调函数。
if (m_flags.initialized)
{
// No initialization is necessary. Notify the application immediately.
event_send(&evt_success);
return FDS_SUCCESS;
}
if (nrf_atomic_flag_set_fetch(&m_flags.initializing))
{
// If we were already initializing, return.
return FDS_SUCCESS;
}
接下来的一个操作是flash_subsystem_init,字面上无法理解是干嘛的。进去一看,该函数主要有两个操作,一个是flash_bounds_set,然后是nrf_fstorage_init。
因为fds依赖于fstorage,因此fds的初始化操作必然要进行fstorage的初始化。
然后从函数名可以知道flash_bounds_set是确定如何分配fds的真实页面地址和边界,这里隐含的信息就是,fds所分配的真实页面是一块连续的区域。
flash_bounds_set函数主要内容如下: