Browse Source

Merge branch 'feature/support_refresh_brownout_v1' into 'master'

spi_flash: send reset when brownout detected on XMC flash

Closes IDF-3882

See merge request espressif/esp-idf!16873
Michael (XIAO Xufeng) 3 years ago
parent
commit
773715d900
36 changed files with 360 additions and 148 deletions
  1. 6 0
      components/bootloader_support/bootloader_flash/include/bootloader_flash.h
  2. 41 0
      components/bootloader_support/bootloader_flash/src/bootloader_flash.c
  3. 2 2
      components/driver/esp32/touch_sensor.c
  4. 2 2
      components/driver/esp32s2/touch_sensor.c
  5. 1 1
      components/driver/esp32s3/touch_sensor.c
  6. 25 1
      components/esp_hw_support/include/esp_private/rtc_ctrl.h
  7. 4 0
      components/esp_hw_support/intr_alloc.c
  8. 2 0
      components/esp_hw_support/port/esp32/Kconfig.hw_support
  9. 60 8
      components/esp_hw_support/rtc_module.c
  10. 12 0
      components/esp_system/Kconfig
  11. 34 22
      components/esp_system/port/brownout.c
  12. 4 1
      components/esp_system/startup.c
  13. 1 1
      components/esp_system/xt_wdt.c
  14. 7 14
      components/hal/esp32/brownout_hal.c
  15. 2 1
      components/hal/esp32c2/brownout_hal.c
  16. 2 1
      components/hal/esp32c3/brownout_hal.c
  17. 2 1
      components/hal/esp32h2/brownout_hal.c
  18. 2 2
      components/hal/esp32s2/brownout_hal.c
  19. 2 1
      components/hal/esp32s3/brownout_hal.c
  20. 5 13
      components/hal/include/hal/brownout_hal.h
  21. 0 1
      components/soc/esp32/include/soc/soc_caps.h
  22. 4 4
      components/soc/esp32s3/include/soc/Kconfig.soc_caps.in
  23. 0 25
      components/soc/esp32s3/include/soc/brownout_caps.h
  24. 1 1
      components/soc/esp32s3/include/soc/soc_caps.h
  25. 1 0
      components/spi_flash/CMakeLists.txt
  26. 22 0
      components/spi_flash/Kconfig
  27. 39 0
      components/spi_flash/flash_brownout_hook.c
  28. 10 13
      components/spi_flash/include/esp_flash.h
  29. 23 1
      components/spi_flash/include/esp_private/spi_flash_os.h
  30. 5 13
      components/spi_flash/include/memspi_host_driver.h
  31. 1 0
      components/spi_flash/linker.lf
  32. 18 13
      components/spi_flash/spi_flash_chip_generic.c
  33. 14 0
      components/spi_flash/spi_flash_os_func_app.c
  34. 0 5
      tools/ci/check_copyright_ignore.txt
  35. 2 1
      tools/unit-test-app/configs/default
  36. 4 0
      tools/unit-test-app/configs/default_32_2

+ 6 - 0
components/bootloader_support/bootloader_flash/include/bootloader_flash.h

@@ -49,6 +49,12 @@ esp_err_t bootloader_flash_xmc_startup(void);
   */
 esp_err_t  __attribute__((weak)) bootloader_flash_unlock(void);
 
+/**
+ * @brief Reset the flash chip (66H + 99H).
+ *
+ * @return ESP_OK if success, otherwise ESP_FAIL.
+ */
+esp_err_t bootloader_flash_reset_chip(void);
 
 #ifdef __cplusplus
 }

+ 41 - 0
components/bootloader_support/bootloader_flash/src/bootloader_flash.c

@@ -730,3 +730,44 @@ esp_err_t IRAM_ATTR bootloader_flash_xmc_startup(void)
 }
 
 #endif //XMC_SUPPORT
+
+FORCE_INLINE_ATTR void bootloader_mspi_reset(void)
+{
+#if CONFIG_IDF_TARGET_ESP32
+    SPI1.slave.sync_reset = 0;
+    SPI0.slave.sync_reset = 0;
+    SPI1.slave.sync_reset = 1;
+    SPI0.slave.sync_reset = 1;
+    SPI1.slave.sync_reset = 0;
+    SPI0.slave.sync_reset = 0;
+#else
+    SPIMEM1.ctrl2.sync_reset = 0;
+    SPIMEM0.ctrl2.sync_reset = 0;
+    SPIMEM1.ctrl2.sync_reset = 1;
+    SPIMEM0.ctrl2.sync_reset = 1;
+    SPIMEM1.ctrl2.sync_reset = 0;
+    SPIMEM0.ctrl2.sync_reset = 0;
+#endif
+}
+
+esp_err_t IRAM_ATTR bootloader_flash_reset_chip(void)
+{
+    bootloader_mspi_reset();
+    // Seems that sync_reset cannot make host totally idle.'
+    // Sending an extra(useless) command to make the host idle in order to send reset command.
+    bootloader_execute_flash_command(0x05, 0, 0, 0);
+#if CONFIG_IDF_TARGET_ESP32
+    if (SPI1.ext2.st != 0)
+#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
+    if (SPIMEM1.fsm.st != 0)
+#else
+    if (SPIMEM1.fsm.spi0_mst_st != 0)
+#endif
+    {
+        return ESP_FAIL;
+    }
+    bootloader_execute_flash_command(0x66, 0, 0, 0);
+    bootloader_execute_flash_command(0x99, 0, 0, 0);
+
+    return ESP_OK;
+}

+ 2 - 2
components/driver/esp32/touch_sensor.c

