]> granicus.if.org Git - esp-idf/commitdiff
esp32: Fixes watchdog problem when printing core dump to uart
authorAlexey Gerenkov <alexey@espressif.com>
Thu, 19 Jan 2017 17:24:55 +0000 (20:24 +0300)
committerAlexey Gerenkov <alexey@espressif.com>
Wed, 1 Feb 2017 15:39:28 +0000 (18:39 +0300)
Also fixes generation of core dumps when flash cache is disabled

components/esp32/core_dump.c
components/esp32/cpu_start.c
components/esp32/intr_alloc.c
components/esp32/ld/esp32.common.ld
components/esp32/panic.c
components/spi_flash/flash_ops.c
components/spi_flash/include/esp_spi_flash.h

index 85301f4dd646da0f2162cbbc90c7c5f42715e7df..ecc658ebdc61aa760a3ae7eb5742dd4c35176d1d 100644 (file)
 #if CONFIG_ESP32_ENABLE_COREDUMP
 #define LOG_LOCAL_LEVEL CONFIG_ESP32_CORE_DUMP_LOG_LEVEL
 #include "esp_log.h"
-const static char *TAG = "esp_core_dump";
+const static DRAM_ATTR char TAG[] = "esp_core_dump";
 
-#define ESP_COREDUMP_LOGE( format, ... )  if (LOG_LOCAL_LEVEL >= ESP_LOG_ERROR)   { ets_printf(LOG_FORMAT(E, format), esp_log_early_timestamp(), TAG, ##__VA_ARGS__); }
-#define ESP_COREDUMP_LOGW( format, ... )  if (LOG_LOCAL_LEVEL >= ESP_LOG_WARN)    { ets_printf(LOG_FORMAT(W, format), esp_log_early_timestamp(), TAG, ##__VA_ARGS__); }
-#define ESP_COREDUMP_LOGI( format, ... )  if (LOG_LOCAL_LEVEL >= ESP_LOG_INFO)    { ets_printf(LOG_FORMAT(I, format), esp_log_early_timestamp(), TAG, ##__VA_ARGS__); }
-#define ESP_COREDUMP_LOGD( format, ... )  if (LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG)   { ets_printf(LOG_FORMAT(D, format), esp_log_early_timestamp(), TAG, ##__VA_ARGS__); }
-#define ESP_COREDUMP_LOGV( format, ... )  if (LOG_LOCAL_LEVEL >= ESP_LOG_VERBOSE) { ets_printf(LOG_FORMAT(V, format), esp_log_early_timestamp(), TAG, ##__VA_ARGS__); }
+#define ESP_COREDUMP_LOG( level, format, ... )  if (LOG_LOCAL_LEVEL >= level)   { ets_printf(DRAM_STR(format), esp_log_early_timestamp(), (const char *)TAG, ##__VA_ARGS__); }
+#define ESP_COREDUMP_LOGE( format, ... )  ESP_COREDUMP_LOG(ESP_LOG_ERROR, LOG_FORMAT(E, format), ##__VA_ARGS__)
+#define ESP_COREDUMP_LOGW( format, ... )  ESP_COREDUMP_LOG(ESP_LOG_WARN, LOG_FORMAT(W, format), ##__VA_ARGS__)
+#define ESP_COREDUMP_LOGI( format, ... )  ESP_COREDUMP_LOG(ESP_LOG_INFO, LOG_FORMAT(I, format), ##__VA_ARGS__)
+#define ESP_COREDUMP_LOGD( format, ... )  ESP_COREDUMP_LOG(ESP_LOG_DEBUG, LOG_FORMAT(D, format), ##__VA_ARGS__)
+#define ESP_COREDUMP_LOGV( format, ... )  ESP_COREDUMP_LOG(ESP_LOG_VERBOSE, LOG_FORMAT(V, format), ##__VA_ARGS__)
 
 #if CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH
-#define ESP_COREDUMP_LOG_PROCESS( format, ... )  if (LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG)   { ets_printf(LOG_FORMAT(D, format), esp_log_early_timestamp(), TAG, ##__VA_ARGS__); }
+#define ESP_COREDUMP_LOG_PROCESS( format, ... )  ESP_COREDUMP_LOGD(format, ##__VA_ARGS__)
 #else
 #define ESP_COREDUMP_LOG_PROCESS( format, ... )  do{/*(__VA_ARGS__);*/}while(0)
 #endif
@@ -345,8 +346,9 @@ void esp_core_dump_to_flash(XtExcFrame *frame)
 #endif
 
 #if CONFIG_ESP32_ENABLE_COREDUMP_TO_UART
