目录

一、Windows系统为例

二、文件系统的结构与特性

为什么要应用文件分配表?

三、FatFs文件系统

1- FatFs 文件系统源码介绍

2- FatFs在程序中的关系网

四、配置FatFs移植程序

1-配置diskio.c文件

2-配置移植程序

3-其余问题汇总


把文件系统FatFs移植到串行FLASH中。能够将文档(txt、bmp、docx等格式文件)存入FLASH中(W25Q64芯片)。

文件系统,就是对数据进行管理的方式,可有效地管理存储介质(磁盘、U盘等等)。

使用文件系统时,它为了存储和管理数据,在存储介质建立了一些组织结构,这些结构包括操作系统引导区、目录和文件。目录:FLASH芯片自己建立了一个目录,可以知道自己存储空间里面的数据有什么,地址在哪里。

FatFs是在嵌入式里面应用非常广泛的文件系统,就是一个代码库,这个代码库能对FLASH进行操作,以便于管理FLASH这个存储介质中的文件。

注意:本实验中可能会丢掉原来FLASH中存储的数据,导致液晶屏显示会出现中文乱码,但后面会有重新刷FLASH的教程。

一、Windows系统为例

常见的windows下的文件系统格式包括FAT32、NTFS、exFAT。在使用文件系统前,要先对存储介质进行格式化。格式化时会在存储介质上新建一个文件分配表和目录。这样,文件系统就可以记录数据存放的物理地址,剩余空间。

Windows操作系统为了便于用户对磁盘的管理。加入了磁盘分区的概念,即将一块磁盘逻辑划分为几块,它会把磁盘的分区信息记录到硬盘分区表中。下图中的分区表就相当于目录,指向了基本分区所在的位置。

二、文件系统的结构与特性

使用文件系统时,数据都以文件的形式存储。写入新文件时,先在目录中创建一个文件索引,它指示了文件存放的物理地址,再把数据存储到该地址中。当需要读取数据时,可以从目录中找到该文件的索引,进而在相应的地址中读取出数据。具体还涉及到逻辑地址、簇大小(类似于扇区,最小删除单位)、不连续存储等一系列辅助结构或处理过程。

文件系统的存在使存取数据时,不再是简单地向某物理地址直接读写,而是要遵循它的读写格式。如经过逻辑转换,一个完整的文件可能被分开成多段存储到不连续的物理地址,使用目录或链表的方式来获知下一段的位置。

文件系统的空间示意图:

存储了A.TXT,B.TXT,C.TXT文件  簇可以理解为扇区。

其中,目录表示意图如下:

记录了文件的开始簇位置、大小等信息

开始簇:该文件的起始位置。

文件分配表(存储在FLASH的第0扇区)

第一个扇区指向目录,第二个扇区指向第三个扇区文件。我们根据目录项中指定的A.txt 的首簇为2,然后找到文件分配表的第2簇记录,上面登记的是3,就能确定下一簇是3。找到文件分配表的第3簇记录,上面登记的是4,就能确定下一簇是4......直到指到第11簇,发现下一个指向是FF,就是结束。文件便读取完毕。

为什么要应用文件分配表?

这是我们原本的文件分配表,B.txt文件是从12-65的,我们要删除B文件插入D文件,但是D文件比B文件大,12-65写不开,我们可以从65指向87(空余空间)接着进行存储。

目录表和文件分配表在存储介质格式化的时候就已经创建好。

三、FatFs文件系统

底层是如何写入、擦除、读取字节的程序在FatFs文件系统中是没有的,这些程序是留给用户自己去写,想用在FLASH上就写FLASH相关的操作程序;想用在EEPROM上就写EEPROM相关的操作程序(EEPROM存储空间较小,所以没有用文件系统去管控),想用在SD卡上就写SD卡相关的操作程序。

利用前面写好的SPI Flash芯片驱动,把FatFs文件系统代码移植到工程之中,就可以利用文件系统的各种函数,对SPI Flash芯片以“文件”格式进行读写操作了。

1- FatFs 文件系统源码介绍

FatFs文件系统源码:doc文件夹里面是一些使用帮助文档;在src是FatFs文件系统的源代码。

