diff --git a/components/esp32/include/esp_deep_sleep.h b/components/esp32/include/esp_deep_sleep.h index ea4601818..a953008e1 100644 --- a/components/esp32/include/esp_deep_sleep.h +++ b/components/esp32/include/esp_deep_sleep.h @@ -47,6 +47,11 @@ inline static esp_err_t esp_deep_sleep_enable_timer_wakeup(uint64_t time_in_us) return esp_sleep_enable_timer_wakeup(time_in_us); } +inline static esp_err_t esp_deep_sleep_disable_timer_wakeup(void) +{ + return esp_sleep_disable_timer_wakeup(); +} + inline static esp_err_t esp_deep_sleep_enable_touchpad_wakeup(void) { return esp_sleep_enable_touchpad_wakeup(); diff --git a/components/esp32/include/esp_sleep.h b/components/esp32/include/esp_sleep.h index d2c4b122f..fdf942e25 100644 --- a/components/esp32/include/esp_sleep.h +++ b/components/esp32/include/esp_sleep.h @@ -75,7 +75,7 @@ typedef enum { */ esp_err_t esp_sleep_enable_ulp_wakeup(); -/** + /** * @brief Enable wakeup by timer * @param time_in_us time before wakeup, in microseconds * @return @@ -84,6 +84,23 @@ esp_err_t esp_sleep_enable_ulp_wakeup(); */ esp_err_t esp_sleep_enable_timer_wakeup(uint64_t time_in_us); +/** + * @brief Disable timer wakeup + * + * This function is used to deactivate timer wakeup trigger + * after first sleep for example to allow wakeup from other sources. + * + * @note This function does not modify wakeup configuration in RTC. + * It will be performed in esp_sleep_start function. + * + * See docs/sleep-modes.rst for details. + * + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_STATE if trigger was not active + */ +esp_err_t esp_sleep_disable_timer_wakeup(); + /** * @brief Enable wakeup by touch sensor * diff --git a/components/esp32/sleep_modes.c b/components/esp32/sleep_modes.c index 240363830..4cb9f1e1b 100644 --- a/components/esp32/sleep_modes.c +++ b/components/esp32/sleep_modes.c @@ -303,6 +303,22 @@ esp_err_t esp_sleep_enable_timer_wakeup(uint64_t time_in_us) return ESP_OK; } +esp_err_t esp_sleep_disable_timer_wakeup() +{ + if (s_config.wakeup_triggers & RTC_TIMER_TRIG_EN) { + // The only timer wakeup trigger should be disabled, setup will + // be performed in rtc_sleep_start() which updates wakeup options + // in RTC peripheral registers + s_config.wakeup_triggers &= ~RTC_TIMER_TRIG_EN; + s_config.sleep_duration = 0; + } + else { + ESP_LOGE(TAG, "The timer wake-up trigger is not set."); + return ESP_ERR_INVALID_STATE; + } + return ESP_OK; +} + static void timer_wakeup_prepare() { uint32_t period = esp_clk_slowclk_cal_get(); diff --git a/components/esp32/test/test_sleep.c b/components/esp32/test/test_sleep.c index 8db4a0f4b..32b1a5a24 100644 --- a/components/esp32/test/test_sleep.c +++ b/components/esp32/test/test_sleep.c @@ -5,6 +5,9 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" +#define ESP_EXT0_WAKEUP_LEVEL_LOW 0 +#define ESP_EXT0_WAKEUP_LEVEL_HIGH 1 + TEST_CASE("esp_deepsleep works", "[deepsleep][reset=DEEPSLEEP_RESET]") { esp_deep_sleep(2000000); @@ -33,7 +36,6 @@ TEST_CASE("wake up using timer", "[deepsleep][reset=DEEPSLEEP_RESET]") esp_deep_sleep_start(); } - TEST_CASE("wake up from light sleep using timer", "[deepsleep]") { esp_sleep_enable_timer_wakeup(2000000); @@ -46,6 +48,44 @@ TEST_CASE("wake up from light sleep using timer", "[deepsleep]") TEST_ASSERT_INT32_WITHIN(500, 2000, (int) dt); } +TEST_CASE("wake up disable timer for ext0 wakeup (13 low)", "[deepsleep][ignore]") +{ + // Setup timer to wakeup with timeout + esp_sleep_enable_timer_wakeup(2000000); + struct timeval tv_start, tv_stop; + gettimeofday(&tv_start, NULL); + esp_light_sleep_start(); + gettimeofday(&tv_stop, NULL); + float dt = (tv_stop.tv_sec - tv_start.tv_sec) * 1e3f + + (tv_stop.tv_usec - tv_start.tv_usec) * 1e-3f; + printf("Timer sleep time = %d\r\n", (int)dt); + + TEST_ASSERT_INT32_WITHIN(500, 2000, (int) dt); + + // Setup ext0 configuration to wake up + ESP_ERROR_CHECK(rtc_gpio_init(GPIO_NUM_13)); + ESP_ERROR_CHECK(gpio_pullup_en(GPIO_NUM_13)); + ESP_ERROR_CHECK(gpio_pulldown_dis(GPIO_NUM_13)); + ESP_ERROR_CHECK(esp_sleep_enable_ext0_wakeup(GPIO_NUM_13, ESP_EXT0_WAKEUP_LEVEL_LOW)); + + // Disable timer wakeup trigger to wakeup from ext0 source + // instead of timer wakeup + ESP_ERROR_CHECK(esp_sleep_disable_timer_wakeup()); + printf("Waiting low level on GPIO_13\r\n"); + + gettimeofday(&tv_start, NULL); + esp_light_sleep_start(); + gettimeofday(&tv_stop, NULL); + + dt = (tv_stop.tv_sec - tv_start.tv_sec) * 1e3f + + (tv_stop.tv_usec - tv_start.tv_usec) * 1e-3f; + printf("Ext0 sleep time = %d\r\n", (int)dt); + + // Check error message + esp_err_t err_code = esp_sleep_disable_timer_wakeup(); + TEST_ASSERT(err_code == ESP_ERR_INVALID_STATE); +} + #ifndef CONFIG_FREERTOS_UNICORE TEST_CASE("enter deep sleep on APP CPU and wake up using timer", "[deepsleep][reset=DEEPSLEEP_RESET]") { @@ -60,7 +100,7 @@ TEST_CASE("wake up using ext0 (13 high)", "[deepsleep][ignore]") ESP_ERROR_CHECK(rtc_gpio_init(GPIO_NUM_13)); ESP_ERROR_CHECK(gpio_pullup_dis(GPIO_NUM_13)); ESP_ERROR_CHECK(gpio_pulldown_en(GPIO_NUM_13)); - ESP_ERROR_CHECK(esp_sleep_enable_ext0_wakeup(GPIO_NUM_13, 1)); + ESP_ERROR_CHECK(esp_sleep_enable_ext0_wakeup(GPIO_NUM_13, ESP_EXT0_WAKEUP_LEVEL_HIGH)); esp_deep_sleep_start(); } @@ -69,7 +109,7 @@ TEST_CASE("wake up using ext0 (13 low)", "[deepsleep][ignore]") ESP_ERROR_CHECK(rtc_gpio_init(GPIO_NUM_13)); ESP_ERROR_CHECK(gpio_pullup_en(GPIO_NUM_13)); ESP_ERROR_CHECK(gpio_pulldown_dis(GPIO_NUM_13)); - ESP_ERROR_CHECK(esp_sleep_enable_ext0_wakeup(GPIO_NUM_13, 0)); + ESP_ERROR_CHECK(esp_sleep_enable_ext0_wakeup(GPIO_NUM_13, ESP_EXT0_WAKEUP_LEVEL_LOW)); esp_deep_sleep_start(); } diff --git a/docs/api-reference/system/sleep_modes.rst b/docs/api-reference/system/sleep_modes.rst index 3e6d8344b..0cd9b59e3 100644 --- a/docs/api-reference/system/sleep_modes.rst +++ b/docs/api-reference/system/sleep_modes.rst @@ -37,6 +37,10 @@ The following function can be used to enable deep sleep wakeup using a timer. .. doxygenfunction:: esp_sleep_enable_timer_wakeup +The timer wakeup functionality can be disabled to use other wakeup sources instead of timer after first sleep. The function below can be used in this case. + +.. doxygenfunction:: esp_sleep_disable_timer_wakeup + Touch pad ^^^^^^^^^