Remove erase in favor of trim

For better or worse, erase in the block device API is intended for flash
erases, which is a low-level operation that must occur before every
write and limits the write size of the underlying blocks. This is
different than the erase size found in SD cards, which does not limit
the write size for blocks.

Following the standard set by ATA and the ioctl function, we are adding
a seperate operation for the SD card erase behaviour named trim.

See for more info:
https://en.wikipedia.org/wiki/Trim_(computing)
pull/7774/head
Christopher Haster 2017-08-15 17:04:11 -05:00
parent 1d3fa9db3a
commit 69f3902e95
2 changed files with 21 additions and 28 deletions

View File

@ -545,9 +545,17 @@ int SDBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size)
return status; return status;
} }
int SDBlockDevice::erase(bd_addr_t addr, bd_size_t size) bool SDBlockDevice::_is_valid_trim(bd_addr_t addr, bd_size_t size)
{ {
if (!is_valid_erase(addr, size)) { return (
addr % _erase_size == 0 &&
size % _erase_size == 0 &&
addr + size <= this->size());
}
int SDBlockDevice::trim(bd_addr_t addr, bd_size_t size)
{
if (!_is_valid_trim(addr, size)) {
return SD_BLOCK_DEVICE_ERROR_PARAMETER; return SD_BLOCK_DEVICE_ERROR_PARAMETER;
} }
@ -558,15 +566,7 @@ int SDBlockDevice::erase(bd_addr_t addr, bd_size_t size)
} }
int status = BD_ERROR_OK; int status = BD_ERROR_OK;
// Toss out erases that are too small, this is fine as the block device api size -= _block_size;
// doesn't garuntee the final state of erased bytes and a following program
// will still work fine.
if (size < _erase_size) {
_lock.unlock();
return status;
}
size -= _erase_size;
// SDSC Card (CCS=0) uses byte unit address // SDSC Card (CCS=0) uses byte unit address
// SDHC and SDXC Cards (CCS=1) use block unit address (512 Bytes unit) // SDHC and SDXC Cards (CCS=1) use block unit address (512 Bytes unit)
if (SDCARD_V2HC == _card_type) { if (SDCARD_V2HC == _card_type) {
@ -600,11 +600,6 @@ bd_size_t SDBlockDevice::get_program_size() const
return _block_size; return _block_size;
} }
bd_size_t SDBlockDevice::get_erase_size() const
{
return _block_size;
}
bd_size_t SDBlockDevice::size() const bd_size_t SDBlockDevice::size() const
{ {
bd_size_t sectors = 0; bd_size_t sectors = 0;

View File

@ -85,15 +85,18 @@ public:
*/ */
virtual int program(const void *buffer, bd_addr_t addr, bd_size_t size); virtual int program(const void *buffer, bd_addr_t addr, bd_size_t size);
/** Erase blocks on a block device /** Mark blocks as no longer in use
* *
* The state of an erased block is undefined until it has been programmed * This function provides a hint to the underlying block device that a region of blocks
* is no longer in use and may be erased without side effects. Erase must still be called
* before programming, but trimming allows flash-translation-layers to schedule erases when
* the device is not busy.
* *
* @param addr Address of block to begin erasing * @param addr Address of block to mark as unused
* @param size Size to erase in bytes, must be a multiple of erase block size * @param size Size to mark as unused in bytes, must be a multiple of erase block size
* @return 0 on success, negative error code on failure * @return 0 on success, negative error code on failure
*/ */
virtual int erase(bd_addr_t addr, bd_size_t size); virtual int trim(bd_addr_t addr, bd_size_t size);
/** Get the size of a readable block /** Get the size of a readable block
* *
@ -108,13 +111,6 @@ public:
*/ */
virtual bd_size_t get_program_size() const; virtual bd_size_t get_program_size() const;
/** Get the size of a eraseable block
*
* @return Size of a eraseable block in bytes
* @note Must be a multiple of the program size
*/
virtual bd_size_t get_erase_size() const;
/** Get the total size of the underlying device /** Get the total size of the underlying device
* *
* @return Size of the underlying device in bytes * @return Size of the underlying device in bytes
@ -196,6 +192,8 @@ private:
uint32_t _sectors; uint32_t _sectors;
uint32_t _sd_sectors(); uint32_t _sd_sectors();
bool _is_valid_trim(bd_addr_t addr, bd_size_t size);
/* SPI functions */ /* SPI functions */
Timer _spi_timer; /**< Timer Class object used for busy wait */ Timer _spi_timer; /**< Timer Class object used for busy wait */
uint32_t _init_sck; /**< Intial SPI frequency */ uint32_t _init_sck; /**< Intial SPI frequency */