integer.h:文件中包含了一些数值类型定义(typedef)。

diskio.c:包含底层存储介质的操作函数,这些函数需要用户自己实现,主要添加底层驱动函数。

ff.c:    FatFs核心文件,文件管理的实现方法。该文件独立于底层介质操作文件的函数,利用这些函数实现文件的读写。

cc936.c:本文件在option目录下,是简体中文支持所需要添加的文件,包含了简体中文的GBK和Unicode相互转换功能函数。

除diskio.c文件外,其他文件都是可以直接移植到其他存储介质中去使用的。为了使用文件系统,只需要理解integer.h及diskio.c文件并会调用ff.c文件中的函数就可以了。

2- FatFs在程序中的关系网

用户应用程序需要由用户编写,想实现什么功能就编写什么的程序,一般我们只用到f_mount()、f_open()、f_write()、f_read()就可以实现文件的读写操作。FatFs组件中只需要修改ffconf.h(修改宏定义)和diskio.c两个文件。

函数

条件(ffconf.h)

备注

disk_status
disk_initialize
disk_read

总是需要

底层设备驱动函数

disk_write
get_fattime
disk_ioctl (CTRL_SYNC)

_FS_READONLY == 0

支持写、读文档,为1不支持写入,只读

disk_ioctl (GET_SECTOR_COUNT)
disk_ioctl (GET_BLOCK_SIZE)

_USE_MKFS == 1

格式化(目录表等写进去)

disk_ioctl (GET_SECTOR_SIZE)

_MAX_SS != _MIN_SS

获取最大最小的缓冲 配置扇区大小

disk_ioctl (CTRL_TRIM)

_USE_TRIM == 1

ff_convert
ff_wtoupper

_USE_LFN != 0

Unicode支持,为支持简体中文,添加cc936.c到工程即可

ff_cre_syncobj
ff_del_syncobj
ff_req_grant
ff_rel_grant

_FS_REENTRANT == 1

FatFs可重入配置,需要多任务系统支持(一般不需要)

ff_mem_alloc
ff_mem_free

_USE_LFN == 3

长文件名支持,缓冲区设置在堆空间(一般设置_USE_LFN = 2 )

四、配置FatFs移植程序

1-配置diskio.c文件

1. DSTATUS disk_status 函数

用于获取底层设备(FLASH)的状态。

形参:设备号

返回值:STA_NOINIT:指示设备尚未初始化,尚未准备好工作。

STA_NODISK:驱动器中没有介质

STA_PROTECT:写保护状态

/* Disk Status Bits (DSTATUS) */#define STA_NOINIT       0x01    /* Drive not initialized */
#define STA_NODISK      0x02    /* No medium in the drive */
#define STA_PROTECT     0x04    /* Write protected */

2.disk_initialize 函数

初始化所用的设备

形参与返回值与上面函数相同

3.disk_read 函数

DRESULT disk_read (BYTE pdrv,        /* Physical drive nmuber to identify the drive */BYTE *buff,        /* Data buffer to store read data */DWORD sector,   /* Sector address in LBA */UINT count       /* Number of sectors to read */
)

形参:设备号,上层ff.c文件调用此函数从FLASH(设备号的设备)读出来的数据存储在*buff(指针指向的数组缓冲区)中,需要读取FLASH(设备)哪个扇区,要读取多少个扇区。

返回值:RES_OK (0)    函数成功。

RES_ERROR   读取操作期间发生不可恢复的硬错误。

RES_PARERR  传入的形参有错误。

RES_NOTRDY 设备尚未初始化。

4.disk_write 函数

DRESULT disk_write (BYTE pdrv,           /* Physical drive nmuber to identify the drive */const BYTE *buff,  /* Data to be written */DWORD sector,       /* Sector address in LBA */UINT count           /* Number of sectors to write */
)

形参:设备号,要写入数据的指针(数组),要写入的扇区的地址,写入多少个扇区。

返回值与上面的read函数一样。

5.disk_ioctl 函数

控制设备特定的功能和其他功能,而不是一般的读/写。

DRESULT disk_ioctl (BYTE pdrv,       /* Physical drive nmuber (0..) */BYTE cmd,      /* Control code */void *buff        /* Buffer to send/receive control data */
)

