From f927996275d6406745c3a67d645b0d40ce016986 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Fri, 21 Apr 2017 04:03:28 -0500 Subject: [PATCH 1/3] fatfs: Added lower bound to block sizes Some block devices (for example I2C EEPROM) can be erased at the byte level. These aren't really block devices, but fall under the block device API. For these devices, the fat filesystem needs to use a lower bound on the block size. In this case we used 512 bytes is used since it is already a standard. --- features/filesystem/fat/FATFileSystem.cpp | 25 +++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/features/filesystem/fat/FATFileSystem.cpp b/features/filesystem/fat/FATFileSystem.cpp index 3fa35ecaaf..a936a03419 100644 --- a/features/filesystem/fat/FATFileSystem.cpp +++ b/features/filesystem/fat/FATFileSystem.cpp @@ -160,6 +160,21 @@ void ff_memfree(void *p) } // Implementation of diskio functions (see ChaN/diskio.h) +static WORD disk_get_sector_size(BYTE pdrv) +{ + WORD ssize = _ffs[pdrv]->get_erase_size(); + if (ssize < 512) { + ssize = 512; + } + + return ssize; +} + +static DWORD disk_get_sector_count(BYTE pdrv) +{ + return _ffs[pdrv]->size() / disk_get_sector_size(pdrv); +} + DSTATUS disk_status(BYTE pdrv) { debug_if(FFS_DBG, "disk_status on pdrv [%d]\n", pdrv); @@ -175,7 +190,7 @@ DSTATUS disk_initialize(BYTE pdrv) DRESULT disk_read(BYTE pdrv, BYTE *buff, DWORD sector, UINT count) { debug_if(FFS_DBG, "disk_read(sector %d, count %d) on pdrv [%d]\n", sector, count, pdrv); - bd_size_t ssize = _ffs[pdrv]->get_erase_size(); + DWORD ssize = disk_get_sector_size(pdrv); int err = _ffs[pdrv]->read(buff, sector*ssize, count*ssize); return err ? RES_PARERR : RES_OK; } @@ -183,7 +198,7 @@ DRESULT disk_read(BYTE pdrv, BYTE *buff, DWORD sector, UINT count) DRESULT disk_write(BYTE pdrv, const BYTE *buff, DWORD sector, UINT count) { debug_if(FFS_DBG, "disk_write(sector %d, count %d) on pdrv [%d]\n", sector, count, pdrv); - bd_size_t ssize = _ffs[pdrv]->get_erase_size(); + DWORD ssize = disk_get_sector_size(pdrv); int err = _ffs[pdrv]->erase(sector*ssize, count*ssize); if (err) { return RES_PARERR; @@ -211,16 +226,14 @@ DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff) if (_ffs[pdrv] == NULL) { return RES_NOTRDY; } else { - DWORD count = _ffs[pdrv]->size() / _ffs[pdrv]->get_erase_size(); - *((DWORD*)buff) = count; + *((DWORD*)buff) = disk_get_sector_count(pdrv); return RES_OK; } case GET_SECTOR_SIZE: if (_ffs[pdrv] == NULL) { return RES_NOTRDY; } else { - WORD size = _ffs[pdrv]->get_erase_size(); - *((WORD*)buff) = size; + *((WORD*)buff) = disk_get_sector_size(pdrv); return RES_OK; } case GET_BLOCK_SIZE: From a153dc625c3e65ff284769712e258f37ed863f0f Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Tue, 15 Aug 2017 13:58:01 -0500 Subject: [PATCH 2/3] fatfs: Changed documentation of format to emphasize byte clusters --- features/filesystem/fat/FATFileSystem.cpp | 4 ++-- features/filesystem/fat/FATFileSystem.h | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/features/filesystem/fat/FATFileSystem.cpp b/features/filesystem/fat/FATFileSystem.cpp index a936a03419..f39029686b 100644 --- a/features/filesystem/fat/FATFileSystem.cpp +++ b/features/filesystem/fat/FATFileSystem.cpp @@ -308,7 +308,7 @@ int FATFileSystem::unmount() /* See http://elm-chan.org/fsw/ff/en/mkfs.html for details of f_mkfs() and * associated arguments. */ -int FATFileSystem::format(BlockDevice *bd, int allocation_unit) { +int FATFileSystem::format(BlockDevice *bd, bd_size_t cluster_size) { FATFileSystem fs; int err = fs.mount(bd, false); if (err) { @@ -317,7 +317,7 @@ int FATFileSystem::format(BlockDevice *bd, int allocation_unit) { // Logical drive number, Partitioning rule, Allocation unit size (bytes per cluster) fs.lock(); - FRESULT res = f_mkfs(fs._fsid, 1, allocation_unit); + FRESULT res = f_mkfs(fs._fsid, 1, cluster_size); fs.unlock(); if (res != FR_OK) { return fat_error_remap(res); diff --git a/features/filesystem/fat/FATFileSystem.h b/features/filesystem/fat/FATFileSystem.h index d46535b9c4..6324093e07 100644 --- a/features/filesystem/fat/FATFileSystem.h +++ b/features/filesystem/fat/FATFileSystem.h @@ -49,18 +49,18 @@ public: * The block device to format should be mounted when this function is called. * * @param bd - * This is the block device that will be formated. + * This is the block device that will be formatted. * - * @param allocation_unit - * This is the number of bytes per cluster size. The valid value is N - * times the sector size. N is a power of 2 from 1 to 128 for FAT - * volume and upto 16MiB for exFAT volume. If zero is given, - * the default allocation unit size is selected by the underlying - * filesystem, which depends on the volume size. + * @param cluster_size + * This is the number of bytes per cluster. A larger cluster size will decrease + * the overhead of the FAT table, but also increase the minimum file size. The + * cluster_size must be a multiple of the underlying device's allocation unit + * and is currently limited to a max of 32,768 bytes. If zero, a cluster size + * will be determined from the device's allocation unit. Defaults to zero. * * @return 0 on success, negative error code on failure */ - static int format(BlockDevice *bd, int allocation_unit = 0); + static int format(BlockDevice *bd, bd_size_t cluster_size = 0); /** Mounts a filesystem to a block device * From 626256e1047df9217eae344f5bea93d40c8a2d43 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Fri, 18 Aug 2017 11:03:18 -0500 Subject: [PATCH 3/3] fatfs: Added some asserts on block device geometry --- features/filesystem/fat/FATFileSystem.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/features/filesystem/fat/FATFileSystem.cpp b/features/filesystem/fat/FATFileSystem.cpp index f39029686b..2a0feddd81 100644 --- a/features/filesystem/fat/FATFileSystem.cpp +++ b/features/filesystem/fat/FATFileSystem.cpp @@ -167,12 +167,17 @@ static WORD disk_get_sector_size(BYTE pdrv) ssize = 512; } + MBED_ASSERT(ssize >= _MIN_SS && ssize <= _MAX_SS); + MBED_ASSERT(_ffs[pdrv]->get_read_size() <= _ffs[pdrv]->get_erase_size()); + MBED_ASSERT(_ffs[pdrv]->get_program_size() <= _ffs[pdrv]->get_erase_size()); return ssize; } static DWORD disk_get_sector_count(BYTE pdrv) { - return _ffs[pdrv]->size() / disk_get_sector_size(pdrv); + DWORD scount = _ffs[pdrv]->size() / disk_get_sector_size(pdrv); + MBED_ASSERT(scount >= 64); + return scount; } DSTATUS disk_status(BYTE pdrv)