| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 |
- /*
- * SPDX-FileCopyrightText: 2017-2023 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Unlicense OR CC0-1.0
- */
- #include <stdio.h>
- #include <time.h>
- #include <sys/time.h>
- #include "sdkconfig.h"
- #include "soc/soc_caps.h"
- #include "freertos/FreeRTOS.h"
- #include "freertos/task.h"
- #include "esp_sleep.h"
- #include "esp_log.h"
- #include "driver/rtc_io.h"
- #include "nvs_flash.h"
- #include "nvs.h"
- #include "deep_sleep_example.h"
- #if SOC_RTC_FAST_MEM_SUPPORTED
- static RTC_DATA_ATTR struct timeval sleep_enter_time;
- #else
- static struct timeval sleep_enter_time;
- #endif
- static void deep_sleep_task(void *args)
- {
- /**
- * Prefer to use RTC mem instead of NVS to save the deep sleep enter time, unless the chip
- * does not support RTC mem(such as esp32c2). Because the time overhead of NVS will cause
- * the recorded deep sleep enter time to be not very accurate.
- */
- #if !SOC_RTC_FAST_MEM_SUPPORTED
- // Initialize NVS
- esp_err_t err = nvs_flash_init();
- if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
- // NVS partition was truncated and needs to be erased
- // Retry nvs_flash_init
- ESP_ERROR_CHECK(nvs_flash_erase());
- err = nvs_flash_init();
- }
- ESP_ERROR_CHECK(err);
- nvs_handle_t nvs_handle;
- err = nvs_open("storage", NVS_READWRITE, &nvs_handle);
- if (err != ESP_OK) {
- printf("Error (%s) opening NVS handle!\n", esp_err_to_name(err));
- } else {
- printf("Open NVS done\n");
- }
- // Get deep sleep enter time
- nvs_get_i32(nvs_handle, "slp_enter_sec", (int32_t *)&sleep_enter_time.tv_sec);
- nvs_get_i32(nvs_handle, "slp_enter_usec", (int32_t *)&sleep_enter_time.tv_usec);
- #endif
- struct timeval now;
- gettimeofday(&now, NULL);
- int sleep_time_ms = (now.tv_sec - sleep_enter_time.tv_sec) * 1000 + (now.tv_usec - sleep_enter_time.tv_usec) / 1000;
- switch (esp_sleep_get_wakeup_cause()) {
- case ESP_SLEEP_WAKEUP_TIMER: {
- printf("Wake up from timer. Time spent in deep sleep: %dms\n", sleep_time_ms);
- break;
- }
- #if CONFIG_EXAMPLE_GPIO_WAKEUP
- case ESP_SLEEP_WAKEUP_GPIO: {
- uint64_t wakeup_pin_mask = esp_sleep_get_gpio_wakeup_status();
- if (wakeup_pin_mask != 0) {
- int pin = __builtin_ffsll(wakeup_pin_mask) - 1;
- printf("Wake up from GPIO %d\n", pin);
- } else {
- printf("Wake up from GPIO\n");
- }
- break;
- }
- #endif //CONFIG_EXAMPLE_GPIO_WAKEUP
- #if CONFIG_EXAMPLE_EXT0_WAKEUP
- case ESP_SLEEP_WAKEUP_EXT0: {
- printf("Wake up from ext0\n");
- break;
- }
- #endif // CONFIG_EXAMPLE_EXT0_WAKEUP
- #ifdef CONFIG_EXAMPLE_EXT1_WAKEUP
- case ESP_SLEEP_WAKEUP_EXT1: {
- uint64_t wakeup_pin_mask = esp_sleep_get_ext1_wakeup_status();
- if (wakeup_pin_mask != 0) {
- int pin = __builtin_ffsll(wakeup_pin_mask) - 1;
- printf("Wake up from GPIO %d\n", pin);
- } else {
- printf("Wake up from GPIO\n");
- }
- break;
- }
- #endif // CONFIG_EXAMPLE_EXT1_WAKEUP
- #ifdef CONFIG_EXAMPLE_TOUCH_WAKEUP
- case ESP_SLEEP_WAKEUP_TOUCHPAD: {
- printf("Wake up from touch on pad %d\n", esp_sleep_get_touchpad_wakeup_status());
- break;
- }
- #endif // CONFIG_EXAMPLE_TOUCH_WAKEUP
- case ESP_SLEEP_WAKEUP_UNDEFINED:
- default:
- printf("Not a deep sleep reset\n");
- }
- vTaskDelay(1000 / portTICK_PERIOD_MS);
- #if CONFIG_IDF_TARGET_ESP32
- // Isolate GPIO12 pin from external circuits. This is needed for modules
- // which have an external pull-up resistor on GPIO12 (such as ESP32-WROVER)
- // to minimize current consumption.
- rtc_gpio_isolate(GPIO_NUM_12);
- #endif
- printf("Entering deep sleep\n");
- // get deep sleep enter time
- gettimeofday(&sleep_enter_time, NULL);
- #if !SOC_RTC_FAST_MEM_SUPPORTED
- // record deep sleep enter time via nvs
- ESP_ERROR_CHECK(nvs_set_i32(nvs_handle, "slp_enter_sec", sleep_enter_time.tv_sec));
- ESP_ERROR_CHECK(nvs_set_i32(nvs_handle, "slp_enter_usec", sleep_enter_time.tv_usec));
- ESP_ERROR_CHECK(nvs_commit(nvs_handle));
- nvs_close(nvs_handle);
- #endif
- // enter deep sleep
- esp_deep_sleep_start();
- }
- static void example_deep_sleep_register_rtc_timer_wakeup(void)
- {
- const int wakeup_time_sec = 20;
- printf("Enabling timer wakeup, %ds\n", wakeup_time_sec);
- ESP_ERROR_CHECK(esp_sleep_enable_timer_wakeup(wakeup_time_sec * 1000000));
- }
- void app_main(void)
- {
- /* Enable wakeup from deep sleep by rtc timer */
- example_deep_sleep_register_rtc_timer_wakeup();
- #if CONFIG_EXAMPLE_GPIO_WAKEUP
- /* Enable wakeup from deep sleep by gpio */
- example_deep_sleep_register_gpio_wakeup();
- #endif
- #if CONFIG_EXAMPLE_EXT0_WAKEUP
- /* Enable wakeup from deep sleep by ext0 */
- example_deep_sleep_register_ext0_wakeup();
- #endif
- #if CONFIG_EXAMPLE_EXT1_WAKEUP
- /* Enable wakeup from deep sleep by ext1 */
- example_deep_sleep_register_ext1_wakeup();
- #endif
- #if CONFIG_EXAMPLE_TOUCH_WAKEUP
- /* Enable wakeup from deep sleep by touch */
- example_deep_sleep_register_touch_wakeup();
- #endif
- xTaskCreate(deep_sleep_task, "deep_sleep_task", 4096, NULL, 6, NULL);
- }
|