形参:设备号;命令;输入或输出一个指针(依据命令而定)

返回值与上面的read函数一样。

常用的命令:

GET_SECTOR_COUNT:存储设备有多大 该命令是DWORD类型

GET_SECTOR_SIZE:每个扇区有多大 配置要支持的扇区大小范围,当_MAX_SS大于_MIN_SS时,FatF被配置为可变扇区大小。我们应该更改ffconf.h里面的:_MAX_SS宏定义为4096,因为FLASH 每个扇区是 4096 个字节。该命令是WORD类型

GET_BLOCK_SIZE:每个block有多大 文件系统以block为单位进行擦除 该命令是DWORD类型。

switch(cmd)//对传入的命令进行分析
{case GET_SECTOR_COUNT://存储设备有多大*(DWORD*)buff = 2048-514;//有2048个扇区break;case GET_SECTOR_SIZE://每个扇区有多大*(WORD*)buff = 4096;//每个扇区4096个字节break;case GET_BLOCK_SIZE://每个block有多大*(DWORD*)buff = 1;//文件系统以block为单位进行擦除break;
}
res = RES_OK;
return res;

这些程序是底层的程序,在使用文件系统的时候最好不要直接调用,我们一般使用f_mount函数来调用这些底层函数,实现底层程序与上层程序之间的隔离。

2-配置移植程序

1.f_mount 函数

FRESULT f_mount (FATFS* fs,          /* Pointer to the file system object (NULL:unmount)*/const TCHAR* path, /* Logical drive number to be mounted/unmounted */BYTE opt          /* 0:Do not mount (delayed mount), 1:Mount immediately */
)

形参:文件系统指针;字符串类型的路径(也就是我们宏定义的设备的号码);安装选项:0:现在不挂载(要在第一次访问时挂载),1:强制挂载并检查它是否准备好工作,一般配置为1。

2.f_mkfs 函数

格式化,创建文件系统

形参:选择要格式化的文件系统;第二个参数为0(硬盘);每个存储单元(扇区)的大小。

3.f_open 函数

打开文件函数

FRESULT f_open (FIL* fp,         /* Pointer to the blank file object */const TCHAR* path,    /* Pointer to the file name */BYTE mode         /* Access mode and file open mode flags */
)

形参:文件指针;创建的文件名,这里要包含创建文件所在的目录(1: 代表着是在FLASH下);模式(对该文件的权限)

权限如下:

其中:FA_CREATE_ALWAYS:创建一个新文件。如果文件存在,它将被截断并覆盖。

4. f_write 函数

往文件里面写入数据。

FRESULT f_write (FIL* fp,            /* Pointer to the file object */const void *buff,   /* Pointer to the data to be written */UINT btw,            /* Number of bytes to write */UINT* bw          /* Pointer to number of bytes written */
)

形参:文件指针;要写入的内容;要写入多少个字节;返回值,返回写入了多少个字节。

5.f_close 函数

要关闭哪个文件。

FRESULT f_close (FIL *fp     /* Pointer to the file object to be closed */
)

形参:文件指针

6.f_read 函数

读取文件内容。

FRESULT f_read (FIL* fp,         /* Pointer to the file object */void* buff,     /* Pointer to data buffer */UINT btr,       /* Number of bytes to read */UINT* br       /* Pointer to number of bytes read */
)

形参:文件指针;你要读取的内容存储在哪里(指针);要读取多少个字节;真正读回来多少个字节

3-其余问题汇总

如何设置长文件名?

在ffconf.h文件中我们把下面这个宏定义改为1,并且要添加cc936.c文件,这样我们文件的文件名也可以用中文来命名。

为何进行地址的偏移

这里用的flash芯片有8M字节,每个扇区4096字节,我们把前面2M字节空出用于其他(野火板子自带的内容),后面6M字节给FatFS使用。那么,需要将所有的地址都偏移2M,即512个扇区的空间。

在我们写完这个程序之后,我们可以与官方例程中的“USB—外部FLASH模拟U盘”程序结合,将这个程序下载到板子里面之后,再下载官方的那个程序,板子要用数据线与电脑相连,这样FLASH就可以当作U盘使用,我们写的文件也会在里面体现。

