代码改变世界

FATFS 初学之 f_open/ f_close

2014-08-13 10:36  Danhuise  阅读(7227)  评论(0编辑  收藏  举报

 

f_open:

  1 /*-----------------------------------------------------------------------*/
  2 /* Open or Create a File                                                 */
  3 /*-----------------------------------------------------------------------*/
  4 
  5 FRESULT f_open (
  6     FIL *fp,            /* Pointer to the blank file object */
  7     const TCHAR *path,    /* Pointer to the file name */
  8     BYTE mode            /* Access mode and file open mode flags */
  9 )
 10 {
 11     FRESULT res;
 12     DIR dj;
 13     BYTE *dir;
 14     DEF_NAMEBUF;
 15 
 16 
 17     fp->fs = 0;            /* Clear file object */
 18 
 19 #if !_FS_READONLY
 20     mode &= FA_READ | FA_WRITE | FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW;
 21     res = chk_mounted(&path, &dj.fs, (BYTE)(mode & ~FA_READ));
 22 #else
 23     mode &= FA_READ;
 24     res = chk_mounted(&path, &dj.fs, 0);
 25 #endif
 26     INIT_BUF(dj);
 27     if (res == FR_OK)
 28         res = follow_path(&dj, path);    /* Follow the file path */
 29     dir = dj.dir;
 30 
 31 #if !_FS_READONLY    /* R/W configuration */
 32     if (res == FR_OK) {
 33         if (!dir)    /* Current dir itself */
 34             res = FR_INVALID_NAME;
 35 #if _FS_SHARE
 36         else
 37             res = chk_lock(&dj, (mode & ~FA_READ) ? 1 : 0);
 38 #endif
 39     }
 40     /* Create or Open a file */
 41     if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) {
 42         DWORD dw, cl;
 43 
 44         if (res != FR_OK) {                    /* No file, create new */
 45             if (res == FR_NO_FILE)            /* There is no file to open, create a new entry */
 46 #if _FS_SHARE
 47                 res = enq_lock() ? dir_register(&dj) : FR_TOO_MANY_OPEN_FILES;
 48 #else
 49                 res = dir_register(&dj);
 50 #endif
 51             mode |= FA_CREATE_ALWAYS;        /* File is created */
 52             dir = dj.dir;                    /* New entry */
 53         }
 54         else {                                /* Any object is already existing */
 55             if (dir[DIR_Attr] & (AM_RDO | AM_DIR)) {    /* Cannot overwrite it (R/O or DIR) */
 56                 res = FR_DENIED;
 57             } else {
 58                 if (mode & FA_CREATE_NEW)    /* Cannot create as new file */
 59                     res = FR_EXIST;
 60             }
 61         }
 62         if (res == FR_OK && (mode & FA_CREATE_ALWAYS)) {    /* Truncate it if overwrite mode */
 63             dw = get_fattime();                    /* Created time */
 64             ST_DWORD(dir+DIR_CrtTime, dw);
 65             dir[DIR_Attr] = 0;                    /* Reset attribute */
 66             ST_DWORD(dir+DIR_FileSize, 0);        /* size = 0 */
 67             cl = LD_CLUST(dir);                    /* Get start cluster */
 68             ST_CLUST(dir, 0);                    /* cluster = 0 */
 69             dj.fs->wflag = 1;
 70             if (cl) {                            /* Remove the cluster chain if exist */
 71                 dw = dj.fs->winsect;
 72                 res = remove_chain(dj.fs, cl);
 73                 if (res == FR_OK) {
 74                     dj.fs->last_clust = cl - 1;    /* Reuse the cluster hole */
 75                     res = move_window(dj.fs, dw);
 76                 }
 77             }
 78         }
 79     }
 80     else {    /* Open an existing file */
 81         if (res == FR_OK) {                        /* Follow succeeded */
 82             if (dir[DIR_Attr] & AM_DIR) {        /* It is a directory */
 83                 res = FR_NO_FILE;
 84             } else {
 85                 if ((mode & FA_WRITE) && (dir[DIR_Attr] & AM_RDO)) /* R/O violation */
 86                     res = FR_DENIED;
 87             }
 88         }
 89     }
 90     if (res == FR_OK) {
 91         if (mode & FA_CREATE_ALWAYS)            /* Set file change flag if created or overwritten */
 92             mode |= FA__WRITTEN;
 93         fp->dir_sect = dj.fs->winsect;            /* Pointer to the directory entry */
 94         fp->dir_ptr = dir;
 95 #if _FS_SHARE
 96         fp->lockid = inc_lock(&dj, (mode & ~FA_READ) ? 1 : 0);
 97         if (!fp->lockid) res = FR_INT_ERR;
 98 #endif
 99     }
100 
101 #else                /* R/O configuration */
102     if (res == FR_OK) {                    /* Follow succeeded */
103         if (!dir) {                        /* Current dir itself */
104             res = FR_INVALID_NAME;
105         } else {
106             if (dir[DIR_Attr] & AM_DIR)    /* It is a directory */
107                 res = FR_NO_FILE;
108         }
109     }
110 #endif
111     FREE_BUF();
112 
113     if (res == FR_OK) {
114         fp->flag = mode;                    /* File access mode */
115         fp->sclust = LD_CLUST(dir);            /* File start cluster */
116         fp->fsize = LD_DWORD(dir+DIR_FileSize);    /* File size */
117         fp->fptr = 0;                        /* File pointer */
118         fp->dsect = 0;
119 #if _USE_FASTSEEK
120         fp->cltbl = 0;                        /* Normal seek mode */
121 #endif
122         fp->fs = dj.fs; fp->id = dj.fs->id;    /* Validate file object */
123     }
124 
125     LEAVE_FF(dj.fs, res);
126 }
View Code

