فهرست منبع

Merge branch 'bugfix/spi_flash_yield_coredump' into 'master'

fixes for core dump regressions

See merge request espressif/esp-idf!8978
Angus Gratton 5 سال پیش
والد
کامیت
61ab64439b

+ 6 - 3
components/freertos/xtensa/include/freertos/FreeRTOSConfig.h

@@ -181,11 +181,14 @@ int xt_clock_freq(void) __attribute__((deprecated));
 #define configMAX_PRIORITIES			( 25 )
 #endif
 
-#ifndef CONFIG_APPTRACE_ENABLE
-#define configMINIMAL_STACK_SIZE		768
-#else
+#if defined(CONFIG_APPTRACE_ENABLE)
 /* apptrace module requires at least 2KB of stack per task */
 #define configMINIMAL_STACK_SIZE		2048
+#elif defined(CONFIG_COMPILER_OPTIMIZATION_NONE)
+/* with optimizations disabled, scheduler uses additional stack */
+#define configMINIMAL_STACK_SIZE		1024
+#else
+#define configMINIMAL_STACK_SIZE		768
 #endif
 
 #ifndef configIDLE_TASK_STACK_SIZE

+ 1 - 1
components/freertos/xtensa/include/freertos/portmacro.h

@@ -144,7 +144,7 @@ static inline uint32_t xPortGetCoreID(void);
 // They can be called from interrupts too.
 // WARNING: Only applies to current CPU. See notes above.
 static inline unsigned portENTER_CRITICAL_NESTED(void) {
-	unsigned state = XTOS_SET_INTLEVEL(XCHAL_EXCM_LEVEL);
+	unsigned state = XTOS_SET_MIN_INTLEVEL(XCHAL_EXCM_LEVEL);
 	portbenchmarkINTERRUPT_DISABLE();
 	return state;
 }

+ 2 - 2
components/soc/include/soc/spinlock.h

@@ -67,7 +67,7 @@ static inline bool __attribute__((always_inline)) spinlock_acquire(spinlock_t *l
     uint32_t core_id, other_core_id;
    
     assert(lock);
-    irq_status = XTOS_SET_INTLEVEL(XCHAL_EXCM_LEVEL);    
+    irq_status = XTOS_SET_MIN_INTLEVEL(XCHAL_EXCM_LEVEL);    
  
     if(timeout != SPINLOCK_WAIT_FOREVER){
         RSR(CCOUNT, ccount_start);   
@@ -139,7 +139,7 @@ static inline void __attribute__((always_inline)) spinlock_release(spinlock_t *l
     uint32_t core_id;
 
     assert(lock);
-    irq_status = XTOS_SET_INTLEVEL(XCHAL_EXCM_LEVEL);
+    irq_status = XTOS_SET_MIN_INTLEVEL(XCHAL_EXCM_LEVEL);
         
     RSR(PRID, core_id);
     assert(core_id == lock->owner); // This is a mutex we didn't lock, or it's corrupt

+ 3 - 1
components/spi_flash/esp_flash_api.c

@@ -372,7 +372,9 @@ esp_err_t IRAM_ATTR esp_flash_erase_region(esp_flash_t *chip, uint32_t start, ui
         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);
+            if (chip->os_func->yield) {
+                chip->os_func->yield(chip->os_func_data);
+            }
         }
 #endif
     }

+ 17 - 5
components/spi_flash/flash_ops.c

@@ -82,6 +82,7 @@ static spi_flash_counters_t s_flash_stats;
 
 static esp_err_t spi_flash_translate_rc(esp_rom_spiflash_result_t rc);
 static bool is_safe_write_address(size_t addr, size_t size);
+static void spi_flash_os_yield(void);
 
 const DRAM_ATTR spi_flash_guard_funcs_t g_flash_guard_default_ops = {
     .start                  = spi_flash_disable_interrupts_caches_and_other_cpu,
@@ -89,18 +90,20 @@ const DRAM_ATTR spi_flash_guard_funcs_t g_flash_guard_default_ops = {
     .op_lock                = spi_flash_op_lock,
     .op_unlock              = spi_flash_op_unlock,
 #if !CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED
-    .is_safe_write_address  = is_safe_write_address
+    .is_safe_write_address  = is_safe_write_address,
 #endif
+    .yield                  = spi_flash_os_yield,
 };
 
 const DRAM_ATTR spi_flash_guard_funcs_t g_flash_guard_no_os_ops = {
     .start                  = spi_flash_disable_interrupts_caches_and_other_cpu_no_os,
     .end                    = spi_flash_enable_interrupts_caches_no_os,
-    .op_lock                = 0,
-    .op_unlock              = 0,
+    .op_lock                = NULL,
+    .op_unlock              = NULL,
 #if !CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED
-    .is_safe_write_address  = 0
+    .is_safe_write_address  = NULL,
 #endif
+    .yield                  = NULL,
 };
 
 static const spi_flash_guard_funcs_t *s_flash_guard_ops;
@@ -185,6 +188,13 @@ static inline void IRAM_ATTR spi_flash_guard_op_unlock(void)
     }
 }
 
