diff --git a/features/filesystem/fat/ChaN/ff.cpp b/features/filesystem/fat/ChaN/ff.cpp index db660f7e830..36389482886 100644 --- a/features/filesystem/fat/ChaN/ff.cpp +++ b/features/filesystem/fat/ChaN/ff.cpp @@ -2249,6 +2249,13 @@ FRESULT find_volume ( /* FR_OK(0): successful, !=0: any error occurred */ #if _MAX_SS != _MIN_SS /* Get sector size (multiple sector size cfg only) */ if (disk_ioctl(fs->drv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK || SS(fs) < _MIN_SS || SS(fs) > _MAX_SS) return FR_DISK_ERR; +#endif +#if _FS_HEAPBUF + if (!fs->win) { + fs->win = (BYTE*)ff_memalloc(SS(fs)); /* Allocate buffer to back window if necessary */ + if (!fs->win) + return FR_NOT_ENOUGH_CORE; + } #endif /* Find an FAT partition on the drive. Supports only generic partitioning, FDISK and SFD. */ bsect = 0; @@ -2423,12 +2430,18 @@ FRESULT f_mount ( if (!ff_del_syncobj(cfs->sobj)) return FR_INT_ERR; #endif cfs->fs_type = 0; /* Clear old fs object */ +#if _FS_HEAPBUF + ff_memfree(cfs->win); /* Clean up window buffer */ +#endif } if (fs) { fs->fs_type = 0; /* Clear new fs object */ #if _FS_REENTRANT /* Create sync object for the new volume */ if (!ff_cre_syncobj((BYTE)vol, &fs->sobj)) return FR_INT_ERR; +#endif +#if _FS_HEAPBUF + fs->win = 0; /* NULL buffer to prevent use of uninitialized buffer */ #endif } FatFs[vol] = fs; /* Register new fs object */ @@ -2570,6 +2583,11 @@ FRESULT f_open ( #endif fp->fs = dj.fs; /* Validate file object */ fp->id = fp->fs->id; +#if !_FS_TINY && _FS_HEAPBUF + fp->buf = (BYTE*)ff_memalloc(SS(dj.fs)); /* Allocate buffer if necessary */ + if (!fp->buf) + return FR_NOT_ENOUGH_CORE; +#endif } } @@ -2892,6 +2910,9 @@ FRESULT f_close ( fp->fs = 0; /* Invalidate file object */ #if _FS_REENTRANT unlock_fs(fs, FR_OK); /* Unlock volume */ +#endif +#if !_FS_TINY && _FS_HEAPBUF + ff_memfree(fp->buf); /* Deallocate buffer */ #endif } } @@ -4112,6 +4133,13 @@ FRESULT f_mkfs ( #if _MAX_SS != _MIN_SS /* Get disk sector size */ if (disk_ioctl(pdrv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK || SS(fs) > _MAX_SS || SS(fs) < _MIN_SS) return FR_DISK_ERR; +#endif +#if _FS_HEAPBUF + if (!fs->win) { + fs->win = (BYTE*)ff_memalloc(SS(fs)); /* Allocate buffer to back window if necessary */ + if (!fs->win) + return FR_NOT_ENOUGH_CORE; + } #endif if (_MULTI_PARTITION && part) { /* Get partition information from partition table in the MBR */ diff --git a/features/filesystem/fat/ChaN/ff.h b/features/filesystem/fat/ChaN/ff.h index da823dc3da9..3653a807708 100644 --- a/features/filesystem/fat/ChaN/ff.h +++ b/features/filesystem/fat/ChaN/ff.h @@ -104,7 +104,11 @@ typedef struct { DWORD dirbase; /* Root directory start sector (FAT32:Cluster#) */ DWORD database; /* Data start sector */ DWORD winsect; /* Current sector appearing in the win[] */ +#if _FS_HEAPBUF + BYTE *win; /* Disk access window for Directory, FAT (and file data at tiny cfg) */ +#else BYTE win[_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */ +#endif } FATFS; @@ -132,8 +136,12 @@ typedef struct { UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */ #endif #if !_FS_TINY +#if _FS_HEAPBUF + BYTE *buf; /* File private data read/write window */ +#else BYTE buf[_MAX_SS]; /* File private data read/write window */ #endif +#endif } FIL; @@ -264,14 +272,16 @@ TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the fil DWORD get_fattime (void); #endif +/* Memory functions */ +#if _USE_LFN == 3 || _FS_HEAPBUF +void* ff_memalloc (UINT msize); /* Allocate memory block */ +void ff_memfree (void* mblock); /* Free memory block */ +#endif + /* Unicode support functions */ #if _USE_LFN /* Unicode - OEM code conversion */ WCHAR ff_convert (WCHAR chr, UINT dir); /* OEM-Unicode bidirectional conversion */ WCHAR ff_wtoupper (WCHAR chr); /* Unicode upper-case conversion */ -#if _USE_LFN == 3 /* Memory functions */ -void* ff_memalloc (UINT msize); /* Allocate memory block */ -void ff_memfree (void* mblock); /* Free memory block */ -#endif #endif /* Sync functions */ diff --git a/features/filesystem/fat/ChaN/ffconf.h b/features/filesystem/fat/ChaN/ffconf.h index b1e5a616210..9d461c1e260 100644 --- a/features/filesystem/fat/ChaN/ffconf.h +++ b/features/filesystem/fat/ChaN/ffconf.h @@ -162,7 +162,7 @@ #define _MIN_SS 512 -#define _MAX_SS 512 +#define _MAX_SS 4096 /* These options configure the range of sector size to be supported. (512, 1024, / 2048 or 4096) Always set both 512 for most systems, all type of memory cards and / harddisk. But a larger value may be required for on-board flash memory and some @@ -194,7 +194,7 @@ / System Configurations /---------------------------------------------------------------------------*/ -#define _FS_TINY 0 +#define _FS_TINY 1 /* This option switches tiny buffer configuration. (0:Normal or 1:Tiny) / At the tiny configuration, size of the file object (FIL) is reduced _MAX_SS / bytes. Instead of private sector buffer eliminated from the file object, @@ -202,6 +202,14 @@ / data transfer. */ +#define _FS_HEAPBUF 1 +/* This option enables the use of the heap for allocating buffers. Otherwise +/ _MAX_SS sized buffers are allocated statically in relevant structures (in +/ FATFS if _FS_TINY, otherwise in FATFS and FIL) +/ This option allows the filesystem to dynamically allocate the buffers based +/ on underlying sector size. */ + + #define _FS_NORTC 0 #define _NORTC_MON 1 #define _NORTC_MDAY 1 diff --git a/features/filesystem/fat/FATFileSystem.cpp b/features/filesystem/fat/FATFileSystem.cpp index 9706f196b81..caf04a7da4f 100644 --- a/features/filesystem/fat/FATFileSystem.cpp +++ b/features/filesystem/fat/FATFileSystem.cpp @@ -146,6 +146,16 @@ DWORD get_fattime(void) | (DWORD)(ptm->tm_sec/2 ); } +void *ff_memalloc(UINT size) +{ + return malloc(size); +} + +void ff_memfree(void *p) +{ + free(p); +} + // Implementation of diskio functions (see ChaN/diskio.h) DSTATUS disk_status(BYTE pdrv) {