@@ -70,13 +70,13 @@ static esp_err_t _touch_pad_read(touch_pad_t touch_num, uint16_t *touch_value, t
 esp_err_t touch_pad_isr_handler_register(void (*fn)(void *), void *arg, int no_use, intr_handle_t *handle_no_use)
 {
     ESP_RETURN_ON_FALSE(fn, ESP_ERR_INVALID_ARG, TOUCH_TAG,  "Touch_Pad ISR null");
-    return rtc_isr_register(fn, arg, RTC_CNTL_TOUCH_INT_ST_M);
+    return rtc_isr_register(fn, arg, RTC_CNTL_TOUCH_INT_ST_M, 0);
 }
 
 esp_err_t touch_pad_isr_register(intr_handler_t fn, void *arg)
 {
     ESP_RETURN_ON_FALSE(fn, ESP_ERR_INVALID_ARG, TOUCH_TAG,  "Touch_Pad ISR null");
-    return rtc_isr_register(fn, arg, RTC_CNTL_TOUCH_INT_ST_M);
+    return rtc_isr_register(fn, arg, RTC_CNTL_TOUCH_INT_ST_M, 0);
 }
 
 static uint32_t _touch_filter_iir(uint32_t in_now, uint32_t out_last, uint32_t k)

+ 2 - 2
components/driver/esp32s2/touch_sensor.c

@@ -106,10 +106,10 @@ esp_err_t touch_pad_isr_register(intr_handler_t fn, void *arg, touch_pad_intr_ma
         en_msk |= RTC_CNTL_TOUCH_APPROACH_LOOP_DONE_INT_ST_M;
     }
 #endif
-    esp_err_t ret = rtc_isr_register(fn, arg, en_msk);
+    esp_err_t ret = rtc_isr_register(fn, arg, en_msk, 0);
     /* Must ensure: After being registered, it is executed first. */
     if ( (ret == ESP_OK) && (reg_flag == false) && (intr_mask & (TOUCH_PAD_INTR_MASK_SCAN_DONE | TOUCH_PAD_INTR_MASK_TIMEOUT)) ) {
-        rtc_isr_register(touch_pad_workaround_isr_internal, NULL, RTC_CNTL_TOUCH_SCAN_DONE_INT_ST_M | RTC_CNTL_TOUCH_TIMEOUT_INT_ST_M);
+        rtc_isr_register(touch_pad_workaround_isr_internal, NULL, RTC_CNTL_TOUCH_SCAN_DONE_INT_ST_M | RTC_CNTL_TOUCH_TIMEOUT_INT_ST_M, 0);
         reg_flag = true;
     }
 

+ 1 - 1
components/driver/esp32s3/touch_sensor.c

@@ -85,7 +85,7 @@ esp_err_t touch_pad_isr_register(intr_handler_t fn, void *arg, touch_pad_intr_ma
         en_msk |= RTC_CNTL_TOUCH_APPROACH_LOOP_DONE_INT_ST_M;
     }
 #endif
-    esp_err_t ret = rtc_isr_register(fn, arg, en_msk);
+    esp_err_t ret = rtc_isr_register(fn, arg, en_msk, 0);
 
     return ret;
 }

+ 25 - 1
components/esp_hw_support/include/esp_private/rtc_ctrl.h

@@ -14,6 +14,8 @@
 extern "C" {
 #endif
 
+#define RTC_INTR_FLAG_IRAM   (BIT(0))  /*< Some rtc interrupts can be called with cache disabled */
+
 /**
  * @brief Register a handler for specific RTC_CNTL interrupts
  *
@@ -25,13 +27,17 @@ extern "C" {
  * @param handler_arg  argument to be passed to the handler
  * @param rtc_intr_mask  combination of RTC_CNTL_*_INT_ENA bits indicating the
  *                       sources to call the handler for
+ * @param flags  An ORred mask of the RTC_INTR_FLAG_* defines. You can pass different
+ *               flags to it to realize different purpose. If 0, the interrupt will
+ *               not handle anything special. If you pass `RTC_INTR_FLAG_IRAM`, means
+ *               the interrupt can be triggered with cache disabled.
  * @return
  *      - ESP_OK on success
  *      - ESP_ERR_NO_MEM not enough memory to allocate handler structure
  *      - other errors returned by esp_intr_alloc
  */
 esp_err_t rtc_isr_register(intr_handler_t handler, void* handler_arg,
-                            uint32_t rtc_intr_mask);
+                            uint32_t rtc_intr_mask, uint32_t flags);
 /**
  * @brief Deregister the handler previously registered using rtc_isr_register
  * @param handler  handler function to call (as passed to rtc_isr_register)
@@ -43,6 +49,24 @@ esp_err_t rtc_isr_register(intr_handler_t handler, void* handler_arg,
  */
 esp_err_t rtc_isr_deregister(intr_handler_t handler, void* handler_arg);
 
+/**
+ * @brief Disable the RTC interrupt that is allowed to be executed when cache is disabled.
+ * cache disabled. Internal interrupt handle function will call this function in interrupt
+ * handler function. Disable bits when `esp_intr_noniram_disable` is called.
+ *
+ * @param cpu CPU number.
+ */
+void rtc_isr_noniram_disable(uint32_t cpu);
+
+/**
+ * @brief Enable the RTC interrupt that is allowed to be executed when cache is disabled.
+ * cache disabled. Internal interrupt handle function will call this function in interrupt
+ * handler function. Enable bits when `esp_intr_noniram_enable` is called.
+ *
+ * @param cpu CPU number.
+ */
+void rtc_isr_noniram_enable(uint32_t cpu);
+
 #ifdef __cplusplus
 }
 #endif

+ 4 - 0
components/esp_hw_support/intr_alloc.c

@@ -20,6 +20,7 @@
 #include "esp_intr_alloc.h"
 #include "esp_attr.h"
 #include "hal/cpu_hal.h"
+#include "esp_private/rtc_ctrl.h"
 #include "hal/interrupt_controller_hal.h"
 
 #if !CONFIG_FREERTOS_UNICORE
@@ -797,6 +798,8 @@ void IRAM_ATTR esp_intr_noniram_disable(void)
     non_iram_int_disabled_flag[cpu] = true;
     oldint = interrupt_controller_hal_read_interrupt_mask();
     interrupt_controller_hal_disable_interrupts(non_iram_ints);
