diff --git a/components/esp_hw_support/include/esp_sleep.h b/components/esp_hw_support/include/esp_sleep.h index 71325754c6..bb5db22e7d 100644 --- a/components/esp_hw_support/include/esp_sleep.h +++ b/components/esp_hw_support/include/esp_sleep.h @@ -483,8 +483,20 @@ esp_err_t esp_sleep_pd_config(esp_sleep_pd_domain_t domain, * then it returns from it. * * The reason for the rejection can be such as a short sleep time. + * + * @return + * - No return - If the sleep is not rejected. + * - ESP_ERR_SLEEP_REJECT sleep request is rejected(wakeup source set before the sleep request) */ -void esp_deep_sleep_start(void); +esp_err_t esp_deep_sleep_try_to_start(void); + +/** + * @brief Enter deep sleep with the configured wakeup options + * + * @note The function does not do a return (no rejection). Even if wakeup source set before the sleep request + * it goes to deep sleep anyway. + */ +void esp_deep_sleep_start(void) __attribute__((__noreturn__)); /** * @brief Enter light sleep with the configured wakeup options @@ -514,9 +526,29 @@ esp_err_t esp_light_sleep_start(void); * The reason for the rejection can be such as a short sleep time. * * @param time_in_us deep-sleep time, unit: microsecond + * + * @return + * - No return - If the sleep is not rejected. + * - ESP_ERR_SLEEP_REJECT sleep request is rejected(wakeup source set before the sleep request) */ -void esp_deep_sleep(uint64_t time_in_us); +esp_err_t esp_deep_sleep_try(uint64_t time_in_us); +/** + * @brief Enter deep-sleep mode + * + * The device will automatically wake up after the deep-sleep time + * Upon waking up, the device calls deep sleep wake stub, and then proceeds + * to load application. + * + * Call to this function is equivalent to a call to esp_deep_sleep_enable_timer_wakeup + * followed by a call to esp_deep_sleep_start. + * + * @note The function does not do a return (no rejection).. Even if wakeup source set before the sleep request + * it goes to deep sleep anyway. + * + * @param time_in_us deep-sleep time, unit: microsecond + */ +void esp_deep_sleep(uint64_t time_in_us) __attribute__((__noreturn__)); /** * @brief Register a callback to be called from the deep sleep prepare diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index b112109005..a4720d8ef3 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -372,6 +372,12 @@ void esp_deep_sleep(uint64_t time_in_us) esp_deep_sleep_start(); } +esp_err_t esp_deep_sleep_try(uint64_t time_in_us) +{ + esp_sleep_enable_timer_wakeup(time_in_us); + return esp_deep_sleep_try_to_start(); +} + esp_err_t esp_deep_sleep_register_hook(esp_deep_sleep_cb_t new_dslp_cb) { portENTER_CRITICAL(&spinlock_rtc_deep_sleep); @@ -569,7 +575,7 @@ FORCE_INLINE_ATTR void misc_modules_wake_prepare(void) inline static uint32_t call_rtc_sleep_start(uint32_t reject_triggers, uint32_t lslp_mem_inf_fpu, bool dslp); -static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t mode) +static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t mode, bool allow_sleep_rejection) { // Stop UART output so that output is not lost due to APB frequency change. // For light sleep, suspend UART output — it will resume after wakeup. @@ -667,7 +673,7 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m } #endif - uint32_t reject_triggers = s_config.wakeup_triggers & RTC_SLEEP_REJECT_MASK; + uint32_t reject_triggers = allow_sleep_rejection ? (s_config.wakeup_triggers & RTC_SLEEP_REJECT_MASK) : 0; if (!deep_sleep) { /* Enable sleep reject for faster return from this function, @@ -708,7 +714,7 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m // Configure timer wakeup if (!should_skip_sleep && (s_config.wakeup_triggers & RTC_TIMER_TRIG_EN)) { if (timer_wakeup_prepare(sleep_duration) != ESP_OK) { - should_skip_sleep = true; + should_skip_sleep = allow_sleep_rejection ? true : false; } } @@ -836,7 +842,7 @@ inline static uint32_t IRAM_ATTR call_rtc_sleep_start(uint32_t reject_triggers, #endif } -void IRAM_ATTR esp_deep_sleep_start(void) +static esp_err_t IRAM_ATTR deep_sleep_start(bool allow_sleep_rejection) { #if CONFIG_IDF_TARGET_ESP32S2 /* Due to hardware limitations, on S2 the brownout detector sometimes trigger during deep sleep @@ -897,7 +903,9 @@ void IRAM_ATTR esp_deep_sleep_start(void) #endif // Enter sleep - if (esp_sleep_start(force_pd_flags | pd_flags, ESP_SLEEP_MODE_DEEP_SLEEP) == ESP_ERR_SLEEP_REJECT) { + esp_err_t err = ESP_OK; + if (esp_sleep_start(force_pd_flags | pd_flags, ESP_SLEEP_MODE_DEEP_SLEEP, allow_sleep_rejection) == ESP_ERR_SLEEP_REJECT) { + err = ESP_ERR_SLEEP_REJECT; #if CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION /* Cache Resume 2: if CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION is enabled, cache has been suspended in esp_sleep_start */ resume_cache(); @@ -913,6 +921,21 @@ void IRAM_ATTR esp_deep_sleep_start(void) // Never returns here, except that the sleep is rejected. esp_ipc_isr_release_other_cpu(); portEXIT_CRITICAL(&spinlock_rtc_deep_sleep); + return err; +} + +void IRAM_ATTR esp_deep_sleep_start(void) +{ + bool allow_sleep_rejection = true; + deep_sleep_start(!allow_sleep_rejection); + // Never returns here + abort(); +} + +esp_err_t IRAM_ATTR esp_deep_sleep_try_to_start(void) +{ + bool allow_sleep_rejection = true; + return deep_sleep_start(allow_sleep_rejection); } /** @@ -930,7 +953,7 @@ static esp_err_t esp_light_sleep_inner(uint32_t pd_flags, #endif // Enter sleep - esp_err_t reject = esp_sleep_start(pd_flags, ESP_SLEEP_MODE_LIGHT_SLEEP); + esp_err_t reject = esp_sleep_start(pd_flags, ESP_SLEEP_MODE_LIGHT_SLEEP, false); #if SOC_CONFIGURABLE_VDDSDIO_SUPPORTED // If VDDSDIO regulator was controlled by RTC registers before sleep,