+static void IRAM_ATTR spi_flash_os_yield(void)
+{
+#ifdef CONFIG_SPI_FLASH_YIELD_DURING_ERASE
+    vTaskDelay(CONFIG_SPI_FLASH_ERASE_YIELD_TICKS);
+#endif
+}
+
 #ifdef CONFIG_SPI_FLASH_USE_LEGACY_IMPL
 static esp_rom_spiflash_result_t IRAM_ATTR spi_flash_unlock(void)
 {
@@ -263,7 +273,9 @@ esp_err_t IRAM_ATTR spi_flash_erase_range(size_t start_addr, size_t size)
             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);
+                if (s_flash_guard_ops && s_flash_guard_ops->yield) {
+                    s_flash_guard_ops->yield();
+                }
             }
 #endif
         }

+ 3 - 0
components/spi_flash/include/esp_flash.h

@@ -50,6 +50,9 @@ typedef struct {
 
     /** Delay for at least 'us' microseconds. Called in between 'start' and 'end'. */
     esp_err_t (*delay_us)(void *arg, unsigned us);
+
+    /** Yield to other tasks. Called during erase operations. */
+    esp_err_t (*yield)(void *arg);
 } esp_flash_os_functions_t;
 
 /** @brief Structure to describe a SPI flash chip connected to the system.

+ 5 - 0
components/spi_flash/include/esp_spi_flash.h

@@ -341,6 +341,10 @@ typedef void (*spi_flash_op_unlock_func_t)(void);
  * @brief Function to protect SPI flash critical regions corruption.
  */
 typedef bool (*spi_flash_is_safe_write_address_t)(size_t addr, size_t size);
+/**
+ * @brief Function to yield to the OS during erase operation.
+ */
+typedef void (*spi_flash_os_yield_t)(void);
 
 /**
  * Structure holding SPI flash access critical sections management functions.
@@ -381,6 +385,7 @@ typedef struct {
 #if !CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED
     spi_flash_is_safe_write_address_t   is_safe_write_address; /**< checks flash write addresses.*/
 #endif