+    // Disable the RTC bit which don't want to be put in IRAM.
+    rtc_isr_noniram_disable(cpu);
     // Save disabled ints
     non_iram_int_disabled[cpu] = oldint & non_iram_ints;
     portEXIT_CRITICAL_SAFE(&spinlock);
@@ -812,6 +815,7 @@ void IRAM_ATTR esp_intr_noniram_enable(void)
     }
     non_iram_int_disabled_flag[cpu] = false;
     interrupt_controller_hal_enable_interrupts(non_iram_ints);
+    rtc_isr_noniram_enable(cpu);
     portEXIT_CRITICAL_SAFE(&spinlock);
 }
 

+ 2 - 0
components/esp_hw_support/port/esp32/Kconfig.hw_support

@@ -7,6 +7,8 @@ choice ESP32_REV_MIN
 
     config ESP32_REV_MIN_0
         bool "Rev 0"
+        # Brownout on Rev 0 is bugged, must use interrupt
+        select ESP_SYSTEM_BROWNOUT_INTR
     config ESP32_REV_MIN_1
         bool "Rev 1"
     config ESP32_REV_MIN_2

+ 60 - 8
components/esp_hw_support/rtc_module.c

@@ -19,6 +19,7 @@
 #include "esp_intr_alloc.h"
 #include "sys/lock.h"
 #include "esp_private/rtc_ctrl.h"
+#include "esp_attr.h"
 
 #ifndef NDEBUG
 // Enable built-in checks in queue.h in debug builds
@@ -26,7 +27,15 @@
 #endif
 #include "sys/queue.h"
 
+#define NOT_REGISTERED      (-1)
+
 portMUX_TYPE rtc_spinlock = portMUX_INITIALIZER_UNLOCKED;
+// Disable the interrupt which cannot work without cache.
+static DRAM_ATTR uint32_t rtc_intr_cache;
+static DRAM_ATTR uint32_t rtc_intr_enabled;
+static DRAM_ATTR int rtc_isr_cpu = NOT_REGISTERED;  // Unused number
+static void s_rtc_isr_noniram_hook(uint32_t rtc_intr_mask);
+static void s_rtc_isr_noniram_hook_relieve(uint32_t rtc_intr_mask);
 
 /*---------------------------------------------------------------
                         INTERRUPT HANDLER
@@ -37,15 +46,16 @@ typedef struct rtc_isr_handler_ {
     uint32_t mask;
     intr_handler_t handler;
     void* handler_arg;
+    uint32_t flags;
     SLIST_ENTRY(rtc_isr_handler_) next;
 } rtc_isr_handler_t;
 
-static SLIST_HEAD(rtc_isr_handler_list_, rtc_isr_handler_) s_rtc_isr_handler_list =
+static DRAM_ATTR SLIST_HEAD(rtc_isr_handler_list_, rtc_isr_handler_) s_rtc_isr_handler_list =
         SLIST_HEAD_INITIALIZER(s_rtc_isr_handler_list);
-portMUX_TYPE s_rtc_isr_handler_list_lock = portMUX_INITIALIZER_UNLOCKED;
+static DRAM_ATTR portMUX_TYPE s_rtc_isr_handler_list_lock = portMUX_INITIALIZER_UNLOCKED;
 static intr_handle_t s_rtc_isr_handle;
 
-static void rtc_isr(void* arg)
+IRAM_ATTR static void rtc_isr(void* arg)
 {
     uint32_t status = REG_READ(RTC_CNTL_INT_ST_REG);
     rtc_isr_handler_t* it;
@@ -71,32 +81,37 @@ static esp_err_t rtc_isr_ensure_installed(void)
 
     REG_WRITE(RTC_CNTL_INT_ENA_REG, 0);
     REG_WRITE(RTC_CNTL_INT_CLR_REG, UINT32_MAX);
-    err = esp_intr_alloc(ETS_RTC_CORE_INTR_SOURCE, 0, &rtc_isr, NULL, &s_rtc_isr_handle);
+    err = esp_intr_alloc(ETS_RTC_CORE_INTR_SOURCE, ESP_INTR_FLAG_IRAM, &rtc_isr, NULL, &s_rtc_isr_handle);
     if (err != ESP_OK) {
         goto out;
     }
-
+    rtc_isr_cpu = esp_intr_get_cpu(s_rtc_isr_handle);
 out:
     portEXIT_CRITICAL(&s_rtc_isr_handler_list_lock);
     return err;
 }
 
-
-esp_err_t rtc_isr_register(intr_handler_t handler, void* handler_arg, uint32_t rtc_intr_mask)
+esp_err_t rtc_isr_register(intr_handler_t handler, void* handler_arg, uint32_t rtc_intr_mask, uint32_t flags)
 {
     esp_err_t err = rtc_isr_ensure_installed();
     if (err != ESP_OK) {
         return err;
     }
 
-    rtc_isr_handler_t* item = malloc(sizeof(*item));
+    rtc_isr_handler_t* item = heap_caps_malloc(sizeof(*item), MALLOC_CAP_INTERNAL);
     if (item == NULL) {
         return ESP_ERR_NO_MEM;
     }
     item->handler = handler;
     item->handler_arg = handler_arg;
     item->mask = rtc_intr_mask;
+    item->flags = flags;
     portENTER_CRITICAL(&s_rtc_isr_handler_list_lock);
+    if (flags & RTC_INTR_FLAG_IRAM) {
+        s_rtc_isr_noniram_hook(rtc_intr_mask);
+    } else {
+        s_rtc_isr_noniram_hook_relieve(rtc_intr_mask);
+    }
     SLIST_INSERT_HEAD(&s_rtc_isr_handler_list, item, next);
     portEXIT_CRITICAL(&s_rtc_isr_handler_list_lock);
     return ESP_OK;
@@ -116,6 +131,9 @@ esp_err_t rtc_isr_deregister(intr_handler_t handler, void* handler_arg)
                 SLIST_REMOVE_AFTER(prev, next);
             }
             found = true;
+            if (it->flags & RTC_INTR_FLAG_IRAM) {
+                s_rtc_isr_noniram_hook_relieve(it->mask);
+            }
             free(it);
             break;
         }
@@ -124,3 +142,37 @@ esp_err_t rtc_isr_deregister(intr_handler_t handler, void* handler_arg)
     portEXIT_CRITICAL(&s_rtc_isr_handler_list_lock);
     return found ? ESP_OK : ESP_ERR_INVALID_STATE;
 }
+
+/**
+ * @brief This helper function can be used to avoid the interrupt to be triggered with cache disabled.
+ *        There are lots of different signals on RTC module (i.e. sleep_wakeup, wdt, brownout_detect, etc.)
+ *        We might want some of them can be triggered with cache disabled, some are not. Therefore, this function
+ *        is created to avoid those which do not want to be triggered with cache disabled.
+ *
+ * @param rtc_intr_mask the mask of the rtc interrupt.
+ */
+static void s_rtc_isr_noniram_hook(uint32_t rtc_intr_mask)
+{
+    rtc_intr_cache |= rtc_intr_mask;
+}
+
+static void s_rtc_isr_noniram_hook_relieve(uint32_t rtc_intr_mask)
+{
+    rtc_intr_cache &= ~rtc_intr_mask;
+}
+
+IRAM_ATTR void rtc_isr_noniram_disable(uint32_t cpu)
+{
+    if (rtc_isr_cpu == cpu) {
+        rtc_intr_enabled |= RTCCNTL.int_ena.val;
+        RTCCNTL.int_ena.val &= rtc_intr_cache;
+    }
+}
+
+IRAM_ATTR void rtc_isr_noniram_enable(uint32_t cpu)
+{
+    if (rtc_isr_cpu == cpu) {
+        RTCCNTL.int_ena.val = rtc_intr_enabled;
+        rtc_intr_enabled = 0;
+    }
+}

