diff --git a/bdk/libs/fatfs/ff.c b/bdk/libs/fatfs/ff.c index 81e951da..c6b05e3c 100644 --- a/bdk/libs/fatfs/ff.c +++ b/bdk/libs/fatfs/ff.c @@ -3933,15 +3933,12 @@ FRESULT f_read_fast ( { FRESULT res; FATFS *fs; - UINT csize_bytes; - DWORD clst; - UINT count = 0; + UINT csize_bytes, count; + DWORD clst, work_bytes; FSIZE_t work_sector = 0; FSIZE_t sector_base = 0; BYTE *wbuff = (BYTE*)buff; - // TODO support sector reading inside a cluster - res = validate(&fp->obj, &fs); /* Check validity of the file object */ if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) { EFSPRINTF("FOV"); @@ -3951,9 +3948,15 @@ FRESULT f_read_fast ( if (!(fp->flag & FA_READ)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */ FSIZE_t remain = fp->obj.objsize - fp->fptr; if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */ + if (!btr) + goto out; csize_bytes = fs->csize * SS(fs); + //!TODO: support sector reading inside a cluster + DWORD csect = (UINT)((fp->fptr / SS(fs)) & (fs->csize - 1)); /* Sector offset in the cluster */ + if (csect) { EFSPRINTF("ICSR"); ABORT(fs, FR_INT_ERR); } + if (!fp->fptr) { /* On the top of the file? */ clst = fp->obj.sclust; /* Follow from the origin */ } else { @@ -3966,9 +3969,10 @@ FRESULT f_read_fast ( fp->clust = clst; /* Set working cluster */ sector_base = clst2sect(fs, fp->clust); - count += fs->csize; - btr -= csize_bytes; - fp->fptr += csize_bytes; + work_bytes = MIN(btr, csize_bytes); + count = work_bytes / SS(fs); + fp->fptr += work_bytes; + btr -= work_bytes; while (btr) { clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */ @@ -3979,26 +3983,27 @@ FRESULT f_read_fast ( fp->clust = clst; work_sector = clst2sect(fs, fp->clust); - if ((work_sector - sector_base) == count) count += fs->csize; + work_bytes = MIN(btr, csize_bytes); + if ((work_sector - sector_base) == count) count += work_bytes / SS(fs); else { if (disk_read(fs->pdrv, wbuff, sector_base, count) != RES_OK) ABORT(fs, FR_DISK_ERR); wbuff += count * SS(fs); sector_base = work_sector; - count = fs->csize; + count = work_bytes / SS(fs); } - fp->fptr += MIN(btr, csize_bytes); - btr -= MIN(btr, csize_bytes); - - // TODO: what about if data is smaller than cluster? - // Must read-write back that cluster. - - if (!btr) { /* Final cluster/sectors read. */ - if (disk_read(fs->pdrv, wbuff, sector_base, count) != RES_OK) ABORT(fs, FR_DISK_ERR); - } + fp->fptr += work_bytes; + btr -= work_bytes; } + if (!btr) { /* Final cluster/sectors read. */ + if (work_bytes % SS(fs)) + count++; /* Read an extra block. Expects buffer being big enough. */ + if (disk_read(fs->pdrv, wbuff, sector_base, count) != RES_OK) ABORT(fs, FR_DISK_ERR); + } + +out: LEAVE_FF(fs, FR_OK); } #endif @@ -4158,15 +4163,12 @@ FRESULT f_write_fast ( { FRESULT res; FATFS *fs; - UINT csize_bytes; - DWORD clst; - UINT count = 0; + UINT csize_bytes, count; + DWORD clst, work_bytes; FSIZE_t work_sector = 0; FSIZE_t sector_base = 0; const BYTE *wbuff = (const BYTE*)buff; - // TODO support sector writing inside a cluster - res = validate(&fp->obj, &fs); /* Check validity of the file object */ if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) { EFSPRINTF("FOV"); @@ -4174,6 +4176,9 @@ FRESULT f_write_fast ( } if (!(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */ + if (!btw) + goto out; + /* Check fptr wrap-around (file size cannot reach 4 GiB at FAT volume) */ if ((!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) && (DWORD)(fp->fptr + btw) < (DWORD)fp->fptr) { btw = (UINT)(0xFFFFFFFF - (DWORD)fp->fptr); @@ -4181,22 +4186,26 @@ FRESULT f_write_fast ( csize_bytes = fs->csize * SS(fs); + // TODO support sector writing inside a cluster + DWORD csect = (UINT)((fp->fptr / SS(fs)) & (fs->csize - 1)); /* Sector offset in the cluster */ + if (csect) { EFSPRINTF("ICSR"); ABORT(fs, FR_INT_ERR); } + if (!fp->fptr) { /* On the top of the file? */ clst = fp->obj.sclust; /* Follow from the origin */ } else { if (fp->cltbl) clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */ else { EFSPRINTF("CLTBL"); ABORT(fs, FR_CLTBL_NO_INIT); } } - if (clst < 2) { EFSPRINTF("CCHK"); ABORT(fs, FR_INT_ERR); } else if (clst == 0xFFFFFFFF) { EFSPRINTF("DERR"); ABORT(fs, FR_DISK_ERR); } fp->clust = clst; /* Set working cluster */ sector_base = clst2sect(fs, fp->clust); - count += fs->csize; - btw -= csize_bytes; - fp->fptr += csize_bytes; + work_bytes = MIN(btw, csize_bytes); + count = work_bytes / SS(fs); + fp->fptr += work_bytes; + btw -= work_bytes; while (btw) { clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */ @@ -4207,28 +4216,30 @@ FRESULT f_write_fast ( fp->clust = clst; work_sector = clst2sect(fs, fp->clust); - if ((work_sector - sector_base) == count) count += fs->csize; + work_bytes = MIN(btw, csize_bytes); + if ((work_sector - sector_base) == count) count += work_bytes / SS(fs); else { if (disk_write(fs->pdrv, wbuff, sector_base, count) != RES_OK) ABORT(fs, FR_DISK_ERR); wbuff += count * SS(fs); sector_base = work_sector; - count = fs->csize; + count = work_bytes / SS(fs); } - fp->fptr += MIN(btw, csize_bytes); - btw -= MIN(btw, csize_bytes); + fp->fptr += work_bytes; + btw -= work_bytes; + } - // what about if data is smaller than cluster? - // Probably must read-write back that cluster. - if (!btw) { /* Final cluster/sectors write. */ - if (disk_write(fs->pdrv, wbuff, sector_base, count) != RES_OK) ABORT(fs, FR_DISK_ERR); - fp->flag &= (BYTE)~FA_DIRTY; - } + if (!btw) { /* Final cluster/sectors write. */ + if (work_bytes % SS(fs)) + count++; /* Write an extra block. Cluster is always > storage block. */ + if (disk_write(fs->pdrv, wbuff, sector_base, count) != RES_OK) ABORT(fs, FR_DISK_ERR); + fp->flag &= (BYTE)~FA_DIRTY; } fp->flag |= FA_MODIFIED; /* Set file change flag */ +out: LEAVE_FF(fs, FR_OK); } #endif @@ -6754,7 +6765,6 @@ int f_puts ( { putbuff pb; - if (str == (void *)0) return EOF; /* String is NULL */ putc_init(&pb, fp); @@ -6782,7 +6792,6 @@ int f_printf ( DWORD v; TCHAR c, d, str[32], *p; - if (fmt == (void *)0) return EOF; /* String is NULL */ putc_init(&pb, fp); diff --git a/bdk/libs/fatfs/ff.h b/bdk/libs/fatfs/ff.h index 3a6c4238..720fee6c 100644 --- a/bdk/libs/fatfs/ff.h +++ b/bdk/libs/fatfs/ff.h @@ -264,8 +264,10 @@ FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode); /* Open or create a f FRESULT f_close (FIL* fp); /* Close an open file object */ FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br); /* Read data from the file */ FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw); /* Write data to the file */ +#if FF_FASTFS /* buff needs to be block aligned. Intercluster data access is not supported. */ FRESULT f_read_fast (FIL* fp, const void* buff, UINT btr); /* Fast read data from the file */ FRESULT f_write_fast (FIL* fp, const void* buff, UINT btw); /* Fast write data to the file */ +#endif FRESULT f_lseek (FIL* fp, FSIZE_t ofs); /* Move file pointer of the file object */ FRESULT f_truncate (FIL* fp); /* Truncate the file */ FRESULT f_sync (FIL* fp); /* Flush cached data of the writing file */ @@ -287,7 +289,9 @@ FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs); /* Get numbe FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn); /* Get volume label */ FRESULT f_setlabel (const TCHAR* label); /* Set volume label */ FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */ +#if FF_FASTFS DWORD *f_expand_cltbl (FIL* fp, UINT tblsz, FSIZE_t ofs); /* Expand file and populate cluster table */ +#endif FRESULT f_expand (FIL* fp, FSIZE_t fsz, BYTE opt); /* Allocate a contiguous block to the file */ FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */ FRESULT f_mkfs (const TCHAR* path, BYTE opt, DWORD au, void* work, UINT len); /* Create a FAT volume */