Kaynağa Gözat

fix(esp_hw_support): Return deep sleep APIs to the original behavior

Closes https://github.com/espressif/esp-idf/issues/12359
KonstantinKondrashov 2 yıl önce
ebeveyn
işleme
cd64b228b1

+ 34 - 2
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)
+ */
+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);
+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

+ 29 - 6
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,