+ 12 - 0
components/esp_system/Kconfig

@@ -533,6 +533,18 @@ menu "ESP System Settings"
     # Insert chip-specific system config
     rsource "./port/soc/$IDF_TARGET/Kconfig.system"
 
+    config ESP_SYSTEM_BROWNOUT_INTR
+        bool
+        default n
+        help
+            This config allows to trigger an interrupt when brownout detected. Software restart will be done
+            at the end of the default callback.
+            Two occasions need to restart the chip with interrupt so far.
+            (1). For ESP32 version 1, brown-out reset function doesn't work (see ESP32 errata 3.4).
+                  So that we must restart from interrupt.
+            (2). For special workflow, the chip needs do more things instead of restarting directly. This part
+                 needs to be done in callback function of interrupt.
+
 endmenu  # ESP System Settings
 
 menu "IPC (Inter-Processor Call)"

+ 34 - 22
components/esp_system/port/brownout.c

@@ -11,6 +11,7 @@
 
 #include "esp_private/system_internal.h"
 #include "esp_private/rtc_ctrl.h"
+#include "esp_private/spi_flash_os.h"
 
 #include "esp_rom_sys.h"
 
@@ -18,6 +19,9 @@
 #include "esp_cpu.h"
 #include "soc/rtc_periph.h"
 #include "hal/cpu_hal.h"
+#include "esp_attr.h"
+#include "bootloader_flash.h"
+#include "esp_intr_alloc.h"
 
 #include "hal/brownout_hal.h"
 
@@ -29,48 +33,58 @@
 #define BROWNOUT_DET_LVL 0
 #endif
 
-#if SOC_BROWNOUT_RESET_SUPPORTED
-#define BROWNOUT_RESET_EN true
-#else
-#define BROWNOUT_RESET_EN false
-#endif // SOC_BROWNOUT_RESET_SUPPORTED
-
-#ifndef SOC_BROWNOUT_RESET_SUPPORTED
-static void rtc_brownout_isr_handler(void *arg)
+#if CONFIG_ESP_SYSTEM_BROWNOUT_INTR
+IRAM_ATTR static void rtc_brownout_isr_handler(void *arg)
 {
     /* Normally RTC ISR clears the interrupt flag after the application-supplied
      * handler returns. Since restart is called here, the flag needs to be
      * cleared manually.
      */
     brownout_hal_intr_clear();
-    /* Stall the other CPU to make sure the code running there doesn't use UART
-     * at the same time as the following esp_rom_printf.
-     */
+    // Stop the other core.
     esp_cpu_stall(!cpu_hal_get_core_id());
     esp_reset_reason_set_hint(ESP_RST_BROWNOUT);
-    esp_rom_printf("\r\nBrownout detector was triggered\r\n\r\n");
+#if CONFIG_SPI_FLASH_BROWNOUT_RESET
+    if (spi_flash_brownout_need_reset()) {
+        bootloader_flash_reset_chip();
+    } else
+#endif // CONFIG_SPI_FLASH_BROWNOUT_RESET
+    {
+        esp_rom_printf("\r\nBrownout detector was triggered\r\n\r\n");
+    }
+
     esp_restart_noos();
 }
