Code: Select all
foreach sector: sector_range
flashStartEraseSector(sector)
flashWaitErase()
Most flash devices have variable sector sizes for erase. The above operation would use the default sector size as described in the flash_descriptor_t. Using the default sector size could be 10x slower, than optimally erasing the address range using a combination of sector sizes (which only the LLD is aware of).
I propose adding the following to BaseFlash methods:
Code: Select all
flash_error_t (*erase_range)(void *instance, flash_offset_t off, size_t n, void (*cb)(msg_t progress))
This would be a blocking call. As you can see, I also propose adding a callback in the function parameters to call a user specified routine between sector erases (as the LLD is looping thru erasing sectors). This is important because the erase operation could take a long time, and could trip an application watchdog. It could additionally provide a progress counter with the sectors remaining (or make it a float with percentage - as the application layer wouldn't know how to translate sectors remaining into a progress indicator).
Below is an example for an snor device I use:
Code: Select all
flash_error_t snor_device_erase_range(void *instance, flash_offset_t off, size_t n, void (*watchdog)(void)) {
SNORDriver * devp = instance;
size_t len_masked = n & ~SECTOR_4K_MASK;
size_t off_masked = off & ~SECTOR_4K_MASK;
osalDbgCheck(n == len_masked);
osalDbgCheck(off == off_masked);
size_t cur_off = off_masked;
flash_error_t err;
uint32_t cmd;
while (cur_off < (off + n - 1U))
{
size_t rco4k, rco32k, rco64k; // round current offset up
size_t erase_len;
rco4k = ROUND_UP_PWR2(cur_off, 4U*1024U);
rco32k = ROUND_UP_PWR2(cur_off, 32U*1024U);
rco64k = ROUND_UP_PWR2(cur_off, 64U*1024U);
if((cur_off == rco64k) && ((cur_off + 64U*1024U) <= (off + n)))
{
cmd = IS25LP256D_CMD_4BER64;
erase_len = 64U*1024U;
}
else if((cur_off == rco32k) && ((cur_off + 32U*1024U) <= (off + n)))
{
cmd = IS25LP256D_CMD_4BER32;
erase_len = 32U*1024U;
}
else if ((cur_off == rco4k) && ((cur_off + 4U*1024U) <= (off + n)))
{
cmd = IS25LP256D_CMD_4SER;
erase_len = 4U*1024U;
}
else
{
osalDbgCheck(false);
return FLASH_ERROR_ERASE;
}
/* Enabling write operation.*/
bus_cmd(devp->config->busp, IS25LP256D_CMD_WREN);
/* Sector erase command.*/
bus_cmd_addr(devp->config->busp, cmd, cur_off);
err = flashWaitErase((BaseFlash *)instance);
if (err != FLASH_NO_ERROR)
{
return err;
}
cur_off += erase_len;
if (watchdog != NULL)
{
(*watchdog)();
}
}
return FLASH_NO_ERROR;
}