STM32 串行FLASH文件系统FatFs相关推荐

  1. STM32CUBEIDE之SPI读写FLASH进阶串行FLASH文件系统FatFs

    预备知识 >>W25Q128是16M spi flash,一共有256个block ,每个Block 64KB. >>一个Block可以分割为16个扇区(small secto ...

  2. 第 26 章 串行 FLASH 文件系统 FatFs

    26.1 文件系统 26.2 FatFs 文件系统简介 2.1 FatFs 的目录结构 2.2 FatFs 帮助文档 2.3 FATFS 源码 src 文件夹下的源码文件功能 (1)integer.h ...

  3. 串行FLASH文件系统FatFs介绍并在STM32F1上移植

          先对内存存储有一个理解,比如在FALSH中存储数据时,已知在STM32F1 开发板上都有自带有一个外部 FLASH(W25Q128.128Mbit=16MByte,即16M内存),FLAS ...

  4. c++ 文件读写_串行FLASH 文件系统FatFs

    文件系统 即使大家可能不了解文件系统,但也一定对"文件"这个概念十分熟悉.数据在PC上是以文件的形式储存在磁盘中的,这些数据的形式一般为ASCII 码或二进制形式.如需要记录本书的 ...

  5. STM32-串行FLASH文件系统FatFs

    串行FLASH文件系统FatFs FatFs官方链接 FatFs文件系统的源码可以从FatFs官方下载:官方链接http://elm-chan.org/fsw/ff/00index_e.html Fa ...

  6. 串行FLASH文件系统FatFs---转自野火论坛

    为了支持长文件名,需要用到FATFS源码中的cc936.c的两个函数ff_convert,ff_wtoupper:这里面直接用了两个大数组(127KB)来做unicode转gbk(OEM)的对照表,这 ...

  7. 25章 SPI—读写串行FLASH

    SPI 协议简介 3 条总线分别为SCK(时钟).MOSI(主出从入).MISO(主入从出),片选线为SS1.2.3(从设备)(多少设备也就这三条ss) MOSI和MISO能看出是全双工(输入输出两条 ...

  8. 第24章 SPI—读写串行FLASH—零死角玩转STM32-F429系列

    第24章     SPI-读写串行FLASH 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/ ...

  9. SPI—读写串行FLASH(时序中的无关项)

    SPI-读写串行FLASH 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/firege 本章 ...

最新文章

  1. 区块链有哪些技术特征
  2. 利用Docker构建开发环境
  3. jQuery时间轴特效
  4. 金融风控实战——迁移学习
  5. Android-简单拨号器案例
  6. 实验四---继承与派生练习以及运算符[ ]重载练习
  7. 如何正确地使用Java的@deprecated标注
  8. mysql导出二进制日志_使用mysqlbinlog提取二进制日志
  9. Python+numpy实现矩阵QR分解
  10. 需要学习的技术知识备忘录
  11. 爱奇艺客户端启动优化实践
  12. 微信模板消息字体设置变大
  13. 多个pdf怎么合并成一个pdf?如何将几个pdf文件合并成一个pdf?
  14. 学生HTML个人网页作业作品~蛋糕甜品店铺共11个页面(HTML+CSS+JavaScript)
  15. 点点动画~画出懂你的3D魔方
  16. 数据挖掘经典十大算法_对基本概念的理解
  17. Django--request 对象
  18. 电路邱关源学习笔记——1.7基尔霍夫定律
  19. “重感知·轻地图”重新定义自动驾驶
  20. oracle consistent gets,consistent gets在Oracle使用特例

热门文章

  1. MDT自动部署弹出Dirty Environment Found
  2. 在mysql中 创建视图需要使用_语句_SQL如何通过CREATE VIEW 语句创建视图
  3. 大数据技术之Kafka
  4. Android获取本地图片缩略图终极解决方案
  5. 统计计算方法上机考试
  6. JavaScript的form表单验证中的身份证校验
  7. 台达屏幕modbus通信解析
  8. 考研成绩公布了,分享一下自己曾经走过的那些坑
  9. Swift UIImageView简单动画
  10. 使用AVPlayer自定义支持全屏的播放器(一)