-#endif // not SOC_BROWNOUT_RESET_SUPPORTED
+#endif // CONFIG_ESP_SYSTEM_BROWNOUT_INTR
 
 void esp_brownout_init(void)
 {
+#if CONFIG_ESP_SYSTEM_BROWNOUT_INTR
     brownout_hal_config_t cfg = {
         .threshold = BROWNOUT_DET_LVL,
         .enabled = true,
-        .reset_enabled = BROWNOUT_RESET_EN,
+        .reset_enabled = false,
         .flash_power_down = true,
         .rf_power_down = true,
     };
 
     brownout_hal_config(&cfg);
+    brownout_hal_intr_clear();
+    rtc_isr_register(rtc_brownout_isr_handler, NULL, RTC_CNTL_BROWN_OUT_INT_ENA_M, RTC_INTR_FLAG_IRAM);
+    brownout_hal_intr_enable(true);
 
+#else // brownout without interrupt
 
-#ifndef SOC_BROWNOUT_RESET_SUPPORTED
-    rtc_isr_register(rtc_brownout_isr_handler, NULL, RTC_CNTL_BROWN_OUT_INT_ENA_M);
+    brownout_hal_config_t cfg = {
+        .threshold = BROWNOUT_DET_LVL,
+        .enabled = true,
+        .reset_enabled = true,
+        .flash_power_down = true,
+        .rf_power_down = true,
+    };
 
-    brownout_hal_intr_enable(true);
-#endif // not SOC_BROWNOUT_RESET_SUPPORTED
+    brownout_hal_config(&cfg);
+#endif
 }
 
 void esp_brownout_disable(void)
@@ -80,10 +94,8 @@ void esp_brownout_disable(void)
     };
 
     brownout_hal_config(&cfg);
-
-#ifndef SOC_BROWNOUT_RESET_SUPPORTED
+#if CONFIG_ESP_SYSTEM_BROWNOUT_INTR
     brownout_hal_intr_enable(false);
-
     rtc_isr_deregister(rtc_brownout_isr_handler, NULL);
-#endif // not SOC_BROWNOUT_RESET_SUPPORTED
+#endif // CONFIG_ESP_SYSTEM_BROWNOUT_INTR
 }

+ 4 - 1
components/esp_system/startup.c

@@ -66,7 +66,7 @@
 
 #include "esp_pthread.h"
 #include "esp_private/esp_clk.h"
-
+#include "esp_private/spi_flash_os.h"
 #include "esp_private/brownout.h"
 
 #include "esp_rom_sys.h"
@@ -301,6 +301,9 @@ static void do_core_init(void)
     esp_err_t flash_ret = esp_flash_init_default_chip();
     assert(flash_ret == ESP_OK);
     (void)flash_ret;
+#if CONFIG_SPI_FLASH_BROWNOUT_RESET
+    spi_flash_needs_reset_check();
+#endif // CONFIG_SPI_FLASH_BROWNOUT_RESET
 
 #ifdef CONFIG_EFUSE_VIRTUAL
     ESP_LOGW(TAG, "eFuse virtual mode is enabled. If Secure boot or Flash encryption is enabled then it does not provide any security. FOR TESTING ONLY!");

+ 1 - 1
components/esp_system/xt_wdt.c

@@ -62,7 +62,7 @@ esp_err_t esp_xt_wdt_init(const esp_xt_wdt_config_t *cfg)
         xt_wdt_hal_enable_backup_clk(&s_hal_ctx, rtc_clk_frequency_khz);
     }
 
-    ESP_GOTO_ON_ERROR(rtc_isr_register(rtc_xt_wdt_default_isr_handler, NULL, XT_WDT_LL_XTAL32_DEAD_INTR_MASK), err, TAG, "Failed to register isr");
+    ESP_GOTO_ON_ERROR(rtc_isr_register(rtc_xt_wdt_default_isr_handler, NULL, XT_WDT_LL_XTAL32_DEAD_INTR_MASK, 0), err, TAG, "Failed to register isr");
 
     xt_wdt_hal_enable(&s_hal_ctx, 1);
 

+ 7 - 14
components/hal/esp32/brownout_hal.c

@@ -1,20 +1,13 @@
 
-// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+/*
+ * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
 
 #include "hal/brownout_hal.h"
 #include "soc/rtc_cntl_struct.h"
+#include "esp_attr.h"
 
 void brownout_hal_config(const brownout_hal_config_t *cfg)
 {
@@ -35,7 +28,7 @@ void brownout_hal_intr_enable(bool enable)
     RTCCNTL.int_ena.rtc_brown_out = enable;
 }
 
-void brownout_hal_intr_clear(void)
+IRAM_ATTR void brownout_hal_intr_clear(void)
 {
     RTCCNTL.int_clr.rtc_brown_out = 1;
 }

+ 2 - 1
components/hal/esp32c2/brownout_hal.c

@@ -10,6 +10,7 @@
 #include "soc/rtc_cntl_reg.h"
 #include "esp_private/regi2c_ctrl.h"
 #include "regi2c_brownout.h"
+#include "esp_attr.h"
 
 
 void brownout_hal_config(const brownout_hal_config_t *cfg)
@@ -31,7 +32,7 @@ void brownout_hal_intr_enable(bool enable)
     RTCCNTL.int_ena.rtc_brown_out = enable;
 }
 
-void brownout_hal_intr_clear(void)
+IRAM_ATTR void brownout_hal_intr_clear(void)
 {
     RTCCNTL.int_clr.rtc_brown_out = 1;
 }

+ 2 - 1
components/hal/esp32c3/brownout_hal.c

@@ -10,6 +10,7 @@
 #include "soc/rtc_cntl_reg.h"
 #include "esp_private/regi2c_ctrl.h"
 #include "regi2c_brownout.h"
+#include "esp_attr.h"
 
 
 void brownout_hal_config(const brownout_hal_config_t *cfg)
@@ -31,7 +32,7 @@ void brownout_hal_intr_enable(bool enable)
     RTCCNTL.int_ena.rtc_brown_out = enable;
 }
 
-void brownout_hal_intr_clear(void)
+IRAM_ATTR void brownout_hal_intr_clear(void)
 {
     RTCCNTL.int_clr.rtc_brown_out = 1;
 }

+ 2 - 1
components/hal/esp32h2/brownout_hal.c

@@ -11,6 +11,7 @@
 #include "i2c_pmu.h"
 #include "esp_private/regi2c_ctrl.h"
 #include "regi2c_brownout.h"
+#include "esp_attr.h"
 
 
 void brownout_hal_config(const brownout_hal_config_t *cfg)
