收藏 分销(赏)

FatFs使用流程.doc

上传人:可**** 文档编号:1356517 上传时间:2024-04-23 格式:DOC 页数:5 大小:35KB
下载 相关 举报
FatFs使用流程.doc_第1页
第1页 / 共5页
FatFs使用流程.doc_第2页
第2页 / 共5页
FatFs使用流程.doc_第3页
第3页 / 共5页
FatFs使用流程.doc_第4页
第4页 / 共5页
FatFs使用流程.doc_第5页
第5页 / 共5页
亲,该文档总共5页,全部预览完了,如果喜欢就下载吧!
资源描述

1、一、读文件流程。1、程序结构 res = f_mount(0, &fs); res = f_open(&file, data.txt, FA_OPEN_EXISTING | FA_READ); while(1) if(fgets(data, sizeof(data), &file)=NULL) break; prints(data); f_close(&file);总共四个与文件系统相关的函数,下面就沿着函数执行路径去探索一下。2、f_mount(0, &fs)的执行 参数0是卷号,就像电脑上的CDE盘等。fs是一个未初始化的一个文件系统对象,其定义在此:FATFS fs。这个函数好像就做了两

2、个个事,使全局文件系统指针FatFS指向fs对象,并使fs.fstype=0。3、f_open(&file, data.txt, FA_OPEN_EXISTING | FA_READ)的执行参数&file是提供一个文件对象指针,打开文件过程中获得的一些信息都填入这个结构体。FA_OPEN_EXISTING | FA_READ表示要打开和读取相应的文件。源程序如下:FRESULT f_open ( FIL *fp, /* fp就指向传入的对象file */ const char *path, /*path指向data.txt的地址*/ BYTE mode /* Access mode and f

3、ile open mode flags */) DIR dj; 目录对象 BYTE *dir; 目录项指针 char fn8+3+1; 8.3文件名。 / 程序开头定义了这么三个变量,007c版本中由于支持长文件名,最好一个改为NAMEBUF(sfn, lfn)。fp-fs = NULL; 每个文件对象都指向具体的文件系统,这里先清0 auto_mount(&path, &dj.fs, (BYTE)(mode) ); /这个函数看来很关键了。旧版的函数没有中间这个参数。Path本来就是一个指针,&path就是一个指向指针的指针,&dj.fs因为dj对象还未设置,这个指针传入应该是供auto_m

