赞
踩
目录
把文件系统FatFs移植到串行FLASH中。能够将文档(txt、bmp、docx等格式文件)存入FLASH中(W25Q64芯片)。
文件系统,就是对数据进行管理的方式,可有效地管理存储介质(磁盘、U盘等等)。
使用文件系统时,它为了存储和管理数据,在存储介质建立了一些组织结构,这些结构包括操作系统引导区、目录和文件。目录:FLASH芯片自己建立了一个目录,可以知道自己存储空间里面的数据有什么,地址在哪里。
FatFs是在嵌入式里面应用非常广泛的文件系统,就是一个代码库,这个代码库能对FLASH进行操作,以便于管理FLASH这个存储介质中的文件。
注意:本实验中可能会丢掉原来FLASH中存储的数据,导致液晶屏显示会出现中文乱码,但后面会有重新刷FLASH的教程。
常见的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文件系统中是没有的,这些程序是留给用户自己去写,想用在FLASH上就写FLASH相关的操作程序;想用在EEPROM上就写EEPROM相关的操作程序(EEPROM存储空间较小,所以没有用文件系统去管控),想用在SD卡上就写SD卡相关的操作程序。
利用前面写好的SPI Flash芯片驱动,把FatFs文件系统代码移植到工程之中,就可以利用文件系统的各种函数,对SPI Flash芯片以“文件”格式进行读写操作了。
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文件中的函数就可以了。
用户应用程序需要由用户编写,想实现什么功能就编写什么的程序,一般我们只用到f_mount()、f_open()、f_write()、f_read()就可以实现文件的读写操作。FatFs组件中只需要修改ffconf.h(修改宏定义)和diskio.c两个文件。
函数 | 条件(ffconf.h) | 备注 |
disk_status | 总是需要 | 底层设备驱动函数 |
disk_write | _FS_READONLY == 0 支持写、读文档,为1不支持写入,只读 | |
disk_ioctl (GET_SECTOR_COUNT) | _USE_MKFS == 1 格式化(目录表等写进去) | |
disk_ioctl (GET_SECTOR_SIZE) | _MAX_SS != _MIN_SS 获取最大最小的缓冲 配置扇区大小 | |
disk_ioctl (CTRL_TRIM) | _USE_TRIM == 1 | |
ff_convert | _USE_LFN != 0 | Unicode支持,为支持简体中文,添加cc936.c到工程即可 |
ff_cre_syncobj | _FS_REENTRANT == 1 | FatFs可重入配置,需要多任务系统支持(一般不需要) |
ff_mem_alloc | _USE_LFN == 3 | 长文件名支持,缓冲区设置在堆空间(一般设置_USE_LFN = 2 )
|
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函数来调用这些底层函数,实现底层程序与上层程序之间的隔离。
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 */
- )
形参:文件指针;你要读取的内容存储在哪里(指针);要读取多少个字节;真正读回来多少个字节
如何设置长文件名?
在ffconf.h文件中我们把下面这个宏定义改为1,并且要添加cc936.c文件,这样我们文件的文件名也可以用中文来命名。
为何进行地址的偏移
这里用的flash芯片有8M字节,每个扇区4096字节,我们把前面2M字节空出用于其他(野火板子自带的内容),后面6M字节给FatFS使用。那么,需要将所有的地址都偏移2M,即512个扇区的空间。
在我们写完这个程序之后,我们可以与官方例程中的“USB—外部FLASH模拟U盘”程序结合,将这个程序下载到板子里面之后,再下载官方的那个程序,板子要用数据线与电脑相连,这样FLASH就可以当作U盘使用,我们写的文件也会在里面体现。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。