+
 static void esp_core_dump_b64_encode(const uint8_t *src, uint32_t src_len, uint8_t *dst) {
-    static const char *b64 =
+    const static DRAM_ATTR char b64[] =
         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
     int i, j, a, b, c;
 
@@ -373,14 +375,14 @@ static void esp_core_dump_b64_encode(const uint8_t *src, uint32_t src_len, uint8
 static esp_err_t esp_core_dump_uart_write_start(void *priv)
 {
     esp_err_t err = ESP_OK;
-    ets_printf("================= CORE DUMP START =================\r\n");
+    ets_printf(DRAM_STR("================= CORE DUMP START =================\r\n"));
     return err;
 }
 
 static esp_err_t esp_core_dump_uart_write_end(void *priv)
 {
     esp_err_t err = ESP_OK;
-    ets_printf("================= CORE DUMP END =================\r\n");
+    ets_printf(DRAM_STR("================= CORE DUMP END =================\r\n"));
     return err;
 }
 
@@ -398,7 +400,7 @@ static esp_err_t esp_core_dump_uart_write_data(void *priv, void * data, uint32_t
         memcpy(tmp, addr, len);
         esp_core_dump_b64_encode((const uint8_t *)tmp, len, (uint8_t *)buf);
         addr += len;
-        ets_printf("%s\r\n", buf);
+        ets_printf(DRAM_STR("%s\r\n"), buf);
     }
 
     return err;
@@ -427,7 +429,8 @@ void esp_core_dump_to_uart(XtExcFrame *frame)
     wr_cfg.priv = NULL;
 
     //Make sure txd/rxd are enabled
-    gpio_pullup_dis(1);
+    // use direct reg access instead of gpio_pullup_dis which can cause exception when flash cache is disabled
+    REG_CLR_BIT(GPIO_PIN_REG_1, FUN_PU);
     PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD_U0RXD);
     PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD_U0TXD);
 
@@ -438,10 +441,6 @@ void esp_core_dump_to_uart(XtExcFrame *frame)
         tm_cur = xthal_get_ccount() / (XT_CLOCK_FREQ / 1000);
         if (tm_cur >= tm_end)
             break;
-        /* Feed the Cerberus. */
-        TIMERG0.wdt_wprotect = TIMG_WDT_WKEY_VALUE;
-        TIMERG0.wdt_feed = 1;
-        TIMERG0.wdt_wprotect = 0;
         ch = esp_core_dump_uart_get_char();
     }
     ESP_COREDUMP_LOGI("Print core dump to uart...");
@@ -455,18 +454,18 @@ void esp_core_dump_init()
 #if CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH
     const esp_partition_t *core_part;
 
-    ESP_LOGI(TAG, "Init core dump to flash");
+    ESP_COREDUMP_LOGI("Init core dump to flash");
     core_part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_COREDUMP, NULL);
     if (!core_part) {
-        ESP_LOGE(TAG, "No core dump partition found!");
+        ESP_COREDUMP_LOGE("No core dump partition found!");
         return;
     }
-    ESP_LOGI(TAG, "Found partition '%s' @ %x %d bytes", core_part->label, core_part->address, core_part->size);
+    ESP_COREDUMP_LOGI("Found partition '%s' @ %x %d bytes", core_part->label, core_part->address, core_part->size);
     s_core_part_start = core_part->address;
     s_core_part_size = core_part->size;
 #endif
 #if CONFIG_ESP32_ENABLE_COREDUMP_TO_UART
-    ESP_LOGI(TAG, "Init core dump to UART");
+    ESP_COREDUMP_LOGI("Init core dump to UART");
 #endif
 }
 
index edc2881a284dba7cc89883ed53455eba5cdd8334..001d1706e1e6211224aa309166eb5615742d387e 100644 (file)
@@ -210,6 +210,10 @@ void start_cpu0_default(void)
     /* init default OS-aware flash access critical section */
     spi_flash_guard_set(&g_flash_guard_default_ops);
 
+#if CONFIG_ESP32_ENABLE_COREDUMP
+    esp_core_dump_init();
+#endif
+
 #if CONFIG_ESP32_PHY_AUTO_INIT
     nvs_flash_init();
     do_phy_init();
@@ -221,10 +225,6 @@ void start_cpu0_default(void)
     }
 #endif
 
-#if CONFIG_ESP32_ENABLE_COREDUMP
-    esp_core_dump_init();
-#endif
-
     xTaskCreatePinnedToCore(&main_task, "main",
             ESP_TASK_MAIN_STACK, NULL,
             ESP_TASK_MAIN_PRIO, NULL, 0);
index d9cc627e17d8c1e3e34754694b16675f3e372beb..b35973144c22df9957e0f0a7162f94ef1e59c801 100644 (file)
@@ -686,7 +686,7 @@ esp_err_t IRAM_ATTR esp_intr_disable(intr_handle_t handle)
 }
 
 