函数功能:创建/打开一个用于访问文件的文件对象

描述:如果函数成功,则创建一个文件对象。该文件对象被后续的读/写函数用来访问文件。如果想要关闭一个打开的文件对象,则使用f_close函数。如果不关闭修改后的文件,那么文件可能会崩溃。

在使用任何文件函数之前,必须使用 f_mount函数为驱动器注册一个工作区。只有这样,其他文件函数才能正常工作。

将打开的文件名、文件目录及读写属性等装入 fp,为后续操作做准备。

 

f_close:

 1 /*-----------------------------------------------------------------------*/
 2 /* Close File                                                            */
 3 /*-----------------------------------------------------------------------*/
 4 
 5 FRESULT f_close (
 6     FIL *fp        /* Pointer to the file object to be closed */
 7 )
 8 {
 9     FRESULT res;
10 
11 #if _FS_READONLY
12     FATFS *fs = fp->fs;
13     res = validate(fs, fp->id);
14     if (res == FR_OK) fp->fs = 0;    /* Discard file object */
15     LEAVE_FF(fs, res);
16 
17 #else
18     res = f_sync(fp);        /* Flush cached data */
19 #if _FS_SHARE
20     if (res == FR_OK) {        /* Decrement open counter */
21 #if _FS_REENTRANT
22         res = validate(fp->fs, fp->id);
23         if (res == FR_OK) {
24             res = dec_lock(fp->lockid);    
25             unlock_fs(fp->fs, FR_OK);
26         }
27 #else
28         res = dec_lock(fp->lockid);
29 #endif
30     }
31 #endif
32     if (res == FR_OK) fp->fs = 0;    /* Discard file object */
33     return res;
34 #endif
35 }
View Code

函数功能:关闭一个已打开的文件

描述:f_close函数关闭一个打开的文件对象。无论向文件写入任何数据,文件的缓存信息都将被写回到磁盘。该函数成功后,文件对象不再有效,并且可以被丢弃。如果文件对象是在只读模式下打开的,不需要使用该函数,也能被丢弃。

 

例:

 1 FATFS fs;        /* 逻辑驱动器的工作区(文件系统对象) */
 2 FIL fsrc;        /* 文件对象 */
 3 FRESULT res;    /* FatFs 函数公共结果代码 */
 4 
 5 void main(void)
 6 {
 7     // 设备初始化...
 8     
 9     f_mount(0,&fs);
10     res = f_open(&fdst,"0:/Demo.TXT", FA_WRITE | FA_READ);
11     if(FR_OK == res)
12     {
13         // ...
14         f_close(&fdst);
15     }
16     else
17     {
18         // ...
19     }
20     
21     f_mount(0, NULL);
22 }