GD32(5)文件系统

文件系统介绍

       文件系统:操作系统用于明确存储设备(常见的是磁盘,也有基于NAND Flash的固态硬盘)或分区上的文件的方法和数据结构;即在存储设备上组织文件的方法。操作系统中负责管理和存储文件信息的软件机构称为文件管理系统,简称文件系统。

       简单来说,就是组织存储设备中的数据,使其不再成为分立,无意义的数据,而是组合起来形成一个个文件,以最简单的计算机为例,本质上显示在屏幕上的文件夹、文件在磁盘上都是1和0,但通过组织则形成了docx、exe等文件形式,并且不会和其它文件混淆,这就是文件系统的作用。

       Windows下常见的文件系统格式包括FAT32、NTFS、exFAT等,下面主要介绍FatFs文件系统。

       FatFs文件系统是一种面向小型嵌入式系统的通用FAT文件系统。该系统完全由ANSIC语言(即标准C语言)编写并且完全独立于底层的I/O介质,可以很容易地移植到其他的处理器。FatFs文件系统支持多个存储媒介,具有独立的缓冲区,可以读写多个文件,并且该系统特别根据8位和16位微控制器进行了优化。文件系统实际上有点类似NAND Flash管理中的FTL层和内存管理中的内存管理表,当然文件系统的实际内容更加复杂,为了方便使用,一般只需要为其提供相应的接口函数,即可使用文件系统。

FatFs文件系统组成

       下面以SD卡作为存储设备,介绍基于SD卡文件系统的使用。

       从文件系统的使用上来说,文件系统实际上就是用于管理存储块的程序,该程序包括但不限于ff.c、diskio.c等文件,这些文件组成了FatFs组件,并为应用程序提供控制文件的函数

       文件系统向上提供控制函数的同时,向下通过相应函数完成对存储块的读写,这部分读写函数则需要用户提供,作为接口,如下图的sd_block_read函数即是向SD卡写入数据的函数。

在这里插入图片描述

       关于FatFs组件的各个文件描述如下:

在这里插入图片描述

文件系统存储

       与内存管理中的内存管理表一样,文件系统同样会形成1个表来管理各个文件,当然这里的表不再是简单的数组,而是在存储器中形成文件分配表以及目录,如下图所示,文件分配表用于记录各个文件的存储位置。目录用于记录文件系统中各个文件的开始簇和文件大小等文件信息。A.TXT、B.TXT和C.TXT等为文件。

       其中“簇”是文件系统操作的最小单位,每个文件至少占用一个簇的空间。簇的大小在格式化时被确定,“簇”越小,读写速度越慢;“簇”越大,读写速度越快,但对于小文件来说存在浪费空间的问题(所以特殊情况下需要对“簇”的大小进行权衡)。FatFs文件系统通常使用的“簇”的大小为4KB。

在这里插入图片描述

文件分配表

       文件分配表的内容如下图所示,用于记录各个文件的存储位置,其中第一行为对应的簇号,第二行为该文件存储的下一簇的簇号,当第二行为FF时表示对应文件存储已经结束。对照上图可得,簇号为1的存储空间存放着目录,簇号2 ~ 11存储着1个文件,簇号12 ~ 15、66 ~ 86同,而簇号87 ~ 99则未用于存储(第二行为00)。

在这里插入图片描述

目录

       目录的内容如下图所示,用于记录文件系统中各个文件的开始簇和文件大小等文件信息。以下图为例,每个文件都需要100字节的空间存储相应的信息,即0.1KB。

在这里插入图片描述

文件系统移植步骤

       没错,本文介绍的是文件系统的移植步骤而不是搭建步骤,文件系统实际上是由十分复杂的程序构成,不是一朝一夕能吃透、搭建出来的,庆幸的是已经有大佬创造并分享了十分容易移植的文件系统,文件系统的下载可通过FatFs,该网址中除了FatFs的各个版本外,还有其基础知识、用户论坛以及用于FatFs入门的程序节点等,并且还有各个文件操作函数(f_open、f_read等)的解释,在移植完文件系统后可以通过相应函数进行操作文件。接下来介绍文件系统的移植步骤。

  1. 将文件系统(从FatFs下载的FatFs文件夹添加至工程中)。

路径添加不用多说,几乎FatFs文件夹及子文件夹都需要加进去,源文件(.c文件)只需要添加diskio.c和ff.c文件即可。

  1. 修改ffconf.h文件的相关宏定义,如下所示,ffconf.h包含了对FatFs功能配置的宏定义。
#ifndef _FFCONF#define	_USE_MKFS		1	/*设置 _USE_MKFS1以使能f_mkfs()函数*/#define _CODE_PAGE	936     /*设置_CODE_PAGE936以使用中文编码而不是932日文编码*/#define _VOLUMES	3		/*支持3个盘符*/#define	_FS_LOCK	3	    /*设置_FS_LOCK3,支持同时打开3个文件*/#define _WORD_ACCESS	1	/*设置_WORD_ACCESS1,支持WORD*/#include "diskio.h"

#endif
  1. 完善diskio.c文件中的底层设备驱动函数

       需要完善的底层设备驱动函数包括设备状态获取函数(disk_status)、设备初始化函数(disk_initialize)、扇区读取函数(disk_read)、扇区写入函数(disk_write)和其他控制函数(disk_ioctl),这些函数用于文件系统向下完成对存储块的读写,需要读者实现。

       通过上述步骤即可完成对文件系统的移植,在程序运行时通过f_mount函数即可为相应存储介质挂载文件系统,并通过f_open、f_close和f_read等函数操作文件。