-void esp_intr_noniram_disable() 
+void IRAM_ATTR esp_intr_noniram_disable()
 {
     int oldint;
     int cpu=xPortGetCoreID();
@@ -705,7 +705,7 @@ void esp_intr_noniram_disable()
     non_iram_int_disabled[cpu]=oldint&non_iram_int_mask[cpu];
 }
 
-void esp_intr_noniram_enable() 
+void IRAM_ATTR esp_intr_noniram_enable()
 {
     int cpu=xPortGetCoreID();
     int intmask=non_iram_int_disabled[cpu];
index 3e5d6b7d83d6a3aa7756f623e948d76d3641caba..ac04c07d57b2634d7c7912c2eabefd42c6661cf1 100644 (file)
@@ -80,6 +80,7 @@ SECTIONS
     *(.iram1 .iram1.*)
     *libfreertos.a:(.literal .text .literal.* .text.*)
     *libesp32.a:panic.o(.literal .text .literal.* .text.*)
+    *libesp32.a:core_dump.o(.literal .text .literal.* .text.*)
     *libphy.a:(.literal .text .literal.* .text.*)
     *librtc.a:(.literal .text .literal.* .text.*)
     *libpp.a:(.literal .text .literal.* .text.*)
index 6180770bd674cc4c89ed4a4489ccef6a473e51fa..4f0497d6ea19ff0912be526283b2691ba00550f1 100644 (file)
@@ -267,7 +267,7 @@ static void reconfigureAllWdts()
     TIMERG1.wdt_wprotect = 0;
 }
 
-#if CONFIG_ESP32_PANIC_GDBSTUB || CONFIG_ESP32_PANIC_PRINT_HALT
+#if CONFIG_ESP32_PANIC_GDBSTUB || CONFIG_ESP32_PANIC_PRINT_HALT || CONFIG_ESP32_ENABLE_COREDUMP
 /*
   This disables all the watchdogs for when we call the gdbstub.
 */
@@ -367,11 +367,15 @@ static void commonErrorHandler(XtExcFrame *frame)
     panicPutStr("Entering gdb stub now.\r\n");
     esp_gdbstub_panic_handler(frame);
 #else
+#if CONFIG_ESP32_ENABLE_COREDUMP
+    disableAllWdts();
 #if CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH
     esp_core_dump_to_flash(frame);
 #endif
 #if CONFIG_ESP32_ENABLE_COREDUMP_TO_UART && !CONFIG_ESP32_PANIC_SILENT_REBOOT
     esp_core_dump_to_uart(frame);
+#endif
+    reconfigureAllWdts();
 #endif
 #if CONFIG_ESP32_PANIC_PRINT_REBOOT || CONFIG_ESP32_PANIC_SILENT_REBOOT
     panicPutStr("Rebooting...\r\n");
index 0d3e0da87c20bfcdbe5b40caac60f6b88a309bc6..3581b34141744846fdb8c39d11d955dd6e2f80b7 100644 (file)
@@ -61,13 +61,17 @@ static spi_flash_counters_t s_flash_stats;
 static esp_err_t spi_flash_translate_rc(SpiFlashOpResult rc);
 
 const DRAM_ATTR spi_flash_guard_funcs_t g_flash_guard_default_ops = {
-        .start  = spi_flash_disable_interrupts_caches_and_other_cpu,
-        .end    = spi_flash_enable_interrupts_caches_and_other_cpu
+        .start     = spi_flash_disable_interrupts_caches_and_other_cpu,
+        .end       = spi_flash_enable_interrupts_caches_and_other_cpu,
+        .op_lock   = spi_flash_op_lock,
+        .op_unlock = spi_flash_op_unlock
 };
 
 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
+        .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
 };
 
 static const spi_flash_guard_funcs_t *s_flash_guard_ops;
@@ -80,12 +84,12 @@ void spi_flash_init()
 #endif
 }
 
-void spi_flash_guard_set(const spi_flash_guard_funcs_t* funcs)
+void IRAM_ATTR spi_flash_guard_set(const spi_flash_guard_funcs_t* funcs)
 {
     s_flash_guard_ops = funcs;
 }
 
-size_t spi_flash_get_chip_size()
+size_t IRAM_ATTR spi_flash_get_chip_size()
 {
     return g_rom_flashchip.chip_size;
 }
