-
Notifications
You must be signed in to change notification settings - Fork 3k
fatfs: Add lower bound to block sizes #4843
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -160,6 +160,26 @@ 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; | ||
} | ||
|
||
MBED_ASSERT(ssize >= _MIN_SS && ssize <= _MAX_SS); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the assertions should be moved in the constructor, something like: MBED_ASSERT(bd->get_program_size() == bd->get_read_size()); The erase size should then be checked by There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The block device needs to be initialized before We could bring up the block device to check things before mounting, but since these are asserts anyways it's easier to just put them in the chan-disk layer. The assert for I did add some other checks on program/read size though 👍 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Alright, I forgot the fields are populated after the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The read/write paths are already bounded by the speed of the underlying block devices. In the read/program/erase funtions you will find similar asserts. If you are looking for speed can't you just compile in release mode? Release mode will disable these asserts, but they will still have been validated while developing. |
||
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) | ||
{ | ||
DWORD scount = _ffs[pdrv]->size() / disk_get_sector_size(pdrv); | ||
MBED_ASSERT(scount >= 64); | ||
return scount; | ||
} | ||
|
||
DSTATUS disk_status(BYTE pdrv) | ||
{ | ||
debug_if(FFS_DBG, "disk_status on pdrv [%d]\n", pdrv); | ||
|
@@ -175,15 +195,15 @@ 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; | ||
} | ||
|
||
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 +231,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: | ||
|
@@ -295,7 +313,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) { | ||
|
@@ -304,7 +322,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); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It probably makes sense to use
get_read_size
here (the invariant here is that read size == wirte size, right?) sinceget_erase_size()
can assume whatever value the HW reports and the block driver will act accordingly.The rounding to 512 isn't needed anymore since we found the erase size for that particular card isn't 128 but 64K, I think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For most of the other block devices an erase is required before programming (flash in particular). The SD card is the exception. If we program less than an erase block on NOR flash, the data will just become corrupted.
For the block device API, the
erase
function makes a block available for programming. Theget_erase_size
should return the smallest block size that can be rewritten. Since the FAT fs doesn't schedule erases seperately, it needs to erase a block during a write. So the sector size here is bounded to the underlying device'sget_erase_size
.The rounding to 512 is still useful for I2C EEPROM chips, which actually have
get_erase_size
of 1 byte.