diff --git a/components/esp32/deep_sleep.c b/components/esp32/deep_sleep.c index c6785375d..aadb6067e 100644 --- a/components/esp32/deep_sleep.c +++ b/components/esp32/deep_sleep.c @@ -191,6 +191,16 @@ esp_err_t esp_deep_sleep_enable_touchpad_wakeup() return ESP_OK; } +touch_pad_t esp_deep_sleep_get_touchpad_wakeup_status() +{ + if (esp_deep_sleep_get_wakeup_cause() != ESP_DEEP_SLEEP_WAKEUP_TOUCHPAD) { + return TOUCH_PAD_MAX; + } + uint32_t touch_mask = REG_GET_FIELD(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_MEAS_EN); + assert(touch_mask != 0 && "wakeup reason is RTC_TOUCH_TRIG_EN but SENS_TOUCH_MEAS_EN is zero"); + return (touch_pad_t) (__builtin_ffs(touch_mask) - 1); +} + esp_err_t esp_deep_sleep_enable_ext0_wakeup(gpio_num_t gpio_num, int level) { if (level < 0 || level > 1) { @@ -294,8 +304,7 @@ static void ext1_wakeup_prepare() uint64_t esp_deep_sleep_get_ext1_wakeup_status() { - int wakeup_reason = REG_GET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, RTC_CNTL_WAKEUP_CAUSE); - if (wakeup_reason != RTC_EXT_EVENT1_TRIG) { + if (esp_deep_sleep_get_wakeup_cause() != ESP_DEEP_SLEEP_WAKEUP_EXT1) { return 0; } uint32_t status = REG_GET_FIELD(RTC_CNTL_EXT_WAKEUP1_STATUS_REG, RTC_CNTL_EXT_WAKEUP1_STATUS); @@ -314,6 +323,28 @@ uint64_t esp_deep_sleep_get_ext1_wakeup_status() return gpio_mask; } +esp_deep_sleep_wakeup_cause_t esp_deep_sleep_get_wakeup_cause() +{ + if (rtc_get_reset_reason(0) != DEEPSLEEP_RESET) { + return ESP_DEEP_SLEEP_WAKEUP_UNDEFINED; + } + + uint32_t wakeup_cause = REG_GET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, RTC_CNTL_WAKEUP_CAUSE); + if (wakeup_cause & RTC_EXT_EVENT0_TRIG) { + return ESP_DEEP_SLEEP_WAKEUP_EXT0; + } else if (wakeup_cause & RTC_EXT_EVENT1_TRIG) { + return ESP_DEEP_SLEEP_WAKEUP_EXT1; + } else if (wakeup_cause & RTC_TIMER_EXPIRE) { + return ESP_DEEP_SLEEP_WAKEUP_TIMER; + } else if (wakeup_cause & RTC_TOUCH_TRIG) { + return ESP_DEEP_SLEEP_WAKEUP_TOUCHPAD; + } else if (wakeup_cause & RTC_SAR_TRIG) { + return ESP_DEEP_SLEEP_WAKEUP_ULP; + } else { + return ESP_DEEP_SLEEP_WAKEUP_UNDEFINED; + } +} + esp_err_t esp_deep_sleep_pd_config(esp_deep_sleep_pd_domain_t domain, esp_deep_sleep_pd_option_t option) { diff --git a/components/esp32/include/esp_deep_sleep.h b/components/esp32/include/esp_deep_sleep.h index ed53b9496..61d3642b5 100644 --- a/components/esp32/include/esp_deep_sleep.h +++ b/components/esp32/include/esp_deep_sleep.h @@ -17,6 +17,7 @@ #include #include "esp_err.h" #include "driver/gpio.h" +#include "driver/touch_pad.h" #ifdef __cplusplus extern "C" { @@ -50,6 +51,18 @@ typedef enum { ESP_PD_OPTION_AUTO //!< Keep power domain enabled in deep sleep, if it is needed by one of the wakeup options. Otherwise power it down. } esp_deep_sleep_pd_option_t; +/** + * @brief Deep sleep wakeup cause + */ +typedef enum { + ESP_DEEP_SLEEP_WAKEUP_UNDEFINED, //! Wakeup was not caused by deep sleep + ESP_DEEP_SLEEP_WAKEUP_EXT0, //! Wakeup caused by external signal using RTC_IO + ESP_DEEP_SLEEP_WAKEUP_EXT1, //! Wakeup caused by external signal using RTC_CNTL + ESP_DEEP_SLEEP_WAKEUP_TIMER, //! Wakeup caused by timer + ESP_DEEP_SLEEP_WAKEUP_TOUCHPAD, //! Wakeup caused by touchpad + ESP_DEEP_SLEEP_WAKEUP_ULP, //! Wakeup caused by ULP program +} esp_deep_sleep_wakeup_cause_t; + /** * @brief Enable wakeup by ULP coprocessor @@ -86,6 +99,15 @@ esp_err_t esp_deep_sleep_enable_timer_wakeup(uint64_t time_in_us); */ esp_err_t esp_deep_sleep_enable_touchpad_wakeup(); +/** + * @brief Get the touch pad which caused wakeup + * + * If wakeup was caused by another source, this function will return TOUCH_PAD_MAX; + * + * @return touch pad which caused wakeup + */ +touch_pad_t esp_deep_sleep_get_touchpad_wakeup_status(); + /** * @brief Enable wakeup using a pin * @@ -210,6 +232,15 @@ void esp_deep_sleep(uint64_t time_in_us) __attribute__((noreturn)); */ void system_deep_sleep(uint64_t time_in_us) __attribute__((noreturn, deprecated)); + +/** + * @brief Get the source which caused deep sleep wakeup + * + * @return wakeup cause, or ESP_DEEP_SLEEP_WAKEUP_UNDEFINED if reset reason is other than deep sleep reset. + */ +esp_deep_sleep_wakeup_cause_t esp_deep_sleep_get_wakeup_cause(); + + /** * @brief Default stub to run on wake from deep sleep. * diff --git a/docs/api/system/deep_sleep.rst b/docs/api/system/deep_sleep.rst index 14904881a..aacb25218 100644 --- a/docs/api/system/deep_sleep.rst +++ b/docs/api/system/deep_sleep.rst @@ -27,7 +27,7 @@ The following function can be used to enable deep sleep wakeup using a timer. .. doxygenfunction:: esp_deep_sleep_enable_timer_wakeup Touch pad -^^^^^ +^^^^^^^^^ RTC IO module contains logic to trigger wakeup when a touch sensor interrupt occurs. You need to configure the touch pad interrupt before the chip starts deep sleep. @@ -100,6 +100,17 @@ The following function can be used to enter deep sleep once wakeup sources are c .. doxygenfunction:: esp_deep_sleep_start +Checking deep sleep wakeup cause +-------------------------------- + +The following function can be used to check which wakeup source has triggered wakeup from deep sleep mode. For touch pad and ext1 wakeup sources, it is possible to identify pin or touch pad which has caused wakeup. + +.. doxygenfunction:: esp_deep_sleep_get_wakeup_cause +.. doxygenenum:: esp_deep_sleep_wakeup_cause_t +.. doxygenfunction:: esp_deep_sleep_get_touchpad_wakeup_status +.. doxygenfunction:: esp_deep_sleep_get_ext1_wakeup_status + + Application Example -------------------