]> granicus.if.org Git - esp-idf/commitdiff
espcoredump: fix issue with spi_flash access
authorAlex Lisitsyn <aleks@espressif.com>
Fri, 6 Sep 2019 07:37:55 +0000 (15:37 +0800)
committerAngus Gratton <angus@espressif.com>
Fri, 6 Sep 2019 07:37:55 +0000 (15:37 +0800)
spi_flash has been updated and its functions work from flash by default instead of IRAM that cause issue
add Kconfig value into espcoredump to enable spi_flash legacy mode (CONFIG_SPI_FLASH_USE_LEGACY_IMPL) when core dump is selected
fix spi_flash issues to work correctly with legacy mode when CONFIG_SPI_FLASH_USE_LEGACY_IMPL is used

12 files changed:
components/esp32/Kconfig
components/esp32/cpu_start.c
components/esp32/panic.c
components/esp_gdbstub/linker.lf
components/espcoredump/Kconfig
components/espcoredump/linker.lf
components/espcoredump/src/core_dump_flash.c
components/espcoredump/src/core_dump_port.c
components/spi_flash/cache_utils.c
components/spi_flash/include/esp_spi_flash.h
components/spi_flash/partition.c
docs/en/api-guides/fatal-errors.rst

index d0e9b5da0feafff64f178aa64bd4c7a3487cf08c..63afe63a821a70d61c2a119ed7903e9c9dd77a3e 100644 (file)
@@ -776,6 +776,20 @@ menu "ESP32-specific"
             To prevent interrupting DPORT workarounds,
             need to disable interrupt with a maximum used level in the system.
 
+    config ESP32_PANIC_HANDLER_IRAM
+        bool "Place panic handler code in IRAM"
+        default n
+        help
+            If this option is disabled (default), the panic handler code is placed in flash not IRAM.
+            This means that if ESP-IDF crashes while flash cache is disabled, the panic handler will
+            automatically re-enable flash cache before running GDB Stub or Core Dump. This adds some minor
+            risk, if the flash cache status is also corrupted during the crash.
+
+            If this option is enabled, the panic handler code is placed in IRAM. This allows the panic
+            handler to run without needing to re-enable cache first. This may be necessary to debug some
+            complex issues with crashes while flash cache is disabled (for example, when writing to
+            SPI flash.)
+
 endmenu  # ESP32-Specific
 
 menu "Power Management"
index 9ce5df4aefe1febc78cafddbc2d6a349fd29fcd7..975f09b30916e8f0eeb67b6dae3972f0d0838fbe 100644 (file)
@@ -404,9 +404,11 @@ void start_cpu0_default(void)
     /* init default OS-aware flash access critical section */
     spi_flash_guard_set(&g_flash_guard_default_ops);
 
+#ifndef CONFIG_SPI_FLASH_USE_LEGACY_IMPL
     esp_flash_app_init();
     esp_err_t flash_ret = esp_flash_init_default_chip();
     assert(flash_ret == ESP_OK);
+#endif
 
     uint8_t revision = esp_efuse_get_chip_ver();
     ESP_LOGI(TAG, "Chip Revision: %d", revision);
index 294c3635d2bfd8c49bfad83af6e99a0f671d8c01..d84ec1ecb4c6feab450e020aa3a9a7d2b0b25c0e 100644 (file)
@@ -608,6 +608,14 @@ static __attribute__((noreturn)) void commonErrorHandler(XtExcFrame *frame)
     reconfigureAllWdts();
 #endif
 
+#if !CONFIG_ESP32_PANIC_HANDLER_IRAM
+    // Re-enable CPU cache for current CPU if it was disabled
+    if (!spi_flash_cache_enabled()) {
+        spi_flash_enable_cache(core_id);
+        panicPutStr("Re-enable cpu cache.\r\n");
+    }
+#endif
+
 #if CONFIG_ESP32_PANIC_GDBSTUB
     disableAllWdts();
     rtc_wdt_disable();
index b5d88a26758da81a9d012e357529a7f6a2cae32c..7093ea8b2aec4cc4a4d842f4475b6ad47d4dee42 100644 (file)
@@ -1,4 +1,7 @@
 [mapping:esp_gdbstub]
 archive: libesp_gdbstub.a
