From 2c4a1837d1155a9ea801b163a965057c44b593bc Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Tue, 21 Jul 2026 14:31:13 +0800 Subject: [PATCH] fix(esp_hw_support): fix deepsleep deadlock at s_phy_int_mux --- components/esp_hw_support/sleep_modes.c | 28 +++++++++++++------------ 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index a3d940c47ae..27695c90ec7 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -1259,15 +1259,6 @@ static esp_err_t FORCE_IRAM_ATTR deep_sleep_start(bool allow_sleep_rejection) esp_sync_timekeeping_timers(); - // Must acquire all spinlocks which may be acquired during sleep process before stalling other core, - // otherwise deadlock may occur. - esp_os_enter_critical(&s_config.lock); -#if !CONFIG_FREERTOS_UNICORE - extern portMUX_TYPE rtc_spinlock; - esp_os_enter_critical_safe(&rtc_spinlock); // Maybe acquired from temp_sensor_get_raw_value by phy_close_rf callback - esp_clk_private_lock(); // Maybe acquired from esp_clk_slowclk_cal_set -#endif - #if CONFIG_ESP_INT_WDT && CONFIG_ESP32_ECO3_CACHE_LOCK_FIX // The other core will be stalled by high-priority interrupt and spins on variables in internal RAM, // which naturally avoids cache livelock, so the 20ms livelock workaround timeout is not needed. @@ -1275,10 +1266,25 @@ static esp_err_t FORCE_IRAM_ATTR deep_sleep_start(bool allow_sleep_rejection) // esp_int_wdt_livelock_workaround, which may cause deadlock. esp_int_wdt_livelock_workaround(false); #endif + /* Disable interrupts and stall another core in case another task writes * to RTC memory while we calculate RTC memory CRC. */ + esp_os_enter_critical(&s_config.lock); + +#if CONFIG_FREERTOS_PORT_THREAD_SAFE_CLAIM esp_ipc_isr_stall_other_cpu(); +#else + /* Retry with the lock held on success. Drop the lock on failure so the other + * CPU can leave its critical section (and to avoid deadlock on s_config.lock). + */ + while (esp_ipc_isr_stall_other_cpu_safe() != ESP_OK) { + esp_os_exit_critical(&s_config.lock); + esp_rom_delay_us(portTICK_PERIOD_MS * 1000 / 10); + esp_os_enter_critical(&s_config.lock); + } +#endif + esp_ipc_isr_stall_pause(); // record current RTC time @@ -1368,10 +1374,6 @@ static esp_err_t FORCE_IRAM_ATTR deep_sleep_start(bool allow_sleep_rejection) #if CONFIG_ESP_INT_WDT && CONFIG_ESP32_ECO3_CACHE_LOCK_FIX // Configure WDT to use livelock workaround timeout after releasing other CPU esp_int_wdt_livelock_workaround(true); -#endif -#if !CONFIG_FREERTOS_UNICORE - esp_clk_private_unlock(); - esp_os_exit_critical_safe(&rtc_spinlock); #endif esp_os_exit_critical(&s_config.lock);