/-----------------------------------------------------------------------/
2 /* Read File /
3 /-----------------------------------------------------------------------*/
4
5 FRESULT f_read (
6 FIL fp, / Pointer to the file object */
7 void buff, / Pointer to data buffer /
8 UINT btr, / Number of bytes to read */
9 UINT br / Pointer to number of bytes read */
10 )
11 {
12 FRESULT res;
13 DWORD clst, sect, remain;
14 UINT rcnt, cc;
15 BYTE csect, *rbuff = buff;
16
17
18 br = 0; / Initialize byte counter /
19
20 res = validate(fp->fs, fp->id); / Check validity /
21 if (res != FR_OK) LEAVE_FF(fp->fs, res);
22 if (fp->flag & FA__ERROR) / Aborted file? /
23 LEAVE_FF(fp->fs, FR_INT_ERR);
24 if (!(fp->flag & FA_READ)) / Check access mode /
25 LEAVE_FF(fp->fs, FR_DENIED);
26 remain = fp->fsize - fp->fptr;
27 if (btr > remain) btr = (UINT)remain; / Truncate btr by remaining bytes /
28
29 for ( ; btr; / Repeat until all data read */
30 rbuff += rcnt, fp->fptr += rcnt, br += rcnt, btr -= rcnt) {
31 if ((fp->fptr % SS(fp->fs)) == 0) { / On the sector boundary? /
32 csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); / Sector offset in the cluster /
33 if (!csect) { / On the cluster boundary? /
34 if (fp->fptr == 0) { / On the top of the file? /
35 clst = fp->sclust; / Follow from the origin /
36 } else { / Middle or end of the file /
37 #if _USE_FASTSEEK
38 if (fp->cltbl)
39 clst = clmt_clust(fp, fp->fptr); / Get cluster# from the CLMT /
40 else
41 #endif
42 clst = get_fat(fp->fs, fp->clust); / Follow cluster chain on the FAT /
43 }
44 if (clst < 2) ABORT(fp->fs, FR_INT_ERR);
45 if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR);
46 fp->clust = clst; / Update current cluster /
47 }
48 sect = clust2sect(fp->fs, fp->clust); / Get current sector /
49 if (!sect) ABORT(fp->fs, FR_INT_ERR);
50 sect += csect;
51 cc = btr / SS(fp->fs); / When remaining bytes >= sector size, /
52 if (cc) { / Read maximum contiguous sectors directly /
53 if (csect + cc > fp->fs->csize) / Clip at cluster boundary /
54 cc = fp->fs->csize - csect;
55 if (disk_read(fp->fs->drv, rbuff, sect, (BYTE)cc) != RES_OK)
56 ABORT(fp->fs, FR_DISK_ERR);
57 #if !_FS_READONLY && _FS_MINIMIZE <= 2 / Replace one of the read sectors with cached data if it contains a dirty sector /
58 #if _FS_TINY
59 if (fp->fs->wflag && fp->fs->winsect - sect < cc)
60 mem_cpy(rbuff + ((fp->fs->winsect - sect) * SS(fp->fs)), fp->fs->win, SS(fp->fs));
61 #else
62 if ((fp->flag & FA__DIRTY) && fp->dsect - sect < cc)
63 mem_cpy(rbuff + ((fp->dsect - sect) * SS(fp->fs)), fp->buf, SS(fp->fs));
64 #endif
65 #endif
66 rcnt = SS(fp->fs) * cc; / Number of bytes transferred /
67 continue;
68 }
69 #if !_FS_TINY
70 if (fp->dsect != sect) { / Load data sector if not in cache /
71 #if !_FS_READONLY
72 if (fp->flag & FA__DIRTY) { / Write-back dirty sector cache /
73 if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)
74 ABORT(fp->fs, FR_DISK_ERR);
75 fp->flag &= ~FA__DIRTY;
76 }
77 #endif
78 if (disk_read(fp->fs->drv, fp->buf, sect, 1) != RES_OK) / Fill sector cache /
79 ABORT(fp->fs, FR_DISK_ERR);
80 }
81 #endif
82 fp->dsect = sect;
83 }
84 rcnt = SS(fp->fs) - (fp->fptr % SS(fp->fs)); / Get partial sector data from sector buffer /
85 if (rcnt > btr) rcnt = btr;
86 #if _FS_TINY
87 if (move_window(fp->fs, fp->dsect)) / Move sector window /
88 ABORT(fp->fs, FR_DISK_ERR);
89 mem_cpy(rbuff, &fp->fs->win[fp->fptr % SS(fp->fs)], rcnt); / Pick partial sector /
90 #else
91 mem_cpy(rbuff, &fp->buf[fp->fptr % SS(fp->fs)], rcnt); / Pick partial sector */
92 #endif
93 }
94
95 LEAVE_FF(fp->fs, FR_OK);
96 }
View Code
函数功能:从已打开的文件中读取数据。
描述:文件对象中的读/写指针以已读取字节数增加。该函数成功后,应该检查 *ByteRead 来检测文件是否结束。在读操作过程中,一旦 *ByteRead < ByteToRead ,则读/写指针到达了文件结束位置。
f_write:
1 /-----------------------------------------------------------------------/
2 /* Write File /
3 /-----------------------------------------------------------------------*/
4
5 FRESULT f_write (
6 FIL fp, / Pointer to the file object */
7 const void buff, / Pointer to the data to be written /
8 UINT btw, / Number of bytes to write */
9 UINT bw / Pointer to number of bytes written */
10 )
11 {
12 FRESULT res;
13 DWORD clst, sect;
14 UINT wcnt, cc;
15 const BYTE *wbuff = buff;
16 BYTE csect;
17
18
19 bw = 0; / Initialize byte counter /
20
21 res = validate(fp->fs, fp->id); / Check validity /
22 if (res != FR_OK) LEAVE_FF(fp->fs, res);
23 if (fp->flag & FA__ERROR) / Aborted file? /
24 LEAVE_FF(fp->fs, FR_INT_ERR);
25 if (!(fp->flag & FA_WRITE)) / Check access mode /
26 LEAVE_FF(fp->fs, FR_DENIED);
27 if ((DWORD)(fp->fsize + btw) < fp->fsize) btw = 0; / File size cannot reach 4GB /
28
29 for ( ; btw; / Repeat until all data written */
30 wbuff += wcnt, fp->fptr += wcnt, bw += wcnt, btw -= wcnt) {
31 if ((fp->fptr % SS(fp->fs)) == 0) { / On the sector boundary? /
32 csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); / Sector offset in the cluster /
33 if (!csect) { / On the cluster boundary? /
34 if (fp->fptr == 0) { / On the top of the file? /
35 clst = fp->sclust; / Follow from the origin /
36 if (clst == 0) / When no cluster is allocated, /
37 fp->sclust = clst = create_chain(fp->fs, 0); / Create a new cluster chain /
38 } else { / Middle or end of the file /
39 #if _USE_FASTSEEK
40 if (fp->cltbl)
41 clst = clmt_clust(fp, fp->fptr); / Get cluster# from the CLMT /
42 else
43 #endif
44 clst = create_chain(fp->fs, fp->clust); / Follow or stretch cluster chain on the FAT /
45 }
46 if (clst == 0) break; / Could not allocate a new cluster (disk full) /
47 if (clst == 1) ABORT(fp->fs, FR_INT_ERR);
48 if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR);
49 fp->clust = clst; / Update current cluster /
50 }
51 #if _FS_TINY
52 if (fp->fs->winsect == fp->dsect && move_window(fp->fs, 0)) / Write-back sector cache /
53 ABORT(fp->fs, FR_DISK_ERR);
54 #else
55 if (fp->flag & FA__DIRTY) { / Write-back sector cache /
56 if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)
57 ABORT(fp->fs, FR_DISK_ERR);
58 fp->flag &= ~FA__DIRTY;
59 }
60 #endif
61 sect = clust2sect(fp->fs, fp->clust); / Get current sector /
62 if (!sect) ABORT(fp->fs, FR_INT_ERR);
63 sect += csect;
64 cc = btw / SS(fp->fs); / When remaining bytes >= sector size, /
65 if (cc) { / Write maximum contiguous sectors directly /
66 if (csect + cc > fp->fs->csize) / Clip at cluster boundary /
67 cc = fp->fs->csize - csect;
68 if (disk_write(fp->fs->drv, wbuff, sect, (BYTE)cc) != RES_OK)
69 ABORT(fp->fs, FR_DISK_ERR);
70 #if _FS_TINY
71 if (fp->fs->winsect - sect < cc) { / Refill sector cache if it gets invalidated by the direct write /
72 mem_cpy(fp->fs->win, wbuff + ((fp->fs->winsect - sect) * SS(fp->fs)), SS(fp->fs));
73 fp->fs->wflag = 0;
74 }
75 #else
76 if (fp->dsect - sect < cc) { / Refill sector cache if it gets invalidated by the direct write /
77 mem_cpy(fp->buf, wbuff + ((fp->dsect - sect) * SS(fp->fs)), SS(fp->fs));
78 fp->flag &= ~FA__DIRTY;
79 }
80 #endif
81 wcnt = SS(fp->fs) * cc; / Number of bytes transferred /
82 continue;
83 }
84 #if _FS_TINY
85 if (fp->fptr >= fp->fsize) { / Avoid silly cache filling at growing edge /
86 if (move_window(fp->fs, 0)) ABORT(fp->fs, FR_DISK_ERR);
87 fp->fs->winsect = sect;
88 }
89 #else
90 if (fp->dsect != sect) { / Fill sector cache with file data /
91 if (fp->fptr < fp->fsize &&
92 disk_read(fp->fs->drv, fp->buf, sect, 1) != RES_OK)
93 ABORT(fp->fs, FR_DISK_ERR);
94 }
95 #endif
96 fp->dsect = sect;
97 }
98 wcnt = SS(fp->fs) - (fp->fptr % SS(fp->fs));/ Put partial sector into file I/O buffer /
99 if (wcnt > btw) wcnt = btw;
100 #if _FS_TINY
101 if (move_window(fp->fs, fp->dsect)) / Move sector window /
102 ABORT(fp->fs, FR_DISK_ERR);
103 mem_cpy(&fp->fs->win[fp->fptr % SS(fp->fs)], wbuff, wcnt); / Fit partial sector /
104 fp->fs->wflag = 1;
105 #else
106 mem_cpy(&fp->buf[fp->fptr % SS(fp->fs)], wbuff, wcnt); / Fit partial sector /
107 fp->flag |= FA__DIRTY;
108 #endif
109 }
110
111 if (fp->fptr > fp->fsize) fp->fsize = fp->fptr; / Update file size if needed /
112 fp->flag |= FA__WRITTEN; / Set file change flag */
113
114 LEAVE_FF(fp->fs, FR_OK);
115 }
View Code
函数功能:向已打开的问价中写入数据。
描述:文件对象中的读/写指针以已写入字节数增加。该函数成功后,应该检查 *ByteWritten 来检测磁盘是否满。在写操作过程中,一旦 *ByteWritten < *ByteToWritten ,则意味着该卷已满。
这两个函数在调用过程中会将文件读写指针 fp->fptr的值累加,使得下次再次对该文件操作时从上次操作的断点处继续向下操作。
例:
1 void main (void)
2 {
3 FATFS fs[2]; /* 逻辑驱动器的工作区(文件系统对象) /
4 FIL fsrc, fdst; / 文件对象 /
5 BYTE buffer[4096]; / 文件拷贝缓冲区 /
6 FRESULT res; / FatFs 函数公共结果代码 /
7 UINT br, bw; / 文件读/写字节计数 /
8
9 / 为逻辑驱动器注册工作区 /
10 f_mount(0, &fs[0]);
11 f_mount(1, &fs[1]);
12
13 / 打开驱动器 1 上的源文件 /
14 res = f_open(&fsrc, “1:srcfile.dat”, FA_OPEN_EXISTING | FA_READ);
15 if (res) die(res);
16
17 / 在驱动器 0 上创建目标文件 /
18 res = f_open(&fdst, “0:dstfile.dat”, FA_CREATE_ALWAYS | FA_WRITE);
19 if (res) die(res);
20
21 / 拷贝源文件到目标文件 /
22 for (;? {
23 res = f_read(&fsrc, buffer, sizeof(buffer), &br);
24 if (res || br == 0) break; / 文件结束错误 /
25 res = f_write(&fdst, buffer, br, &bw);
26 if (res || bw < br) break; / 磁盘满错误 /
27 }
28
29 / 关闭打开的文件 /
30 f_close(&fsrc);
31 f_close(&fdst);
32
33 / 注销工作区(在废弃前) */
34 f_mount(0, NULL);
35 f_mount(1, NULL);
36 }