在学习嵌入式系统的过程中,需要将传感器数据存储起来供用户查询和处理,在裸机操作中一般是将数据存储在数组中,数组的长度是有限的,重启后数据就丢失了,或者是直接将数据存储在内存空间了,这个时候就有可能覆盖了代码空间,为了方便的查询和管理数据,这个时候就可以使用RTT的文件系统。
名称解释
DFS框架
DFS 框架 是 RT-Thread 提供的虚拟文件系统组件,全称为 Device File System,即设备虚拟文件系统。DFS 框架为应用程序提供统一的 POSIX 文件和目录操作接口,如 read、write、poll/select 等。DFS 框架支持多种类型的文件系统,如 FatFS、RomFS、DevFS 等,并提供普通文件、设备文件、网络文件描述符的管理。
1.DFS框架的介绍
rt-thread的文件系统采用了三层结构,分为 POSIX 接口层、虚拟文件系统层和设备抽象层。
顶层:POSIX 文件接口层
这一层是给开发者使用的接口函数层,开发者使用这一层提供的POSIX 文件接口进行文件的相关操
作,不用关心文件系统是如何实现的,也不用关心数据是存放在哪个存储器中。
中间层:文件系统实现层
中间层是各种具体文件系统的实现,这里所说文件系统指各种不同类型的文件系统,比如ELM FatFS
、RomFS、devfs、Yaffs2、Uffs2 等。需要知道的是,不同的文件系统类型是独立于存储设备驱动而
实现的。因此,想要正确地使用这些文件系统,需要把底层存储设备的驱动接口和文件系统对接起来。
底层:存储设备驱动层
这一层是存储设备驱动层,具体的功能是初始化存储设备并向上层提供存储设备的驱动接口。存储设
备的类型可能是SPI Flash,SD卡等。
2.文件系统的移植
我使用的是正点原子的潘多拉STM32L475开发板,这里我就使用这个块开发板做演示,其他的的芯片也是同样的移植方法。
2.1准备工程
2.2移植过程介绍
文件系统的移植主要包括下面几个方面:
- 开启/配置DFS 框架
- 开启/配置指定的文件系统
- 开启存储器外设驱动
2.3在源码中找到对应的BSP
在ENV中输入scons --dist命令,将生产的dist文件夹拷贝到自己的文件夹(路径中不要有中文,不让ENV编译会出错)
2.4 menuconfig 配置文件系统
这一步主要是添加DFS组件和要使用的文件系统
在menuconfig 配置界面依次选择Thread Components → Device virtual file system下图所
示:
打开文件系统
使能 Enable elm-chan fatfs使用elm-chan FatFs文件文件系统
这里需要注意的是还需要进入到elm-chan’s FatFs, Generic FAT Filesystem Module 选项中修改关
于长文件名支持的选项,否则在后面使用文件系统的过程中,创建的文件或者文件夹的名称不能超过
8 个字符。修改方式如下图所示:
设置文件系统扇区大小,表示可处理的最大字节数,这里设置为 4096 字节。设置的值需要根据存储器件手册确定,不能小于存储器件的最小可擦除扇区。
stm32的闪存擦除方式可以是一页一页的擦除也可以全部擦除,参考文档
stm32l479的最小页面为2k,所以设置最小可擦除扇区的大小应大于2048
因为要使用一些C 库函数,所以需要打开libc 功能:
到这一步我们已经将elm FatFS文件系统添加到项目中了。接下来应该添加的是底层的存储器驱动
2.5存储设备初始化
我使用的潘多拉开发板上有片外的FLASH(W25Q128)和SD卡,这里我就用SD做示范。
开启SPI设备驱动
从原理图上我们可以看到SD卡是连接在SPI1上,SD卡片选(SD_CS)连接PC3
在RT-Thread Components → Device Drivers 界面中选中Using SPIBus/Device device drivers 以及Using Serial Flash Universal Driver 选项,
开启spi设备驱动后,还要打开spi1
因为我使用的BSP已经添加了SD卡外设,但这里我不使用这个,是先打开spi设备,在自己把设备注册了。
保存选项并退出,在env 中输入命令scons --target=mdk5 -s 生成mdk5 工程,编译并下载程序。
2.6检查存储设备
我们输入list_device命令可以看到只是显示了spi1总线,没有显示我们添加的spi设备,这是因为我们添加的spi设备并没注册到设备管理器中,这个时候需要我们自己编写程序将设备注册到设备管理器中,并注册为块设备。
新建一个名为drv_spi_tfcard.c的文件添加到Drivers中,代码如下:
#include <rtthread.h>
#include <rtdevice.h>
#include "drv_spi.h"
#include "spi_msd.h"
static int rt_hw_spi1_tfcard(void)
{
__HAL_RCC_GPIOC_CLK_ENABLE();
rt_hw_spi_device_attach("spi1", "spi10", GPIOC, GPIO_PIN_3);
return msd_init("sd0", "spi10");
}
INIT_COMPONENT_EXPORT(rt_hw_spi1_tfcard);
这里的代码是将GPIO_C3注册名为spi10的spi设备,因为文件系统挂载的是块设备,所以msd_init注册一个sd0的块设备,将代码添加到工程后,编译并下载运行后,输入list_device命令后如图显示出了sd0块设备。
到这里我们的存储设备配置就完成了
2.7挂载
这个时候就差挂载设备了,如果sd卡或者是Flash外设是第一次挂载文件系统,要先用mkfs命令格式化。如图:
现在就可以挂载文件系统了,文件系统的挂载指的是将文件系统和具体的存储设备关联起来,并挂载到某个挂载点,这个挂载点即为这个文件系统的根目录。在下面的示例中,我们将 elm FatFS 文件系统和名为 SD储设备关联起来,并且挂载到 /i 文件夹中。
将下面的代码添加到main线程或者是自定义线程中进行文件系统的挂载。
if (dfs_mount("sd0", "/", "elm", 0, 0) == 0)
{
LOG_I("Filesystem initialized!");
}
else
{
LOG_E("Failed to initialize filesystem!");
}
文件系统的应用
文件系统的应用可以参照rt-thread的文档