-entries:
-    * (noflash)
+entries: 
+   if ESP32_PANIC_HANDLER_IRAM = y:
+        * (noflash_text)
+   else:
+        * (default)
\ No newline at end of file
index 991bf18f7b16f1190c7c959f02cbd031f90c9890..fe8b6e45539ade77d6fd6493ef27e25a006f10ab 100644 (file)
@@ -13,6 +13,7 @@ menu "Core dump"
         config ESP32_ENABLE_COREDUMP_TO_FLASH
             bool "Flash"
             select ESP32_ENABLE_COREDUMP
+            select SPI_FLASH_USE_LEGACY_IMPL
         config ESP32_ENABLE_COREDUMP_TO_UART
             bool "UART"
             select ESP32_ENABLE_COREDUMP
index 02dd9cfe78d636f488f7d7ebe4b14b8003827c86..131e10c30b0b70ee643c79bfd27ce227080aa189 100644 (file)
@@ -1,7 +1,10 @@
 [mapping:espcoredump]
 archive: libespcoredump.a
 entries: 
-    core_dump_uart (noflash_text)
-    core_dump_flash (noflash_text)
-    core_dump_common (noflash_text)
-    core_dump_port (noflash_text)
\ No newline at end of file
+    if ESP32_PANIC_HANDLER_IRAM = y:
+        core_dump_uart (noflash_text)
+        core_dump_flash (noflash_text)
+        core_dump_common (noflash_text)
+        core_dump_port (noflash_text)
+    else:
+        * (default)
index 9c2ac78766c4f319ffea685ee364e9c6df21650c..21e85731e09a1956f08170d890ca3c00c4537bdf 100644 (file)
@@ -200,8 +200,8 @@ static esp_err_t esp_core_dump_flash_write_data(void *priv, void * data, uint32_
 
 void esp_core_dump_to_flash(XtExcFrame *frame)
 {
-    core_dump_write_config_t wr_cfg;
-    core_dump_write_flash_data_t wr_data;
+    static core_dump_write_config_t wr_cfg;
+    static core_dump_write_flash_data_t wr_data;
 
     core_dump_crc_t crc = esp_core_dump_calc_flash_config_crc();
     if (s_core_flash_config.partition_config_crc != crc) {
@@ -214,8 +214,10 @@ void esp_core_dump_to_flash(XtExcFrame *frame)
         return;
     }
 
-    /* init non-OS flash access critical section */
+#if CONFIG_SPI_FLASH_USE_LEGACY_IMPL
+    // init non-OS flash access critical section
     spi_flash_guard_set(&g_flash_guard_no_os_ops);
+#endif
 
     memset(&wr_cfg, 0, sizeof(wr_cfg));
     wr_cfg.prepare = esp_core_dump_flash_write_prepare;
index 2ac1b6482b67bf9e32ea5ffaeab2a2ec6e02d000..1e6ab6a90668ecdb72dec0a31723607333d1641e 100644 (file)
@@ -94,7 +94,9 @@ bool esp_core_dump_process_stack(core_dump_task_header_t* task_snaphort, uint32_
         ESP_COREDUMP_LOG_PROCESS("Stack len = %lu (%x %x)", len,
                 task_snaphort->stack_start, task_snaphort->stack_end);
         // Take stack padding into account
-        *length = (len + sizeof(uint32_t) - 1) & ~(sizeof(uint32_t) - 1);
+        if (length) {
+            *length = (len + sizeof(uint32_t) - 1) & ~(sizeof(uint32_t) - 1);
+        }
         task_is_valid = true;
     }
     return task_is_valid;
index 25f937d749a5fe5b2c53eb8339a8ea78e80fc994..63603097ce510c4bd7bba5090b2f861590cabbc7 100644 (file)
 #include "esp_spi_flash.h"
 #include "esp_log.h"
 
+#define DPORT_CACHE_BIT(cpuid, regid) DPORT_ ## cpuid ## regid
+
+#define DPORT_CACHE_MASK(cpuid) (DPORT_CACHE_BIT(cpuid, _CACHE_MASK_OPSDRAM) | DPORT_CACHE_BIT(cpuid, _CACHE_MASK_DROM0) | \
+                                DPORT_CACHE_BIT(cpuid, _CACHE_MASK_DRAM1) | DPORT_CACHE_BIT(cpuid, _CACHE_MASK_IROM0) | \
+                                DPORT_CACHE_BIT(cpuid, _CACHE_MASK_IRAM1) | DPORT_CACHE_BIT(cpuid, _CACHE_MASK_IRAM0) )
+
+#define DPORT_CACHE_VAL(cpuid) (~(DPORT_CACHE_BIT(cpuid, _CACHE_MASK_DROM0) | \
+                                        DPORT_CACHE_BIT(cpuid, _CACHE_MASK_DRAM1) | \
+                                        DPORT_CACHE_BIT(cpuid, _CACHE_MASK_IRAM0)))
+
+#define DPORT_CACHE_GET_VAL(cpuid) (cpuid == 0) ? DPORT_CACHE_VAL(PRO) : DPORT_CACHE_VAL(APP)
+#define DPORT_CACHE_GET_MASK(cpuid) (cpuid == 0) ? DPORT_CACHE_MASK(PRO) : DPORT_CACHE_MASK(APP)
 
 static void IRAM_ATTR spi_flash_disable_cache(uint32_t cpuid, uint32_t* saved_state);
 static void IRAM_ATTR spi_flash_restore_cache(uint32_t cpuid, uint32_t saved_state);
