From 895a3e1bb2f3ba499cfbccc49ce7f012de5dabc4 Mon Sep 17 00:00:00 2001 From: Cao Sen Miao Date: Mon, 30 May 2022 16:47:14 +0800 Subject: [PATCH 1/3] esp_intr: Split RTC interrupt, making some of signals can be triggered with cache disabled --- components/driver/esp32/touch_sensor.c | 4 +- components/driver/esp32s2/touch_sensor.c | 4 +- components/driver/esp32s3/touch_sensor.c | 2 +- .../include/esp_private/rtc_ctrl.h | 26 ++++++- components/esp_hw_support/intr_alloc.c | 4 ++ components/esp_hw_support/rtc_module.c | 68 ++++++++++++++++--- components/esp_system/xt_wdt.c | 2 +- 7 files changed, 95 insertions(+), 15 deletions(-) diff --git a/components/driver/esp32/touch_sensor.c b/components/driver/esp32/touch_sensor.c index 452eff7311..bf9a91b363 100644 --- a/components/driver/esp32/touch_sensor.c +++ b/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) diff --git a/components/driver/esp32s2/touch_sensor.c b/components/driver/esp32s2/touch_sensor.c index cbf99e263c..13322f6f60 100644 --- a/components/driver/esp32s2/touch_sensor.c +++ b/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; } diff --git a/components/driver/esp32s3/touch_sensor.c b/components/driver/esp32s3/touch_sensor.c index e3d485951e..f3d2dab42b 100644 --- a/components/driver/esp32s3/touch_sensor.c +++ b/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; } diff --git a/components/esp_hw_support/include/esp_private/rtc_ctrl.h b/components/esp_hw_support/include/esp_private/rtc_ctrl.h index 2a0f5916c0..bea8bbdd2a 100644 --- a/components/esp_hw_support/include/esp_private/rtc_ctrl.h +++ b/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 diff --git a/components/esp_hw_support/intr_alloc.c b/components/esp_hw_support/intr_alloc.c index 9c5d204e58..1801f483c9 100644 --- a/components/esp_hw_support/intr_alloc.c +++ b/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); } diff --git a/components/esp_hw_support/rtc_module.c b/components/esp_hw_support/rtc_module.c index 76bdd26e8c..640f4c1db6 100644 --- a/components/esp_hw_support/rtc_module.c +++ b/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; + } +} diff --git a/components/esp_system/xt_wdt.c b/components/esp_system/xt_wdt.c index 67d9977fb8..90bbb8e443 100644 --- a/components/esp_system/xt_wdt.c +++ b/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); From 890f046ee9d7d1997decf8c397ba39c0d904f339 Mon Sep 17 00:00:00 2001 From: Cao Sen Miao Date: Mon, 30 May 2022 16:48:30 +0800 Subject: [PATCH 2/3] test: split a new banch of testing to save IRAM --- tools/unit-test-app/configs/default | 3 ++- tools/unit-test-app/configs/default_32_2 | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 tools/unit-test-app/configs/default_32_2 diff --git a/tools/unit-test-app/configs/default b/tools/unit-test-app/configs/default index 2edd93d470..b3048b444d 100644 --- a/tools/unit-test-app/configs/default +++ b/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 diff --git a/tools/unit-test-app/configs/default_32_2 b/tools/unit-test-app/configs/default_32_2 new file mode 100644 index 0000000000..4daf14d44d --- /dev/null +++ b/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 From 6a2d3509dcedc2fe67a98ae3a0fd5a089c256ef8 Mon Sep 17 00:00:00 2001 From: Cao Sen Miao Date: Mon, 30 May 2022 16:49:19 +0800 Subject: [PATCH 3/3] spi_flash: Making XMC flash works more stable when brownout detected --- .../include/bootloader_flash.h | 6 ++ .../bootloader_flash/src/bootloader_flash.c | 41 +++++++++++++ .../port/esp32/Kconfig.hw_support | 2 + components/esp_system/Kconfig | 12 ++++ components/esp_system/port/brownout.c | 60 +++++++++++-------- components/esp_system/startup.c | 5 +- components/hal/esp32/brownout_hal.c | 21 +++---- components/hal/esp32c2/brownout_hal.c | 3 +- components/hal/esp32c3/brownout_hal.c | 3 +- components/hal/esp32h2/brownout_hal.c | 3 +- components/hal/esp32s2/brownout_hal.c | 4 +- components/hal/esp32s3/brownout_hal.c | 3 +- components/hal/include/hal/brownout_hal.h | 18 ++---- components/soc/esp32/include/soc/soc_caps.h | 1 - .../esp32s3/include/soc/Kconfig.soc_caps.in | 8 +-- .../soc/esp32s3/include/soc/brownout_caps.h | 25 -------- components/soc/esp32s3/include/soc/soc_caps.h | 2 +- components/spi_flash/CMakeLists.txt | 1 + components/spi_flash/Kconfig | 22 +++++++ components/spi_flash/flash_brownout_hook.c | 39 ++++++++++++ components/spi_flash/include/esp_flash.h | 23 ++++--- .../include/esp_private/spi_flash_os.h | 24 +++++++- .../spi_flash/include/memspi_host_driver.h | 18 ++---- components/spi_flash/linker.lf | 1 + components/spi_flash/spi_flash_chip_generic.c | 31 ++++++---- components/spi_flash/spi_flash_os_func_app.c | 14 +++++ tools/ci/check_copyright_ignore.txt | 5 -- 27 files changed, 261 insertions(+), 134 deletions(-) delete mode 100644 components/soc/esp32s3/include/soc/brownout_caps.h create mode 100644 components/spi_flash/flash_brownout_hook.c diff --git a/components/bootloader_support/bootloader_flash/include/bootloader_flash.h b/components/bootloader_support/bootloader_flash/include/bootloader_flash.h index 51a466fd82..7c48728cf0 100644 --- a/components/bootloader_support/bootloader_flash/include/bootloader_flash.h +++ b/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 } diff --git a/components/bootloader_support/bootloader_flash/src/bootloader_flash.c b/components/bootloader_support/bootloader_flash/src/bootloader_flash.c index 2957737081..531653cc8d 100644 --- a/components/bootloader_support/bootloader_flash/src/bootloader_flash.c +++ b/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; +} diff --git a/components/esp_hw_support/port/esp32/Kconfig.hw_support b/components/esp_hw_support/port/esp32/Kconfig.hw_support index 2ed4badd62..91711dc941 100644 --- a/components/esp_hw_support/port/esp32/Kconfig.hw_support +++ b/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 diff --git a/components/esp_system/Kconfig b/components/esp_system/Kconfig index 5cf117ebbb..a6e4c483fe 100644 --- a/components/esp_system/Kconfig +++ b/components/esp_system/Kconfig @@ -531,6 +531,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)" diff --git a/components/esp_system/port/brownout.c b/components/esp_system/port/brownout.c index 21ec6800be..9d0d66c165 100644 --- a/components/esp_system/port/brownout.c +++ b/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); - - -#ifndef SOC_BROWNOUT_RESET_SUPPORTED - rtc_isr_register(rtc_brownout_isr_handler, NULL, RTC_CNTL_BROWN_OUT_INT_ENA_M); - + 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); -#endif // not SOC_BROWNOUT_RESET_SUPPORTED + +#else // brownout without interrupt + + brownout_hal_config_t cfg = { + .threshold = BROWNOUT_DET_LVL, + .enabled = true, + .reset_enabled = true, + .flash_power_down = true, + .rf_power_down = true, + }; + + 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 } diff --git a/components/esp_system/startup.c b/components/esp_system/startup.c index 786466b652..6bd8d3bac7 100644 --- a/components/esp_system/startup.c +++ b/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!"); diff --git a/components/hal/esp32/brownout_hal.c b/components/hal/esp32/brownout_hal.c index 5fc448601b..0d53698068 100644 --- a/components/hal/esp32/brownout_hal.c +++ b/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; } diff --git a/components/hal/esp32c2/brownout_hal.c b/components/hal/esp32c2/brownout_hal.c index 7c32faaeda..ee0c7377e6 100644 --- a/components/hal/esp32c2/brownout_hal.c +++ b/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; } diff --git a/components/hal/esp32c3/brownout_hal.c b/components/hal/esp32c3/brownout_hal.c index 7c32faaeda..ee0c7377e6 100644 --- a/components/hal/esp32c3/brownout_hal.c +++ b/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; } diff --git a/components/hal/esp32h2/brownout_hal.c b/components/hal/esp32h2/brownout_hal.c index 70b55e7f55..aff79650c0 100644 --- a/components/hal/esp32h2/brownout_hal.c +++ b/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; } diff --git a/components/hal/esp32s2/brownout_hal.c b/components/hal/esp32s2/brownout_hal.c index 3b95074ee5..04ce19f5c8 100644 --- a/components/hal/esp32s2/brownout_hal.c +++ b/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; } diff --git a/components/hal/esp32s3/brownout_hal.c b/components/hal/esp32s3/brownout_hal.c index 567adf8acc..558faac017 100644 --- a/components/hal/esp32s3/brownout_hal.c +++ b/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; } diff --git a/components/hal/include/hal/brownout_hal.h b/components/hal/include/hal/brownout_hal.h index b56823b399..07952bbc65 100644 --- a/components/hal/include/hal/brownout_hal.h +++ b/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 diff --git a/components/soc/esp32/include/soc/soc_caps.h b/components/soc/esp32/include/soc/soc_caps.h index 38cbe76484..e957870f6c 100644 --- a/components/soc/esp32/include/soc/soc_caps.h +++ b/components/soc/esp32/include/soc/soc_caps.h @@ -127,7 +127,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 diff --git a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in index 443c3da2f5..5e073483b0 100644 --- a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in +++ b/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 @@ -287,6 +283,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 diff --git a/components/soc/esp32s3/include/soc/brownout_caps.h b/components/soc/esp32s3/include/soc/brownout_caps.h deleted file mode 100644 index 797d33ebb9..0000000000 --- a/components/soc/esp32s3/include/soc/brownout_caps.h +++ /dev/null @@ -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 diff --git a/components/soc/esp32s3/include/soc/soc_caps.h b/components/soc/esp32s3/include/soc/soc_caps.h index bf0a452094..32804c62b3 100644 --- a/components/soc/esp32s3/include/soc/soc_caps.h +++ b/components/soc/esp32s3/include/soc/soc_caps.h @@ -100,7 +100,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" diff --git a/components/spi_flash/CMakeLists.txt b/components/spi_flash/CMakeLists.txt index 55f6638fa0..69b95528f8 100644 --- a/components/spi_flash/CMakeLists.txt +++ b/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) diff --git a/components/spi_flash/Kconfig b/components/spi_flash/Kconfig index ba8c559b12..6bb4716299 100644 --- a/components/spi_flash/Kconfig +++ b/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 diff --git a/components/spi_flash/flash_brownout_hook.c b/components/spi_flash/flash_brownout_hook.c new file mode 100644 index 0000000000..7d070c0b19 --- /dev/null +++ b/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 +#include +#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 diff --git a/components/spi_flash/include/esp_flash.h b/components/spi_flash/include/esp_flash.h index c5adb279dc..a203fe0a09 100644 --- a/components/spi_flash/include/esp_flash.h +++ b/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. diff --git a/components/spi_flash/include/esp_private/spi_flash_os.h b/components/spi_flash/include/esp_private/spi_flash_os.h index 914ddd8e3b..d4c622bb50 100644 --- a/components/spi_flash/include/esp_private/spi_flash_os.h +++ b/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. * diff --git a/components/spi_flash/include/memspi_host_driver.h b/components/spi_flash/include/memspi_host_driver.h index 1c7b3cb29c..29379e21a2 100644 --- a/components/spi_flash/include/memspi_host_driver.h +++ b/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" diff --git a/components/spi_flash/linker.lf b/components/spi_flash/linker.lf index 2e3376c88c..fa333dea61 100644 --- a/components/spi_flash/linker.lf +++ b/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) diff --git a/components/spi_flash/spi_flash_chip_generic.c b/components/spi_flash/spi_flash_chip_generic.c index c1173c9b83..a2d7f3fe94 100644 --- a/components/spi_flash/spi_flash_chip_generic.c +++ b/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 #include @@ -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) { diff --git a/components/spi_flash/spi_flash_os_func_app.c b/components/spi_flash/spi_flash_os_func_app.c index 94a2e5089c..f5642d4ec1 100644 --- a/components/spi_flash/spi_flash_os_func_app.c +++ b/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) diff --git a/tools/ci/check_copyright_ignore.txt b/tools/ci/check_copyright_ignore.txt index 01d5f74b45..591a0e0e2b 100644 --- a/tools/ci/check_copyright_ignore.txt +++ b/tools/ci/check_copyright_ignore.txt @@ -775,7 +775,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 @@ -859,7 +858,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 @@ -1536,10 +1534,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 @@ -1553,7 +1549,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