@@ -32,7 +33,7 @@ void brownout_hal_intr_enable(bool enable)
     RTCCNTL.int_ena.rtc_brown_out = enable;
 }
 
-void brownout_hal_intr_clear(void)
+IRAM_ATTR void brownout_hal_intr_clear(void)
 {
     RTCCNTL.int_clr.rtc_brown_out = 1;
 }

+ 2 - 2
components/hal/esp32s2/brownout_hal.c

@@ -10,7 +10,7 @@
 #include "soc/rtc_cntl_reg.h"
 #include "esp_private/regi2c_ctrl.h"
 #include "regi2c_brownout.h"
-
+#include "esp_attr.h"
 
 void brownout_hal_config(const brownout_hal_config_t *cfg)
 {
@@ -33,7 +33,7 @@ void brownout_hal_intr_enable(bool enable)
     RTCCNTL.int_ena.rtc_brown_out = enable;
 }
 
-void brownout_hal_intr_clear(void)
+IRAM_ATTR void brownout_hal_intr_clear(void)
 {
     RTCCNTL.int_clr.rtc_brown_out = 1;
 }

+ 2 - 1
components/hal/esp32s3/brownout_hal.c

@@ -10,6 +10,7 @@
 #include "soc/rtc_cntl_reg.h"
 #include "esp_private/regi2c_ctrl.h"
 #include "regi2c_brownout.h"
+#include "esp_attr.h"
 
 
 void brownout_hal_config(const brownout_hal_config_t *cfg)
@@ -32,7 +33,7 @@ void brownout_hal_intr_enable(bool enable)
     RTCCNTL.int_ena.rtc_brown_out = enable;
 }
 
-void brownout_hal_intr_clear(void)
+IRAM_ATTR void brownout_hal_intr_clear(void)
 {
     RTCCNTL.int_clr.rtc_brown_out = 1;
 }

+ 5 - 13
components/hal/include/hal/brownout_hal.h

@@ -1,16 +1,8 @@
-// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+/*
+ * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
 
 /*******************************************************************************
  * NOTICE

+ 0 - 1
components/soc/esp32/include/soc/soc_caps.h

@@ -126,7 +126,6 @@
 #define SOC_ADC_RTC_MAX_BITWIDTH                (12)
 #define SOC_RTC_SLOW_CLOCK_SUPPORT_8MD256       (1)
 
-
 /*-------------------------- BROWNOUT CAPS -----------------------------------*/
 #if SOC_CAPS_ECO_VER >= 1
 #define SOC_BROWNOUT_RESET_SUPPORTED 1

+ 4 - 4
components/soc/esp32s3/include/soc/Kconfig.soc_caps.in

@@ -3,10 +3,6 @@
 # using gen_soc_caps_kconfig.py, do not edit manually
 #####################################################
 
-config SOC_BROWNOUT_RESET_SUPPORTED
-    bool
-    default y
-
 config SOC_CPU_BREAKPOINTS_NUM
     int
     default 2
@@ -283,6 +279,10 @@ config SOC_APB_BACKUP_DMA
     bool
     default y
 
+config SOC_BROWNOUT_RESET_SUPPORTED
+    bool
+    default y
+
 config SOC_DS_SIGNATURE_MAX_BIT_LEN
     int
     default 4096

+ 0 - 25
components/soc/esp32s3/include/soc/brownout_caps.h

@@ -1,25 +0,0 @@
-// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define SOC_BROWNOUT_RESET_SUPPORTED 1
-
-#ifdef __cplusplus
-}
-#endif

+ 1 - 1
components/soc/esp32s3/include/soc/soc_caps.h

@@ -99,7 +99,7 @@
 #define SOC_APB_BACKUP_DMA              (1)
 
 /*-------------------------- BROWNOUT CAPS -----------------------------------*/
-#include "brownout_caps.h"
+#define SOC_BROWNOUT_RESET_SUPPORTED 1
 
 /*-------------------------- CPU CAPS ----------------------------------------*/
 #include "cpu_caps.h"

+ 1 - 0
components/spi_flash/CMakeLists.txt

@@ -25,6 +25,7 @@ else()
     set(srcs
         "partition.c"
         "partition_target.c"
+        "flash_brownout_hook.c"
     )
 
     if(CONFIG_ESPTOOLPY_OCT_FLASH)

+ 22 - 0
components/spi_flash/Kconfig

@@ -209,6 +209,28 @@ menu "SPI Flash driver"
 
             See example: custom_chip_driver under examples/storage for more details.
 
+    menu "SPI Flash behavior when brownout"
+
+        config SPI_FLASH_BROWNOUT_RESET_XMC
+            bool "Enable sending reset when brownout for XMC flash chips"
+            default y
+            select SPI_FLASH_BROWNOUT_RESET
+            help
+                When this option is selected, the patch will be enabled for XMC.
+                Follow the recommended flow by XMC for better stability.
+
+                DO NOT DISABLE UNLESS YOU KNOW WHAT YOU ARE DOING.
+
+        config SPI_FLASH_BROWNOUT_RESET
+            bool
+            default y
+            select ESP_SYSTEM_BROWNOUT_INTR
+            help
+                When brownout happens during flash erase/write operations,
+                send reset command to stop the flash operations to improve stability.
+
+    endmenu
+
     menu "Auto-detect flash chips"
         visible if !SPI_FLASH_OVERRIDE_CHIP_DRIVER_LIST
 

+ 39 - 0
components/spi_flash/flash_brownout_hook.c

@@ -0,0 +1,39 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "esp_attr.h"
+#include "sdkconfig.h"
+#include "esp_rom_spiflash.h"
+
+#if CONFIG_SPI_FLASH_BROWNOUT_RESET
+
+static bool flash_brownout_needs_reset = false;
+static bool flash_erasing = false;
+
+// This function could be called in startup
+void spi_flash_needs_reset_check(void)
+{
+    // Currently only XMC is suggested to reset when brownout
+#if CONFIG_SPI_FLASH_BROWNOUT_RESET_XMC
+    if ((g_rom_flashchip.device_id >> 16) == 0x20) {
+        flash_brownout_needs_reset = true;
+    }
+#endif
+}
+
+void spi_flash_set_erasing_flag(bool status)
+{
+    flash_erasing = status;
+}
+
+bool spi_flash_brownout_need_reset(void)
+{
+    return (flash_brownout_needs_reset && flash_erasing);
+}
+
+#endif //CONFIG_SPI_FLASH_BROWNOUT_RESET

