spi_flash(LEGACY_IMPL): Add vTaskDelay while a long erasing

Added Kconfig options to enable yield operation during flash erase

Closes: https://github.com/espressif/esp-idf/issues/2083
Closes: https://github.com/espressif/esp-idf/issues/4916
Closes: IDFGH-261
This commit is contained in:
KonstantinKondrashov
2020-04-02 14:27:33 +08:00
parent f7a2bfc873
commit 1554fd3d8a
2 changed files with 36 additions and 0 deletions

View File

@@ -84,6 +84,28 @@ menu "SPI Flash driver"
The implementation of SPI flash has been greatly changed in IDF v4.0. The implementation of SPI flash has been greatly changed in IDF v4.0.
Enable this option to use the legacy implementation. 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" menu "Auto-detect flash chips"
config SPI_FLASH_SUPPORT_ISSI_CHIP config SPI_FLASH_SUPPORT_ISSI_CHIP

View File

@@ -42,6 +42,7 @@
#include "cache_utils.h" #include "cache_utils.h"
#include "esp_flash.h" #include "esp_flash.h"
#include "esp_attr.h" #include "esp_attr.h"
#include "esp_timer.h"
/* bytes erased by SPIEraseBlock() ROM function */ /* 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; esp_rom_spiflash_result_t rc;
rc = spi_flash_unlock(); rc = spi_flash_unlock();
if (rc == ESP_ROM_SPIFLASH_RESULT_OK) { 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; ) { 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(); spi_flash_guard_start();
if (sector % sectors_per_block == 0 && end - sector >= sectors_per_block) { if (sector % sectors_per_block == 0 && end - sector >= sectors_per_block) {
rc = esp_rom_spiflash_erase_block(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); COUNTER_ADD_BYTES(erase, SPI_FLASH_SEC_SIZE);
} }
spi_flash_guard_end(); 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); COUNTER_STOP(erase);