Page 1 of 1

BaseFlash: Add erase_range

Posted: Mon Oct 31, 2022 5:01 pm
by faisal
I need to be able to erase a range of flash. Currently the only way to do it at the application layer would be something like this:

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;
}

Re: BaseFlash: Add erase_range

Posted: Mon Oct 31, 2022 6:35 pm
by faisal
Just thinking about it, the callback should include the number of bytes erased thus far. That should do it ... the application would know the progress as it provided the erase range to begin with.

Re: BaseFlash: Add erase_range

Posted: Mon Oct 31, 2022 6:52 pm
by faisal
Of course the snor erase range code I provided was buggy, lol. I updated the first post with a hopefully corrected version - but anyways, you get the point.