Просмотр исходного кода

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
KonstantinKondrashov 5 лет назад
Родитель
Сommit
98ac272a3f
2 измененных файлов с 36 добавлено и 0 удалено
  1. 22 0
      components/spi_flash/Kconfig
  2. 14 0
      components/spi_flash/flash_ops.c

+ 22 - 0
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

+ 14 - 0
components/spi_flash/flash_ops.c

@@ -35,6 +35,7 @@
 #include "esp_flash_partitions.h"
 #include "cache_utils.h"
 #include "esp_flash.h"
+#include "esp_timer.h"
 
 /* bytes erased by SPIEraseBlock() ROM function */
 #define BLOCK_ERASE_SIZE 65536
@@ -227,7 +228,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);
@@ -239,6 +246,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);