From 3cb655eaabd136700071c9225f33715ea4915917 Mon Sep 17 00:00:00 2001 From: KonstantinKondrashov Date: Thu, 2 Apr 2020 14:27:33 +0800 Subject: [PATCH] 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 --- components/spi_flash/Kconfig | 22 ++++++++++++++++++++++ components/spi_flash/flash_ops.c | 14 ++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/components/spi_flash/Kconfig b/components/spi_flash/Kconfig index 7135d076736f..c9dd305a1fc6 100644 --- a/components/spi_flash/Kconfig +++ b/components/spi_flash/Kconfig @@ -100,6 +100,28 @@ menu "SPI Flash driver" this option, and the lock will be bypassed on SPI1 bus. Otherwise if extra devices are needed to attach to SPI1 bus, enable this option. + 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 5629e2973067..91d77c77c7b5 100644 --- a/components/spi_flash/flash_ops.c +++ b/components/spi_flash/flash_ops.c @@ -44,6 +44,7 @@ #include "cache_utils.h" #include "esp_flash.h" #include "esp_attr.h" +#include "esp_timer.h" esp_rom_spiflash_result_t IRAM_ATTR spi_flash_write_encrypted_chip(size_t dest_addr, const void *src, size_t size); @@ -238,7 +239,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); @@ -250,6 +257,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);