文件系统操作函数

       与文件系统操作有关的函数约有40个,具体可参考FatFs中的内容,下面简单介绍其中的几个函数。

f_mount

       f_mount函数用于为存储介质挂载一个文件系统,文件系统的挂载是指将这个文件系统放在全局文件系统树的某个目录下,完成挂载后才能访问文件系统中的文件,该函数的参数及解释如下。

FRESULT f_mount (
  FATFS*        fs ,     /* [IN] 文件系统对象 */ 
  const TCHAR* path ,   /* [IN] 逻辑驱动器号 */ 
  BYTE          opt     /* [IN] 初始化选项 */
);

       SD卡挂载文件系统示例:其中FS_VOLUME_SD在diskio.h中定义,1表示强制挂载以检查其是否准备好工作。

FATFS fs;

f_mount(&fs, FS_VOLUME_SD, 1);

f_open

       f_open函数用于打开或创建一个文件,该函数的参数及解释如下。

FRESULT f_open (
  FIL* fp,           /* [OUT] 指向文件对象结构的指针 */
  const TCHAR* path, /* [IN] 文件名 */
  BYTE mode          /* [IN] 模式标志 */
);

       其中fp为FTL类型的指针变量,后续对该文件的操作都通过该指针。path为包含文件名的完整路径。mode为对该文件的操作模式,在ff.h文件中定义,各个操作模式的作用如下:
在这里插入图片描述

       SD卡打开文件示例:创建a.txt文件并开启其读权限,若该文件已创建则返回FR_EXIST。

FIL fil;        /* 文件对象 */ 

f_open(&fil, "0:/a.txt", FA_CREATE_NEW | FA_READ);

f_close

       f_close函数用于关闭已打开的文件,该函数的参数及解释如下。

FRESULT f_close (
  FIL* fp     /* [IN] 指向文件对象的指针 */
);

       其中fp为FTL类型的指针变量,即f_open函数打开文件时使用的指针。

f_write

       f_write函数用于向文件写入相应长度的数据,该函数的参数及解释如下。

FRESULT f_write (
  FIL* fp,          /* [IN] 指向文件对象结构的指针 */
  const void* buff, /* [IN] 指向要写入的数据的指针 */
  UINT btw,         /* [IN] 要写入的字节数 */
  UINT* bw          /* [OUT] 指向变量的指针,返回写入的字节数 */
);

       其中fp为FTL类型的指针变量,即f_open函数打开文件时使用的指针。

f_read

       f_readf函数用于向文件写入相应长度的数据,该函数的参数及解释如下。

FRESULT f_read (
  FIL* fp,          /* [IN] 指向文件对象结构的指针 */
  void* buff,       /* [IN]  存储读取数据的缓冲区 */
  UINT btr,         /* [IN] 要读取的字节数 */
  UINT* br          /* [OUT] 指向变量的指针,返回读取的字节数 */
);

       其中fp为FTL类型的指针变量,即f_open函数打开文件时使用的指针。

  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. 硬件平台选择 首先,需要选择一个适合自己应用的硬件平台,可以根据自己的需求选择不同的平台,比如STM32、GD32、ESP32、Arduino等等。 在本文中,我们选择了GD32F303VCT6作为硬件平台。 2. FatFs库介绍 FatFs是一个轻量级的文件系统,支持FAT12、FAT16、FAT32等多种文件系统格式,可以在各种嵌入式系统中运行。FatFs提供了一组API函数,可以方便地对文件系统进行读写操作。 3. 移植步骤 步骤一:创建工程 首先,需要创建一个GD32的Keil工程,选择自己的芯片型号。然后,在工程目录下新建一个fatfs文件夹,用于存放FatFs库和相关的驱动代码。 步骤二:添加FatFs库 将FatFs库添加到工程中。可以在官网上下载最新的FatFs库,然后将其解压到fatfs文件夹下。 步骤三:配置FatFsfatfs文件夹下创建一个diskio.h文件,用于定义磁盘驱动接口。然后,在fatfs文件夹下创建一个ffconf.h文件,用于配置FatFs的一些参数,比如支持的文件系统格式、簇大小等等。 步骤四:实现磁盘驱动接口 在diskio.h文件中,定义以下磁盘驱动接口: ``` DSTATUS disk_initialize(BYTE pdrv); DSTATUS disk_status(BYTE pdrv); DRESULT disk_read(BYTE pdrv, BYTE *buff, DWORD sector, UINT count); DRESULT disk_write(BYTE pdrv, const BYTE *buff, DWORD sector, UINT count); DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff); ``` 这些接口函数需要在磁盘驱动文件中实现,比如SD卡驱动文件sdio_sd.c中就实现了这些接口函数。 步骤五:初始化FatFs 在main函数中,调用以下代码初始化FatFs: ``` FATFS fs; FRESULT res; res = f_mount(&fs, "", 1); if (res != FR_OK) { // mount failed } ``` 这段代码将FatFs挂载到默认的磁盘上,如果挂载失败,则说明磁盘不存在或者格式不支持。 步骤六:使用FatFs 使用FatFs的API函数对文件系统进行读写操作,比如: ``` FIL file; FRESULT res; res = f_open(&file, "file.txt", FA_READ); if (res != FR_OK) { // open failed } char buf[128]; UINT read_bytes; res = f_read(&file, buf, sizeof(buf), &read_bytes); if (res != FR_OK) { // read failed } f_close(&file); ``` 这段代码打开一个名为file.txt的文件,并读取其中的内容。 至此,FatFs文件系统的移植工作完成。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值