@@ -105,18 +109,32 @@ static SpiFlashOpResult IRAM_ATTR spi_flash_unlock()
 
 static inline void IRAM_ATTR spi_flash_guard_start()
 {
-    if (s_flash_guard_ops) {
+    if (s_flash_guard_ops && s_flash_guard_ops->start) {
         s_flash_guard_ops->start();
     }
 }
 
 static inline void IRAM_ATTR spi_flash_guard_end()
 {
-    if (s_flash_guard_ops) {
+    if (s_flash_guard_ops && s_flash_guard_ops->end) {
         s_flash_guard_ops->end();
     }
 }
 
+static inline void IRAM_ATTR spi_flash_guard_op_lock()
+{
+    if (s_flash_guard_ops && s_flash_guard_ops->op_lock) {
+        s_flash_guard_ops->op_lock();
+    }
+}
+
+static inline void IRAM_ATTR spi_flash_guard_op_unlock()
+{
+    if (s_flash_guard_ops && s_flash_guard_ops->op_unlock) {
+        s_flash_guard_ops->op_unlock();
+    }
+}
+
 esp_err_t IRAM_ATTR spi_flash_erase_sector(size_t sec)
 {
     return spi_flash_erase_range(sec * SPI_FLASH_SEC_SIZE, SPI_FLASH_SEC_SIZE);
@@ -251,9 +269,9 @@ esp_err_t IRAM_ATTR spi_flash_write(size_t dst, const void *srcv, size_t size)
 out:
     COUNTER_STOP(write);
 
-    spi_flash_op_lock();
+    spi_flash_guard_op_lock();
     spi_flash_mark_modified_region(dst, size);
-    spi_flash_op_unlock();
+    spi_flash_guard_op_unlock();
 
     return spi_flash_translate_rc(rc);
 }
@@ -320,9 +338,9 @@ esp_err_t IRAM_ATTR spi_flash_write_encrypted(size_t dest_addr, const void *src,
     }
     COUNTER_ADD_BYTES(write, size);
 
-    spi_flash_op_lock();
+    spi_flash_guard_op_lock();
     spi_flash_mark_modified_region(dest_addr, size);
-    spi_flash_op_unlock();
+    spi_flash_guard_op_unlock();
 
     return spi_flash_translate_rc(rc);
 }
@@ -444,7 +462,7 @@ esp_err_t IRAM_ATTR spi_flash_read_encrypted(size_t src, void *dstv, size_t size
 }
 
 
-static esp_err_t spi_flash_translate_rc(SpiFlashOpResult rc)
+static esp_err_t IRAM_ATTR spi_flash_translate_rc(SpiFlashOpResult rc)
 {
     switch (rc) {
     case SPI_FLASH_RESULT_OK:
index c1ad7d56fa73bab1f97091ba1bbdd82b2a05a53f..060d598ec0f2beab067f62ccba0982e463a13260 100644 (file)
@@ -205,16 +205,44 @@ typedef void (*spi_flash_guard_start_func_t)(void);
  * @brief SPI flash critical section exit function.
  */
 typedef void (*spi_flash_guard_end_func_t)(void);
+/**
+ * @brief SPI flash operation lock function.
+ */
+typedef void (*spi_flash_op_lock_func_t)(void);
+/**
+ * @brief SPI flash operation unlock function.
+ */
+typedef void (*spi_flash_op_unlock_func_t)(void);
 
 /**
- * Structure holding SPI flash access critical section management functions
+ * Structure holding SPI flash access critical sections management functions.
+ *
+ * Flash API uses two types of flash access management functions:
+ * 1) Functions which prepare/restore flash cache and interrupts before calling
+ *    appropriate ROM functions (SPIWrite, SPIRead and SPIEraseBlock):
+ *   - 'start' function should disables flash cache and non-IRAM interrupts and
+ *      is invoked before the call to one of ROM function above.
+ *   - 'end' function should restore state of flash cache and non-IRAM interrupts and
+ *      is invoked after the call to one of ROM function above.
+ * 2) Functions which synchronizes access to internal data used by flash API.
+ *    This functions are mostly intended to synchronize access to flash API internal data
+ *    in multithreaded environment and use OS primitives:
+ *   - 'op_lock' locks access to flash API internal data.
+ *   - 'op_unlock' unlocks access to flash API internal data.
+ * Different versions of the guarding functions should be used depending on the context of
+ * execution (with or without functional OS). In normal conditions when flash API is called
+ * from task the functions use OS primitives. When there is no OS at all or when
+ * it is not guaranteed that OS is functional (accessing flash from exception handler) these
+ * functions cannot use OS primitives or even does not need them (multithreaded access is not possible).
  *
  * @note Structure and corresponding guard functions should not reside in flash.
  *       For example structure can be placed in DRAM and functions in IRAM sections.
  */
 typedef struct {
-    spi_flash_guard_start_func_t    start;  /**< critical section start func */
-    spi_flash_guard_end_func_t      end;    /**< critical section end func */
+    spi_flash_guard_start_func_t    start;      /**< critical section start func */
+    spi_flash_guard_end_func_t      end;        /**< critical section end func */
+    spi_flash_op_lock_func_t        op_lock;    /**< flash access API lock func */
+    spi_flash_op_unlock_func_t      op_unlock;  /**< flash access API unlock func */
 } spi_flash_guard_funcs_t;
 
 /**