@@ -256,13 +268,10 @@ void IRAM_ATTR spi_flash_enable_interrupts_caches_no_os(void)
  * Cache_Flush before Cache_Read_Enable, even if cached data was not modified.
  */
 
-static const uint32_t cache_mask  = DPORT_APP_CACHE_MASK_OPSDRAM | DPORT_APP_CACHE_MASK_DROM0 |
-        DPORT_APP_CACHE_MASK_DRAM1 | DPORT_APP_CACHE_MASK_IROM0 |
-        DPORT_APP_CACHE_MASK_IRAM1 | DPORT_APP_CACHE_MASK_IRAM0;
-
 static void IRAM_ATTR spi_flash_disable_cache(uint32_t cpuid, uint32_t* saved_state)
 {
     uint32_t ret = 0;
+    const uint32_t cache_mask = DPORT_CACHE_GET_MASK(cpuid);
     if (cpuid == 0) {
         ret |= DPORT_GET_PERI_REG_BITS2(DPORT_PRO_CACHE_CTRL1_REG, cache_mask, 0);
         while (DPORT_GET_PERI_REG_BITS2(DPORT_PRO_DCACHE_DBUG0_REG, DPORT_PRO_CACHE_STATE, DPORT_PRO_CACHE_STATE_S) != 1) {
@@ -281,6 +290,7 @@ static void IRAM_ATTR spi_flash_disable_cache(uint32_t cpuid, uint32_t* saved_st
 
 static void IRAM_ATTR spi_flash_restore_cache(uint32_t cpuid, uint32_t saved_state)
 {
+    const uint32_t cache_mask = DPORT_CACHE_GET_MASK(cpuid);
     if (cpuid == 0) {
         DPORT_SET_PERI_REG_BITS(DPORT_PRO_CACHE_CTRL_REG, 1, 1, DPORT_PRO_CACHE_ENABLE_S);
         DPORT_SET_PERI_REG_BITS(DPORT_PRO_CACHE_CTRL1_REG, cache_mask, saved_state, 0);
@@ -290,7 +300,6 @@ static void IRAM_ATTR spi_flash_restore_cache(uint32_t cpuid, uint32_t saved_sta
     }
 }
 
-
 IRAM_ATTR bool spi_flash_cache_enabled(void)
 {
     bool result = (DPORT_REG_GET_BIT(DPORT_PRO_CACHE_CTRL_REG, DPORT_PRO_CACHE_ENABLE) != 0);
@@ -299,3 +308,12 @@ IRAM_ATTR bool spi_flash_cache_enabled(void)
 #endif
     return result;
 }
+
+void IRAM_ATTR spi_flash_enable_cache(uint32_t cpuid)
+{
+    uint32_t cache_value = DPORT_CACHE_GET_VAL(cpuid);
+    cache_value &= DPORT_CACHE_GET_MASK(cpuid);
+
+    // Re-enable cache on this CPU
+    spi_flash_restore_cache(cpuid, cache_value);
+}
index 33bdc4d83c6545d9293bbaba2c14d017d7256e81..5966f0ecc130d454136c05439e23496e88f69fbf 100644 (file)
@@ -295,6 +295,13 @@ const void *spi_flash_phys2cache(size_t phys_offs, spi_flash_mmap_memory_t memor
  */
 bool spi_flash_cache_enabled(void);
 
+/**
+ * @brief Re-enable cache for the core defined as cpuid parameter.
+ *
+ * @param cpuid the core number to enable instruction cache for
+ */
+void spi_flash_enable_cache(uint32_t cpuid);
+
 /**
  * @brief SPI flash critical section enter function.
  *
index 14de32c9f50d2e3e2389d12b28b07132f1c8c4c6..a6b33a1382b099facba6ee4c3889bd3a951deb3f 100644 (file)
@@ -172,7 +172,9 @@ static esp_err_t load_partitions(void)
             err = ESP_ERR_NO_MEM;
             break;
         }
+#ifndef CONFIG_SPI_FLASH_USE_LEGACY_IMPL
         item->info.flash_chip = esp_flash_default_chip;
+#endif
         item->info.address = it->pos.offset;
         item->info.size = it->pos.size;
         item->info.type = it->type;
@@ -334,10 +336,11 @@ esp_err_t esp_partition_read(const esp_partition_t* partition,
 #endif // CONFIG_SPI_FLASH_USE_LEGACY_IMPL
     } else {
 #if CONFIG_SECURE_FLASH_ENC_ENABLED
+#ifndef CONFIG_SPI_FLASH_USE_LEGACY_IMPL
         if (partition->flash_chip != esp_flash_default_chip) {
             return ESP_ERR_NOT_SUPPORTED;
         }
-
+#endif
         /* Encrypted partitions need to be read via a cache mapping */
         const void *buf;
         spi_flash_mmap_handle_t handle;
@@ -376,9 +379,11 @@ esp_err_t esp_partition_write(const esp_partition_t* partition,
 #endif // CONFIG_SPI_FLASH_USE_LEGACY_IMPL
     } else {
 #if CONFIG_SECURE_FLASH_ENC_ENABLED
+#ifndef CONFIG_SPI_FLASH_USE_LEGACY_IMPL
         if (partition->flash_chip != esp_flash_default_chip) {
             return ESP_ERR_NOT_SUPPORTED;
         }
+#endif
         return spi_flash_write_encrypted(dst_offset, src, size);
 #else
         return ESP_ERR_NOT_SUPPORTED;
@@ -428,9 +433,11 @@ esp_err_t esp_partition_mmap(const esp_partition_t* partition, size_t offset, si
     if (offset + size > partition->size) {
         return ESP_ERR_INVALID_SIZE;
     }
+#ifndef CONFIG_SPI_FLASH_USE_LEGACY_IMPL
     if (partition->flash_chip != esp_flash_default_chip) {
         return ESP_ERR_NOT_SUPPORTED;
     }
+#endif
     size_t phys_addr = partition->address + offset;
     // offset within 64kB block
     size_t region_offset = phys_addr & 0xffff;
index c64268fb760afedb785ddbba11f8f42b57857c05..f1ca3f1842d11af25de879ecc39acba35f659f01 100644 (file)
@@ -62,6 +62,10 @@ Behavior of panic handler is affected by two other configuration options.
 
 - If :doc:`Core Dump <core_dump>` feature is enabled (``CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH`` or ``CONFIG_ESP32_ENABLE_COREDUMP_TO_UART`` options), then system state (task stacks and registers) will be dumped either to Flash or UART, for later analysis.
 
+- If :ref:`CONFIG_ESP32_PANIC_HANDLER_IRAM` is disabled (disabled by default), the panic handler code is placed in flash memory not IRAM. This means that if ESP-IDF crashes while flash cache is disabled, the panic handler will automatically re-enable flash cache before running GDB Stub or Core Dump. This adds some minor risk, if the flash cache status is also corrupted during the crash.
+  
+  If this option is enabled, the panic handler code is placed in IRAM. This allows the panic handler to run without needing to re-enable cache first. This may be necessary to debug some complex issues with crashes while flash cache is disabled (for example, when writing to SPI flash).
+
 The following diagram illustrates panic handler behavior:
 
 .. blockdiag::