FAT: Added support for block sizes of 512-4096 bytes

This is necessary for support of block devices with >512 byte
blocks, such as most SPI flash parts.

- Enabled support of up to 4096 byte blocks
- Added support for heap-backed buffers using _FS_HEAPBUF
  - Necessary to avoid stack overflows
  - Avoids over-aggresive allocations of _MAX_SS
- Enabled _FS_TINY to further reduce memory footprint
  - Haven't found a downside for this yet except for possible
    thread contention
pull/3972/head
Christopher Haster 2017-03-20 15:05:55 -05:00 committed by Martin Kojtal
parent 5f138810a9
commit c0aa841ffd
4 changed files with 62 additions and 6 deletions

View File

@ -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 _MAX_SS != _MIN_SS /* Get sector size (multiple sector size cfg only) */
if (disk_ioctl(fs->drv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK if (disk_ioctl(fs->drv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK
|| SS(fs) < _MIN_SS || SS(fs) > _MAX_SS) return FR_DISK_ERR; || 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 #endif
/* Find an FAT partition on the drive. Supports only generic partitioning, FDISK and SFD. */ /* Find an FAT partition on the drive. Supports only generic partitioning, FDISK and SFD. */
bsect = 0; bsect = 0;
@ -2423,12 +2430,18 @@ FRESULT f_mount (
if (!ff_del_syncobj(cfs->sobj)) return FR_INT_ERR; if (!ff_del_syncobj(cfs->sobj)) return FR_INT_ERR;
#endif #endif
cfs->fs_type = 0; /* Clear old fs object */ cfs->fs_type = 0; /* Clear old fs object */
#if _FS_HEAPBUF
ff_memfree(cfs->win); /* Clean up window buffer */
#endif
} }
if (fs) { if (fs) {
fs->fs_type = 0; /* Clear new fs object */ fs->fs_type = 0; /* Clear new fs object */
#if _FS_REENTRANT /* Create sync object for the new volume */ #if _FS_REENTRANT /* Create sync object for the new volume */
if (!ff_cre_syncobj((BYTE)vol, &fs->sobj)) return FR_INT_ERR; 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 #endif
} }
FatFs[vol] = fs; /* Register new fs object */ FatFs[vol] = fs; /* Register new fs object */
@ -2570,6 +2583,11 @@ FRESULT f_open (
#endif #endif
fp->fs = dj.fs; /* Validate file object */ fp->fs = dj.fs; /* Validate file object */
fp->id = fp->fs->id; 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 */ fp->fs = 0; /* Invalidate file object */
#if _FS_REENTRANT #if _FS_REENTRANT
unlock_fs(fs, FR_OK); /* Unlock volume */ unlock_fs(fs, FR_OK); /* Unlock volume */
#endif
#if !_FS_TINY && _FS_HEAPBUF
ff_memfree(fp->buf); /* Deallocate buffer */
#endif #endif
} }
} }
@ -4112,6 +4133,13 @@ FRESULT f_mkfs (
#if _MAX_SS != _MIN_SS /* Get disk sector size */ #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) if (disk_ioctl(pdrv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK || SS(fs) > _MAX_SS || SS(fs) < _MIN_SS)
return FR_DISK_ERR; 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 #endif
if (_MULTI_PARTITION && part) { if (_MULTI_PARTITION && part) {
/* Get partition information from partition table in the MBR */ /* Get partition information from partition table in the MBR */

View File

@ -104,7 +104,11 @@ typedef struct {
DWORD dirbase; /* Root directory start sector (FAT32:Cluster#) */ DWORD dirbase; /* Root directory start sector (FAT32:Cluster#) */
DWORD database; /* Data start sector */ DWORD database; /* Data start sector */
DWORD winsect; /* Current sector appearing in the win[] */ 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) */ BYTE win[_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */
#endif
} FATFS; } FATFS;
@ -132,8 +136,12 @@ typedef struct {
UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */ UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */
#endif #endif
#if !_FS_TINY #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 */ BYTE buf[_MAX_SS]; /* File private data read/write window */
#endif #endif
#endif
} FIL; } FIL;
@ -264,14 +272,16 @@ TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the fil
DWORD get_fattime (void); DWORD get_fattime (void);
#endif #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 */ /* Unicode support functions */
#if _USE_LFN /* Unicode - OEM code conversion */ #if _USE_LFN /* Unicode - OEM code conversion */
WCHAR ff_convert (WCHAR chr, UINT dir); /* OEM-Unicode bidirectional conversion */ WCHAR ff_convert (WCHAR chr, UINT dir); /* OEM-Unicode bidirectional conversion */
WCHAR ff_wtoupper (WCHAR chr); /* Unicode upper-case 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 #endif
/* Sync functions */ /* Sync functions */

View File

@ -162,7 +162,7 @@
#define _MIN_SS 512 #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, /* 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 / 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 / harddisk. But a larger value may be required for on-board flash memory and some
@ -194,7 +194,7 @@
/ System Configurations / System Configurations
/---------------------------------------------------------------------------*/ /---------------------------------------------------------------------------*/
#define _FS_TINY 0 #define _FS_TINY 1
/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny) /* 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 / 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, / bytes. Instead of private sector buffer eliminated from the file object,
@ -202,6 +202,14 @@
/ data transfer. */ / 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 _FS_NORTC 0
#define _NORTC_MON 1 #define _NORTC_MON 1
#define _NORTC_MDAY 1 #define _NORTC_MDAY 1

View File

@ -146,6 +146,16 @@ DWORD get_fattime(void)
| (DWORD)(ptm->tm_sec/2 ); | (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) // Implementation of diskio functions (see ChaN/diskio.h)
DSTATUS disk_status(BYTE pdrv) DSTATUS disk_status(BYTE pdrv)
{ {