]> granicus.if.org Git - esp-idf/commitdiff
spi_flash: Add vTaskDelay while a long erasing
authorKonstantin Kondrashov <konstantin@espressif.com>
Wed, 17 Apr 2019 01:18:11 +0000 (09:18 +0800)
committerbot <bot@espressif.com>
Tue, 23 Apr 2019 10:47:09 +0000 (10:47 +0000)
Added Kconfig options to enable yield operation during flash erase

Closes: https://github.com/espressif/esp-idf/issues/2083
Closes: IDFGH-261
components/spi_flash/Kconfig
components/spi_flash/flash_ops.c

index 7ffb5660a32eac87da0e0a2bee140461b590fa44..42d38eceb41d9d8c4c59393059b79ce061bf71df 100644 (file)
@@ -77,6 +77,28 @@ menu "SPI Flash driver"
                 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
 
 
index fa23e2a901124659fe941402778074afbabc23b5..7a5315cbf7ce1f1a94667bad4402fcc68f6471db 100644 (file)
@@ -34,6 +34,7 @@
 #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
@@ -224,6 +225,9 @@ esp_err_t IRAM_ATTR spi_flash_erase_range(uint32_t start_addr, uint32_t size)
     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);
@@ -235,6 +239,17 @@ esp_err_t IRAM_ATTR spi_flash_erase_range(uint32_t start_addr, uint32_t size)
                 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);