4、ount函数设置的。4、auto_mount(&path, &dj.fs, (BYTE)(mode) )的执行先分析旧版的:FRESULT auto_mount ( /* FR_OK(0): successful, !=0: any error occured */ const char *path, /* Pointer to pointer to the path name (drive number) */ BYTE chk_wp /* !=0: Check media write protection for write access) DWORD bootsect, fatsize,

5、 totalsect, maxclust; const char *p = *path; /指针p现在就指向文件名字符串了。 FATFS *fs; memset(fs, 0, sizeof(FATFS); /*将全局文件系统结构清0 */ stat = disk_initialize(0); /*磁盘初始化程序,在这里调用的 */ fmt = check_fs(bootsect = 0); /* Check sector 0 as an SFD format */这里主要是调用了check_fs(bootsect = 0)函数检测是否存在FAT文件系统。下面是源代码:BYTE check_fs

6、 ( /* 0:The FAT boot record, 1:Valid boot record but not an FAT, 2:Not a boot record or error */ DWORD sect /* Sector# to check if it is an FAT boot record or not */) FATFS *fs = FatFs; if (disk_read(0, fs-win, sect, 1) != RES_OK) /* Load boot record */ return 2; if (LD_WORD(&fs-winBS_55AA) != 0xAA5

7、5) /*Check record signature */ return 2; if (!memcmp(&fs-winBS_FilSysType, FAT, 3)/* Check FAT signature */ return 0; if (!memcmp(&fs-winBS_FilSysType32, FAT32, 5) & !(fs-winBPB_ExtFlags & 0x80) return 0; return 1;这个函数的主要操作是:将磁盘的0扇区读入fs-win【】扇区缓冲。并对其中的特殊位置进行检验。如果读入错误或者末尾不是55AA,返回2。如果确实是FAT文件系统返回0。如果

8、返回1可能是主引导扇区,继续从分区引导扇区读取。auto_mount继续往下执行: fatsize = LD_DWORD(&fs-winBPB_FATSz32); fs-sects_fat = (CLUST)fatsize; /每个FAT表的扇区数目 fs-n_fats = fs-winBPB_NumFATs; /* FAT表的个数 */ fatsize *= fs-n_fats; /* (Number of sectors in FAT area) */ fs-fatbase = bootsect + LD_WORD(&fs-winBPB_RsvdSecCnt); /* FAT start

9、sector (lba) */FAT表开始于开始扇区+保留扇区。 fs-csize = fs-winBPB_SecPerClus; /* 每个簇的扇区数目 */ fs-n_rootdir = LD_WORD(&fs-winBPB_RootEntCnt); /* Nmuber of root directory entries */ totalsect = LD_DWORD(&fs-winBPB_TotSec32); fs-max_clust = maxclust; fmt = FS_FAT32; if (fmt = FS_FAT32) fs-dirbase = LD_DWORD(&fs-win

10、BPB_RootClus); fs-database = fs-fatbase + fatsize + fs-n_rootdir / 16; /* Data start sector (lba) fs-free_clust = (CLUST)0xFFFFFFFF;/以上代码主要是根据引导扇区里的数据,填充文件系统对象结构体的信息:包括FAT表大小、数目、根目录区起始地址、数据区起始扇区、文件系统类型等等。后面还有一些代码,也是做同样工作的,这里就不再叙述了。函数下面回到f_open继续执行。Auto_mount函数早期有个转折,如果文件系统类型已经定义,则直接返回,后续代码不会执行。5、f_o

11、pen()执行完auto_mount()后下一个函数:trace_path(&dj, fn, path, &dir); /* Trace the file path */这个函数里面只有path指向文件路径,其它三个都是未经初始化的指针,应该都是在这个函数里面进行设置。Dj是目录结构体,fn是8.3文件名数组,dir是指向fs扇区缓冲里当前文件目录项的指针。从函数名称和参数可以推断出它的主要功能是将文件名从路径中提取出来,并转变成从标准8.3格式,同时找到文件所在目录,并将目录扇区读入文件系统缓冲区,依据文件目录项的信息填充dj结构体。新的007c代码中已经改成了follow_path();以

12、下是源代码:FRESULT trace_path ( DIR *dj, char *fn,const char *path, BYTE *dir ) dj-fs = fs; clust = fs-dirbase; if (fs-fs_type = FS_FAT32) dj-clust = dj-sclust = clust; /目录项的当前簇和开始簇都指向根目录区 dj-sect = clust2sect(clust); /从簇号得到相应的扇区。 dj-index = 0; /目录索引项先初始化为0 for (;) ds = make_dirfile(&path, fn); /* Get a

13、paragraph into fn */make_dirfile(&path, fn)功能是获得文件名,跟进源代码看一看:有些地方还不是太清晰,但大概意思是抽取目录。有效格式如:/dir1/dir11/file1.txt等,执行该函数后fn应该=“dir1*.*”,性质是目录。move_window(dj-sect);/这个函数是将对应簇读到文件系统缓冲区。dptr = &fs-win(dj-index & 15) * 32; /这是一个目录项的指针。memcmp(&dptrDIR_Name, fn, 8+3); /将文件名或目录名与当前目录项比较,看是不是需要打开的文件或者目录。如果不是,则

14、取出下一个目录项:next_dir_entry(dj);然后进行循环。没有找到的。外层循环继续把目录剥离,往下寻找。最终找到对应的文件。trace_path()函数返回以后,f_open()函数主要根据trace_path所得到的信息填充file文件结构体。比如: fp-dir_sect = dj.fs-winsect; /* 指向目录项所在扇区 */ fp-dir_ptr = dir; /指向扇区中对应目录项的指针 fp-flag = mode; /* File access mode */ fp-org_clust = /* File start cluster */ (DWORD)LD_

15、WORD(&dirDIR_FstClusHI) fsize = LD_DWORD(&dirDIR_FileSize); /* File size */ fp-fptr = 0; fp-csect = 255; /* 文件读写指针为0 */ fp-fs = dj.fs; fp-id = dj.fs-id; /* Owner file system object of the file */f_open()到此执行结束。6、fgets(data, sizeof(data), &file)的执行该函数的主要参数是数据缓冲区data,和文件结构描述符file。跟进源代码: while (i fsize

16、 - fp-fptr; /文件大小减去当前位置,得到剩下的字节数。if (btr remain) btr = (UINT)remain;/如果要读的字节数大于剩余字节数,则调整。 举个例子,从文件头开始读5128个字节,共占据11个扇区。一簇以8个扇区计算。 for ( ; btr; /* Repeat until all data transferred */ rbuff += rcnt, fp-fptr += rcnt, *br += rcnt, btr -= rcnt) if (fp-fptr % 512U) = 0) /*读初始指针位于扇区位于边界 */ sect = clust2se

17、ct(fp-curr_clust) + fp-csect; /* 簇的第一个扇区 */ cc = btr / 512U; /* cc=10表示多于一个扇区, */ if (cc) /* Read maximum contiguous sectors directly */ if (fp-csect + cc fp-fs-csize) /* 多于一个簇 */ cc = fp-fs-csize - fp-csect; /暂时先读一个簇。 if (disk_read(0, rbuff, sect, (BYTE)cc) != RES_OK) goto fr_error; fp-csect += (BY

18、TE)cc; /* 移动到下一个簇 */ rcnt = 512U * cc; /* Number of bytes transferred */ continue;第二次读时,要执行下面语句:第二次要读两个扇区 if (fp-csect = fp-fs-csize) /* 移动到下一簇 */ clust = (fp-fptr = 0) ? /* On the top of the file? */ fp-org_clust : get_cluster(fp-curr_clust); if (clust = fp-fs-max_clust) goto fr_error; fp-curr_clus

19、t = clust; /*更新当前簇 */ fp-csect = 0; /* 簇内扇区号变为0 */ 第二次读时额外执行的语句。 fp-csect+; /* 这个在第三次读时也会执行 */ /往下语句也会在第三次读时执行。 sect = clust2sect(fp-curr_clust) + fp-csect - 1; /* 如果文件读写指针不在扇区边界,为了读到数据,必须往前走一个扇区 */ if (!move_window(sect) goto fr_error; /* Move sector window */ rcnt = 512U - (fp-fptr % 512U); * Get

20、partial sector from sector window */ if (rcnt btr) rcnt = btr; memcpy(rbuff, &fp-fs-winfp-fptr % 512U, rcnt); 8、f_close() 主要做了两个工作:(1)res = f_sync(fp);将文件的改动写入,同时调用函数sync()将文件系统变化写入文件系统相应信息区域。(2)fp-fs=0,将文件关闭。/-二、写文件流程分析1、写文件程序结构。 res = f_open(&file, 331.txt, FA_CREATE_ALWAYS | FA_WRITE); res = f_wr

21、ite(&file, data, 512, &br); f_close(&file); 2、函数f_open(&file, 331.txt, FA_CREATE_ALWAYS | FA_WRITE)的执行仍然是打开文件,但是以创建和写的方式打开,其执行与读方式的打开就稍有不同。以下是写部分的操作源代码: 先执行函数reserve_direntry(&dj, &dir); 这个函数的作用是通过dj目录对象在相应目录的簇里查找一个空闲目录项,并用dir指向它。并设置该文件目录项的属性等。3、f_write(&file, data, 512, &br);函数的执行这个函数执行文件写入操作,file是

22、文件信息结构体:包括它对应的文件系统结构体指针、目录项扇区号、文件对用的起始簇号、当前簇号、当前扇区号、文件对象写指针。有了这些信息,就好操作文件。Data是写入数据的缓冲区,512是要写的数据个数,br是写入成功的个数(这个是返回值)。部分源代码如下: cc = btw / 512U; /* When remaining bytes = sector size, */ if (cc) * Write maximum contiguous sectors directly */ if (fp-csect + cc fp-fs-csize) /* Clip at cluster boundary */ cc = fp-fs-csize - fp-csect; if (disk_write(0, wbuff, sect, (BYTE)cc) != RES_OK)实际操作与读文件差不多,只是在写入数目操作本簇的时候,有这个操作,clust = create_chain(fp-curr_clust)文件系统会分配一个新的簇。

展开阅读全文
相似文档                                   自信AI助手自信AI助手
猜你喜欢                                   自信AI导航自信AI导航
搜索标签

当前位置:首页 > 包罗万象 > 大杂烩

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        获赠5币

©2010-2024 宁波自信网络信息技术有限公司  版权所有

客服电话:4008-655-100  投诉/维权电话:4009-655-100

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :gzh.png    weibo.png    LOFTER.png 

客服