diff --git a/components/spi_flash/Kconfig b/components/spi_flash/Kconfig index 046146e006..18b60978f1 100644 --- a/components/spi_flash/Kconfig +++ b/components/spi_flash/Kconfig @@ -84,6 +84,28 @@ menu "SPI Flash driver" The implementation of SPI flash has been greatly changed in IDF v4.0. Enable this option to use the legacy implementation. + config SPI_FLASH_YIELD_DURING_ERASE + bool "Enables yield operation during flash erase" + default y + help + This allows to yield the CPUs between erase commands. + Prevents starvation of other tasks. + + config SPI_FLASH_ERASE_YIELD_DURATION_MS + int "Duration of erasing to yield CPUs (ms)" + depends on SPI_FLASH_YIELD_DURING_ERASE + default 20 + help + If a duration of one erase command is large + then it will yield CPUs after finishing a current command. + + config SPI_FLASH_ERASE_YIELD_TICKS + int "CPU release time (tick)" + depends on SPI_FLASH_YIELD_DURING_ERASE + default 1 + help + Defines how many ticks will be before returning to continue a erasing. + menu "Auto-detect flash chips" config SPI_FLASH_SUPPORT_ISSI_CHIP diff --git a/components/spi_flash/flash_ops.c b/components/spi_flash/flash_ops.c index a8ffc78106..105d2b4c09 100644 --- a/components/spi_flash/flash_ops.c +++ b/components/spi_flash/flash_ops.c @@ -42,6 +42,7 @@ #include "cache_utils.h" #include "esp_flash.h" #include "esp_attr.h" +#include "esp_timer.h" /* bytes erased by SPIEraseBlock() ROM function */ @@ -235,7 +236,13 @@ esp_err_t IRAM_ATTR spi_flash_erase_range(size_t start_addr, size_t size) esp_rom_spiflash_result_t rc; rc = spi_flash_unlock(); if (rc == ESP_ROM_SPIFLASH_RESULT_OK) { +#ifdef CONFIG_SPI_FLASH_YIELD_DURING_ERASE + int64_t no_yield_time_us = 0; +#endif for (size_t sector = start; sector != end && rc == ESP_ROM_SPIFLASH_RESULT_OK; ) { +#ifdef CONFIG_SPI_FLASH_YIELD_DURING_ERASE + int64_t start_time_us = esp_timer_get_time(); +#endif spi_flash_guard_start(); if (sector % sectors_per_block == 0 && end - sector >= sectors_per_block) { rc = esp_rom_spiflash_erase_block(sector / sectors_per_block); @@ -247,6 +254,13 @@ esp_err_t IRAM_ATTR spi_flash_erase_range(size_t start_addr, size_t size) COUNTER_ADD_BYTES(erase, SPI_FLASH_SEC_SIZE); } spi_flash_guard_end(); +#ifdef CONFIG_SPI_FLASH_YIELD_DURING_ERASE + no_yield_time_us += (esp_timer_get_time() - start_time_us); + if (no_yield_time_us / 1000 >= CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS) { + no_yield_time_us = 0; + vTaskDelay(CONFIG_SPI_FLASH_ERASE_YIELD_TICKS); + } +#endif } } COUNTER_STOP(erase);