+    spi_flash_os_yield_t                yield;      /**< yield to the OS during flash erase */
 } spi_flash_guard_funcs_t;
 
 /**

+ 13 - 1
components/spi_flash/spi_flash_os_func_app.c

@@ -17,6 +17,8 @@
 #include "esp_spi_flash.h"   //for ``g_flash_guard_default_ops``
 #include "esp_flash.h"
 #include "esp_flash_partitions.h"
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
 #include "hal/spi_types.h"
 #include "sdkconfig.h"
 
@@ -101,6 +103,14 @@ static IRAM_ATTR esp_err_t delay_us(void *arg, unsigned us)
     return ESP_OK;
 }
 
+static IRAM_ATTR esp_err_t spi_flash_os_yield(void *arg)
+{
+#ifdef CONFIG_SPI_FLASH_YIELD_DURING_ERASE
+    vTaskDelay(CONFIG_SPI_FLASH_ERASE_YIELD_TICKS);
+#endif
+    return ESP_OK;
+}
+
 static IRAM_ATTR esp_err_t main_flash_region_protected(void* arg, size_t start_addr, size_t size)
 {
     if (((spi1_app_func_arg_t*)arg)->no_protect || esp_partition_main_flash_region_safe(start_addr, size)) {
@@ -117,14 +127,16 @@ static DRAM_ATTR spi1_app_func_arg_t main_flash_arg = {};
 static const DRAM_ATTR esp_flash_os_functions_t esp_flash_spi1_default_os_functions = {
     .start = spi1_start,
     .end = spi1_end,
-    .delay_us = delay_us,
     .region_protected = main_flash_region_protected,
+    .delay_us = delay_us,
+    .yield = spi_flash_os_yield,
 };
 
 static const esp_flash_os_functions_t esp_flash_spi23_default_os_functions = {
     .start = spi_start,
     .end = spi_end,
     .delay_us = delay_us,
+    .yield = spi_flash_os_yield
 };
 
 static spi_bus_lock_dev_handle_t register_dev(int host_id)

+ 1 - 0
components/spi_flash/spi_flash_os_func_noos.c

@@ -76,6 +76,7 @@ const DRAM_ATTR esp_flash_os_functions_t esp_flash_noos_functions = {
     .end = end,
     .delay_us = delay_us,
     .region_protected = NULL,
+    .yield = NULL,
 };
 
 esp_err_t IRAM_ATTR esp_flash_app_disable_os_functions(esp_flash_t* chip)

+ 1 - 0
tools/test_apps/system/build_test/sdkconfig.ci.no_flash_delay

@@ -0,0 +1 @@
+CONFIG_SPI_FLASH_YIELD_DURING_ERASE=n

+ 32 - 0
tools/test_apps/system/panic/app_test.py

@@ -128,6 +128,22 @@ def test_coredump_uart_abort(env, extra_data):
         # TODO: check the contents of core dump output
 
 
+@panic_test()
+def test_coredump_uart_int_wdt(env, extra_data):
+    with get_dut(env, "coredump_uart", "test_int_wdt") as dut:
+        dut.expect_gme("Interrupt wdt timeout on CPU0")
+        dut.expect_reg_dump(0)
+        dut.expect("Backtrace:")
+        dut.expect_none("CORRUPTED", "Guru Meditation")
+        dut.expect_reg_dump(1)
+        dut.expect("Backtrace:")
+        dut.expect_elf_sha256()
+        dut.expect_none("CORRUPTED", "Guru Meditation")
+        dut.expect("Rebooting...")
+        dut.process_coredump_uart()
+        # TODO: check the contents of core dump output
+
+
 @panic_test()
 def test_coredump_flash_abort(env, extra_data):
     with get_dut(env, "coredump_flash", "test_abort") as dut:
@@ -140,5 +156,21 @@ def test_coredump_flash_abort(env, extra_data):
         # TODO: check the contents of core dump output
 
 
+@panic_test()
+def test_coredump_flash_int_wdt(env, extra_data):
+    with get_dut(env, "coredump_flash", "test_int_wdt") as dut:
+        dut.expect_gme("Interrupt wdt timeout on CPU0")
+        dut.expect_reg_dump(0)
+        dut.expect("Backtrace:")
+        dut.expect_none("CORRUPTED", "Guru Meditation")
+        dut.expect_reg_dump(1)
+        dut.expect("Backtrace:")
+        dut.expect_elf_sha256()
+        dut.expect_none("CORRUPTED", "Guru Meditation")
+        dut.expect("Rebooting...")
+        dut.process_coredump_flash()
+        # TODO: check the contents of core dump output
+
+
 if __name__ == '__main__':
     run_all(__file__)

+ 1 - 0
tools/test_apps/system/startup/sdkconfig.ci.opt_o0

@@ -1 +1,2 @@
 CONFIG_COMPILER_OPTIMIZATION_NONE=y
+CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK=y