+ 10 - 13
components/spi_flash/include/esp_flash.h

@@ -1,16 +1,8 @@
-// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+/*
+ * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
 
 #pragma once
 #include "esp_err.h"
@@ -80,6 +72,11 @@ typedef struct {
     /** Called for get system time. */
     int64_t (*get_system_time)(void *arg);
 
+    #define SPI_FLASH_OS_IS_ERASING_STATUS_FLAG   BIT(0)
+
+    /** Call to set flash operation status */
+    void (*set_flash_op_status)(uint32_t op_status);
+
 } esp_flash_os_functions_t;
 
 /** @brief Structure to describe a SPI flash chip connected to the system.

+ 23 - 1
components/spi_flash/include/esp_private/spi_flash_os.h

@@ -1,5 +1,5 @@
 /*
- * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
  *
  * SPDX-License-Identifier: Apache-2.0
  */
@@ -101,6 +101,28 @@ bool spi_timing_is_tuned(void);
  */
 void spi_flash_set_vendor_required_regs(void);
 
+/**
+ * @brief Judge whether need to reset flash when brownout.
+ *        Set` flash_brownout_needs_reset` inside the function if really need reset.
+ */
+void spi_flash_needs_reset_check(void);
+
+/**
+ * @brief Set flag to reset flash. set when erase chip or program chip
+ *
+ * @param bool status. True if flash is eraing. False if flash is not erasing.
+ *
+ * @return None.
+ */
+void spi_flash_set_erasing_flag(bool status);
+
+/**
+ * @brief Judge whether need to reset flash when brownout.
+ *
+ * @return true if need reset, otherwise false.
+ */
+bool spi_flash_brownout_need_reset(void);
+
 /**
  * @brief Enable SPI flash high performance mode.
  *

+ 5 - 13
components/spi_flash/include/memspi_host_driver.h

@@ -1,16 +1,8 @@
-// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+/*
+ * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
 
 #pragma once
 #include "hal/spi_flash_hal.h"

+ 1 - 0
components/spi_flash/linker.lf

@@ -9,6 +9,7 @@ entries:
     spi_flash_chip_boya (noflash)
     spi_flash_chip_th (noflash)
     memspi_host_driver (noflash)
+    flash_brownout_hook (noflash)
 
     if IDF_TARGET_ESP32S3 = y:
         spi_flash_timing_tuning (noflash)

+ 18 - 13
components/spi_flash/spi_flash_chip_generic.c

@@ -1,16 +1,8 @@
-// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+/*
+ * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
 
 #include <stdlib.h>
 #include <string.h>
@@ -20,6 +12,7 @@
 #include "hal/spi_flash_encrypt_hal.h"
 #include "esp_log.h"
 #include "esp_attr.h"
+#include "esp_private/spi_flash_os.h"
 
 typedef struct flash_chip_dummy {
     uint8_t dio_dummy_bitlen;
@@ -69,6 +62,12 @@ const DRAM_ATTR flash_chip_op_timeout_t spi_flash_chip_generic_timeout = {
     .page_program_timeout = SPI_FLASH_GENERIC_PAGE_PROGRAM_TIMEOUT_MS * 1000,
 };
 
+#define SET_FLASH_ERASE_STATUS(CHIP, status) do { \
+    if (CHIP->os_func->set_flash_op_status) { \
+        CHIP->os_func->set_flash_op_status(status); \
+    } \
+} while(0)
+
 static const char TAG[] = "chip_generic";
 
 #ifndef CONFIG_SPI_FLASH_ROM_IMPL
@@ -130,6 +129,7 @@ esp_err_t spi_flash_chip_generic_erase_chip(esp_flash_t *chip)
     }
     //The chip didn't accept the previous write command. Ignore this in preparation stage.
     if (err == ESP_OK || err == ESP_ERR_NOT_SUPPORTED) {
+        SET_FLASH_ERASE_STATUS(chip, SPI_FLASH_OS_IS_ERASING_STATUS_FLAG);
         chip->host->driver->erase_chip(chip->host);
         chip->busy = 1;
 #ifdef CONFIG_SPI_FLASH_CHECK_ERASE_TIMEOUT_DISABLED
@@ -137,6 +137,7 @@ esp_err_t spi_flash_chip_generic_erase_chip(esp_flash_t *chip)
 #else
         err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->chip_erase_timeout);
 #endif
+        SET_FLASH_ERASE_STATUS(chip, 0);
     }
     // Ensure WEL is 0, even if the erase failed.
     if (err == ESP_ERR_NOT_SUPPORTED) {
@@ -154,6 +155,7 @@ esp_err_t spi_flash_chip_generic_erase_sector(esp_flash_t *chip, uint32_t start_
     }
     //The chip didn't accept the previous write command. Ignore this in preparationstage.
     if (err == ESP_OK || err == ESP_ERR_NOT_SUPPORTED) {
+        SET_FLASH_ERASE_STATUS(chip, SPI_FLASH_OS_IS_ERASING_STATUS_FLAG);
         chip->host->driver->erase_sector(chip->host, start_address);
         chip->busy = 1;
 #ifdef CONFIG_SPI_FLASH_CHECK_ERASE_TIMEOUT_DISABLED
@@ -161,6 +163,7 @@ esp_err_t spi_flash_chip_generic_erase_sector(esp_flash_t *chip, uint32_t start_
 #else
         err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->sector_erase_timeout);
 #endif
+        SET_FLASH_ERASE_STATUS(chip, 0);
     }
     // Ensure WEL is 0, even if the erase failed.
     if (err == ESP_ERR_NOT_SUPPORTED) {
@@ -178,6 +181,7 @@ esp_err_t spi_flash_chip_generic_erase_block(esp_flash_t *chip, uint32_t start_a
     }
     //The chip didn't accept the previous write command. Ignore this in preparationstage.
     if (err == ESP_OK || err == ESP_ERR_NOT_SUPPORTED) {
+        SET_FLASH_ERASE_STATUS(chip, SPI_FLASH_OS_IS_ERASING_STATUS_FLAG);
         chip->host->driver->erase_block(chip->host, start_address);
         chip->busy = 1;
 #ifdef CONFIG_SPI_FLASH_CHECK_ERASE_TIMEOUT_DISABLED
@@ -185,6 +189,7 @@ esp_err_t spi_flash_chip_generic_erase_block(esp_flash_t *chip, uint32_t start_a
 #else
         err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->block_erase_timeout);
 #endif
+        SET_FLASH_ERASE_STATUS(chip, 0);
     }
     // Ensure WEL is 0, even if the erase failed.
     if (err == ESP_ERR_NOT_SUPPORTED) {

+ 14 - 0
components/spi_flash/spi_flash_os_func_app.c

@@ -18,6 +18,7 @@
 #include "esp_log.h"
 #include "esp_compiler.h"
 #include "esp_rom_sys.h"
+#include "esp_private/spi_flash_os.h"
 
 #include "driver/spi_common_internal.h"
 
@@ -185,6 +186,13 @@ static IRAM_ATTR esp_err_t main_flash_region_protected(void* arg, size_t start_a
     }
 }
 
+
+static IRAM_ATTR void main_flash_op_status(uint32_t op_status)
+{
+    bool is_erasing = op_status & SPI_FLASH_OS_IS_ERASING_STATUS_FLAG;
+    spi_flash_set_erasing_flag(is_erasing);
+}
+
 static DRAM_ATTR spi1_app_func_arg_t main_flash_arg = {};
 
 //for SPI1, we have to disable the cache and interrupts before using the SPI bus
@@ -197,6 +205,11 @@ static const DRAM_ATTR esp_flash_os_functions_t esp_flash_spi1_default_os_functi
     .release_temp_buffer = release_buffer_malloc,
     .check_yield = spi1_flash_os_check_yield,
     .yield = spi1_flash_os_yield,
+#if CONFIG_SPI_FLASH_BROWNOUT_RESET
+    .set_flash_op_status = main_flash_op_status,
+#else
+    .set_flash_op_status = NULL,
+#endif
 };
 
 static const esp_flash_os_functions_t esp_flash_spi23_default_os_functions = {
@@ -208,6 +221,7 @@ static const esp_flash_os_functions_t esp_flash_spi23_default_os_functions = {
     .region_protected = NULL,
     .check_yield = NULL,
     .yield = NULL,
+    .set_flash_op_status = NULL,
 };
 
 static bool use_bus_lock(int host_id)

+ 0 - 5
tools/ci/check_copyright_ignore.txt

@@ -774,7 +774,6 @@ components/hal/aes_hal.c
 components/hal/cpu_hal.c
 components/hal/dac_hal.c
 components/hal/ds_hal.c
-components/hal/esp32/brownout_hal.c
 components/hal/esp32/gpio_hal_workaround.c
 components/hal/esp32/include/hal/aes_ll.h
 components/hal/esp32/include/hal/can_hal.h
@@ -858,7 +857,6 @@ components/hal/esp32s3/include/hal/usb_serial_jtag_ll.h
 components/hal/esp32s3/interrupt_descriptor_table.c
 components/hal/include/hal/aes_hal.h
 components/hal/include/hal/aes_types.h
-components/hal/include/hal/brownout_hal.h
 components/hal/include/hal/cpu_types.h
 components/hal/include/hal/dac_hal.h
 components/hal/include/hal/dac_types.h
@@ -1530,10 +1528,8 @@ components/soc/include/soc/usb_periph.h
 components/soc/lldesc.c
 components/soc/soc_include_legacy_warn.c
 components/spi_flash/cache_utils.h
-components/spi_flash/include/esp_flash.h
 components/spi_flash/include/esp_spi_flash.h
 components/spi_flash/include/esp_spi_flash_counters.h
-components/spi_flash/include/memspi_host_driver.h
 components/spi_flash/include/spi_flash_chip_boya.h
 components/spi_flash/include/spi_flash_chip_driver.h
 components/spi_flash/include/spi_flash_chip_gd.h
@@ -1547,7 +1543,6 @@ components/spi_flash/sim/flash_mock_util.c
 components/spi_flash/sim/sdkconfig/sdkconfig.h
 components/spi_flash/spi_flash_chip_boya.c
 components/spi_flash/spi_flash_chip_gd.c
-components/spi_flash/spi_flash_chip_generic.c
 components/spi_flash/spi_flash_chip_issi.c
 components/spi_flash/spi_flash_chip_mxic.c
 components/spi_flash/spi_flash_chip_mxic_opi.c

+ 2 - 1
tools/unit-test-app/configs/default

@@ -1,4 +1,5 @@
 # This config is split between targets since different component needs to be included (esp32, esp32s2)
+# IRAM is full... split some component to default_32_2
 CONFIG_IDF_TARGET="esp32"
-TEST_COMPONENTS=freertos esp_hw_support esp_ipc esp_system esp_timer driver heap pthread soc spi_flash vfs
+TEST_COMPONENTS=freertos esp_hw_support esp_ipc esp_system esp_timer driver heap
 CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD=y

+ 4 - 0
tools/unit-test-app/configs/default_32_2

@@ -0,0 +1,4 @@
+# continue from default
+CONFIG_IDF_TARGET="esp32"
+TEST_COMPONENTS=pthread soc spi_flash vfs
+CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD=y