转载请注明出处:http://blog.csdn.net/drivelinux/article/details/8784805
我现在所用的是Cortex M3+UC/OS II的平台,之前采用的文件系统是zlg.fs,在使用的过程中发现不能对已经存在并且有内容的文件从文件的起始处进行修改,并且zlg.fs在性能上也不是很好,因此决定移植新的文件系统。FATFS虽然是日货,但是在开源的小型嵌入式文件系统中还是不错的,因此,就开始研究移植FATFS。
FATFS源码及相关的参考资料可以从以下网址获取:
http://elm-chan.org/fsw/ff/00index_e.html
下载得到的源码有两个目录,doc目录下是说明文档,src目录下则是fatfs的源码和一个说明文件00readme.txt。通过阅读00readme.txt文件,我们能够对FATFS的源码有一个清晰的认识。FATFS中的文件的作用如下:
ffconf.h FatFs模块的配置文件
源码中最关键的两个文件是ff.c和diskio.c,本次移植也只用了这两个C文件和相关的头文件。由于我的系统中存储设备可以通过电脑直接格式化为FAT格式,因此只要保证移植后的文件系统能够支持文件的打开、关闭、和读写功能即可。移植时只需要将ff.c和diskio.c文件以及各个头文件加入到原来的工程中就可以了。接下来的工作就是完善diskio.c中的各个接口,主要是disk_initialize()、disk_read()和disk_write()三个函数,disk_status()和disk_ioctl()在仅要求文件系统有读写文件的功能时可以不用实现,在移植时返回0即可。也就是把操作底层存储设备的初始化、读写函数填充到diskio.c文件中的各个函数中。原理很简单,不过,也不是简单的填充函数,一定要满足文件系统读写的要求,即文件系统在操作的过程中都是以扇区(512 Bytes)为单位。由于打开文件的过程中需要从存储设备中读取建立在该存储设备上的文件系统的信息,如文件系统的类型(包括FAT12、FAT16和FAT32)、文件所在的起始扇区等信息,因此,一定要首先保证底层的读驱动函数能够正常工作。之后,在根据每个函数的返回值逐步调试。
下面贴出一个简单的测试函数,用于测试FATFS是否移植成功并且能够可靠工作。
FATFS fs; void fatfs_test() { FIL fp; int ret = 0; int count; int i = 513; char buf[20]; char *test="0123456789ABCDEFG\n"; ret =f_mount(0, &fs); ret = f_open(&fp,"fish.txt",FA_READ | FA_WRITE); if(ret != 0) { TraceMsg(1,"Can not open file[%d] !\n",ret); return; } TraceMsg(1,"Read file test start:\n\n"); i = 513; while(i--) { memset(buf,0,18); f_read(&fp,buf,18,&count); TraceMsg(1,"++[%d][%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c]\n", i,buf[0],buf[1],buf[2],buf[3],buf[4],buf[5],buf[6],buf[7], buf[8],buf[9],buf[10],buf[11],buf[12],buf[13],buf[14],buf[15], buf[16],buf[17]); } TraceMsg(1,"Write file test start:\n\n"); f_lseek(&fp,0); i = 513; while(i--) { f_write(&fp,test,strlen(test),&count); } f_close(&fp); TraceMsg(1,"FS test over!!!!!\n\n"); }
FATFS是怎样获取建立在存储设备上的FAT文件系统的信息的呢?从一个文件的打开流程我们就可以知道FATFS获取FAT文件系统信息的原理。
f_open()
->chk_mounted()
->check_fs(fs, bsect = 0); //读取存储设备的第一个扇区,并判断存储设备上是否为FAT文件系统,如果是,之后还会继续获取各个分区的状态等信息
->disk_read() //读取存储设备的扇区