bool "Allowed"
endchoice
+ 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.
+
endmenu
#include "esp_flash_partitions.h"
#include "esp_ota_ops.h"
#include "cache_utils.h"
+#include "esp_timer.h"
/* bytes erased by SPIEraseBlock() ROM function */
#define BLOCK_ERASE_SIZE 65536
rc = spi_flash_unlock();
if (rc == ESP_ROM_SPIFLASH_RESULT_OK) {
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);
COUNTER_ADD_BYTES(erase, SPI_FLASH_SEC_SIZE);
}
spi_flash_guard_end();
+#ifdef CONFIG_SPI_FLASH_YIELD_DURING_ERASE
+ int dt_ms = (esp_timer_get_time() - start_time_us) / 1000;
+ if (dt_ms >= CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS ||
+ dt_ms * 2 >= CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS) {
+ /* For example when dt_ms = 15 and CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS = 20.
+ * In this case we need to call vTaskDelay because
+ * the duration of this command + the next command probably will exceed more than 20.
+ */
+ vTaskDelay(CONFIG_SPI_FLASH_ERASE_YIELD_TICKS);
+ }
+#endif
}
}
COUNTER_STOP(erase);