2021-08-05 11:35:07 -04:00
|
|
|
/*
|
2024-01-01 22:16:55 -05:00
|
|
|
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
2021-08-05 11:35:07 -04:00
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
*/
|
2016-09-12 03:23:15 -04:00
|
|
|
|
|
|
|
#include <stddef.h>
|
2020-11-26 03:56:13 -05:00
|
|
|
#include <string.h>
|
2016-09-12 03:23:15 -04:00
|
|
|
#include <sys/lock.h>
|
2017-04-21 00:32:50 -04:00
|
|
|
#include <sys/param.h>
|
2020-04-23 00:39:07 -04:00
|
|
|
|
2016-12-13 00:23:04 -05:00
|
|
|
#include "esp_attr.h"
|
2024-03-21 07:34:04 -04:00
|
|
|
#include "esp_rom_caps.h"
|
2022-07-21 07:14:41 -04:00
|
|
|
#include "esp_memory_utils.h"
|
2017-04-21 00:32:50 -04:00
|
|
|
#include "esp_sleep.h"
|
2022-09-16 08:25:44 -04:00
|
|
|
#include "esp_private/esp_sleep_internal.h"
|
2020-02-06 01:00:18 -05:00
|
|
|
#include "esp_private/esp_timer_private.h"
|
2024-04-16 06:06:35 -04:00
|
|
|
#include "esp_private/rtc_clk.h"
|
2023-07-06 03:52:21 -04:00
|
|
|
#include "esp_private/sleep_event.h"
|
2020-09-03 06:17:24 -04:00
|
|
|
#include "esp_private/system_internal.h"
|
2024-05-20 08:18:25 -04:00
|
|
|
#include "esp_private/io_mux.h"
|
2016-12-13 00:23:04 -05:00
|
|
|
#include "esp_log.h"
|
2017-04-21 00:32:50 -04:00
|
|
|
#include "esp_newlib.h"
|
2020-05-04 06:17:06 -04:00
|
|
|
#include "esp_timer.h"
|
2021-08-03 02:35:29 -04:00
|
|
|
#include "esp_ipc_isr.h"
|
2020-05-04 06:17:06 -04:00
|
|
|
#include "freertos/FreeRTOS.h"
|
|
|
|
#include "freertos/task.h"
|
2020-11-26 03:56:13 -05:00
|
|
|
#include "soc/soc_caps.h"
|
2020-05-04 06:17:06 -04:00
|
|
|
#include "driver/rtc_io.h"
|
2020-11-26 03:56:13 -05:00
|
|
|
#include "hal/rtc_io_hal.h"
|
2024-04-16 06:06:35 -04:00
|
|
|
#include "hal/clk_tree_hal.h"
|
2023-01-30 03:37:20 -05:00
|
|
|
|
2023-12-05 00:38:47 -05:00
|
|
|
#if SOC_SLEEP_SYSTIMER_STALL_WORKAROUND
|
|
|
|
#include "hal/systimer_ll.h"
|
|
|
|
#endif
|
|
|
|
|
2023-12-26 07:50:52 -05:00
|
|
|
#if SOC_SLEEP_TGWDT_STOP_WORKAROUND
|
|
|
|
#include "hal/mwdt_ll.h"
|
|
|
|
#include "hal/timer_ll.h"
|
|
|
|
#endif
|
|
|
|
|
2022-03-13 23:33:01 -04:00
|
|
|
#if SOC_PM_SUPPORT_PMU_MODEM_STATE
|
|
|
|
#include "esp_private/pm_impl.h"
|
|
|
|
#endif
|
|
|
|
|
2023-12-22 06:36:24 -05:00
|
|
|
#if !SOC_PMU_SUPPORTED
|
2021-11-26 05:09:24 -05:00
|
|
|
#include "hal/rtc_cntl_ll.h"
|
2023-01-30 03:37:20 -05:00
|
|
|
#endif
|
2023-12-22 06:36:24 -05:00
|
|
|
#include "hal/rtc_hal.h"
|
2020-11-26 03:56:13 -05:00
|
|
|
|
2017-04-11 03:44:43 -04:00
|
|
|
#include "soc/rtc.h"
|
2020-09-09 22:37:58 -04:00
|
|
|
#include "soc/soc_caps.h"
|
2022-01-25 01:23:53 -05:00
|
|
|
#include "regi2c_ctrl.h" //For `REGI2C_ANA_CALI_PD_WORKAROUND`, temp
|
2020-05-04 06:17:06 -04:00
|
|
|
|
2023-06-25 05:50:17 -04:00
|
|
|
#include "hal/cache_hal.h"
|
2023-09-14 00:14:08 -04:00
|
|
|
#include "hal/cache_ll.h"
|
2020-05-04 06:17:06 -04:00
|
|
|
#include "hal/wdt_hal.h"
|
|
|
|
#include "hal/uart_hal.h"
|
2022-07-21 01:42:25 -04:00
|
|
|
#if SOC_TOUCH_SENSOR_SUPPORTED
|
2020-05-04 06:17:06 -04:00
|
|
|
#include "hal/touch_sensor_hal.h"
|
2020-11-26 03:56:13 -05:00
|
|
|
#endif
|
2020-05-04 06:17:06 -04:00
|
|
|
|
2016-12-12 10:20:15 -05:00
|
|
|
#include "sdkconfig.h"
|
2020-04-23 00:39:07 -04:00
|
|
|
#include "esp_rom_uart.h"
|
2021-07-12 22:45:06 -04:00
|
|
|
#include "esp_rom_sys.h"
|
2021-11-23 07:11:33 -05:00
|
|
|
#include "esp_private/brownout.h"
|
2023-10-27 06:23:50 -04:00
|
|
|
#include "esp_private/sleep_console.h"
|
2023-01-12 05:08:14 -05:00
|
|
|
#include "esp_private/sleep_cpu.h"
|
2022-03-13 23:33:01 -04:00
|
|
|
#include "esp_private/sleep_modem.h"
|
2021-11-18 22:42:01 -05:00
|
|
|
#include "esp_private/esp_clk.h"
|
2022-07-07 02:54:15 -04:00
|
|
|
#include "esp_private/esp_task_wdt.h"
|
2023-03-14 22:39:52 -04:00
|
|
|
#include "esp_private/sar_periph_ctrl.h"
|
2023-03-16 02:44:46 -04:00
|
|
|
#include "esp_private/mspi_timing_tuning.h"
|
2020-04-23 00:39:07 -04:00
|
|
|
|
|
|
|
#ifdef CONFIG_IDF_TARGET_ESP32
|
|
|
|
#include "esp32/rom/cache.h"
|
2020-05-04 06:17:06 -04:00
|
|
|
#include "esp32/rom/rtc.h"
|
2021-02-07 05:49:05 -05:00
|
|
|
#include "esp_private/gpio.h"
|
2021-08-19 09:57:17 -04:00
|
|
|
#include "esp_private/sleep_gpio.h"
|
2020-04-23 00:39:07 -04:00
|
|
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
|
|
|
#include "esp32s2/rom/rtc.h"
|
|
|
|
#include "soc/extmem_reg.h"
|
2021-02-07 05:49:05 -05:00
|
|
|
#include "esp_private/gpio.h"
|
2020-07-29 01:13:51 -04:00
|
|
|
#elif CONFIG_IDF_TARGET_ESP32S3
|
|
|
|
#include "esp32s3/rom/rtc.h"
|
2023-02-22 23:54:37 -05:00
|
|
|
#include "esp_private/mspi_timing_tuning.h"
|
2020-11-26 03:56:13 -05:00
|
|
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
|
|
|
#include "esp32c3/rom/rtc.h"
|
2022-01-17 21:32:56 -05:00
|
|
|
#elif CONFIG_IDF_TARGET_ESP32C2
|
|
|
|
#include "esp32c2/rom/rtc.h"
|
2022-07-12 07:46:23 -04:00
|
|
|
#elif CONFIG_IDF_TARGET_ESP32C6
|
|
|
|
#include "esp32c6/rom/rtc.h"
|
2023-05-19 04:26:58 -04:00
|
|
|
#include "hal/gpio_ll.h"
|
2024-01-01 22:16:55 -05:00
|
|
|
#elif CONFIG_IDF_TARGET_ESP32C5
|
|
|
|
#include "esp32c5/rom/rtc.h"
|
|
|
|
#include "hal/gpio_ll.h"
|
2022-12-28 22:01:13 -05:00
|
|
|
#elif CONFIG_IDF_TARGET_ESP32H2
|
|
|
|
#include "esp32h2/rom/rtc.h"
|
|
|
|
#include "esp32h2/rom/cache.h"
|
|
|
|
#include "esp32h2/rom/rtc.h"
|
2022-07-12 07:46:23 -04:00
|
|
|
#include "soc/extmem_reg.h"
|
2023-07-03 09:25:56 -04:00
|
|
|
#include "hal/gpio_ll.h"
|
2023-12-22 06:36:24 -05:00
|
|
|
#elif CONFIG_IDF_TARGET_ESP32P4
|
|
|
|
#include "esp32p4/rom/rtc.h"
|
|
|
|
#include "hal/gpio_ll.h"
|
2023-05-22 07:14:42 -04:00
|
|
|
#endif
|
|
|
|
|
2023-05-22 02:17:02 -04:00
|
|
|
#if SOC_LP_TIMER_SUPPORTED
|
|
|
|
#include "hal/lp_timer_hal.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SOC_PMU_SUPPORTED
|
|
|
|
#include "esp_private/esp_pmu.h"
|
|
|
|
#include "esp_private/sleep_sys_periph.h"
|
|
|
|
#include "esp_private/sleep_clock.h"
|
|
|
|
#endif
|
2023-05-22 07:14:42 -04:00
|
|
|
|
2023-12-14 22:29:02 -05:00
|
|
|
#if SOC_PM_RETENTION_SW_TRIGGER_REGDMA
|
2023-05-22 07:14:42 -04:00
|
|
|
#include "esp_private/sleep_retention.h"
|
2020-04-23 00:39:07 -04:00
|
|
|
#endif
|
2016-09-12 03:23:15 -04:00
|
|
|
|
2017-04-21 00:32:50 -04:00
|
|
|
// If light sleep time is less than that, don't power down flash
|
|
|
|
#define FLASH_PD_MIN_SLEEP_TIME_US 2000
|
|
|
|
|
2023-12-06 07:37:28 -05:00
|
|
|
// Default waiting time for the software to wait for Flash ready after waking up from sleep
|
|
|
|
#define ESP_SLEEP_WAIT_FLASH_READY_DEFAULT_DELAY_US 700
|
2017-04-21 00:32:50 -04:00
|
|
|
|
2020-11-06 04:28:57 -05:00
|
|
|
// Cycles for RTC Timer clock source (internal oscillator) calibrate
|
|
|
|
#define RTC_CLK_SRC_CAL_CYCLES (10)
|
2023-05-03 23:46:21 -04:00
|
|
|
#define FAST_CLK_SRC_CAL_CYCLES (2048) /* ~ 127.4 us */
|
2020-11-06 04:28:57 -05:00
|
|
|
|
2020-04-23 00:39:07 -04:00
|
|
|
#ifdef CONFIG_IDF_TARGET_ESP32
|
2020-12-03 22:09:21 -05:00
|
|
|
#define DEFAULT_SLEEP_OUT_OVERHEAD_US (212)
|
|
|
|
#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (60)
|
2020-04-23 00:39:07 -04:00
|
|
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
2020-12-03 22:09:21 -05:00
|
|
|
#define DEFAULT_SLEEP_OUT_OVERHEAD_US (147)
|
|
|
|
#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (28)
|
2020-07-29 01:13:51 -04:00
|
|
|
#elif CONFIG_IDF_TARGET_ESP32S3
|
2021-04-01 07:55:15 -04:00
|
|
|
#define DEFAULT_SLEEP_OUT_OVERHEAD_US (382)
|
|
|
|
#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (133)
|
2020-11-26 03:56:13 -05:00
|
|
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
2020-12-03 22:09:21 -05:00
|
|
|
#define DEFAULT_SLEEP_OUT_OVERHEAD_US (105)
|
2021-06-10 03:22:43 -04:00
|
|
|
#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (37)
|
2022-01-17 21:32:56 -05:00
|
|
|
#elif CONFIG_IDF_TARGET_ESP32C2
|
2022-05-19 07:57:35 -04:00
|
|
|
#define DEFAULT_SLEEP_OUT_OVERHEAD_US (118)
|
|
|
|
#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (9)
|
2022-07-12 07:46:23 -04:00
|
|
|
#elif CONFIG_IDF_TARGET_ESP32C6
|
2023-01-30 03:37:20 -05:00
|
|
|
#define DEFAULT_SLEEP_OUT_OVERHEAD_US (318)
|
|
|
|
#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (56)
|
2024-04-08 05:12:27 -04:00
|
|
|
#elif CONFIG_IDF_TARGET_ESP32C5 // TODO: [ESP32C5] IDF-8638
|
2024-01-01 22:16:55 -05:00
|
|
|
#define DEFAULT_SLEEP_OUT_OVERHEAD_US (318)
|
|
|
|
#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (56)
|
2022-12-28 22:01:13 -05:00
|
|
|
#elif CONFIG_IDF_TARGET_ESP32H2
|
2023-12-22 06:36:24 -05:00
|
|
|
#define DEFAULT_SLEEP_OUT_OVERHEAD_US (118)
|
2022-12-28 22:01:13 -05:00
|
|
|
#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (9)
|
2024-02-19 06:09:20 -05:00
|
|
|
#elif CONFIG_IDF_TARGET_ESP32P4
|
2024-02-26 06:46:17 -05:00
|
|
|
#define DEFAULT_SLEEP_OUT_OVERHEAD_US (324)
|
2023-12-22 06:36:24 -05:00
|
|
|
#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (240)
|
2024-02-19 06:09:20 -05:00
|
|
|
#define LDO_POWER_TAKEOVER_PREPARATION_TIME_US (185)
|
2020-04-23 00:39:07 -04:00
|
|
|
#endif
|
|
|
|
|
2023-05-09 02:01:29 -04:00
|
|
|
// Actually costs 80us, using the fastest slow clock 150K calculation takes about 16 ticks
|
|
|
|
#define SLEEP_TIMER_ALARM_TO_SLEEP_TICKS (16)
|
|
|
|
|
2023-06-02 06:44:25 -04:00
|
|
|
#define SLEEP_UART_FLUSH_DONE_TO_SLEEP_US (450)
|
|
|
|
|
2023-05-29 02:59:22 -04:00
|
|
|
#if SOC_PM_SUPPORT_TOP_PD
|
|
|
|
// IDF console uses 8 bits data mode without parity, so each char occupy 8(data)+1(start)+1(stop)=10bits
|
|
|
|
#define UART_FLUSH_US_PER_CHAR (10*1000*1000 / CONFIG_ESP_CONSOLE_UART_BAUDRATE)
|
|
|
|
#define CONCATENATE_HELPER(x, y) (x##y)
|
|
|
|
#define CONCATENATE(x, y) CONCATENATE_HELPER(x, y)
|
|
|
|
#define CONSOLE_UART_DEV (&CONCATENATE(UART, CONFIG_ESP_CONSOLE_UART_NUM))
|
|
|
|
#endif
|
|
|
|
|
2020-12-03 22:09:21 -05:00
|
|
|
#define LIGHT_SLEEP_TIME_OVERHEAD_US DEFAULT_HARDWARE_OUT_OVERHEAD_US
|
2021-04-01 07:55:15 -04:00
|
|
|
#ifdef CONFIG_ESP_SYSTEM_RTC_EXT_XTAL
|
2022-03-02 02:49:31 -05:00
|
|
|
#define DEEP_SLEEP_TIME_OVERHEAD_US (650 + 100 * 240 / CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ)
|
2020-11-06 04:28:57 -05:00
|
|
|
#else
|
2022-03-02 02:49:31 -05:00
|
|
|
#define DEEP_SLEEP_TIME_OVERHEAD_US (250 + 100 * 240 / CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ)
|
2020-12-03 22:09:21 -05:00
|
|
|
#endif
|
2020-04-23 00:39:07 -04:00
|
|
|
|
2018-04-04 03:05:50 -04:00
|
|
|
// Minimal amount of time we can sleep for
|
2020-11-06 04:28:57 -05:00
|
|
|
#define LIGHT_SLEEP_MIN_TIME_US 200
|
|
|
|
|
|
|
|
#define RTC_MODULE_SLEEP_PREPARE_CYCLES (6)
|
2018-04-04 03:05:50 -04:00
|
|
|
|
2018-03-16 02:57:35 -04:00
|
|
|
#define CHECK_SOURCE(source, value, mask) ((s_config.wakeup_triggers & mask) && \
|
|
|
|
(source == value))
|
|
|
|
|
2023-03-13 07:10:02 -04:00
|
|
|
#define MAX_DSLP_HOOKS 3
|
|
|
|
|
2024-04-01 02:28:32 -04:00
|
|
|
static esp_deep_sleep_cb_t s_dslp_cb[MAX_DSLP_HOOKS] = {0};
|
|
|
|
#if CONFIG_ESP_PHY_ENABLED
|
|
|
|
static esp_deep_sleep_cb_t s_dslp_phy_cb[MAX_DSLP_HOOKS] = {0};
|
|
|
|
#endif
|
2023-03-13 07:10:02 -04:00
|
|
|
|
2016-12-16 01:26:05 -05:00
|
|
|
/**
|
2023-05-04 00:09:26 -04:00
|
|
|
* Internal structure which holds all requested sleep parameters
|
2016-12-16 01:26:05 -05:00
|
|
|
*/
|
|
|
|
typedef struct {
|
2022-12-15 22:25:55 -05:00
|
|
|
struct {
|
|
|
|
esp_sleep_pd_option_t pd_option;
|
|
|
|
int16_t refs;
|
|
|
|
uint16_t reserved; /* reserved for 4 bytes aligned */
|
|
|
|
} domain[ESP_PD_DOMAIN_MAX];
|
|
|
|
portMUX_TYPE lock;
|
2016-12-16 01:26:05 -05:00
|
|
|
uint64_t sleep_duration;
|
2020-11-03 21:47:40 -05:00
|
|
|
uint32_t wakeup_triggers : 15;
|
2023-02-18 01:13:52 -05:00
|
|
|
#if SOC_PM_SUPPORT_EXT1_WAKEUP
|
2023-07-13 02:06:10 -04:00
|
|
|
uint32_t ext1_trigger_mode : 22; // 22 is the maximum RTCIO number in all chips
|
|
|
|
uint32_t ext1_rtc_gpio_mask : 22;
|
2023-02-18 01:13:52 -05:00
|
|
|
#endif
|
|
|
|
#if SOC_PM_SUPPORT_EXT0_WAKEUP
|
2016-12-16 01:26:05 -05:00
|
|
|
uint32_t ext0_trigger_level : 1;
|
|
|
|
uint32_t ext0_rtc_gpio_num : 5;
|
2023-02-18 01:13:52 -05:00
|
|
|
#endif
|
2023-10-08 04:48:00 -04:00
|
|
|
#if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP
|
2023-02-18 01:13:52 -05:00
|
|
|
uint32_t gpio_wakeup_mask : 8; // 8 is the maximum RTCIO number in all chips that support GPIO wakeup
|
|
|
|
uint32_t gpio_trigger_mode : 8;
|
2023-10-08 04:48:00 -04:00
|
|
|
#endif
|
2018-04-04 03:05:50 -04:00
|
|
|
uint32_t sleep_time_adjustment;
|
2020-11-06 04:28:57 -05:00
|
|
|
uint32_t ccount_ticks_record;
|
|
|
|
uint32_t sleep_time_overhead_out;
|
|
|
|
uint32_t rtc_clk_cal_period;
|
2023-01-30 03:37:20 -05:00
|
|
|
uint32_t fast_clk_cal_period;
|
2018-04-04 03:05:50 -04:00
|
|
|
uint64_t rtc_ticks_at_sleep_start;
|
2024-02-19 06:09:20 -05:00
|
|
|
#if SOC_DCDC_SUPPORTED
|
|
|
|
uint64_t rtc_ticks_at_ldo_prepare;
|
|
|
|
#endif
|
2018-04-04 03:05:50 -04:00
|
|
|
} sleep_config_t;
|
2016-12-16 01:26:05 -05:00
|
|
|
|
2021-12-31 03:09:43 -05:00
|
|
|
|
2023-10-08 04:48:00 -04:00
|
|
|
#if CONFIG_ESP_SLEEP_DEBUG
|
|
|
|
static esp_sleep_context_t *s_sleep_ctx = NULL;
|
|
|
|
|
|
|
|
void esp_sleep_set_sleep_context(esp_sleep_context_t *sleep_ctx)
|
|
|
|
{
|
|
|
|
s_sleep_ctx = sleep_ctx;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2023-05-04 00:09:26 -04:00
|
|
|
static uint32_t s_lightsleep_cnt = 0;
|
|
|
|
|
2021-12-31 03:09:43 -05:00
|
|
|
_Static_assert(22 >= SOC_RTCIO_PIN_COUNT, "Chip has more RTCIOs than 22, should increase ext1_rtc_gpio_mask field size");
|
|
|
|
|
2018-04-04 03:05:50 -04:00
|
|
|
static sleep_config_t s_config = {
|
2022-12-15 22:25:55 -05:00
|
|
|
.domain = {
|
|
|
|
[0 ... ESP_PD_DOMAIN_MAX - 1] = {
|
|
|
|
.pd_option = ESP_PD_OPTION_AUTO,
|
|
|
|
.refs = 0
|
|
|
|
}
|
|
|
|
},
|
|
|
|
.lock = portMUX_INITIALIZER_UNLOCKED,
|
2020-11-06 04:28:57 -05:00
|
|
|
.ccount_ticks_record = 0,
|
|
|
|
.sleep_time_overhead_out = DEFAULT_SLEEP_OUT_OVERHEAD_US,
|
2016-12-16 01:26:05 -05:00
|
|
|
.wakeup_triggers = 0
|
|
|
|
};
|
|
|
|
|
2018-12-04 23:22:55 -05:00
|
|
|
/* Internal variable used to track if light sleep wakeup sources are to be
|
|
|
|
expected when determining wakeup cause. */
|
|
|
|
static bool s_light_sleep_wakeup = false;
|
2018-09-04 00:56:47 -04:00
|
|
|
|
2016-09-12 03:23:15 -04:00
|
|
|
/* Updating RTC_MEMORY_CRC_REG register via set_rtc_memory_crc()
|
2020-10-07 03:34:33 -04:00
|
|
|
is not thread-safe, so we need to disable interrupts before going to deep sleep. */
|
|
|
|
static portMUX_TYPE spinlock_rtc_deep_sleep = portMUX_INITIALIZER_UNLOCKED;
|
2016-09-12 03:23:15 -04:00
|
|
|
|
2021-02-02 23:29:31 -05:00
|
|
|
static const char *TAG = "sleep";
|
2022-02-28 05:12:28 -05:00
|
|
|
static RTC_FAST_ATTR bool s_adc_tsen_enabled = false;
|
2022-05-04 15:19:35 -04:00
|
|
|
//in this mode, 2uA is saved, but RTC memory can't use at high temperature, and RTCIO can't be used as INPUT.
|
|
|
|
static bool s_ultra_low_enabled = false;
|
|
|
|
|
2022-07-27 06:08:26 -04:00
|
|
|
static bool s_periph_use_8m_flag = false;
|
|
|
|
|
|
|
|
void esp_sleep_periph_use_8m(bool use_or_not)
|
|
|
|
{
|
|
|
|
s_periph_use_8m_flag = use_or_not;
|
|
|
|
}
|
2016-12-14 01:20:01 -05:00
|
|
|
|
2019-07-16 05:33:30 -04:00
|
|
|
static uint32_t get_power_down_flags(void);
|
2023-02-17 07:30:51 -05:00
|
|
|
#if SOC_PM_SUPPORT_EXT0_WAKEUP
|
2019-07-16 05:33:30 -04:00
|
|
|
static void ext0_wakeup_prepare(void);
|
2023-02-17 07:30:51 -05:00
|
|
|
#endif
|
|
|
|
#if SOC_PM_SUPPORT_EXT1_WAKEUP
|
2019-07-16 05:33:30 -04:00
|
|
|
static void ext1_wakeup_prepare(void);
|
2021-01-12 06:10:21 -05:00
|
|
|
#endif
|
2023-06-02 06:44:25 -04:00
|
|
|
static esp_err_t timer_wakeup_prepare(int64_t sleep_duration);
|
2020-10-26 04:10:37 -04:00
|
|
|
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
2020-04-23 00:39:07 -04:00
|
|
|
static void touch_wakeup_prepare(void);
|
|
|
|
#endif
|
2023-01-31 07:11:25 -05:00
|
|
|
#if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP
|
2022-10-27 03:09:34 -04:00
|
|
|
static void gpio_deep_sleep_wakeup_prepare(void);
|
2021-02-05 04:10:44 -05:00
|
|
|
#endif
|
2020-04-23 00:39:07 -04:00
|
|
|
|
2024-03-21 07:34:04 -04:00
|
|
|
#if ESP_ROM_SUPPORT_DEEP_SLEEP_WAKEUP_STUB && SOC_DEEP_SLEEP_SUPPORTED
|
2021-11-05 05:23:24 -04:00
|
|
|
#if SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY
|
2021-08-11 10:06:47 -04:00
|
|
|
static RTC_FAST_ATTR esp_deep_sleep_wake_stub_fn_t wake_stub_fn_handler = NULL;
|
|
|
|
|
|
|
|
static void RTC_IRAM_ATTR __attribute__((used, noinline)) esp_wake_stub_start(void)
|
|
|
|
{
|
|
|
|
if (wake_stub_fn_handler) {
|
|
|
|
(*wake_stub_fn_handler)();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We must have a default deep sleep wake stub entry function, which must be
|
|
|
|
* located at the start address of the RTC fast memory, and its implementation
|
2024-01-14 22:49:10 -05:00
|
|
|
* must be simple enough to ensure that there is no literal data before the
|
|
|
|
* wake stub entry, otherwise, the literal data before the wake stub entry
|
2021-08-11 10:06:47 -04:00
|
|
|
* will not be CRC checked. */
|
|
|
|
static void __attribute__((section(".rtc.entry.text"))) esp_wake_stub_entry(void)
|
|
|
|
{
|
|
|
|
#define _SYM2STR(s) # s
|
|
|
|
#define SYM2STR(s) _SYM2STR(s)
|
2022-12-26 05:00:51 -05:00
|
|
|
|
|
|
|
#ifdef __riscv
|
2023-02-18 01:13:52 -05:00
|
|
|
__asm__ __volatile__ (
|
|
|
|
"addi sp, sp, -16 \n"
|
|
|
|
"sw ra, 0(sp) \n"
|
|
|
|
"jal ra, " SYM2STR(esp_wake_stub_start) "\n"
|
|
|
|
"lw ra, 0(sp) \n"
|
|
|
|
"addi sp, sp, 16 \n"
|
|
|
|
);
|
2022-12-26 05:00:51 -05:00
|
|
|
#else
|
2021-08-11 10:06:47 -04:00
|
|
|
// call4 has a larger effective addressing range (-524284 to 524288 bytes),
|
|
|
|
// which is sufficient for instruction addressing in RTC fast memory.
|
|
|
|
__asm__ __volatile__ ("call4 " SYM2STR(esp_wake_stub_start) "\n");
|
2022-12-26 05:00:51 -05:00
|
|
|
#endif
|
|
|
|
|
2021-08-11 10:06:47 -04:00
|
|
|
}
|
2023-02-24 00:53:38 -05:00
|
|
|
|
|
|
|
void RTC_IRAM_ATTR esp_set_deep_sleep_wake_stub_default_entry(void)
|
|
|
|
{
|
|
|
|
extern char _rtc_text_start[];
|
|
|
|
#if CONFIG_ESP32S3_RTCDATA_IN_FAST_MEM
|
|
|
|
extern char _rtc_noinit_end[];
|
|
|
|
size_t rtc_fast_length = (size_t)_rtc_noinit_end - (size_t)_rtc_text_start;
|
|
|
|
#else
|
|
|
|
extern char _rtc_force_fast_end[];
|
|
|
|
size_t rtc_fast_length = (size_t)_rtc_force_fast_end - (size_t)_rtc_text_start;
|
|
|
|
#endif
|
|
|
|
esp_rom_set_rtc_wake_addr((esp_rom_wake_func_t)esp_wake_stub_entry, rtc_fast_length);
|
|
|
|
}
|
2021-11-05 05:23:24 -04:00
|
|
|
#endif // SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY
|
2021-08-11 10:06:47 -04:00
|
|
|
|
2016-12-08 09:22:10 -05:00
|
|
|
/* Wake from deep sleep stub
|
|
|
|
See esp_deepsleep.h esp_wake_deep_sleep() comments for details.
|
|
|
|
*/
|
2016-09-12 03:23:15 -04:00
|
|
|
esp_deep_sleep_wake_stub_fn_t esp_get_deep_sleep_wake_stub(void)
|
|
|
|
{
|
2021-11-05 05:23:24 -04:00
|
|
|
#if SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY
|
2021-08-11 10:06:47 -04:00
|
|
|
esp_deep_sleep_wake_stub_fn_t stub_ptr = wake_stub_fn_handler;
|
|
|
|
#else
|
2018-08-26 20:12:28 -04:00
|
|
|
esp_deep_sleep_wake_stub_fn_t stub_ptr = (esp_deep_sleep_wake_stub_fn_t) REG_READ(RTC_ENTRY_ADDR_REG);
|
2021-08-11 10:06:47 -04:00
|
|
|
#endif
|
2018-08-26 20:12:28 -04:00
|
|
|
if (!esp_ptr_executable(stub_ptr)) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return stub_ptr;
|
2016-09-12 03:23:15 -04:00
|
|
|
}
|
|
|
|
|
2023-02-24 00:53:38 -05:00
|
|
|
#if CONFIG_IDF_TARGET_ESP32
|
|
|
|
/* APP core of esp32 can't access to RTC FAST MEMORY, do not define it with RTC_IRAM_ATTR */
|
|
|
|
void
|
|
|
|
#else
|
|
|
|
void RTC_IRAM_ATTR
|
|
|
|
#endif
|
|
|
|
esp_set_deep_sleep_wake_stub(esp_deep_sleep_wake_stub_fn_t new_stub)
|
2016-09-12 03:23:15 -04:00
|
|
|
{
|
2021-11-05 05:23:24 -04:00
|
|
|
#if SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY
|
2021-08-11 10:06:47 -04:00
|
|
|
wake_stub_fn_handler = new_stub;
|
|
|
|
#else
|
2016-09-12 03:23:15 -04:00
|
|
|
REG_WRITE(RTC_ENTRY_ADDR_REG, (uint32_t)new_stub);
|
2021-08-11 10:06:47 -04:00
|
|
|
#endif
|
2016-09-12 03:23:15 -04:00
|
|
|
}
|
|
|
|
|
2021-02-02 23:29:31 -05:00
|
|
|
void RTC_IRAM_ATTR esp_default_wake_deep_sleep(void)
|
|
|
|
{
|
2016-10-12 20:46:51 -04:00
|
|
|
/* Clear MMU for CPU 0 */
|
2020-04-23 00:39:07 -04:00
|
|
|
#if CONFIG_IDF_TARGET_ESP32
|
2017-09-01 06:35:42 -04:00
|
|
|
_DPORT_REG_WRITE(DPORT_PRO_CACHE_CTRL1_REG,
|
2021-02-02 23:29:31 -05:00
|
|
|
_DPORT_REG_READ(DPORT_PRO_CACHE_CTRL1_REG) | DPORT_PRO_CACHE_MMU_IA_CLR);
|
2017-09-01 06:35:42 -04:00
|
|
|
_DPORT_REG_WRITE(DPORT_PRO_CACHE_CTRL1_REG,
|
2021-02-02 23:29:31 -05:00
|
|
|
_DPORT_REG_READ(DPORT_PRO_CACHE_CTRL1_REG) & (~DPORT_PRO_CACHE_MMU_IA_CLR));
|
2023-12-06 07:37:28 -05:00
|
|
|
#if CONFIG_ESP_SLEEP_WAIT_FLASH_READY_EXTRA_DELAY > 0
|
2016-12-12 10:20:15 -05:00
|
|
|
// ROM code has not started yet, so we need to set delay factor
|
2020-07-21 01:07:34 -04:00
|
|
|
// used by esp_rom_delay_us first.
|
2017-01-11 04:17:13 -05:00
|
|
|
ets_update_cpu_frequency_rom(ets_get_detected_xtal_freq() / 1000000);
|
2023-12-06 07:37:28 -05:00
|
|
|
// Time from VDD_SDIO power up to first flash read in ROM code is 700 us,
|
|
|
|
// for some flash chips is not sufficient, this delay is configured in menuconfig,
|
|
|
|
// it can be used to give the flash chip some extra time to become ready.
|
|
|
|
// For later chips, we have EFUSE_FLASH_TPUW field to configure it and do
|
|
|
|
// this delay in the ROM.
|
|
|
|
esp_rom_delay_us(CONFIG_ESP_SLEEP_WAIT_FLASH_READY_EXTRA_DELAY);
|
2020-04-23 00:39:07 -04:00
|
|
|
#endif
|
|
|
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
|
|
|
REG_SET_BIT(EXTMEM_CACHE_DBG_INT_ENA_REG, EXTMEM_CACHE_DBG_EN);
|
2016-12-12 10:20:15 -05:00
|
|
|
#endif
|
2016-09-12 03:23:15 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void __attribute__((weak, alias("esp_default_wake_deep_sleep"))) esp_wake_deep_sleep(void);
|
2022-07-13 09:10:17 -04:00
|
|
|
#endif // SOC_RTC_FAST_MEM_SUPPORTED
|
2016-11-21 10:05:23 -05:00
|
|
|
|
|
|
|
void esp_deep_sleep(uint64_t time_in_us)
|
|
|
|
{
|
2017-04-21 00:32:50 -04:00
|
|
|
esp_sleep_enable_timer_wakeup(time_in_us);
|
2016-12-08 09:22:10 -05:00
|
|
|
esp_deep_sleep_start();
|
|
|
|
}
|
|
|
|
|
2023-10-06 12:42:49 -04:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
2024-04-01 02:28:32 -04:00
|
|
|
static esp_err_t s_sleep_hook_register(esp_deep_sleep_cb_t new_cb, esp_deep_sleep_cb_t s_cb_array[MAX_DSLP_HOOKS])
|
2023-03-13 07:10:02 -04:00
|
|
|
{
|
|
|
|
portENTER_CRITICAL(&spinlock_rtc_deep_sleep);
|
2024-04-01 02:28:32 -04:00
|
|
|
for (int n = 0; n < MAX_DSLP_HOOKS; n++) {
|
|
|
|
if (s_cb_array[n]==NULL || s_cb_array[n]==new_cb) {
|
|
|
|
s_cb_array[n]=new_cb;
|
2023-03-13 07:10:02 -04:00
|
|
|
portEXIT_CRITICAL(&spinlock_rtc_deep_sleep);
|
|
|
|
return ESP_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
portEXIT_CRITICAL(&spinlock_rtc_deep_sleep);
|
|
|
|
ESP_LOGE(TAG, "Registered deepsleep callbacks exceeds MAX_DSLP_HOOKS");
|
|
|
|
return ESP_ERR_NO_MEM;
|
|
|
|
}
|
|
|
|
|
2024-04-01 02:28:32 -04:00
|
|
|
static void s_sleep_hook_deregister(esp_deep_sleep_cb_t old_cb, esp_deep_sleep_cb_t s_cb_array[MAX_DSLP_HOOKS])
|
2023-03-13 07:10:02 -04:00
|
|
|
{
|
|
|
|
portENTER_CRITICAL(&spinlock_rtc_deep_sleep);
|
2024-04-01 02:28:32 -04:00
|
|
|
for (int n = 0; n < MAX_DSLP_HOOKS; n++) {
|
|
|
|
if(s_cb_array[n] == old_cb) {
|
|
|
|
s_cb_array[n] = NULL;
|
2023-03-13 07:10:02 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
portEXIT_CRITICAL(&spinlock_rtc_deep_sleep);
|
|
|
|
}
|
|
|
|
|
2024-04-01 02:28:32 -04:00
|
|
|
esp_err_t esp_deep_sleep_register_hook(esp_deep_sleep_cb_t new_dslp_cb)
|
|
|
|
{
|
|
|
|
return s_sleep_hook_register(new_dslp_cb, s_dslp_cb);
|
|
|
|
}
|
|
|
|
|
|
|
|
void esp_deep_sleep_deregister_hook(esp_deep_sleep_cb_t old_dslp_cb)
|
|
|
|
{
|
|
|
|
s_sleep_hook_deregister(old_dslp_cb, s_dslp_cb);
|
|
|
|
}
|
|
|
|
|
|
|
|
#if CONFIG_ESP_PHY_ENABLED
|
|
|
|
esp_err_t esp_deep_sleep_register_phy_hook(esp_deep_sleep_cb_t new_dslp_cb)
|
|
|
|
{
|
|
|
|
return s_sleep_hook_register(new_dslp_cb, s_dslp_phy_cb);
|
|
|
|
}
|
|
|
|
|
|
|
|
void esp_deep_sleep_deregister_phy_hook(esp_deep_sleep_cb_t old_dslp_cb)
|
|
|
|
{
|
|
|
|
s_sleep_hook_deregister(old_dslp_cb, s_dslp_phy_cb);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void s_do_deep_sleep_phy_callback(void)
|
|
|
|
{
|
|
|
|
for (int n = 0; n < MAX_DSLP_HOOKS; n++) {
|
|
|
|
if (s_dslp_phy_cb[n] != NULL) {
|
|
|
|
s_dslp_phy_cb[n]();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2023-06-28 01:34:52 -04:00
|
|
|
static int s_cache_suspend_cnt = 0;
|
|
|
|
|
2023-06-25 05:12:43 -04:00
|
|
|
// Must be called from critical sections.
|
2023-06-28 01:34:52 -04:00
|
|
|
static void IRAM_ATTR suspend_cache(void) {
|
|
|
|
s_cache_suspend_cnt++;
|
|
|
|
if (s_cache_suspend_cnt == 1) {
|
2023-09-15 08:11:52 -04:00
|
|
|
cache_hal_suspend(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL);
|
2023-06-28 01:34:52 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-25 05:12:43 -04:00
|
|
|
// Must be called from critical sections.
|
2023-06-28 01:34:52 -04:00
|
|
|
static void IRAM_ATTR resume_cache(void) {
|
|
|
|
s_cache_suspend_cnt--;
|
2023-06-25 05:12:43 -04:00
|
|
|
assert(s_cache_suspend_cnt >= 0 && DRAM_STR("cache resume doesn't match suspend ops"));
|
2023-06-28 01:34:52 -04:00
|
|
|
if (s_cache_suspend_cnt == 0) {
|
2023-09-15 08:11:52 -04:00
|
|
|
cache_hal_resume(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL);
|
2023-06-28 01:34:52 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-26 07:50:52 -05:00
|
|
|
#if SOC_SLEEP_TGWDT_STOP_WORKAROUND
|
|
|
|
static uint32_t s_stopped_tgwdt_bmap = 0;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Must be called from critical sections.
|
|
|
|
static void IRAM_ATTR suspend_timers(uint32_t pd_flags) {
|
|
|
|
if (!(pd_flags & RTC_SLEEP_PD_XTAL)) {
|
|
|
|
#if SOC_SLEEP_TGWDT_STOP_WORKAROUND
|
|
|
|
/* If timegroup implemented task watchdog or interrupt watchdog is running, we have to stop it. */
|
|
|
|
for (uint32_t tg_num = 0; tg_num < SOC_TIMER_GROUPS; ++tg_num) {
|
|
|
|
if (mwdt_ll_check_if_enabled(TIMER_LL_GET_HW(tg_num))) {
|
|
|
|
mwdt_ll_write_protect_disable(TIMER_LL_GET_HW(tg_num));
|
|
|
|
mwdt_ll_disable(TIMER_LL_GET_HW(tg_num));
|
|
|
|
mwdt_ll_write_protect_enable(TIMER_LL_GET_HW(tg_num));
|
|
|
|
s_stopped_tgwdt_bmap |= BIT(tg_num);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#if SOC_SLEEP_SYSTIMER_STALL_WORKAROUND
|
|
|
|
for (uint32_t counter_id = 0; counter_id < SOC_SYSTIMER_COUNTER_NUM; ++counter_id) {
|
|
|
|
systimer_ll_enable_counter(&SYSTIMER, counter_id, false);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Must be called from critical sections.
|
|
|
|
static void IRAM_ATTR resume_timers(uint32_t pd_flags) {
|
|
|
|
if (!(pd_flags & RTC_SLEEP_PD_XTAL)) {
|
|
|
|
#if SOC_SLEEP_SYSTIMER_STALL_WORKAROUND
|
|
|
|
for (uint32_t counter_id = 0; counter_id < SOC_SYSTIMER_COUNTER_NUM; ++counter_id) {
|
|
|
|
systimer_ll_enable_counter(&SYSTIMER, counter_id, true);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#if SOC_SLEEP_TGWDT_STOP_WORKAROUND
|
|
|
|
for (uint32_t tg_num = 0; tg_num < SOC_TIMER_GROUPS; ++tg_num) {
|
|
|
|
if (s_stopped_tgwdt_bmap & BIT(tg_num)) {
|
|
|
|
mwdt_ll_write_protect_disable(TIMER_LL_GET_HW(tg_num));
|
|
|
|
mwdt_ll_enable(TIMER_LL_GET_HW(tg_num));
|
|
|
|
mwdt_ll_write_protect_enable(TIMER_LL_GET_HW(tg_num));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-23 00:39:07 -04:00
|
|
|
// [refactor-todo] provide target logic for body of uart functions below
|
2019-07-16 05:33:30 -04:00
|
|
|
static void IRAM_ATTR flush_uarts(void)
|
2018-07-04 00:11:07 -04:00
|
|
|
{
|
2023-03-23 23:42:01 -04:00
|
|
|
for (int i = 0; i < SOC_UART_HP_NUM; ++i) {
|
2020-04-23 00:39:07 -04:00
|
|
|
#ifdef CONFIG_IDF_TARGET_ESP32
|
2024-01-17 04:19:49 -05:00
|
|
|
esp_rom_output_tx_wait_idle(i);
|
2021-01-16 00:58:55 -05:00
|
|
|
#else
|
2023-09-14 23:09:52 -04:00
|
|
|
if (uart_ll_is_enabled(i)) {
|
2024-01-17 04:19:49 -05:00
|
|
|
esp_rom_output_tx_wait_idle(i);
|
2020-04-23 00:39:07 -04:00
|
|
|
}
|
|
|
|
#endif
|
2018-07-04 00:11:07 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-02 06:44:25 -04:00
|
|
|
static uint32_t s_suspended_uarts_bmap = 0;
|
|
|
|
|
2023-05-26 05:54:18 -04:00
|
|
|
/**
|
2023-06-25 05:12:43 -04:00
|
|
|
* Suspend enabled uarts and return suspended uarts bit map.
|
|
|
|
* Must be called from critical sections.
|
2023-05-26 05:54:18 -04:00
|
|
|
*/
|
2023-06-25 05:12:43 -04:00
|
|
|
FORCE_INLINE_ATTR void suspend_uarts(void)
|
2018-04-04 03:05:50 -04:00
|
|
|
{
|
2023-06-02 06:44:25 -04:00
|
|
|
s_suspended_uarts_bmap = 0;
|
2023-03-23 23:42:01 -04:00
|
|
|
for (int i = 0; i < SOC_UART_HP_NUM; ++i) {
|
2020-12-03 22:20:07 -05:00
|
|
|
#ifndef CONFIG_IDF_TARGET_ESP32
|
2023-09-14 23:09:52 -04:00
|
|
|
if (!uart_ll_is_enabled(i)) {
|
2021-02-02 23:29:31 -05:00
|
|
|
continue;
|
|
|
|
}
|
2020-12-03 22:20:07 -05:00
|
|
|
#endif
|
|
|
|
uart_ll_force_xoff(i);
|
2023-06-02 06:44:25 -04:00
|
|
|
s_suspended_uarts_bmap |= BIT(i);
|
2020-12-03 22:20:07 -05:00
|
|
|
#if SOC_UART_SUPPORT_FSM_TX_WAIT_SEND
|
|
|
|
uint32_t uart_fsm = 0;
|
|
|
|
do {
|
2023-08-29 00:25:05 -04:00
|
|
|
uart_fsm = uart_ll_get_tx_fsm_status(i);
|
2021-04-25 21:52:36 -04:00
|
|
|
} while (!(uart_fsm == UART_LL_FSM_IDLE || uart_fsm == UART_LL_FSM_TX_WAIT_SEND));
|
2020-12-03 22:20:07 -05:00
|
|
|
#else
|
2023-08-29 00:25:05 -04:00
|
|
|
while (uart_ll_get_tx_fsm_status(i) != 0) {}
|
2020-04-23 00:39:07 -04:00
|
|
|
#endif
|
2018-04-04 03:05:50 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-25 05:12:43 -04:00
|
|
|
// Must be called from critical sections
|
|
|
|
FORCE_INLINE_ATTR void resume_uarts(void)
|
2018-04-04 03:05:50 -04:00
|
|
|
{
|
2023-03-23 23:42:01 -04:00
|
|
|
for (int i = 0; i < SOC_UART_HP_NUM; ++i) {
|
2023-06-02 06:44:25 -04:00
|
|
|
if (s_suspended_uarts_bmap & 0x1) {
|
2023-05-26 05:54:18 -04:00
|
|
|
uart_ll_force_xon(i);
|
2021-02-02 23:29:31 -05:00
|
|
|
}
|
2023-06-02 06:44:25 -04:00
|
|
|
s_suspended_uarts_bmap >>= 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
UART prepare strategy in sleep:
|
|
|
|
Deepsleep : flush the fifo before enter sleep to avoid data loss
|
|
|
|
|
|
|
|
Lightsleep:
|
|
|
|
Chips not support PD_TOP: Suspend uart before cpu freq switch
|
|
|
|
|
|
|
|
Chips support PD_TOP:
|
|
|
|
For sleep which will not power down the TOP domain (uart belongs it), we can just suspend the UART.
|
|
|
|
|
|
|
|
For sleep which will power down the TOP domain, we need to consider whether the uart flushing will
|
|
|
|
block the sleep process and cause the rtos target tick to be missed upon waking up. It's need to
|
|
|
|
estimate the flush time based on the number of bytes in the uart FIFO, if the predicted flush
|
|
|
|
completion time has exceeded the wakeup time, we should abandon the flush, skip the sleep and
|
|
|
|
return ESP_ERR_SLEEP_REJECT.
|
|
|
|
*/
|
2023-06-25 05:12:43 -04:00
|
|
|
FORCE_INLINE_ATTR bool light_sleep_uart_prepare(uint32_t pd_flags, int64_t sleep_duration)
|
2023-06-02 06:44:25 -04:00
|
|
|
{
|
|
|
|
bool should_skip_sleep = false;
|
2023-07-20 11:48:38 -04:00
|
|
|
#if !SOC_PM_SUPPORT_TOP_PD || !CONFIG_ESP_CONSOLE_UART
|
2023-06-02 06:44:25 -04:00
|
|
|
suspend_uarts();
|
|
|
|
#else
|
2024-02-26 02:20:14 -05:00
|
|
|
#ifdef CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION
|
|
|
|
#define FORCE_FLUSH_CONSOLE_UART 1
|
|
|
|
#else
|
|
|
|
#define FORCE_FLUSH_CONSOLE_UART 0
|
|
|
|
#endif
|
|
|
|
if (FORCE_FLUSH_CONSOLE_UART || (pd_flags & PMU_SLEEP_PD_TOP)) {
|
2023-06-02 06:44:25 -04:00
|
|
|
if ((s_config.wakeup_triggers & RTC_TIMER_TRIG_EN) &&
|
2023-07-20 11:48:38 -04:00
|
|
|
// +1 is for cover the last character flush time
|
2023-06-02 06:44:25 -04:00
|
|
|
(sleep_duration < (int64_t)((UART_LL_FIFO_DEF_LEN - uart_ll_get_txfifo_len(CONSOLE_UART_DEV) + 1) * UART_FLUSH_US_PER_CHAR) + SLEEP_UART_FLUSH_DONE_TO_SLEEP_US)) {
|
|
|
|
should_skip_sleep = true;
|
|
|
|
} else {
|
|
|
|
/* Only flush the uart_num configured to console, the transmission integrity of
|
|
|
|
other uarts is guaranteed by the UART driver */
|
2024-03-19 22:15:31 -04:00
|
|
|
if (CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM != -1) {
|
|
|
|
esp_rom_output_tx_wait_idle(CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM);
|
|
|
|
}
|
2023-06-02 06:44:25 -04:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
suspend_uarts();
|
2018-04-04 03:05:50 -04:00
|
|
|
}
|
2023-06-02 06:44:25 -04:00
|
|
|
#endif
|
|
|
|
return should_skip_sleep;
|
2018-04-04 03:05:50 -04:00
|
|
|
}
|
|
|
|
|
2022-01-25 01:23:53 -05:00
|
|
|
/**
|
|
|
|
* These save-restore workaround should be moved to lower layer
|
|
|
|
*/
|
2023-06-25 05:12:43 -04:00
|
|
|
FORCE_INLINE_ATTR void misc_modules_sleep_prepare(bool deep_sleep)
|
2020-12-24 08:02:32 -05:00
|
|
|
{
|
2023-03-13 07:10:02 -04:00
|
|
|
if (deep_sleep){
|
|
|
|
for (int n = 0; n < MAX_DSLP_HOOKS; n++) {
|
|
|
|
if (s_dslp_cb[n] != NULL) {
|
|
|
|
s_dslp_cb[n]();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2023-10-27 06:23:50 -04:00
|
|
|
#if SOC_USB_SERIAL_JTAG_SUPPORTED && !SOC_USB_SERIAL_JTAG_SUPPORT_LIGHT_SLEEP
|
|
|
|
// Only avoid USJ pad leakage here, USB OTG pad leakage is prevented through USB Host driver.
|
|
|
|
sleep_console_usj_pad_backup_and_disable();
|
|
|
|
#endif
|
2021-08-20 03:15:58 -04:00
|
|
|
#if CONFIG_MAC_BB_PD
|
2023-03-13 07:10:02 -04:00
|
|
|
mac_bb_power_down_cb_execute();
|
2021-08-20 03:15:58 -04:00
|
|
|
#endif
|
2020-11-12 07:39:55 -05:00
|
|
|
#if CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL
|
2023-03-13 07:10:02 -04:00
|
|
|
gpio_sleep_mode_config_apply();
|
2021-08-20 03:15:58 -04:00
|
|
|
#endif
|
2024-01-15 04:27:13 -05:00
|
|
|
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && SOC_PM_CPU_RETENTION_BY_RTCCNTL
|
2023-03-13 07:10:02 -04:00
|
|
|
sleep_enable_cpu_retention();
|
2020-11-12 07:39:55 -05:00
|
|
|
#endif
|
2022-01-25 01:23:53 -05:00
|
|
|
#if REGI2C_ANA_CALI_PD_WORKAROUND
|
2023-03-13 07:10:02 -04:00
|
|
|
regi2c_analog_cali_reg_read();
|
2022-01-25 01:23:53 -05:00
|
|
|
#endif
|
2023-03-29 23:35:05 -04:00
|
|
|
}
|
2023-05-17 22:29:50 -04:00
|
|
|
|
2024-03-28 03:16:12 -04:00
|
|
|
#if !CONFIG_IDF_TARGET_ESP32P4
|
2023-05-17 22:29:50 -04:00
|
|
|
// TODO: IDF-7370
|
2023-03-29 23:35:05 -04:00
|
|
|
if (!(deep_sleep && s_adc_tsen_enabled)){
|
2023-03-13 07:10:02 -04:00
|
|
|
sar_periph_ctrl_power_disable();
|
|
|
|
}
|
2023-12-22 06:36:24 -05:00
|
|
|
#endif
|
2020-11-12 07:39:55 -05:00
|
|
|
}
|
|
|
|
|
2022-01-25 01:23:53 -05:00
|
|
|
/**
|
|
|
|
* These save-restore workaround should be moved to lower layer
|
|
|
|
*/
|
2023-06-25 05:12:43 -04:00
|
|
|
FORCE_INLINE_ATTR void misc_modules_wake_prepare(void)
|
2020-11-12 07:39:55 -05:00
|
|
|
{
|
2023-10-27 06:23:50 -04:00
|
|
|
#if SOC_USB_SERIAL_JTAG_SUPPORTED && !SOC_USB_SERIAL_JTAG_SUPPORT_LIGHT_SLEEP
|
|
|
|
sleep_console_usj_pad_restore();
|
2023-04-24 02:56:50 -04:00
|
|
|
#endif
|
2023-03-14 22:39:52 -04:00
|
|
|
sar_periph_ctrl_power_enable();
|
2024-01-15 04:27:13 -05:00
|
|
|
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && SOC_PM_CPU_RETENTION_BY_RTCCNTL
|
2023-01-12 05:08:14 -05:00
|
|
|
sleep_disable_cpu_retention();
|
2021-08-20 03:15:58 -04:00
|
|
|
#endif
|
|
|
|
#if CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL
|
|
|
|
gpio_sleep_mode_config_unapply();
|
|
|
|
#endif
|
|
|
|
#if CONFIG_MAC_BB_PD
|
|
|
|
mac_bb_power_up_cb_execute();
|
|
|
|
#endif
|
2022-01-25 01:23:53 -05:00
|
|
|
#if REGI2C_ANA_CALI_PD_WORKAROUND
|
|
|
|
regi2c_analog_cali_reg_write();
|
|
|
|
#endif
|
2020-11-12 07:39:55 -05:00
|
|
|
}
|
|
|
|
|
2023-12-01 07:26:08 -05:00
|
|
|
static IRAM_ATTR void sleep_low_power_clock_calibration(bool is_dslp)
|
|
|
|
{
|
|
|
|
// Calibrate rtc slow clock
|
|
|
|
#ifdef CONFIG_ESP_SYSTEM_RTC_EXT_XTAL
|
|
|
|
if (rtc_clk_slow_src_get() == SOC_RTC_SLOW_CLK_SRC_XTAL32K) {
|
|
|
|
uint64_t time_per_us = 1000000ULL;
|
|
|
|
s_config.rtc_clk_cal_period = (time_per_us << RTC_CLK_CAL_FRACT) / rtc_clk_slow_freq_get_hz();
|
|
|
|
} else {
|
|
|
|
// If the external 32 kHz XTAL does not exist, use the internal 150 kHz RC oscillator
|
|
|
|
// as the RTC slow clock source.
|
|
|
|
s_config.rtc_clk_cal_period = rtc_clk_cal(RTC_CAL_RTC_MUX, RTC_CLK_SRC_CAL_CYCLES);
|
|
|
|
esp_clk_slowclk_cal_set(s_config.rtc_clk_cal_period);
|
|
|
|
}
|
|
|
|
#elif CONFIG_RTC_CLK_SRC_INT_RC && CONFIG_IDF_TARGET_ESP32S2
|
|
|
|
s_config.rtc_clk_cal_period = rtc_clk_cal_cycling(RTC_CAL_RTC_MUX, RTC_CLK_SRC_CAL_CYCLES);
|
|
|
|
esp_clk_slowclk_cal_set(s_config.rtc_clk_cal_period);
|
|
|
|
#else
|
|
|
|
#if CONFIG_PM_ENABLE
|
|
|
|
if ((s_lightsleep_cnt % CONFIG_PM_LIGHTSLEEP_RTC_OSC_CAL_INTERVAL == 0) || is_dslp)
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
s_config.rtc_clk_cal_period = rtc_clk_cal(RTC_CAL_RTC_MUX, RTC_CLK_SRC_CAL_CYCLES);
|
|
|
|
esp_clk_slowclk_cal_set(s_config.rtc_clk_cal_period);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Calibrate rtc fast clock, only PMU supported chips sleep process is needed.
|
|
|
|
#if SOC_PMU_SUPPORTED
|
|
|
|
#if CONFIG_PM_ENABLE
|
|
|
|
if ((s_lightsleep_cnt % CONFIG_PM_LIGHTSLEEP_RTC_OSC_CAL_INTERVAL == 0) || is_dslp)
|
|
|
|
#endif
|
|
|
|
{
|
2024-04-06 23:55:06 -04:00
|
|
|
#if !CONFIG_IDF_TARGET_ESP32C5_BETA3_VERSION
|
2023-12-01 07:26:08 -05:00
|
|
|
s_config.fast_clk_cal_period = rtc_clk_cal(RTC_CAL_RC_FAST, FAST_CLK_SRC_CAL_CYCLES);
|
2024-04-06 23:55:06 -04:00
|
|
|
#else
|
|
|
|
s_config.fast_clk_cal_period = 0x8000;
|
|
|
|
#endif
|
2023-12-01 07:26:08 -05:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-01-31 07:11:25 -05:00
|
|
|
inline static uint32_t call_rtc_sleep_start(uint32_t reject_triggers, uint32_t lslp_mem_inf_fpu, bool dslp);
|
2021-01-28 09:28:04 -05:00
|
|
|
|
2023-10-06 12:42:49 -04:00
|
|
|
static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t mode, bool allow_sleep_rejection)
|
2016-12-08 09:22:10 -05:00
|
|
|
{
|
2018-07-04 00:11:07 -04:00
|
|
|
// 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.
|
|
|
|
// For deep sleep, wait for the contents of UART FIFO to be sent.
|
2023-02-01 03:58:42 -05:00
|
|
|
bool deep_sleep = (mode == ESP_SLEEP_MODE_DEEP_SLEEP);
|
2023-05-09 02:01:29 -04:00
|
|
|
bool should_skip_sleep = false;
|
2023-05-26 05:54:18 -04:00
|
|
|
|
2023-06-02 06:44:25 -04:00
|
|
|
int64_t sleep_duration = (int64_t) s_config.sleep_duration - (int64_t) s_config.sleep_time_adjustment;
|
2020-10-07 03:34:33 -04:00
|
|
|
|
2022-10-27 05:18:17 -04:00
|
|
|
#if SOC_RTC_SLOW_CLK_SUPPORT_RC_FAST_D256
|
|
|
|
//Keep the RTC8M_CLK on if RTC clock is rc_fast_d256.
|
2022-04-21 06:24:03 -04:00
|
|
|
bool rtc_using_8md256 = (rtc_clk_slow_src_get() == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256);
|
pm: fixed RTC8M domain power issues
introduced in e44ead535640525969c7e85892f38ca349d5ddf4
1. The int8M power domain config by default is PD. While LEDC is using
RTC8M as clock source, this power domain will be kept on.
But when 8MD256 is used as RTC clock source, the power domain should
also be kept on.
On ESP32, there was protection for it, but broken by commit
e44ead535640525969c7e85892f38ca349d5ddf4. Currently the power domain
will be forced on when LEDC is using RTC8M as clock source &&
!int8m_pd_en (user enable ESP_PDP_DOMAIN_RTC8M in lightsleep). Otherwise
the power domain will be powered off, regardless of RTC clock source.
In other words, int8M domain will be forced off (even when 8MD256
used as RTC clock source) if LEDC not using RTC8M as clock source, user
doesn't enable ESP_PDP_DOMAIN_RTC8M, or in deep sleep.
On later chips, there's no such protection, so 8MD256 could't be used as
RTC clock source in sleep modes.
This commit adds protection of 8MD256 clock to other chips. Fixes the
incorrect protection logic overriding on ESP32. Now the power domain
will be determiend by the logic below (order by priority):
1. When RTC clock source uses 8MD256, power up
2. When LEDC uses RTC8M clock source, power up
3. In deepsleep, power down
4. Otherwise determined by user config of ESP_PDP_DOMAIN_RTC8M,
power down by default. (This is preferred to have highest
priority, but it's kept as is because of current code structure.)
2. Before, after the macro `RTC_SLEEP_CONFIG_DEFAULT` decides dbias, the
protection above may force the int8m PU. This may cause the inconsistent
of dbias and the int8m PU status.
This commit lifts the logic of pd int8m/xtal fpu logic to upper layer
(sleep_modes.c).
Related: https://github.com/espressif/esp-idf/issues/8007, https://github.com/espressif/esp-idf/pull/8089
temp
2022-03-26 15:02:22 -04:00
|
|
|
#else
|
|
|
|
bool rtc_using_8md256 = false;
|
|
|
|
#endif
|
|
|
|
//Keep the RTC8M_CLK on if the ledc low-speed channel is clocked by RTC8M_CLK in lightsleep mode
|
2022-07-27 06:08:26 -04:00
|
|
|
bool periph_using_8m = !deep_sleep && s_periph_use_8m_flag;
|
pm: fixed RTC8M domain power issues
introduced in e44ead535640525969c7e85892f38ca349d5ddf4
1. The int8M power domain config by default is PD. While LEDC is using
RTC8M as clock source, this power domain will be kept on.
But when 8MD256 is used as RTC clock source, the power domain should
also be kept on.
On ESP32, there was protection for it, but broken by commit
e44ead535640525969c7e85892f38ca349d5ddf4. Currently the power domain
will be forced on when LEDC is using RTC8M as clock source &&
!int8m_pd_en (user enable ESP_PDP_DOMAIN_RTC8M in lightsleep). Otherwise
the power domain will be powered off, regardless of RTC clock source.
In other words, int8M domain will be forced off (even when 8MD256
used as RTC clock source) if LEDC not using RTC8M as clock source, user
doesn't enable ESP_PDP_DOMAIN_RTC8M, or in deep sleep.
On later chips, there's no such protection, so 8MD256 could't be used as
RTC clock source in sleep modes.
This commit adds protection of 8MD256 clock to other chips. Fixes the
incorrect protection logic overriding on ESP32. Now the power domain
will be determiend by the logic below (order by priority):
1. When RTC clock source uses 8MD256, power up
2. When LEDC uses RTC8M clock source, power up
3. In deepsleep, power down
4. Otherwise determined by user config of ESP_PDP_DOMAIN_RTC8M,
power down by default. (This is preferred to have highest
priority, but it's kept as is because of current code structure.)
2. Before, after the macro `RTC_SLEEP_CONFIG_DEFAULT` decides dbias, the
protection above may force the int8m PU. This may cause the inconsistent
of dbias and the int8m PU status.
This commit lifts the logic of pd int8m/xtal fpu logic to upper layer
(sleep_modes.c).
Related: https://github.com/espressif/esp-idf/issues/8007, https://github.com/espressif/esp-idf/pull/8089
temp
2022-03-26 15:02:22 -04:00
|
|
|
|
|
|
|
//Override user-configured power modes.
|
2022-07-27 06:08:26 -04:00
|
|
|
if (rtc_using_8md256 || periph_using_8m) {
|
pm: fixed RTC8M domain power issues
introduced in e44ead535640525969c7e85892f38ca349d5ddf4
1. The int8M power domain config by default is PD. While LEDC is using
RTC8M as clock source, this power domain will be kept on.
But when 8MD256 is used as RTC clock source, the power domain should
also be kept on.
On ESP32, there was protection for it, but broken by commit
e44ead535640525969c7e85892f38ca349d5ddf4. Currently the power domain
will be forced on when LEDC is using RTC8M as clock source &&
!int8m_pd_en (user enable ESP_PDP_DOMAIN_RTC8M in lightsleep). Otherwise
the power domain will be powered off, regardless of RTC clock source.
In other words, int8M domain will be forced off (even when 8MD256
used as RTC clock source) if LEDC not using RTC8M as clock source, user
doesn't enable ESP_PDP_DOMAIN_RTC8M, or in deep sleep.
On later chips, there's no such protection, so 8MD256 could't be used as
RTC clock source in sleep modes.
This commit adds protection of 8MD256 clock to other chips. Fixes the
incorrect protection logic overriding on ESP32. Now the power domain
will be determiend by the logic below (order by priority):
1. When RTC clock source uses 8MD256, power up
2. When LEDC uses RTC8M clock source, power up
3. In deepsleep, power down
4. Otherwise determined by user config of ESP_PDP_DOMAIN_RTC8M,
power down by default. (This is preferred to have highest
priority, but it's kept as is because of current code structure.)
2. Before, after the macro `RTC_SLEEP_CONFIG_DEFAULT` decides dbias, the
protection above may force the int8m PU. This may cause the inconsistent
of dbias and the int8m PU status.
This commit lifts the logic of pd int8m/xtal fpu logic to upper layer
(sleep_modes.c).
Related: https://github.com/espressif/esp-idf/issues/8007, https://github.com/espressif/esp-idf/pull/8089
temp
2022-03-26 15:02:22 -04:00
|
|
|
pd_flags &= ~RTC_SLEEP_PD_INT_8M;
|
|
|
|
}
|
|
|
|
|
2023-06-02 06:44:25 -04:00
|
|
|
// Sleep UART prepare
|
|
|
|
if (deep_sleep) {
|
|
|
|
flush_uarts();
|
|
|
|
} else {
|
|
|
|
should_skip_sleep = light_sleep_uart_prepare(pd_flags, sleep_duration);
|
|
|
|
}
|
|
|
|
|
2024-04-01 02:28:32 -04:00
|
|
|
#if CONFIG_ESP_PHY_ENABLED
|
|
|
|
// Do deep-sleep PHY related callback, which need to be executed when the PLL clock is exists.
|
|
|
|
// For light-sleep, PHY state is managed by the upper layer of the wifi/bt protocol stack.
|
|
|
|
if (deep_sleep) {
|
|
|
|
s_do_deep_sleep_phy_callback();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2023-06-09 05:19:24 -04:00
|
|
|
// Will switch to XTAL turn down MSPI speed
|
|
|
|
mspi_timing_change_speed_mode_cache_safe(true);
|
|
|
|
|
2023-12-14 22:29:02 -05:00
|
|
|
#if SOC_PM_RETENTION_SW_TRIGGER_REGDMA
|
2023-11-29 08:15:41 -05:00
|
|
|
if (!deep_sleep && (pd_flags & PMU_SLEEP_PD_TOP)) {
|
|
|
|
sleep_retention_do_system_retention(true);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2018-04-04 03:05:50 -04:00
|
|
|
// Save current frequency and switch to XTAL
|
2018-07-29 03:50:49 -04:00
|
|
|
rtc_cpu_freq_config_t cpu_freq_config;
|
|
|
|
rtc_clk_cpu_freq_get_config(&cpu_freq_config);
|
|
|
|
rtc_clk_cpu_freq_set_xtal();
|
2016-12-14 01:20:01 -05:00
|
|
|
|
2023-02-17 07:30:51 -05:00
|
|
|
#if SOC_PM_SUPPORT_EXT0_WAKEUP
|
2017-04-11 03:44:43 -04:00
|
|
|
// Configure pins for external wakeup
|
|
|
|
if (s_config.wakeup_triggers & RTC_EXT0_TRIG_EN) {
|
|
|
|
ext0_wakeup_prepare();
|
2016-12-08 09:22:10 -05:00
|
|
|
}
|
2023-11-20 03:35:27 -05:00
|
|
|
// for !(s_config.wakeup_triggers & RTC_EXT0_TRIG_EN), ext0 wakeup will be turned off in hardware in the real call to sleep
|
2023-02-17 07:30:51 -05:00
|
|
|
#endif
|
|
|
|
#if SOC_PM_SUPPORT_EXT1_WAKEUP
|
2017-04-11 03:44:43 -04:00
|
|
|
if (s_config.wakeup_triggers & RTC_EXT1_TRIG_EN) {
|
|
|
|
ext1_wakeup_prepare();
|
|
|
|
}
|
2023-11-20 03:35:27 -05:00
|
|
|
// for !(s_config.wakeup_triggers & RTC_EXT1_TRIG_EN), ext1 wakeup will be turned off in hardware in the real call to sleep
|
2021-01-12 06:10:21 -05:00
|
|
|
#endif
|
2020-04-23 00:39:07 -04:00
|
|
|
|
2021-02-05 04:10:44 -05:00
|
|
|
#if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP
|
2022-10-27 03:09:34 -04:00
|
|
|
if (deep_sleep && (s_config.wakeup_triggers & RTC_GPIO_TRIG_EN)) {
|
|
|
|
gpio_deep_sleep_wakeup_prepare();
|
2021-02-05 04:10:44 -05:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2023-10-25 08:54:16 -04:00
|
|
|
#if CONFIG_ULP_COPROC_ENABLED
|
2017-04-11 03:44:43 -04:00
|
|
|
// Enable ULP wakeup
|
2023-10-25 08:54:16 -04:00
|
|
|
#if CONFIG_ULP_COPROC_TYPE_FSM
|
2017-04-11 03:44:43 -04:00
|
|
|
if (s_config.wakeup_triggers & RTC_ULP_TRIG_EN) {
|
2023-10-25 08:54:16 -04:00
|
|
|
#elif CONFIG_ULP_COPROC_TYPE_RISCV
|
|
|
|
if (s_config.wakeup_triggers & (RTC_COCPU_TRIG_EN | RTC_COCPU_TRAP_TRIG_EN)) {
|
|
|
|
#elif CONFIG_ULP_COPROC_TYPE_LP_CORE
|
|
|
|
if (s_config.wakeup_triggers & RTC_LP_CORE_TRIG_EN) {
|
|
|
|
#endif
|
2022-05-02 00:31:25 -04:00
|
|
|
#ifdef CONFIG_IDF_TARGET_ESP32
|
2020-04-27 02:01:30 -04:00
|
|
|
rtc_hal_ulp_wakeup_enable();
|
2023-10-25 08:54:16 -04:00
|
|
|
#elif CONFIG_ULP_COPROC_TYPE_LP_CORE
|
|
|
|
pmu_ll_hp_clear_sw_intr_status(&PMU);
|
2022-05-02 00:31:25 -04:00
|
|
|
#else
|
|
|
|
rtc_hal_ulp_int_clear();
|
|
|
|
#endif
|
2017-04-11 03:44:43 -04:00
|
|
|
}
|
2023-10-25 08:54:16 -04:00
|
|
|
#endif // CONFIG_ULP_COPROC_ENABLED
|
|
|
|
|
2023-03-13 07:10:02 -04:00
|
|
|
misc_modules_sleep_prepare(deep_sleep);
|
2021-08-20 03:15:58 -04:00
|
|
|
|
2020-10-26 04:10:37 -04:00
|
|
|
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
|
|
|
if (deep_sleep) {
|
|
|
|
if (s_config.wakeup_triggers & RTC_TOUCH_TRIG_EN) {
|
|
|
|
touch_wakeup_prepare();
|
2021-06-22 09:53:16 -04:00
|
|
|
#if CONFIG_IDF_TARGET_ESP32S2
|
2020-10-26 04:10:37 -04:00
|
|
|
/* Workaround: In deep sleep, for ESP32S2, Power down the RTC_PERIPH will change the slope configuration of Touch sensor sleep pad.
|
|
|
|
* The configuration change will change the reading of the sleep pad, which will cause the touch wake-up sensor to trigger falsely.
|
|
|
|
*/
|
|
|
|
pd_flags &= ~RTC_SLEEP_PD_RTC_PERIPH;
|
2021-06-22 09:53:16 -04:00
|
|
|
#endif
|
2020-10-26 04:10:37 -04:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* In light sleep, the RTC_PERIPH power domain should be in the power-on state (Power on the touch circuit in light sleep),
|
|
|
|
* otherwise the touch sensor FSM will be cleared, causing touch sensor false triggering.
|
|
|
|
*/
|
|
|
|
if (touch_ll_get_fsm_state()) { // Check if the touch sensor is working properly.
|
|
|
|
pd_flags &= ~RTC_SLEEP_PD_RTC_PERIPH;
|
|
|
|
}
|
2020-04-23 00:39:07 -04:00
|
|
|
}
|
|
|
|
#endif
|
pm: fixed RTC8M domain power issues
introduced in e44ead535640525969c7e85892f38ca349d5ddf4
1. The int8M power domain config by default is PD. While LEDC is using
RTC8M as clock source, this power domain will be kept on.
But when 8MD256 is used as RTC clock source, the power domain should
also be kept on.
On ESP32, there was protection for it, but broken by commit
e44ead535640525969c7e85892f38ca349d5ddf4. Currently the power domain
will be forced on when LEDC is using RTC8M as clock source &&
!int8m_pd_en (user enable ESP_PDP_DOMAIN_RTC8M in lightsleep). Otherwise
the power domain will be powered off, regardless of RTC clock source.
In other words, int8M domain will be forced off (even when 8MD256
used as RTC clock source) if LEDC not using RTC8M as clock source, user
doesn't enable ESP_PDP_DOMAIN_RTC8M, or in deep sleep.
On later chips, there's no such protection, so 8MD256 could't be used as
RTC clock source in sleep modes.
This commit adds protection of 8MD256 clock to other chips. Fixes the
incorrect protection logic overriding on ESP32. Now the power domain
will be determiend by the logic below (order by priority):
1. When RTC clock source uses 8MD256, power up
2. When LEDC uses RTC8M clock source, power up
3. In deepsleep, power down
4. Otherwise determined by user config of ESP_PDP_DOMAIN_RTC8M,
power down by default. (This is preferred to have highest
priority, but it's kept as is because of current code structure.)
2. Before, after the macro `RTC_SLEEP_CONFIG_DEFAULT` decides dbias, the
protection above may force the int8m PU. This may cause the inconsistent
of dbias and the int8m PU status.
This commit lifts the logic of pd int8m/xtal fpu logic to upper layer
(sleep_modes.c).
Related: https://github.com/espressif/esp-idf/issues/8007, https://github.com/espressif/esp-idf/pull/8089
temp
2022-03-26 15:02:22 -04:00
|
|
|
|
2023-10-06 12:42:49 -04:00
|
|
|
uint32_t reject_triggers = allow_sleep_rejection ? (s_config.wakeup_triggers & RTC_SLEEP_REJECT_MASK) : 0;
|
2023-09-21 03:11:55 -04:00
|
|
|
|
|
|
|
if (!deep_sleep) {
|
|
|
|
/* Enable sleep reject for faster return from this function,
|
2024-01-14 22:49:10 -05:00
|
|
|
* in case the wakeup is already triggered.
|
2023-09-21 03:11:55 -04:00
|
|
|
*/
|
|
|
|
reject_triggers |= sleep_modem_reject_triggers();
|
|
|
|
}
|
2020-06-18 08:01:25 -04:00
|
|
|
|
2022-05-04 15:19:35 -04:00
|
|
|
//Append some flags in addition to power domains
|
|
|
|
uint32_t sleep_flags = pd_flags;
|
|
|
|
if (s_adc_tsen_enabled) {
|
|
|
|
sleep_flags |= RTC_SLEEP_USE_ADC_TESEN_MONITOR;
|
|
|
|
}
|
|
|
|
if (!s_ultra_low_enabled) {
|
|
|
|
sleep_flags |= RTC_SLEEP_NO_ULTRA_LOW;
|
|
|
|
}
|
2022-07-27 06:08:26 -04:00
|
|
|
if (periph_using_8m) {
|
2022-05-04 15:19:35 -04:00
|
|
|
sleep_flags |= RTC_SLEEP_DIG_USE_8M;
|
|
|
|
}
|
2023-10-08 04:48:00 -04:00
|
|
|
|
|
|
|
#if CONFIG_ESP_SLEEP_DEBUG
|
|
|
|
if (s_sleep_ctx != NULL) {
|
|
|
|
s_sleep_ctx->sleep_flags = sleep_flags;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2018-04-04 03:05:50 -04:00
|
|
|
// Enter sleep
|
2023-05-09 02:01:29 -04:00
|
|
|
esp_err_t result;
|
2023-01-31 07:11:25 -05:00
|
|
|
#if SOC_PMU_SUPPORTED
|
2024-02-19 06:09:20 -05:00
|
|
|
|
|
|
|
#if SOC_DCDC_SUPPORTED
|
|
|
|
s_config.rtc_ticks_at_ldo_prepare = rtc_time_get();
|
|
|
|
pmu_sleep_increase_ldo_volt();
|
|
|
|
#endif
|
|
|
|
|
2023-01-30 03:37:20 -05:00
|
|
|
pmu_sleep_config_t config;
|
2023-10-08 04:48:00 -04:00
|
|
|
pmu_sleep_init(pmu_sleep_config_default(&config, sleep_flags, s_config.sleep_time_adjustment,
|
2023-01-30 03:37:20 -05:00
|
|
|
s_config.rtc_clk_cal_period, s_config.fast_clk_cal_period,
|
|
|
|
deep_sleep), deep_sleep);
|
|
|
|
#else
|
2022-05-04 15:19:35 -04:00
|
|
|
rtc_sleep_config_t config;
|
|
|
|
rtc_sleep_get_default_config(sleep_flags, &config);
|
2018-04-04 03:05:50 -04:00
|
|
|
rtc_sleep_init(config);
|
|
|
|
|
2020-11-06 04:28:57 -05:00
|
|
|
// Set state machine time for light sleep
|
2021-02-02 23:29:31 -05:00
|
|
|
if (!deep_sleep) {
|
2020-11-06 04:28:57 -05:00
|
|
|
rtc_sleep_low_init(s_config.rtc_clk_cal_period);
|
|
|
|
}
|
2023-01-30 03:37:20 -05:00
|
|
|
#endif
|
2020-11-06 04:28:57 -05:00
|
|
|
|
2017-04-11 03:44:43 -04:00
|
|
|
// Configure timer wakeup
|
2023-06-02 06:44:25 -04:00
|
|
|
if (!should_skip_sleep && (s_config.wakeup_triggers & RTC_TIMER_TRIG_EN)) {
|
|
|
|
if (timer_wakeup_prepare(sleep_duration) != ESP_OK) {
|
2023-10-06 12:42:49 -04:00
|
|
|
should_skip_sleep = allow_sleep_rejection ? true : false;
|
2023-05-09 02:01:29 -04:00
|
|
|
}
|
2017-04-11 03:44:43 -04:00
|
|
|
}
|
2020-04-23 00:39:07 -04:00
|
|
|
|
2023-03-13 09:30:07 -04:00
|
|
|
|
2023-06-02 06:44:25 -04:00
|
|
|
if (should_skip_sleep) {
|
|
|
|
result = ESP_ERR_SLEEP_REJECT;
|
2024-04-19 00:12:53 -04:00
|
|
|
#if ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE && SOC_PM_CPU_RETENTION_BY_SW
|
2024-01-15 04:27:13 -05:00
|
|
|
esp_sleep_cpu_skip_retention();
|
|
|
|
#endif
|
2023-06-02 06:44:25 -04:00
|
|
|
} else {
|
2023-10-08 04:48:00 -04:00
|
|
|
#if CONFIG_ESP_SLEEP_DEBUG
|
2023-12-05 00:38:47 -05:00
|
|
|
if (s_sleep_ctx != NULL) {
|
|
|
|
s_sleep_ctx->wakeup_triggers = s_config.wakeup_triggers;
|
|
|
|
}
|
2023-10-08 04:48:00 -04:00
|
|
|
#endif
|
2023-05-09 02:01:29 -04:00
|
|
|
if (deep_sleep) {
|
2023-02-21 08:40:20 -05:00
|
|
|
#if !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
|
2023-05-09 02:01:29 -04:00
|
|
|
esp_sleep_isolate_digital_gpio();
|
2022-09-16 08:25:44 -04:00
|
|
|
#endif
|
|
|
|
|
2024-04-07 03:24:42 -04:00
|
|
|
#if ESP_ROM_SUPPORT_DEEP_SLEEP_WAKEUP_STUB && SOC_DEEP_SLEEP_SUPPORTED
|
2021-11-05 05:23:24 -04:00
|
|
|
#if SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY
|
2023-05-09 02:01:29 -04:00
|
|
|
esp_set_deep_sleep_wake_stub_default_entry();
|
2024-03-21 07:34:04 -04:00
|
|
|
#elif !CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP && SOC_RTC_FAST_MEM_SUPPORTED
|
|
|
|
/* If not possible stack is in RTC FAST memory, use the ROM function to calculate the CRC and save ~140 bytes IRAM */
|
|
|
|
set_rtc_memory_crc();
|
|
|
|
#endif // SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY
|
2023-12-22 06:36:24 -05:00
|
|
|
#endif
|
2024-03-21 07:34:04 -04:00
|
|
|
|
2023-05-09 02:01:29 -04:00
|
|
|
// Enter Deep Sleep
|
2024-03-21 07:34:04 -04:00
|
|
|
#if!ESP_ROM_SUPPORT_DEEP_SLEEP_WAKEUP_STUB || SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY || !CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP
|
2023-02-18 01:13:52 -05:00
|
|
|
#if SOC_PMU_SUPPORTED
|
2023-05-09 02:01:29 -04:00
|
|
|
result = call_rtc_sleep_start(reject_triggers, config.power.hp_sys.dig_power.mem_dslp, deep_sleep);
|
2023-02-18 01:13:52 -05:00
|
|
|
#else
|
2023-05-09 02:01:29 -04:00
|
|
|
result = call_rtc_sleep_start(reject_triggers, config.lslp_mem_inf_fpu, deep_sleep);
|
2023-02-18 01:13:52 -05:00
|
|
|
#endif
|
2020-10-07 03:34:33 -04:00
|
|
|
#else
|
2023-05-09 02:01:29 -04:00
|
|
|
/* Otherwise, need to call the dedicated soc function for this */
|
|
|
|
result = rtc_deep_sleep_start(s_config.wakeup_triggers, reject_triggers);
|
2020-04-23 00:39:07 -04:00
|
|
|
#endif
|
2023-05-09 02:01:29 -04:00
|
|
|
} else {
|
2023-12-26 07:50:52 -05:00
|
|
|
suspend_timers(pd_flags);
|
2023-07-31 01:48:27 -04:00
|
|
|
/* Cache Suspend 1: will wait cache idle in cache suspend */
|
|
|
|
suspend_cache();
|
2023-05-09 02:01:29 -04:00
|
|
|
/* On esp32c6, only the lp_aon pad hold function can only hold the GPIO state in the active mode.
|
|
|
|
In order to avoid the leakage of the SPI cs pin, hold it here */
|
2023-02-05 04:18:49 -05:00
|
|
|
#if (CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND)
|
2023-05-19 04:26:58 -04:00
|
|
|
#if !CONFIG_IDF_TARGET_ESP32H2 // ESP32H2 TODO IDF-7359: related rtcio ll func not supported yet
|
2023-06-25 05:12:43 -04:00
|
|
|
if(!(pd_flags & RTC_SLEEP_PD_VDDSDIO)) {
|
2023-07-31 01:48:27 -04:00
|
|
|
/* Cache suspend also means SPI bus IDLE, then we can hold SPI CS pin safely */
|
2023-05-19 04:26:58 -04:00
|
|
|
gpio_ll_hold_en(&GPIO, SPI_CS0_GPIO_NUM);
|
2023-05-09 02:01:29 -04:00
|
|
|
}
|
2023-02-14 01:11:11 -05:00
|
|
|
#endif
|
2023-05-22 02:17:02 -04:00
|
|
|
#endif
|
2023-02-14 01:11:11 -05:00
|
|
|
|
2024-04-16 06:06:35 -04:00
|
|
|
#if SOC_CLK_MPLL_SUPPORTED
|
|
|
|
uint32_t mpll_freq_mhz = rtc_clk_mpll_get_freq();
|
|
|
|
if (mpll_freq_mhz) {
|
|
|
|
rtc_clk_mpll_disable();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2024-02-19 06:09:20 -05:00
|
|
|
#if SOC_DCDC_SUPPORTED
|
|
|
|
uint64_t ldo_increased_us = rtc_time_slowclk_to_us(rtc_time_get() - s_config.rtc_ticks_at_ldo_prepare, s_config.rtc_clk_cal_period);
|
|
|
|
if (ldo_increased_us < LDO_POWER_TAKEOVER_PREPARATION_TIME_US) {
|
|
|
|
esp_rom_delay_us(LDO_POWER_TAKEOVER_PREPARATION_TIME_US - ldo_increased_us);
|
|
|
|
}
|
|
|
|
pmu_sleep_shutdown_dcdc();
|
|
|
|
#endif
|
|
|
|
|
2023-05-22 02:17:02 -04:00
|
|
|
#if SOC_PMU_SUPPORTED
|
2024-04-19 00:12:53 -04:00
|
|
|
#if SOC_PM_CPU_RETENTION_BY_SW && ESP_SLEEP_POWER_DOWN_CPU
|
2023-07-06 03:52:21 -04:00
|
|
|
esp_sleep_execute_event_callbacks(SLEEP_EVENT_HW_GOTO_SLEEP, (void *)0);
|
2024-01-15 04:27:13 -05:00
|
|
|
if (pd_flags & (PMU_SLEEP_PD_CPU | PMU_SLEEP_PD_TOP)) {
|
2023-05-09 02:01:29 -04:00
|
|
|
result = esp_sleep_cpu_retention(pmu_sleep_start, s_config.wakeup_triggers, reject_triggers, config.power.hp_sys.dig_power.mem_dslp, deep_sleep);
|
2023-10-08 04:48:00 -04:00
|
|
|
} else
|
2023-05-22 02:17:02 -04:00
|
|
|
#endif
|
2023-10-08 04:48:00 -04:00
|
|
|
{
|
2024-04-19 00:12:53 -04:00
|
|
|
#if !CONFIG_FREERTOS_UNICORE && ESP_SLEEP_POWER_DOWN_CPU && SOC_PM_CPU_RETENTION_BY_SW
|
2024-01-15 04:27:13 -05:00
|
|
|
// Skip smp retention if CPU power domain power-down is not allowed
|
|
|
|
esp_sleep_cpu_skip_retention();
|
|
|
|
#endif
|
2023-05-09 02:01:29 -04:00
|
|
|
result = call_rtc_sleep_start(reject_triggers, config.power.hp_sys.dig_power.mem_dslp, deep_sleep);
|
|
|
|
}
|
2023-07-06 03:52:21 -04:00
|
|
|
esp_sleep_execute_event_callbacks(SLEEP_EVENT_HW_EXIT_SLEEP, (void *)0);
|
2023-01-31 07:11:25 -05:00
|
|
|
#else
|
2023-05-09 02:01:29 -04:00
|
|
|
result = call_rtc_sleep_start(reject_triggers, config.lslp_mem_inf_fpu, deep_sleep);
|
2023-01-31 07:11:25 -05:00
|
|
|
#endif
|
2023-02-14 01:11:11 -05:00
|
|
|
|
2024-04-16 06:06:35 -04:00
|
|
|
#if SOC_CLK_MPLL_SUPPORTED
|
|
|
|
if (mpll_freq_mhz) {
|
|
|
|
rtc_clk_mpll_enable();
|
|
|
|
rtc_clk_mpll_configure(clk_hal_xtal_get_freq_mhz(), mpll_freq_mhz);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2023-05-09 02:01:29 -04:00
|
|
|
/* Unhold the SPI CS pin */
|
2023-02-05 04:18:49 -05:00
|
|
|
#if (CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND)
|
2023-05-19 04:26:58 -04:00
|
|
|
#if !CONFIG_IDF_TARGET_ESP32H2 // ESP32H2 TODO IDF-7359: related rtcio ll func not supported yet
|
2023-06-25 05:12:43 -04:00
|
|
|
if(!(pd_flags & RTC_SLEEP_PD_VDDSDIO)) {
|
2023-05-19 04:26:58 -04:00
|
|
|
gpio_ll_hold_dis(&GPIO, SPI_CS0_GPIO_NUM);
|
2023-05-09 02:01:29 -04:00
|
|
|
}
|
2023-05-19 04:26:58 -04:00
|
|
|
#endif
|
2023-02-14 01:11:11 -05:00
|
|
|
#endif
|
2023-08-03 22:47:51 -04:00
|
|
|
/* Cache Resume 1: Resume cache for continue running*/
|
|
|
|
resume_cache();
|
2023-12-26 07:50:52 -05:00
|
|
|
resume_timers(pd_flags);
|
2023-12-05 00:38:47 -05:00
|
|
|
}
|
2024-01-05 06:15:23 -05:00
|
|
|
}
|
2023-08-03 22:47:51 -04:00
|
|
|
#if CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION
|
|
|
|
if (pd_flags & RTC_SLEEP_PD_VDDSDIO) {
|
|
|
|
/* Cache Suspend 2: If previous sleep powerdowned the flash, suspend cache here so that the
|
|
|
|
access to flash before flash ready can be explicitly exposed. */
|
|
|
|
suspend_cache();
|
|
|
|
}
|
|
|
|
#endif
|
2018-04-04 03:05:50 -04:00
|
|
|
// Restore CPU frequency
|
2022-03-13 23:33:01 -04:00
|
|
|
#if SOC_PM_SUPPORT_PMU_MODEM_STATE
|
|
|
|
if (pmu_sleep_pll_already_enabled()) {
|
|
|
|
rtc_clk_cpu_freq_to_pll_and_pll_lock_release(esp_pm_impl_get_cpu_freq(PM_MODE_CPU_MAX));
|
|
|
|
} else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
rtc_clk_cpu_freq_set_config(&cpu_freq_config);
|
|
|
|
}
|
2018-04-04 03:05:50 -04:00
|
|
|
|
2023-10-13 04:19:53 -04:00
|
|
|
esp_sleep_execute_event_callbacks(SLEEP_EVENT_SW_CLK_READY, (void *)0);
|
|
|
|
|
2020-11-06 04:28:57 -05:00
|
|
|
if (!deep_sleep) {
|
2022-07-21 07:24:42 -04:00
|
|
|
s_config.ccount_ticks_record = esp_cpu_get_cycle_count();
|
2023-12-14 22:29:02 -05:00
|
|
|
#if SOC_PM_RETENTION_SW_TRIGGER_REGDMA
|
2023-11-29 08:15:41 -05:00
|
|
|
if (pd_flags & PMU_SLEEP_PD_TOP) {
|
|
|
|
sleep_retention_do_system_retention(false);
|
|
|
|
}
|
|
|
|
#endif
|
2021-11-09 01:26:06 -05:00
|
|
|
misc_modules_wake_prepare();
|
2020-11-06 04:28:57 -05:00
|
|
|
}
|
|
|
|
|
2024-04-07 03:24:42 -04:00
|
|
|
#if SOC_SPI_MEM_SUPPORT_TIMING_TUNING
|
2023-11-29 08:15:41 -05:00
|
|
|
if (cpu_freq_config.source == SOC_CPU_CLK_SRC_PLL) {
|
|
|
|
// Turn up MSPI speed if switch to PLL
|
|
|
|
mspi_timing_change_speed_mode_cache_safe(false);
|
|
|
|
}
|
2024-04-07 03:24:42 -04:00
|
|
|
#endif
|
2023-11-29 08:15:41 -05:00
|
|
|
|
2018-04-04 03:05:50 -04:00
|
|
|
// re-enable UART output
|
2023-06-02 06:44:25 -04:00
|
|
|
resume_uarts();
|
2023-06-19 07:32:34 -04:00
|
|
|
return result ? ESP_ERR_SLEEP_REJECT : ESP_OK;
|
2017-04-21 00:32:50 -04:00
|
|
|
}
|
|
|
|
|
2023-01-31 07:11:25 -05:00
|
|
|
inline static uint32_t IRAM_ATTR call_rtc_sleep_start(uint32_t reject_triggers, uint32_t lslp_mem_inf_fpu, bool dslp)
|
2020-10-07 03:34:33 -04:00
|
|
|
{
|
|
|
|
#ifdef CONFIG_IDF_TARGET_ESP32
|
2021-02-02 23:29:31 -05:00
|
|
|
return rtc_sleep_start(s_config.wakeup_triggers, reject_triggers);
|
2023-01-31 07:11:25 -05:00
|
|
|
#elif SOC_PMU_SUPPORTED
|
|
|
|
return pmu_sleep_start(s_config.wakeup_triggers, reject_triggers, lslp_mem_inf_fpu, dslp);
|
2020-10-07 03:34:33 -04:00
|
|
|
#else
|
2021-07-01 23:33:40 -04:00
|
|
|
return rtc_sleep_start(s_config.wakeup_triggers, reject_triggers, lslp_mem_inf_fpu);
|
2020-10-07 03:34:33 -04:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2023-10-06 12:42:49 -04:00
|
|
|
static esp_err_t IRAM_ATTR deep_sleep_start(bool allow_sleep_rejection)
|
2017-04-21 00:32:50 -04:00
|
|
|
{
|
2021-02-09 06:30:43 -05:00
|
|
|
#if CONFIG_IDF_TARGET_ESP32S2
|
|
|
|
/* Due to hardware limitations, on S2 the brownout detector sometimes trigger during deep sleep
|
|
|
|
to circumvent this we disable the brownout detector before sleeping */
|
|
|
|
esp_brownout_disable();
|
|
|
|
#endif //CONFIG_IDF_TARGET_ESP32S2
|
|
|
|
|
2021-12-14 06:01:19 -05:00
|
|
|
esp_sync_timekeeping_timers();
|
2021-08-14 04:55:18 -04:00
|
|
|
|
|
|
|
/* Disable interrupts and stall another core in case another task writes
|
|
|
|
* to RTC memory while we calculate RTC memory CRC.
|
|
|
|
*/
|
|
|
|
portENTER_CRITICAL(&spinlock_rtc_deep_sleep);
|
|
|
|
esp_ipc_isr_stall_other_cpu();
|
2024-04-02 23:46:50 -04:00
|
|
|
esp_ipc_isr_stall_pause();
|
2021-08-14 04:55:18 -04:00
|
|
|
|
2018-04-04 03:05:50 -04:00
|
|
|
// record current RTC time
|
|
|
|
s_config.rtc_ticks_at_sleep_start = rtc_time_get();
|
2020-05-04 06:17:06 -04:00
|
|
|
|
2024-03-21 07:34:04 -04:00
|
|
|
#if ESP_ROM_SUPPORT_DEEP_SLEEP_WAKEUP_STUB
|
2017-04-21 00:32:50 -04:00
|
|
|
// Configure wake stub
|
|
|
|
if (esp_get_deep_sleep_wake_stub() == NULL) {
|
|
|
|
esp_set_deep_sleep_wake_stub(esp_wake_deep_sleep);
|
|
|
|
}
|
2024-03-21 07:34:04 -04:00
|
|
|
#endif // ESP_ROM_SUPPORT_DEEP_SLEEP_WAKEUP_STUB
|
2017-04-21 00:32:50 -04:00
|
|
|
|
|
|
|
// Decide which power domains can be powered down
|
|
|
|
uint32_t pd_flags = get_power_down_flags();
|
|
|
|
|
2023-12-01 07:26:08 -05:00
|
|
|
// Re-calibrate the RTC clock
|
|
|
|
sleep_low_power_clock_calibration(true);
|
2020-11-06 04:28:57 -05:00
|
|
|
|
2018-04-04 03:05:50 -04:00
|
|
|
// Correct the sleep time
|
|
|
|
s_config.sleep_time_adjustment = DEEP_SLEEP_TIME_OVERHEAD_US;
|
|
|
|
|
2023-02-18 01:13:52 -05:00
|
|
|
#if SOC_PMU_SUPPORTED
|
|
|
|
uint32_t force_pd_flags = PMU_SLEEP_PD_TOP | PMU_SLEEP_PD_VDDSDIO | PMU_SLEEP_PD_MODEM | PMU_SLEEP_PD_HP_PERIPH \
|
2023-03-09 21:55:09 -05:00
|
|
|
| PMU_SLEEP_PD_CPU | PMU_SLEEP_PD_MEM | PMU_SLEEP_PD_XTAL;
|
2023-08-03 04:08:06 -04:00
|
|
|
#if SOC_PM_SUPPORT_HP_AON_PD
|
|
|
|
force_pd_flags |= PMU_SLEEP_PD_HP_AON;
|
|
|
|
#endif
|
2024-03-21 07:34:04 -04:00
|
|
|
#if SOC_PM_SUPPORT_CNNT_PD
|
|
|
|
force_pd_flags |= PMU_SLEEP_PD_CNNT;
|
|
|
|
#endif
|
2023-02-18 01:13:52 -05:00
|
|
|
#else
|
pm: fixed RTC8M domain power issues
introduced in e44ead535640525969c7e85892f38ca349d5ddf4
1. The int8M power domain config by default is PD. While LEDC is using
RTC8M as clock source, this power domain will be kept on.
But when 8MD256 is used as RTC clock source, the power domain should
also be kept on.
On ESP32, there was protection for it, but broken by commit
e44ead535640525969c7e85892f38ca349d5ddf4. Currently the power domain
will be forced on when LEDC is using RTC8M as clock source &&
!int8m_pd_en (user enable ESP_PDP_DOMAIN_RTC8M in lightsleep). Otherwise
the power domain will be powered off, regardless of RTC clock source.
In other words, int8M domain will be forced off (even when 8MD256
used as RTC clock source) if LEDC not using RTC8M as clock source, user
doesn't enable ESP_PDP_DOMAIN_RTC8M, or in deep sleep.
On later chips, there's no such protection, so 8MD256 could't be used as
RTC clock source in sleep modes.
This commit adds protection of 8MD256 clock to other chips. Fixes the
incorrect protection logic overriding on ESP32. Now the power domain
will be determiend by the logic below (order by priority):
1. When RTC clock source uses 8MD256, power up
2. When LEDC uses RTC8M clock source, power up
3. In deepsleep, power down
4. Otherwise determined by user config of ESP_PDP_DOMAIN_RTC8M,
power down by default. (This is preferred to have highest
priority, but it's kept as is because of current code structure.)
2. Before, after the macro `RTC_SLEEP_CONFIG_DEFAULT` decides dbias, the
protection above may force the int8m PU. This may cause the inconsistent
of dbias and the int8m PU status.
This commit lifts the logic of pd int8m/xtal fpu logic to upper layer
(sleep_modes.c).
Related: https://github.com/espressif/esp-idf/issues/8007, https://github.com/espressif/esp-idf/pull/8089
temp
2022-03-26 15:02:22 -04:00
|
|
|
uint32_t force_pd_flags = RTC_SLEEP_PD_DIG | RTC_SLEEP_PD_VDDSDIO | RTC_SLEEP_PD_INT_8M | RTC_SLEEP_PD_XTAL;
|
2023-02-18 01:13:52 -05:00
|
|
|
#endif
|
2022-09-21 05:19:27 -04:00
|
|
|
/**
|
|
|
|
* If all wireless modules share one power domain, we name this power domain "modem".
|
|
|
|
* If wireless modules have their own power domain, we give these power domains separate
|
|
|
|
* names.
|
|
|
|
*/
|
2022-02-07 21:53:11 -05:00
|
|
|
#if SOC_PM_SUPPORT_MODEM_PD
|
2022-09-21 05:19:27 -04:00
|
|
|
force_pd_flags |= RTC_SLEEP_PD_MODEM;
|
|
|
|
#endif
|
|
|
|
|
2021-03-09 04:04:13 -05:00
|
|
|
#if SOC_PM_SUPPORT_WIFI_PD
|
|
|
|
force_pd_flags |= RTC_SLEEP_PD_WIFI;
|
|
|
|
#endif
|
2022-09-21 05:19:27 -04:00
|
|
|
|
2021-03-09 04:04:13 -05:00
|
|
|
#if SOC_PM_SUPPORT_BT_PD
|
|
|
|
force_pd_flags |= RTC_SLEEP_PD_BT;
|
|
|
|
#endif
|
|
|
|
|
2017-04-21 00:32:50 -04:00
|
|
|
// Enter sleep
|
2023-10-06 12:42:49 -04:00
|
|
|
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;
|
2023-08-03 22:47:51 -04:00
|
|
|
#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();
|
|
|
|
#endif
|
2023-07-14 03:05:44 -04:00
|
|
|
ESP_EARLY_LOGE(TAG, "Deep sleep request is rejected");
|
|
|
|
} else {
|
|
|
|
// Because RTC is in a slower clock domain than the CPU, it
|
|
|
|
// can take several CPU cycles for the sleep mode to start.
|
|
|
|
while (1) {
|
|
|
|
;
|
|
|
|
}
|
2016-11-21 10:05:23 -05:00
|
|
|
}
|
2023-07-14 03:05:44 -04:00
|
|
|
// Never returns here, except that the sleep is rejected.
|
2024-04-02 23:46:50 -04:00
|
|
|
esp_ipc_isr_stall_resume();
|
2021-08-14 04:55:18 -04:00
|
|
|
esp_ipc_isr_release_other_cpu();
|
|
|
|
portEXIT_CRITICAL(&spinlock_rtc_deep_sleep);
|
2023-10-06 12:42:49 -04:00
|
|
|
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);
|
2016-11-21 10:05:23 -05:00
|
|
|
}
|
|
|
|
|
2017-04-21 00:32:50 -04:00
|
|
|
/**
|
|
|
|
* Helper function which handles entry to and exit from light sleep
|
|
|
|
* Placed into IRAM as flash may need some time to be powered on.
|
|
|
|
*/
|
2017-09-21 23:41:30 -04:00
|
|
|
static esp_err_t esp_light_sleep_inner(uint32_t pd_flags,
|
2023-01-17 06:22:41 -05:00
|
|
|
uint32_t flash_enable_time_us) IRAM_ATTR __attribute__((noinline));
|
2017-09-21 23:41:30 -04:00
|
|
|
|
|
|
|
static esp_err_t esp_light_sleep_inner(uint32_t pd_flags,
|
2023-01-17 06:22:41 -05:00
|
|
|
uint32_t flash_enable_time_us)
|
2017-04-21 00:32:50 -04:00
|
|
|
{
|
2023-08-03 23:58:07 -04:00
|
|
|
#if SOC_CONFIGURABLE_VDDSDIO_SUPPORTED
|
|
|
|
rtc_vddsdio_config_t vddsdio_config = rtc_vddsdio_get_config();
|
|
|
|
#endif
|
|
|
|
|
2017-04-21 00:32:50 -04:00
|
|
|
// Enter sleep
|
2023-10-25 08:54:16 -04:00
|
|
|
esp_err_t reject = esp_sleep_start(pd_flags, ESP_SLEEP_MODE_LIGHT_SLEEP, true);
|
2017-04-21 00:32:50 -04:00
|
|
|
|
2023-01-17 06:22:41 -05:00
|
|
|
#if SOC_CONFIGURABLE_VDDSDIO_SUPPORTED
|
2017-11-01 03:16:32 -04:00
|
|
|
// If VDDSDIO regulator was controlled by RTC registers before sleep,
|
|
|
|
// restore the configuration.
|
|
|
|
if (vddsdio_config.force) {
|
|
|
|
rtc_vddsdio_set_config(vddsdio_config);
|
|
|
|
}
|
2023-01-17 06:22:41 -05:00
|
|
|
#endif
|
2017-11-01 03:16:32 -04:00
|
|
|
|
2017-04-21 00:32:50 -04:00
|
|
|
// If SPI flash was powered down, wait for it to become ready
|
|
|
|
if (pd_flags & RTC_SLEEP_PD_VDDSDIO) {
|
2023-12-06 05:06:34 -05:00
|
|
|
#if SOC_PM_SUPPORT_TOP_PD
|
|
|
|
if (pd_flags & PMU_SLEEP_PD_TOP) {
|
|
|
|
uint32_t flash_ready_hw_waited_time_us = pmu_sleep_get_wakup_retention_cost();
|
|
|
|
uint32_t flash_ready_sw_waited_time_us = (esp_cpu_get_cycle_count() - s_config.ccount_ticks_record) / (esp_clk_cpu_freq() / MHZ);
|
|
|
|
uint32_t flash_ready_waited_time_us = flash_ready_hw_waited_time_us + flash_ready_sw_waited_time_us;
|
|
|
|
if (flash_enable_time_us > flash_ready_waited_time_us){
|
|
|
|
flash_enable_time_us -= flash_ready_waited_time_us;
|
|
|
|
} else {
|
|
|
|
flash_enable_time_us = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2017-04-21 00:32:50 -04:00
|
|
|
// Wait for the flash chip to start up
|
2020-07-21 01:07:34 -04:00
|
|
|
esp_rom_delay_us(flash_enable_time_us);
|
2017-04-21 00:32:50 -04:00
|
|
|
}
|
2022-10-09 02:53:59 -04:00
|
|
|
|
2023-08-03 22:47:51 -04:00
|
|
|
#if CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION
|
|
|
|
if (pd_flags & RTC_SLEEP_PD_VDDSDIO) {
|
|
|
|
/* Cache Resume 2: flash is ready now, we can resume the cache and access flash safely after */
|
|
|
|
resume_cache();
|
|
|
|
}
|
|
|
|
#endif
|
2023-06-28 01:34:52 -04:00
|
|
|
|
2023-06-19 07:32:34 -04:00
|
|
|
return reject;
|
2017-04-21 00:32:50 -04:00
|
|
|
}
|
|
|
|
|
2022-04-30 11:13:50 -04:00
|
|
|
/**
|
|
|
|
* vddsdio is used for power supply of spi flash
|
|
|
|
*
|
|
|
|
* pd flash via menuconfig | pd flash via `esp_sleep_pd_config` | result
|
|
|
|
* ---------------------------------------------------------------------------------------------------
|
|
|
|
* 0 | 0 | no pd flash
|
|
|
|
* x | 1 | pd flash with relaxed conditions(force_pd)
|
|
|
|
* 1 | 0 | pd flash with strict conditions(safe_pd)
|
|
|
|
*/
|
2023-06-25 05:12:43 -04:00
|
|
|
FORCE_INLINE_ATTR bool can_power_down_vddsdio(uint32_t pd_flags, const uint32_t vddsdio_pd_sleep_duration)
|
2022-04-25 23:27:40 -04:00
|
|
|
{
|
2022-04-30 11:13:50 -04:00
|
|
|
bool force_pd = !(s_config.wakeup_triggers & RTC_TIMER_TRIG_EN) || (s_config.sleep_duration > vddsdio_pd_sleep_duration);
|
|
|
|
bool safe_pd = (s_config.wakeup_triggers == RTC_TIMER_TRIG_EN) && (s_config.sleep_duration > vddsdio_pd_sleep_duration);
|
2023-01-30 03:37:20 -05:00
|
|
|
return (pd_flags & RTC_SLEEP_PD_VDDSDIO) ? force_pd : safe_pd;
|
2022-04-25 23:27:40 -04:00
|
|
|
}
|
|
|
|
|
2019-07-16 05:33:30 -04:00
|
|
|
esp_err_t esp_light_sleep_start(void)
|
2017-04-21 00:32:50 -04:00
|
|
|
{
|
2022-12-15 22:25:55 -05:00
|
|
|
s_config.ccount_ticks_record = esp_cpu_get_cycle_count();
|
2023-07-06 03:52:21 -04:00
|
|
|
esp_sleep_execute_event_callbacks(SLEEP_EVENT_SW_GOTO_SLEEP, (void *)0);
|
2022-07-07 02:54:15 -04:00
|
|
|
#if CONFIG_ESP_TASK_WDT_USE_ESP_TIMER
|
|
|
|
esp_err_t timerret = ESP_OK;
|
|
|
|
|
|
|
|
/* If a task watchdog timer is running, we have to stop it. */
|
|
|
|
timerret = esp_task_wdt_stop();
|
|
|
|
#endif // CONFIG_ESP_TASK_WDT_USE_ESP_TIMER
|
|
|
|
|
2022-12-15 22:25:55 -05:00
|
|
|
portENTER_CRITICAL(&s_config.lock);
|
2022-07-28 02:20:16 -04:00
|
|
|
/*
|
|
|
|
Note: We are about to stall the other CPU via the esp_ipc_isr_stall_other_cpu(). However, there is a chance of
|
|
|
|
deadlock if after stalling the other CPU, we attempt to take spinlocks already held by the other CPU that is.
|
|
|
|
|
|
|
|
Thus any functions that we call after stalling the other CPU will need to have the locks taken first to avoid
|
|
|
|
deadlock.
|
|
|
|
|
|
|
|
Todo: IDF-5257
|
|
|
|
*/
|
|
|
|
|
2022-06-14 02:49:26 -04:00
|
|
|
/* We will be calling esp_timer_private_set inside DPORT access critical
|
2018-05-04 00:50:39 -04:00
|
|
|
* section. Make sure the code on the other CPU is not holding esp_timer
|
|
|
|
* lock, otherwise there will be deadlock.
|
|
|
|
*/
|
2020-02-06 01:00:18 -05:00
|
|
|
esp_timer_private_lock();
|
2020-11-06 04:28:57 -05:00
|
|
|
|
2022-07-28 02:20:16 -04:00
|
|
|
/* We will be calling esp_rtc_get_time_us() below. Make sure the code on the other CPU is not holding the
|
|
|
|
* esp_rtc_get_time_us() lock, otherwise there will be deadlock. esp_rtc_get_time_us() is called via:
|
|
|
|
*
|
|
|
|
* - esp_clk_slowclk_cal_set() -> esp_rtc_get_time_us()
|
|
|
|
*/
|
|
|
|
esp_clk_private_lock();
|
|
|
|
|
2018-04-04 03:05:50 -04:00
|
|
|
s_config.rtc_ticks_at_sleep_start = rtc_time_get();
|
2022-07-21 07:24:42 -04:00
|
|
|
uint32_t ccount_at_sleep_start = esp_cpu_get_cycle_count();
|
2023-07-06 03:52:21 -04:00
|
|
|
esp_sleep_execute_event_callbacks(SLEEP_EVENT_HW_TIME_START, (void *)0);
|
2022-04-11 13:50:08 -04:00
|
|
|
uint64_t high_res_time_at_start = esp_timer_get_time();
|
2021-02-02 23:29:31 -05:00
|
|
|
uint32_t sleep_time_overhead_in = (ccount_at_sleep_start - s_config.ccount_ticks_record) / (esp_clk_cpu_freq() / 1000000ULL);
|
2023-10-08 04:48:00 -04:00
|
|
|
|
|
|
|
#if CONFIG_ESP_SLEEP_DEBUG
|
|
|
|
if (s_sleep_ctx != NULL) {
|
|
|
|
s_sleep_ctx->sleep_in_rtc_time_stamp = s_config.rtc_ticks_at_sleep_start;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2024-01-15 04:27:13 -05:00
|
|
|
#if !CONFIG_FREERTOS_UNICORE
|
2024-04-19 00:12:53 -04:00
|
|
|
#if ESP_SLEEP_POWER_DOWN_CPU && SOC_PM_CPU_RETENTION_BY_SW
|
2024-01-15 04:27:13 -05:00
|
|
|
sleep_smp_cpu_sleep_prepare();
|
|
|
|
#else
|
2021-08-03 02:35:29 -04:00
|
|
|
esp_ipc_isr_stall_other_cpu();
|
2024-01-15 04:27:13 -05:00
|
|
|
#endif
|
2024-04-08 02:19:00 -04:00
|
|
|
esp_ipc_isr_stall_pause();
|
2024-01-15 04:27:13 -05:00
|
|
|
#endif
|
2017-04-21 00:32:50 -04:00
|
|
|
|
2023-06-28 01:34:52 -04:00
|
|
|
#if CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION && CONFIG_PM_SLP_IRAM_OPT
|
|
|
|
/* Cache Suspend 0: if CONFIG_PM_SLP_IRAM_OPT is enabled, suspend cache here so that the access to flash
|
|
|
|
during the sleep process can be explicitly exposed. */
|
|
|
|
suspend_cache();
|
|
|
|
#endif
|
|
|
|
|
2017-04-21 00:32:50 -04:00
|
|
|
// Decide which power domains can be powered down
|
|
|
|
uint32_t pd_flags = get_power_down_flags();
|
|
|
|
|
2021-07-16 05:44:03 -04:00
|
|
|
#ifdef CONFIG_ESP_SLEEP_RTC_BUS_ISO_WORKAROUND
|
|
|
|
pd_flags &= ~RTC_SLEEP_PD_RTC_PERIPH;
|
|
|
|
#endif
|
|
|
|
|
2023-12-01 07:26:08 -05:00
|
|
|
// Re-calibrate the RTC clock
|
|
|
|
sleep_low_power_clock_calibration(false);
|
2020-11-06 04:28:57 -05:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Adjustment time consists of parts below:
|
2024-01-14 22:49:10 -05:00
|
|
|
* 1. Hardware time waiting for internal 8M oscillate clock and XTAL;
|
|
|
|
* 2. Hardware state switching time of the rtc main state machine;
|
2020-11-06 04:28:57 -05:00
|
|
|
* 3. Code execution time when clock is not stable;
|
|
|
|
* 4. Code execution time which can be measured;
|
|
|
|
*/
|
2023-01-31 07:11:25 -05:00
|
|
|
#if SOC_PMU_SUPPORTED
|
2023-01-30 03:37:20 -05:00
|
|
|
int sleep_time_sw_adjustment = LIGHT_SLEEP_TIME_OVERHEAD_US + sleep_time_overhead_in + s_config.sleep_time_overhead_out;
|
|
|
|
int sleep_time_hw_adjustment = pmu_sleep_calculate_hw_wait_time(pd_flags, s_config.rtc_clk_cal_period, s_config.fast_clk_cal_period);
|
|
|
|
s_config.sleep_time_adjustment = sleep_time_sw_adjustment + sleep_time_hw_adjustment;
|
|
|
|
#else
|
2020-11-06 04:28:57 -05:00
|
|
|
uint32_t rtc_cntl_xtl_buf_wait_slp_cycles = rtc_time_us_to_slowclk(RTC_CNTL_XTL_BUF_WAIT_SLP_US, s_config.rtc_clk_cal_period);
|
|
|
|
s_config.sleep_time_adjustment = LIGHT_SLEEP_TIME_OVERHEAD_US + sleep_time_overhead_in + s_config.sleep_time_overhead_out
|
2021-02-02 23:29:31 -05:00
|
|
|
+ rtc_time_slowclk_to_us(rtc_cntl_xtl_buf_wait_slp_cycles + RTC_CNTL_CK8M_WAIT_SLP_CYCLES + RTC_CNTL_WAKEUP_DELAY_CYCLES, s_config.rtc_clk_cal_period);
|
2023-01-30 03:37:20 -05:00
|
|
|
#endif
|
2018-04-04 03:05:50 -04:00
|
|
|
|
2017-10-18 08:04:40 -04:00
|
|
|
// Decide if VDD_SDIO needs to be powered down;
|
|
|
|
// If it needs to be powered down, adjust sleep time.
|
2023-12-06 07:37:28 -05:00
|
|
|
const uint32_t flash_enable_time_us = ESP_SLEEP_WAIT_FLASH_READY_DEFAULT_DELAY_US + CONFIG_ESP_SLEEP_WAIT_FLASH_READY_EXTRA_DELAY;
|
2017-04-21 00:32:50 -04:00
|
|
|
|
2021-02-23 21:53:24 -05:00
|
|
|
/**
|
|
|
|
* If VDD_SDIO power domain is requested to be turned off, bit `RTC_SLEEP_PD_VDDSDIO`
|
|
|
|
* will be set in `pd_flags`.
|
2020-11-06 04:28:57 -05:00
|
|
|
*/
|
2021-03-04 04:44:14 -05:00
|
|
|
if (pd_flags & RTC_SLEEP_PD_VDDSDIO) {
|
2021-02-23 21:53:24 -05:00
|
|
|
/*
|
|
|
|
* When VDD_SDIO power domain has to be turned off, the minimum sleep time of the
|
|
|
|
* system needs to meet the sum below:
|
|
|
|
* 1. Wait time for the flash power-on after waking up;
|
|
|
|
* 2. The execution time of codes between RTC Timer get start time
|
|
|
|
* with hardware starts to switch state to sleep;
|
|
|
|
* 3. The hardware state switching time of the rtc state machine during
|
|
|
|
* sleep and wake-up. This process requires 6 cycles to complete.
|
|
|
|
* The specific hardware state switching process and the cycles
|
|
|
|
* consumed are rtc_cpu_run_stall(1), cut_pll_rtl(2), cut_8m(1),
|
|
|
|
* min_protect(2);
|
|
|
|
* 4. All the adjustment time which is s_config.sleep_time_adjustment below.
|
|
|
|
*/
|
|
|
|
const uint32_t vddsdio_pd_sleep_duration = MAX(FLASH_PD_MIN_SLEEP_TIME_US,
|
|
|
|
flash_enable_time_us + LIGHT_SLEEP_MIN_TIME_US + s_config.sleep_time_adjustment
|
|
|
|
+ rtc_time_slowclk_to_us(RTC_MODULE_SLEEP_PREPARE_CYCLES, s_config.rtc_clk_cal_period));
|
|
|
|
|
2023-01-30 03:37:20 -05:00
|
|
|
if (can_power_down_vddsdio(pd_flags, vddsdio_pd_sleep_duration)) {
|
2021-02-23 21:53:24 -05:00
|
|
|
if (s_config.sleep_time_overhead_out < flash_enable_time_us) {
|
|
|
|
s_config.sleep_time_adjustment += flash_enable_time_us;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/**
|
|
|
|
* Minimum sleep time is not enough, then keep the VDD_SDIO power
|
|
|
|
* domain on.
|
|
|
|
*/
|
|
|
|
pd_flags &= ~RTC_SLEEP_PD_VDDSDIO;
|
|
|
|
if (s_config.sleep_time_overhead_out > flash_enable_time_us) {
|
|
|
|
s_config.sleep_time_adjustment -= flash_enable_time_us;
|
|
|
|
}
|
2020-11-06 04:28:57 -05:00
|
|
|
}
|
2017-04-21 00:32:50 -04:00
|
|
|
}
|
2018-04-04 03:05:50 -04:00
|
|
|
|
2020-12-30 03:42:39 -05:00
|
|
|
periph_inform_out_light_sleep_overhead(s_config.sleep_time_adjustment - sleep_time_overhead_in);
|
|
|
|
|
2017-04-21 00:32:50 -04:00
|
|
|
// Safety net: enable WDT in case exit from light sleep fails
|
2023-02-14 22:54:00 -05:00
|
|
|
wdt_hal_context_t rtc_wdt_ctx = RWDT_HAL_CONTEXT_DEFAULT();
|
2019-12-26 03:30:03 -05:00
|
|
|
bool wdt_was_enabled = wdt_hal_is_enabled(&rtc_wdt_ctx); // If WDT was enabled in the user code, then do not change it here.
|
2018-07-23 06:59:37 -04:00
|
|
|
if (!wdt_was_enabled) {
|
2019-12-26 03:30:03 -05:00
|
|
|
wdt_hal_init(&rtc_wdt_ctx, WDT_RWDT, 0, false);
|
|
|
|
uint32_t stage_timeout_ticks = (uint32_t)(1000ULL * rtc_clk_slow_freq_get_hz() / 1000ULL);
|
|
|
|
wdt_hal_write_protect_disable(&rtc_wdt_ctx);
|
|
|
|
wdt_hal_config_stage(&rtc_wdt_ctx, WDT_STAGE0, stage_timeout_ticks, WDT_STAGE_ACTION_RESET_RTC);
|
|
|
|
wdt_hal_enable(&rtc_wdt_ctx);
|
|
|
|
wdt_hal_write_protect_enable(&rtc_wdt_ctx);
|
2018-07-23 06:59:37 -04:00
|
|
|
}
|
2017-04-21 00:32:50 -04:00
|
|
|
|
2022-10-09 02:53:59 -04:00
|
|
|
esp_err_t err = ESP_OK;
|
|
|
|
int64_t final_sleep_duration_us = (int64_t)s_config.sleep_duration - (int64_t)s_config.sleep_time_adjustment;
|
|
|
|
int64_t min_sleep_duration_us = rtc_time_slowclk_to_us(RTC_CNTL_MIN_SLP_VAL_MIN, s_config.rtc_clk_cal_period);
|
2017-04-21 00:32:50 -04:00
|
|
|
|
2022-10-09 05:15:21 -04:00
|
|
|
// reset light sleep wakeup flag before a new light sleep
|
|
|
|
s_light_sleep_wakeup = false;
|
|
|
|
|
2023-10-08 04:48:00 -04:00
|
|
|
s_lightsleep_cnt++;
|
|
|
|
#if CONFIG_ESP_SLEEP_DEBUG
|
|
|
|
if (s_sleep_ctx != NULL) {
|
|
|
|
s_sleep_ctx->lightsleep_cnt = s_lightsleep_cnt;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2022-10-09 02:53:59 -04:00
|
|
|
// if rtc timer wakeup source is enabled, need to compare final sleep duration and min sleep duration to avoid late wakeup
|
|
|
|
if ((s_config.wakeup_triggers & RTC_TIMER_TRIG_EN) && (final_sleep_duration_us <= min_sleep_duration_us)) {
|
|
|
|
err = ESP_ERR_SLEEP_TOO_SHORT_SLEEP_DURATION;
|
|
|
|
} else {
|
|
|
|
// Enter sleep, then wait for flash to be ready on wakeup
|
2023-01-17 06:22:41 -05:00
|
|
|
err = esp_light_sleep_inner(pd_flags, flash_enable_time_us);
|
2022-10-09 02:53:59 -04:00
|
|
|
}
|
2024-04-19 00:12:53 -04:00
|
|
|
#if !CONFIG_FREERTOS_UNICORE && ESP_SLEEP_POWER_DOWN_CPU && SOC_PM_CPU_RETENTION_BY_SW
|
2024-01-15 04:27:13 -05:00
|
|
|
if (err != ESP_OK) {
|
|
|
|
esp_sleep_cpu_skip_retention();
|
|
|
|
}
|
|
|
|
#endif
|
2017-04-21 00:32:50 -04:00
|
|
|
|
2022-10-09 05:15:21 -04:00
|
|
|
// light sleep wakeup flag only makes sense after a successful light sleep
|
|
|
|
s_light_sleep_wakeup = (err == ESP_OK);
|
2018-09-04 00:56:47 -04:00
|
|
|
|
2022-06-14 02:49:26 -04:00
|
|
|
// System timer has been stopped for the duration of the sleep, correct for that.
|
2018-04-04 03:05:50 -04:00
|
|
|
uint64_t rtc_ticks_at_end = rtc_time_get();
|
2020-11-06 04:28:57 -05:00
|
|
|
uint64_t rtc_time_diff = rtc_time_slowclk_to_us(rtc_ticks_at_end - s_config.rtc_ticks_at_sleep_start, s_config.rtc_clk_cal_period);
|
2018-04-04 03:05:50 -04:00
|
|
|
|
2023-10-08 04:48:00 -04:00
|
|
|
#if CONFIG_ESP_SLEEP_DEBUG
|
|
|
|
if (s_sleep_ctx != NULL) {
|
|
|
|
s_sleep_ctx->sleep_out_rtc_time_stamp = rtc_ticks_at_end;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2022-06-14 02:49:26 -04:00
|
|
|
/**
|
|
|
|
* If sleep duration is too small(less than 1 rtc_slow_clk cycle), rtc_time_diff will be zero.
|
|
|
|
* In this case, just ignore the time compensation and keep esp_timer monotonic.
|
2018-04-04 03:05:50 -04:00
|
|
|
*/
|
2022-06-14 02:49:26 -04:00
|
|
|
if (rtc_time_diff > 0) {
|
|
|
|
esp_timer_private_set(high_res_time_at_start + rtc_time_diff);
|
2018-04-04 03:05:50 -04:00
|
|
|
}
|
|
|
|
esp_set_time_from_rtc();
|
2017-04-21 00:32:50 -04:00
|
|
|
|
2022-07-28 02:20:16 -04:00
|
|
|
esp_clk_private_unlock();
|
2020-02-06 01:00:18 -05:00
|
|
|
esp_timer_private_unlock();
|
2023-06-28 01:34:52 -04:00
|
|
|
|
|
|
|
#if CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION && CONFIG_PM_SLP_IRAM_OPT
|
|
|
|
/* Cache Resume 0: sleep process done, resume cache for continue running */
|
|
|
|
resume_cache();
|
|
|
|
#endif
|
|
|
|
|
2024-01-15 04:27:13 -05:00
|
|
|
#if !CONFIG_FREERTOS_UNICORE
|
2024-04-08 02:19:00 -04:00
|
|
|
esp_ipc_isr_stall_resume();
|
2024-04-19 00:12:53 -04:00
|
|
|
#if ESP_SLEEP_POWER_DOWN_CPU && SOC_PM_CPU_RETENTION_BY_SW
|
2024-01-15 04:27:13 -05:00
|
|
|
sleep_smp_cpu_wakeup_prepare();
|
|
|
|
#else
|
2021-08-03 02:35:29 -04:00
|
|
|
esp_ipc_isr_release_other_cpu();
|
2024-01-15 04:27:13 -05:00
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
2018-07-23 06:59:37 -04:00
|
|
|
if (!wdt_was_enabled) {
|
2019-12-26 03:30:03 -05:00
|
|
|
wdt_hal_write_protect_disable(&rtc_wdt_ctx);
|
|
|
|
wdt_hal_disable(&rtc_wdt_ctx);
|
|
|
|
wdt_hal_write_protect_enable(&rtc_wdt_ctx);
|
2018-07-23 06:59:37 -04:00
|
|
|
}
|
2022-07-07 02:54:15 -04:00
|
|
|
|
|
|
|
#if CONFIG_ESP_TASK_WDT_USE_ESP_TIMER
|
|
|
|
/* Restart the Task Watchdog timer as it was stopped before sleeping. */
|
|
|
|
if (timerret == ESP_OK) {
|
|
|
|
esp_task_wdt_restart();
|
|
|
|
}
|
|
|
|
#endif // CONFIG_ESP_TASK_WDT_USE_ESP_TIMER
|
|
|
|
|
2023-07-06 03:52:21 -04:00
|
|
|
esp_sleep_execute_event_callbacks(SLEEP_EVENT_SW_EXIT_SLEEP, (void *)0);
|
2022-12-15 22:25:55 -05:00
|
|
|
s_config.sleep_time_overhead_out = (esp_cpu_get_cycle_count() - s_config.ccount_ticks_record) / (esp_clk_cpu_freq() / 1000000ULL);
|
2023-10-08 04:48:00 -04:00
|
|
|
|
|
|
|
#if CONFIG_ESP_SLEEP_DEBUG
|
|
|
|
if (s_sleep_ctx != NULL) {
|
|
|
|
s_sleep_ctx->sleep_request_result = err;
|
|
|
|
}
|
|
|
|
#endif
|
2024-04-17 22:17:21 -04:00
|
|
|
|
|
|
|
portEXIT_CRITICAL(&s_config.lock);
|
2017-04-21 00:32:50 -04:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2018-03-16 02:57:35 -04:00
|
|
|
esp_err_t esp_sleep_disable_wakeup_source(esp_sleep_source_t source)
|
|
|
|
{
|
|
|
|
// For most of sources it is enough to set trigger mask in local
|
|
|
|
// configuration structure. The actual RTC wake up options
|
|
|
|
// will be updated by esp_sleep_start().
|
2018-08-13 20:43:35 -04:00
|
|
|
if (source == ESP_SLEEP_WAKEUP_ALL) {
|
|
|
|
s_config.wakeup_triggers = 0;
|
|
|
|
} else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_TIMER, RTC_TIMER_TRIG_EN)) {
|
2018-03-16 02:57:35 -04:00
|
|
|
s_config.wakeup_triggers &= ~RTC_TIMER_TRIG_EN;
|
|
|
|
s_config.sleep_duration = 0;
|
2023-02-17 07:30:51 -05:00
|
|
|
#if SOC_PM_SUPPORT_EXT0_WAKEUP
|
2018-08-13 20:42:03 -04:00
|
|
|
} else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_EXT0, RTC_EXT0_TRIG_EN)) {
|
2018-03-16 02:57:35 -04:00
|
|
|
s_config.ext0_rtc_gpio_num = 0;
|
|
|
|
s_config.ext0_trigger_level = 0;
|
|
|
|
s_config.wakeup_triggers &= ~RTC_EXT0_TRIG_EN;
|
2023-02-17 07:30:51 -05:00
|
|
|
#endif
|
|
|
|
#if SOC_PM_SUPPORT_EXT1_WAKEUP
|
2018-08-13 20:42:03 -04:00
|
|
|
} else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_EXT1, RTC_EXT1_TRIG_EN)) {
|
2018-03-16 02:57:35 -04:00
|
|
|
s_config.ext1_rtc_gpio_mask = 0;
|
|
|
|
s_config.ext1_trigger_mode = 0;
|
|
|
|
s_config.wakeup_triggers &= ~RTC_EXT1_TRIG_EN;
|
2021-01-12 06:10:21 -05:00
|
|
|
#endif
|
2021-06-22 09:53:16 -04:00
|
|
|
#if SOC_PM_SUPPORT_TOUCH_SENSOR_WAKEUP
|
2018-08-13 20:42:03 -04:00
|
|
|
} else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_TOUCHPAD, RTC_TOUCH_TRIG_EN)) {
|
2018-03-16 02:57:35 -04:00
|
|
|
s_config.wakeup_triggers &= ~RTC_TOUCH_TRIG_EN;
|
2021-01-12 06:10:21 -05:00
|
|
|
#endif
|
2018-08-13 20:42:03 -04:00
|
|
|
} else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_GPIO, RTC_GPIO_TRIG_EN)) {
|
|
|
|
s_config.wakeup_triggers &= ~RTC_GPIO_TRIG_EN;
|
|
|
|
} else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_UART, (RTC_UART0_TRIG_EN | RTC_UART1_TRIG_EN))) {
|
|
|
|
s_config.wakeup_triggers &= ~(RTC_UART0_TRIG_EN | RTC_UART1_TRIG_EN);
|
2018-03-16 02:57:35 -04:00
|
|
|
}
|
2023-03-09 01:14:09 -05:00
|
|
|
#if CONFIG_ULP_COPROC_TYPE_FSM
|
2018-03-20 02:43:48 -04:00
|
|
|
else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_ULP, RTC_ULP_TRIG_EN)) {
|
2018-03-16 02:57:35 -04:00
|
|
|
s_config.wakeup_triggers &= ~RTC_ULP_TRIG_EN;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
else {
|
|
|
|
ESP_LOGE(TAG, "Incorrect wakeup source (%d) to disable.", (int) source);
|
|
|
|
return ESP_ERR_INVALID_STATE;
|
|
|
|
}
|
|
|
|
return ESP_OK;
|
|
|
|
}
|
|
|
|
|
2019-07-16 05:33:30 -04:00
|
|
|
esp_err_t esp_sleep_enable_ulp_wakeup(void)
|
2016-12-08 09:22:10 -05:00
|
|
|
{
|
2022-01-21 04:13:48 -05:00
|
|
|
#ifndef CONFIG_ULP_COPROC_ENABLED
|
|
|
|
return ESP_ERR_INVALID_STATE;
|
|
|
|
#endif // CONFIG_ULP_COPROC_ENABLED
|
2020-04-27 02:01:30 -04:00
|
|
|
#if CONFIG_IDF_TARGET_ESP32
|
2022-03-02 02:49:31 -05:00
|
|
|
#if ((defined CONFIG_RTC_EXT_CRYST_ADDIT_CURRENT) || (defined CONFIG_RTC_EXT_CRYST_ADDIT_CURRENT_V2))
|
2020-09-18 05:23:28 -04:00
|
|
|
ESP_LOGE(TAG, "Failed to enable wakeup when provide current to external 32kHz crystal");
|
2018-12-22 01:19:46 -05:00
|
|
|
return ESP_ERR_NOT_SUPPORTED;
|
2020-09-18 05:23:28 -04:00
|
|
|
#endif
|
2021-02-02 23:29:31 -05:00
|
|
|
if (s_config.wakeup_triggers & RTC_EXT0_TRIG_EN) {
|
2017-01-27 10:36:52 -05:00
|
|
|
ESP_LOGE(TAG, "Conflicting wake-up trigger: ext0");
|
2017-01-24 02:53:59 -05:00
|
|
|
return ESP_ERR_INVALID_STATE;
|
|
|
|
}
|
2022-06-21 22:20:39 -04:00
|
|
|
#endif //CONFIG_IDF_TARGET_ESP32
|
|
|
|
|
|
|
|
#if CONFIG_ULP_COPROC_TYPE_FSM
|
2017-04-11 03:44:43 -04:00
|
|
|
s_config.wakeup_triggers |= RTC_ULP_TRIG_EN;
|
2016-12-08 09:22:10 -05:00
|
|
|
return ESP_OK;
|
2022-06-21 22:20:39 -04:00
|
|
|
#elif CONFIG_ULP_COPROC_TYPE_RISCV
|
|
|
|
s_config.wakeup_triggers |= (RTC_COCPU_TRIG_EN | RTC_COCPU_TRAP_TRIG_EN);
|
2020-04-27 02:01:30 -04:00
|
|
|
return ESP_OK;
|
2023-03-09 01:14:09 -05:00
|
|
|
#elif CONFIG_ULP_COPROC_TYPE_LP_CORE
|
|
|
|
s_config.wakeup_triggers |= RTC_LP_CORE_TRIG_EN;
|
|
|
|
return ESP_OK;
|
2021-01-12 06:10:21 -05:00
|
|
|
#else
|
|
|
|
return ESP_ERR_NOT_SUPPORTED;
|
2022-06-21 22:20:39 -04:00
|
|
|
#endif //CONFIG_ULP_COPROC_TYPE_FSM
|
2016-12-08 09:22:10 -05:00
|
|
|
}
|
|
|
|
|
2017-04-21 00:32:50 -04:00
|
|
|
esp_err_t esp_sleep_enable_timer_wakeup(uint64_t time_in_us)
|
2016-12-08 09:22:10 -05:00
|
|
|
{
|
2017-04-11 03:44:43 -04:00
|
|
|
s_config.wakeup_triggers |= RTC_TIMER_TRIG_EN;
|
2016-12-16 01:26:05 -05:00
|
|
|
s_config.sleep_duration = time_in_us;
|
2016-12-08 09:22:10 -05:00
|
|
|
return ESP_OK;
|
|
|
|
}
|
|
|
|
|
2023-06-02 06:44:25 -04:00
|
|
|
static esp_err_t timer_wakeup_prepare(int64_t sleep_duration)
|
2017-04-11 03:44:43 -04:00
|
|
|
{
|
2018-04-04 03:05:50 -04:00
|
|
|
if (sleep_duration < 0) {
|
|
|
|
sleep_duration = 0;
|
|
|
|
}
|
2020-04-23 00:39:07 -04:00
|
|
|
|
2020-11-06 04:28:57 -05:00
|
|
|
int64_t ticks = rtc_time_us_to_slowclk(sleep_duration, s_config.rtc_clk_cal_period);
|
2023-05-09 02:01:29 -04:00
|
|
|
int64_t target_wakeup_tick = s_config.rtc_ticks_at_sleep_start + ticks;
|
2023-01-31 07:11:25 -05:00
|
|
|
|
|
|
|
#if SOC_LP_TIMER_SUPPORTED
|
2023-05-09 02:01:29 -04:00
|
|
|
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
|
2023-05-29 02:59:22 -04:00
|
|
|
// Last timer wake-up validity check
|
2023-05-09 02:01:29 -04:00
|
|
|
if ((sleep_duration == 0) || \
|
2023-10-08 04:48:00 -04:00
|
|
|
(target_wakeup_tick < rtc_time_get() + SLEEP_TIMER_ALARM_TO_SLEEP_TICKS)) {
|
2023-05-09 02:01:29 -04:00
|
|
|
// Treat too short sleep duration setting as timer reject
|
|
|
|
return ESP_ERR_SLEEP_REJECT;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
lp_timer_hal_set_alarm_target(0, target_wakeup_tick);
|
2023-01-31 07:11:25 -05:00
|
|
|
#else
|
2023-05-09 02:01:29 -04:00
|
|
|
rtc_hal_set_wakeup_timer(target_wakeup_tick);
|
2022-12-28 23:58:02 -05:00
|
|
|
#endif
|
2023-05-29 02:59:22 -04:00
|
|
|
|
2023-05-09 02:01:29 -04:00
|
|
|
return ESP_OK;
|
2023-01-31 07:11:25 -05:00
|
|
|
}
|
2020-04-23 00:39:07 -04:00
|
|
|
|
2020-10-26 04:10:37 -04:00
|
|
|
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
2020-04-23 00:39:07 -04:00
|
|
|
/* In deep sleep mode, only the sleep channel is supported, and other touch channels should be turned off. */
|
|
|
|
static void touch_wakeup_prepare(void)
|
|
|
|
{
|
2021-02-02 23:29:31 -05:00
|
|
|
uint16_t sleep_cycle = 0;
|
|
|
|
uint16_t meas_times = 0;
|
2020-10-26 04:10:37 -04:00
|
|
|
touch_pad_t touch_num = TOUCH_PAD_NUM0;
|
|
|
|
touch_ll_sleep_get_channel_num(&touch_num); // Check if the sleep pad is enabled.
|
|
|
|
if ((touch_num > TOUCH_PAD_NUM0) && (touch_num < TOUCH_PAD_MAX) && touch_ll_get_fsm_state()) {
|
|
|
|
touch_ll_stop_fsm();
|
|
|
|
touch_ll_clear_channel_mask(TOUCH_PAD_BIT_MASK_ALL);
|
2021-01-29 08:01:38 -05:00
|
|
|
touch_ll_intr_clear(TOUCH_PAD_INTR_MASK_ALL); // Clear state from previous wakeup
|
2021-02-02 23:29:31 -05:00
|
|
|
touch_hal_sleep_channel_get_work_time(&sleep_cycle, &meas_times);
|
|
|
|
touch_ll_set_meas_times(meas_times);
|
|
|
|
touch_ll_set_sleep_time(sleep_cycle);
|
2020-10-26 04:10:37 -04:00
|
|
|
touch_ll_set_channel_mask(BIT(touch_num));
|
|
|
|
touch_ll_start_fsm();
|
|
|
|
}
|
2017-04-11 03:44:43 -04:00
|
|
|
}
|
2020-04-23 00:39:07 -04:00
|
|
|
#endif
|
2017-04-11 03:44:43 -04:00
|
|
|
|
2022-07-21 01:42:25 -04:00
|
|
|
#if SOC_TOUCH_SENSOR_SUPPORTED
|
2021-01-16 01:08:34 -05:00
|
|
|
|
2019-07-16 05:33:30 -04:00
|
|
|
esp_err_t esp_sleep_enable_touchpad_wakeup(void)
|
2017-01-23 23:32:30 -05:00
|
|
|
{
|
2022-08-25 00:27:28 -04:00
|
|
|
#if CONFIG_IDF_TARGET_ESP32
|
2022-03-02 02:49:31 -05:00
|
|
|
#if ((defined CONFIG_RTC_EXT_CRYST_ADDIT_CURRENT) || (defined CONFIG_RTC_EXT_CRYST_ADDIT_CURRENT_V2))
|
2020-09-18 05:23:28 -04:00
|
|
|
ESP_LOGE(TAG, "Failed to enable wakeup when provide current to external 32kHz crystal");
|
2018-12-22 01:19:46 -05:00
|
|
|
return ESP_ERR_NOT_SUPPORTED;
|
|
|
|
#endif
|
2017-04-11 03:44:43 -04:00
|
|
|
if (s_config.wakeup_triggers & (RTC_EXT0_TRIG_EN)) {
|
2017-01-27 10:36:52 -05:00
|
|
|
ESP_LOGE(TAG, "Conflicting wake-up trigger: ext0");
|
2017-01-24 02:53:59 -05:00
|
|
|
return ESP_ERR_INVALID_STATE;
|
|
|
|
}
|
2022-08-25 00:27:28 -04:00
|
|
|
#endif //CONFIG_IDF_TARGET_ESP32
|
|
|
|
|
2017-01-24 02:53:59 -05:00
|
|
|
s_config.wakeup_triggers |= RTC_TOUCH_TRIG_EN;
|
2017-01-23 23:32:30 -05:00
|
|
|
return ESP_OK;
|
|
|
|
}
|
|
|
|
|
2019-07-16 05:33:30 -04:00
|
|
|
touch_pad_t esp_sleep_get_touchpad_wakeup_status(void)
|
2017-01-27 10:48:00 -05:00
|
|
|
{
|
2017-04-21 00:32:50 -04:00
|
|
|
if (esp_sleep_get_wakeup_cause() != ESP_SLEEP_WAKEUP_TOUCHPAD) {
|
2017-01-27 10:48:00 -05:00
|
|
|
return TOUCH_PAD_MAX;
|
|
|
|
}
|
2018-07-05 02:37:37 -04:00
|
|
|
touch_pad_t pad_num;
|
2023-11-06 03:18:33 -05:00
|
|
|
touch_hal_get_wakeup_status(&pad_num);
|
|
|
|
return pad_num;
|
2017-01-27 10:48:00 -05:00
|
|
|
}
|
2021-01-16 01:08:34 -05:00
|
|
|
|
2022-07-21 01:42:25 -04:00
|
|
|
#endif // SOC_TOUCH_SENSOR_SUPPORTED
|
2017-01-27 10:48:00 -05:00
|
|
|
|
2020-11-23 01:09:16 -05:00
|
|
|
bool esp_sleep_is_valid_wakeup_gpio(gpio_num_t gpio_num)
|
|
|
|
{
|
2023-06-30 04:30:03 -04:00
|
|
|
#if SOC_RTCIO_PIN_COUNT > 0
|
2020-11-23 01:09:16 -05:00
|
|
|
return RTC_GPIO_IS_VALID_GPIO(gpio_num);
|
|
|
|
#else
|
2024-04-07 03:27:15 -04:00
|
|
|
#if !CONFIG_IDF_TARGET_ESP32C5_BETA3_VERSION // TODO: IDF-9673
|
2021-02-05 04:10:44 -05:00
|
|
|
return GPIO_IS_DEEP_SLEEP_WAKEUP_VALID_GPIO(gpio_num);
|
2024-04-07 03:27:15 -04:00
|
|
|
#else
|
|
|
|
return true;
|
|
|
|
#endif
|
2023-06-30 04:30:03 -04:00
|
|
|
#endif
|
2020-11-23 01:09:16 -05:00
|
|
|
}
|
|
|
|
|
2023-02-17 07:30:51 -05:00
|
|
|
#if SOC_PM_SUPPORT_EXT0_WAKEUP
|
2017-04-21 00:32:50 -04:00
|
|
|
esp_err_t esp_sleep_enable_ext0_wakeup(gpio_num_t gpio_num, int level)
|
2016-12-08 09:22:10 -05:00
|
|
|
{
|
|
|
|
if (level < 0 || level > 1) {
|
|
|
|
return ESP_ERR_INVALID_ARG;
|
|
|
|
}
|
2020-11-23 01:09:16 -05:00
|
|
|
if (!esp_sleep_is_valid_wakeup_gpio(gpio_num)) {
|
2016-12-08 09:22:10 -05:00
|
|
|
return ESP_ERR_INVALID_ARG;
|
|
|
|
}
|
2022-08-25 00:27:28 -04:00
|
|
|
#if CONFIG_IDF_TARGET_ESP32
|
2017-04-11 03:44:43 -04:00
|
|
|
if (s_config.wakeup_triggers & (RTC_TOUCH_TRIG_EN | RTC_ULP_TRIG_EN)) {
|
2017-01-27 10:36:52 -05:00
|
|
|
ESP_LOGE(TAG, "Conflicting wake-up triggers: touch / ULP");
|
2017-01-24 02:53:59 -05:00
|
|
|
return ESP_ERR_INVALID_STATE;
|
|
|
|
}
|
2022-08-25 00:27:28 -04:00
|
|
|
#endif //CONFIG_IDF_TARGET_ESP32
|
|
|
|
|
2019-07-25 11:11:31 -04:00
|
|
|
s_config.ext0_rtc_gpio_num = rtc_io_number_get(gpio_num);
|
2016-12-16 01:26:05 -05:00
|
|
|
s_config.ext0_trigger_level = level;
|
2017-04-11 03:44:43 -04:00
|
|
|
s_config.wakeup_triggers |= RTC_EXT0_TRIG_EN;
|
2016-12-08 09:22:10 -05:00
|
|
|
return ESP_OK;
|
|
|
|
}
|
|
|
|
|
2019-07-16 05:33:30 -04:00
|
|
|
static void ext0_wakeup_prepare(void)
|
2016-12-16 01:26:05 -05:00
|
|
|
{
|
|
|
|
int rtc_gpio_num = s_config.ext0_rtc_gpio_num;
|
2024-05-20 08:18:25 -04:00
|
|
|
#if SOC_LP_IO_CLOCK_IS_INDEPENDENT
|
|
|
|
io_mux_enable_lp_io_clock(rtc_gpio_num, true);
|
|
|
|
#endif
|
2020-04-27 02:01:30 -04:00
|
|
|
rtcio_hal_ext0_set_wakeup_pin(rtc_gpio_num, s_config.ext0_trigger_level);
|
2024-05-20 08:18:25 -04:00
|
|
|
rtcio_hal_function_select(rtc_gpio_num, RTCIO_LL_FUNC_RTC);
|
2020-04-27 02:01:30 -04:00
|
|
|
rtcio_hal_input_enable(rtc_gpio_num);
|
2016-12-16 01:26:05 -05:00
|
|
|
}
|
2023-11-17 03:53:19 -05:00
|
|
|
|
2023-02-17 07:30:51 -05:00
|
|
|
#endif // SOC_PM_SUPPORT_EXT0_WAKEUP
|
2016-12-16 01:26:05 -05:00
|
|
|
|
2023-02-17 07:30:51 -05:00
|
|
|
#if SOC_PM_SUPPORT_EXT1_WAKEUP
|
2023-07-13 02:06:10 -04:00
|
|
|
esp_err_t esp_sleep_enable_ext1_wakeup(uint64_t io_mask, esp_sleep_ext1_wakeup_mode_t level_mode)
|
2016-12-08 09:22:10 -05:00
|
|
|
{
|
2023-11-09 05:20:35 -05:00
|
|
|
if (io_mask == 0 && level_mode > ESP_EXT1_WAKEUP_ANY_HIGH) {
|
|
|
|
return ESP_ERR_INVALID_ARG;
|
|
|
|
}
|
|
|
|
// Reset all EXT1 configs
|
2023-11-20 06:30:50 -05:00
|
|
|
esp_sleep_disable_ext1_wakeup_io(0);
|
2023-11-09 05:20:35 -05:00
|
|
|
|
2023-11-20 01:27:54 -05:00
|
|
|
return esp_sleep_enable_ext1_wakeup_io(io_mask, level_mode);
|
2023-11-09 05:20:35 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-11-20 01:27:54 -05:00
|
|
|
esp_err_t esp_sleep_enable_ext1_wakeup_io(uint64_t io_mask, esp_sleep_ext1_wakeup_mode_t level_mode)
|
2023-11-09 05:20:35 -05:00
|
|
|
{
|
|
|
|
if (io_mask == 0 && level_mode > ESP_EXT1_WAKEUP_ANY_HIGH) {
|
2016-12-08 09:22:10 -05:00
|
|
|
return ESP_ERR_INVALID_ARG;
|
|
|
|
}
|
|
|
|
// Translate bit map of GPIO numbers into the bit map of RTC IO numbers
|
|
|
|
uint32_t rtc_gpio_mask = 0;
|
2023-07-13 02:06:10 -04:00
|
|
|
for (int gpio = 0; io_mask; ++gpio, io_mask >>= 1) {
|
|
|
|
if ((io_mask & 1) == 0) {
|
2016-12-08 09:22:10 -05:00
|
|
|
continue;
|
|
|
|
}
|
2020-11-23 01:09:16 -05:00
|
|
|
if (!esp_sleep_is_valid_wakeup_gpio(gpio)) {
|
2016-12-08 09:22:10 -05:00
|
|
|
ESP_LOGE(TAG, "Not an RTC IO: GPIO%d", gpio);
|
|
|
|
return ESP_ERR_INVALID_ARG;
|
|
|
|
}
|
2019-07-25 11:11:31 -04:00
|
|
|
rtc_gpio_mask |= BIT(rtc_io_number_get(gpio));
|
2016-12-16 01:26:05 -05:00
|
|
|
}
|
2023-11-09 05:20:35 -05:00
|
|
|
|
|
|
|
#if !SOC_PM_SUPPORT_EXT1_WAKEUP_MODE_PER_PIN
|
|
|
|
uint32_t ext1_rtc_gpio_mask = 0;
|
|
|
|
uint32_t ext1_trigger_mode = 0;
|
|
|
|
|
|
|
|
ext1_rtc_gpio_mask = s_config.ext1_rtc_gpio_mask | rtc_gpio_mask;
|
2023-07-13 02:06:10 -04:00
|
|
|
if (level_mode) {
|
2023-11-09 05:20:35 -05:00
|
|
|
ext1_trigger_mode = s_config.ext1_trigger_mode | rtc_gpio_mask;
|
2023-07-13 02:06:10 -04:00
|
|
|
} else {
|
2023-11-09 05:20:35 -05:00
|
|
|
ext1_trigger_mode = s_config.ext1_trigger_mode & (~rtc_gpio_mask);
|
|
|
|
}
|
|
|
|
if (((ext1_rtc_gpio_mask & ext1_trigger_mode) != ext1_rtc_gpio_mask) &&
|
|
|
|
((ext1_rtc_gpio_mask & ext1_trigger_mode) != 0)) {
|
|
|
|
return ESP_ERR_NOT_ALLOWED;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
s_config.ext1_rtc_gpio_mask |= rtc_gpio_mask;
|
|
|
|
if (level_mode) {
|
|
|
|
s_config.ext1_trigger_mode |= rtc_gpio_mask;
|
|
|
|
} else {
|
|
|
|
s_config.ext1_trigger_mode &= (~rtc_gpio_mask);
|
2023-07-13 02:06:10 -04:00
|
|
|
}
|
2017-04-11 03:44:43 -04:00
|
|
|
s_config.wakeup_triggers |= RTC_EXT1_TRIG_EN;
|
2016-12-16 01:26:05 -05:00
|
|
|
return ESP_OK;
|
|
|
|
}
|
|
|
|
|
2023-11-20 06:30:50 -05:00
|
|
|
esp_err_t esp_sleep_disable_ext1_wakeup_io(uint64_t io_mask)
|
2023-11-09 05:20:35 -05:00
|
|
|
{
|
|
|
|
if (io_mask == 0) {
|
|
|
|
s_config.ext1_rtc_gpio_mask = 0;
|
|
|
|
s_config.ext1_trigger_mode = 0;
|
|
|
|
} else {
|
|
|
|
// Translate bit map of GPIO numbers into the bit map of RTC IO numbers
|
|
|
|
uint32_t rtc_gpio_mask = 0;
|
|
|
|
for (int gpio = 0; io_mask; ++gpio, io_mask >>= 1) {
|
|
|
|
if ((io_mask & 1) == 0) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (!esp_sleep_is_valid_wakeup_gpio(gpio)) {
|
|
|
|
ESP_LOGE(TAG, "Not an RTC IO Considering io_mask: GPIO%d", gpio);
|
|
|
|
return ESP_ERR_INVALID_ARG;
|
|
|
|
}
|
|
|
|
rtc_gpio_mask |= BIT(rtc_io_number_get(gpio));
|
|
|
|
}
|
|
|
|
s_config.ext1_rtc_gpio_mask &= (~rtc_gpio_mask);
|
|
|
|
s_config.ext1_trigger_mode &= (~rtc_gpio_mask);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (s_config.ext1_rtc_gpio_mask == 0) {
|
|
|
|
s_config.wakeup_triggers &= (~RTC_EXT1_TRIG_EN);
|
|
|
|
}
|
|
|
|
return ESP_OK;
|
|
|
|
}
|
|
|
|
|
2023-07-13 02:06:10 -04:00
|
|
|
#if SOC_PM_SUPPORT_EXT1_WAKEUP_MODE_PER_PIN
|
|
|
|
esp_err_t esp_sleep_enable_ext1_wakeup_with_level_mask(uint64_t io_mask, uint64_t level_mask)
|
|
|
|
{
|
|
|
|
if ((level_mask & io_mask) != level_mask) {
|
|
|
|
return ESP_ERR_INVALID_ARG;
|
|
|
|
}
|
|
|
|
// Translate bit map of GPIO numbers into the bit map of RTC IO numbers
|
|
|
|
// Translate bit map of GPIO wakeup mode into the bit map of RTC IO wakeup mode
|
|
|
|
uint32_t rtc_gpio_mask = 0, rtc_gpio_wakeup_mode_mask = 0;
|
|
|
|
for (int gpio = 0; io_mask; ++gpio, io_mask >>= 1, level_mask >>= 1) {
|
|
|
|
if ((io_mask & 1) == 0) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (!esp_sleep_is_valid_wakeup_gpio(gpio)) {
|
|
|
|
ESP_LOGE(TAG, "Not an RTC IO Considering io_mask: GPIO%d", gpio);
|
|
|
|
return ESP_ERR_INVALID_ARG;
|
|
|
|
}
|
|
|
|
rtc_gpio_mask |= BIT(rtc_io_number_get(gpio));
|
|
|
|
if ((level_mask & 1) == 1) {
|
|
|
|
rtc_gpio_wakeup_mode_mask |= BIT(rtc_io_number_get(gpio));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
s_config.ext1_rtc_gpio_mask = rtc_gpio_mask;
|
|
|
|
s_config.ext1_trigger_mode = rtc_gpio_wakeup_mode_mask;
|
|
|
|
s_config.wakeup_triggers |= RTC_EXT1_TRIG_EN;
|
|
|
|
return ESP_OK;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2019-07-16 05:33:30 -04:00
|
|
|
static void ext1_wakeup_prepare(void)
|
2016-12-16 01:26:05 -05:00
|
|
|
{
|
|
|
|
// Configure all RTC IOs selected as ext1 wakeup inputs
|
|
|
|
uint32_t rtc_gpio_mask = s_config.ext1_rtc_gpio_mask;
|
|
|
|
for (int gpio = 0; gpio < GPIO_PIN_COUNT && rtc_gpio_mask != 0; ++gpio) {
|
2019-07-25 11:11:31 -04:00
|
|
|
int rtc_pin = rtc_io_number_get(gpio);
|
2016-12-16 01:26:05 -05:00
|
|
|
if ((rtc_gpio_mask & BIT(rtc_pin)) == 0) {
|
|
|
|
continue;
|
|
|
|
}
|
2024-05-20 08:18:25 -04:00
|
|
|
#if SOC_LP_IO_CLOCK_IS_INDEPENDENT
|
|
|
|
io_mux_enable_lp_io_clock(rtc_pin, true);
|
|
|
|
#endif
|
2020-11-26 03:56:13 -05:00
|
|
|
#if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
|
2016-12-16 01:26:05 -05:00
|
|
|
// Route pad to RTC
|
2024-05-20 08:18:25 -04:00
|
|
|
rtcio_hal_function_select(rtc_pin, RTCIO_LL_FUNC_RTC);
|
sleep: make sure input enable is set for EXT0/EXT1 wakeup
Since commit 94250e4, EXT0 wakeup mechanism, when wakeup level was set
to 0, started waking up chip immediately after entering deep sleep.
This failure was triggered in that commit by a change of
RTC_CNTL_MIN_SLP_VAL (i.e. minimum time in sleep mode until wakeup
can happen) from 128 cycles to 2 cycles.
The reason for this behaviour is related to the way input enable (IE)
signal going into an RTC pad is obtained:
PAD_IE = (SLP_SEL) ? SLP_IE & CHIP_SLEEP : IE,
where SLP_IE, SLP_SEL, and IE are bits of an RTC_IO register related
to the given pad. CHIP_SLEEP is the signal indicating that chip has
entered sleep mode.
The code in prepare_ext{0,1}_wakeup did not enable IE, but did enable
SLP_SEL and SLP_IE. This meant that until CHIP_SLEEP went high, PAD_IE
was 0, hence the input from the pad read 0 even if external signal
was 1. CHIP_SLEEP went high on the 2nd cycle of sleep. So when
RTC_CNTL_MIN_SLP_VAL was set to 2, the input signal from the pad was
latched as 0 at the moment when CHIP_SLEEP went high, causing EXT0
wakeup with level 0 to trigger.
This commit changes the way PAD_IE is enabled: SLP_SEL and SLP_IE are
no longer used, and IE is set to 1. If EXT0 wakeup is used, RTC_IO is
not powered down, so IE signal stays 1 both before CHIP_SLEEP goes
high and after. If EXT1 wakeup is used, RTC_IO may be powered down.
However prepare_ext1_wakeup enables Hold on the pad, locking states
of all the control signals, including IE.
Closes https://github.com/espressif/esp-idf/issues/1931
Closes https://github.com/espressif/esp-idf/issues/2043
2018-06-12 08:23:26 -04:00
|
|
|
// set input enable in sleep mode
|
2020-04-27 02:01:30 -04:00
|
|
|
rtcio_hal_input_enable(rtc_pin);
|
2023-07-11 05:15:59 -04:00
|
|
|
#if SOC_PM_SUPPORT_RTC_PERIPH_PD
|
|
|
|
// Pad configuration depends on RTC_PERIPH state in sleep mode
|
|
|
|
if (s_config.domain[ESP_PD_DOMAIN_RTC_PERIPH].pd_option != ESP_PD_OPTION_ON) {
|
|
|
|
rtcio_hal_hold_enable(rtc_pin);
|
|
|
|
}
|
|
|
|
#endif
|
2023-07-03 09:25:56 -04:00
|
|
|
#else
|
|
|
|
/* ESP32H2 use hp iomux to config rtcio, and there is no complete
|
|
|
|
* rtcio functionality. In the case of EXT1 wakeup, rtcio only provides
|
|
|
|
* a pathway to EXT1. */
|
2020-04-27 02:01:30 -04:00
|
|
|
|
2023-07-03 09:25:56 -04:00
|
|
|
// Route pad to DIGITAL
|
2024-05-20 08:18:25 -04:00
|
|
|
rtcio_hal_function_select(rtc_pin, RTCIO_LL_FUNC_DIGITAL);
|
2023-07-03 09:25:56 -04:00
|
|
|
// set input enable
|
|
|
|
gpio_ll_input_enable(&GPIO, gpio);
|
|
|
|
// hold rtc_pin to use it during sleep state
|
|
|
|
rtcio_hal_hold_enable(rtc_pin);
|
2021-12-20 02:09:07 -05:00
|
|
|
#endif
|
2016-12-16 01:26:05 -05:00
|
|
|
// Keep track of pins which are processed to bail out early
|
|
|
|
rtc_gpio_mask &= ~BIT(rtc_pin);
|
2016-12-08 09:22:10 -05:00
|
|
|
}
|
2020-04-27 02:01:30 -04:00
|
|
|
|
2016-12-16 01:26:05 -05:00
|
|
|
// Clear state from previous wakeup
|
2022-10-27 03:09:34 -04:00
|
|
|
rtc_hal_ext1_clear_wakeup_status();
|
2023-07-18 07:33:30 -04:00
|
|
|
// Set RTC IO pins and mode to be used for wakeup
|
2020-04-27 02:01:30 -04:00
|
|
|
rtc_hal_ext1_set_wakeup_pins(s_config.ext1_rtc_gpio_mask, s_config.ext1_trigger_mode);
|
2016-12-08 09:22:10 -05:00
|
|
|
}
|
|
|
|
|
2019-07-16 05:33:30 -04:00
|
|
|
uint64_t esp_sleep_get_ext1_wakeup_status(void)
|
2016-12-08 09:22:10 -05:00
|
|
|
{
|
2017-04-21 00:32:50 -04:00
|
|
|
if (esp_sleep_get_wakeup_cause() != ESP_SLEEP_WAKEUP_EXT1) {
|
2016-12-08 09:22:10 -05:00
|
|
|
return 0;
|
|
|
|
}
|
2022-10-27 03:09:34 -04:00
|
|
|
uint32_t status = rtc_hal_ext1_get_wakeup_status();
|
2016-12-08 09:22:10 -05:00
|
|
|
// Translate bit map of RTC IO numbers into the bit map of GPIO numbers
|
|
|
|
uint64_t gpio_mask = 0;
|
2016-12-16 01:26:05 -05:00
|
|
|
for (int gpio = 0; gpio < GPIO_PIN_COUNT; ++gpio) {
|
2020-11-23 01:09:16 -05:00
|
|
|
if (!esp_sleep_is_valid_wakeup_gpio(gpio)) {
|
2016-12-08 09:22:10 -05:00
|
|
|
continue;
|
|
|
|
}
|
2019-07-25 11:11:31 -04:00
|
|
|
int rtc_pin = rtc_io_number_get(gpio);
|
2016-12-08 09:22:10 -05:00
|
|
|
if ((status & BIT(rtc_pin)) == 0) {
|
|
|
|
continue;
|
|
|
|
}
|
2017-08-18 03:27:54 -04:00
|
|
|
gpio_mask |= 1ULL << gpio;
|
2016-12-08 09:22:10 -05:00
|
|
|
}
|
|
|
|
return gpio_mask;
|
|
|
|
}
|
2021-01-16 01:08:34 -05:00
|
|
|
|
2023-02-18 01:13:52 -05:00
|
|
|
#endif // SOC_PM_SUPPORT_EXT1_WAKEUP
|
2016-12-14 01:20:01 -05:00
|
|
|
|
2021-02-05 04:10:44 -05:00
|
|
|
#if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP
|
|
|
|
uint64_t esp_sleep_get_gpio_wakeup_status(void)
|
|
|
|
{
|
|
|
|
if (esp_sleep_get_wakeup_cause() != ESP_SLEEP_WAKEUP_GPIO) {
|
|
|
|
return 0;
|
|
|
|
}
|
2022-10-27 03:09:34 -04:00
|
|
|
return rtc_hal_gpio_get_wakeup_status();
|
2021-02-05 04:10:44 -05:00
|
|
|
}
|
|
|
|
|
2022-10-27 03:09:34 -04:00
|
|
|
static void gpio_deep_sleep_wakeup_prepare(void)
|
2021-02-05 04:10:44 -05:00
|
|
|
{
|
|
|
|
for (gpio_num_t gpio_idx = GPIO_NUM_0; gpio_idx < GPIO_NUM_MAX; gpio_idx++) {
|
|
|
|
if (((1ULL << gpio_idx) & s_config.gpio_wakeup_mask) == 0) {
|
|
|
|
continue;
|
|
|
|
}
|
2023-09-14 03:42:35 -04:00
|
|
|
#if CONFIG_ESP_SLEEP_GPIO_ENABLE_INTERNAL_RESISTORS
|
2021-02-05 04:10:44 -05:00
|
|
|
if (s_config.gpio_trigger_mode & BIT(gpio_idx)) {
|
|
|
|
ESP_ERROR_CHECK(gpio_pullup_dis(gpio_idx));
|
|
|
|
ESP_ERROR_CHECK(gpio_pulldown_en(gpio_idx));
|
|
|
|
} else {
|
|
|
|
ESP_ERROR_CHECK(gpio_pullup_en(gpio_idx));
|
|
|
|
ESP_ERROR_CHECK(gpio_pulldown_dis(gpio_idx));
|
|
|
|
}
|
2023-09-14 03:42:35 -04:00
|
|
|
#endif
|
2021-02-05 04:10:44 -05:00
|
|
|
ESP_ERROR_CHECK(gpio_hold_en(gpio_idx));
|
|
|
|
}
|
2022-10-27 03:09:34 -04:00
|
|
|
// Clear state from previous wakeup
|
|
|
|
rtc_hal_gpio_clear_wakeup_status();
|
2023-01-31 07:11:25 -05:00
|
|
|
}
|
2021-02-05 04:10:44 -05:00
|
|
|
|
|
|
|
esp_err_t esp_deep_sleep_enable_gpio_wakeup(uint64_t gpio_pin_mask, esp_deepsleep_gpio_wake_up_mode_t mode)
|
|
|
|
{
|
|
|
|
if (mode > ESP_GPIO_WAKEUP_GPIO_HIGH) {
|
|
|
|
ESP_LOGE(TAG, "invalid mode");
|
|
|
|
return ESP_ERR_INVALID_ARG;
|
|
|
|
}
|
|
|
|
gpio_int_type_t intr_type = ((mode == ESP_GPIO_WAKEUP_GPIO_LOW) ? GPIO_INTR_LOW_LEVEL : GPIO_INTR_HIGH_LEVEL);
|
|
|
|
esp_err_t err = ESP_OK;
|
|
|
|
for (gpio_num_t gpio_idx = GPIO_NUM_0; gpio_idx < GPIO_NUM_MAX; gpio_idx++, gpio_pin_mask >>= 1) {
|
|
|
|
if ((gpio_pin_mask & 1) == 0) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (!esp_sleep_is_valid_wakeup_gpio(gpio_idx)) {
|
2022-10-27 03:09:34 -04:00
|
|
|
ESP_LOGE(TAG, "gpio %d is an invalid deep sleep wakeup IO", gpio_idx);
|
2021-02-05 04:10:44 -05:00
|
|
|
return ESP_ERR_INVALID_ARG;
|
|
|
|
}
|
|
|
|
err = gpio_deep_sleep_wakeup_enable(gpio_idx, intr_type);
|
2021-02-12 00:01:05 -05:00
|
|
|
|
2021-02-05 04:10:44 -05:00
|
|
|
s_config.gpio_wakeup_mask |= BIT(gpio_idx);
|
|
|
|
if (mode == ESP_GPIO_WAKEUP_GPIO_HIGH) {
|
|
|
|
s_config.gpio_trigger_mode |= (mode << gpio_idx);
|
|
|
|
} else {
|
|
|
|
s_config.gpio_trigger_mode &= ~(mode << gpio_idx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
s_config.wakeup_triggers |= RTC_GPIO_TRIG_EN;
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif //SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP
|
|
|
|
|
2019-07-16 05:33:30 -04:00
|
|
|
esp_err_t esp_sleep_enable_gpio_wakeup(void)
|
2018-08-13 20:42:03 -04:00
|
|
|
{
|
2020-11-26 03:56:13 -05:00
|
|
|
#if CONFIG_IDF_TARGET_ESP32
|
2018-08-13 20:42:03 -04:00
|
|
|
if (s_config.wakeup_triggers & (RTC_TOUCH_TRIG_EN | RTC_ULP_TRIG_EN)) {
|
|
|
|
ESP_LOGE(TAG, "Conflicting wake-up triggers: touch / ULP");
|
|
|
|
return ESP_ERR_INVALID_STATE;
|
|
|
|
}
|
2020-11-26 03:56:13 -05:00
|
|
|
#endif
|
2018-08-13 20:42:03 -04:00
|
|
|
s_config.wakeup_triggers |= RTC_GPIO_TRIG_EN;
|
|
|
|
return ESP_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
esp_err_t esp_sleep_enable_uart_wakeup(int uart_num)
|
|
|
|
{
|
|
|
|
if (uart_num == UART_NUM_0) {
|
|
|
|
s_config.wakeup_triggers |= RTC_UART0_TRIG_EN;
|
|
|
|
} else if (uart_num == UART_NUM_1) {
|
|
|
|
s_config.wakeup_triggers |= RTC_UART1_TRIG_EN;
|
|
|
|
} else {
|
|
|
|
return ESP_ERR_INVALID_ARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ESP_OK;
|
|
|
|
}
|
|
|
|
|
2020-04-23 00:39:07 -04:00
|
|
|
esp_err_t esp_sleep_enable_wifi_wakeup(void)
|
|
|
|
{
|
2021-01-12 06:10:21 -05:00
|
|
|
#if SOC_PM_SUPPORT_WIFI_WAKEUP
|
2020-04-23 00:39:07 -04:00
|
|
|
s_config.wakeup_triggers |= RTC_WIFI_TRIG_EN;
|
|
|
|
return ESP_OK;
|
2021-01-12 06:10:21 -05:00
|
|
|
#else
|
|
|
|
return ESP_ERR_NOT_SUPPORTED;
|
2020-04-23 00:39:07 -04:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2021-04-21 03:17:16 -04:00
|
|
|
esp_err_t esp_sleep_disable_wifi_wakeup(void)
|
|
|
|
{
|
|
|
|
#if SOC_PM_SUPPORT_WIFI_WAKEUP
|
|
|
|
s_config.wakeup_triggers &= (~RTC_WIFI_TRIG_EN);
|
|
|
|
return ESP_OK;
|
|
|
|
#else
|
|
|
|
return ESP_ERR_NOT_SUPPORTED;
|
|
|
|
#endif
|
|
|
|
}
|
2020-04-23 00:39:07 -04:00
|
|
|
|
2022-03-13 23:33:01 -04:00
|
|
|
esp_err_t esp_sleep_enable_wifi_beacon_wakeup(void)
|
|
|
|
{
|
|
|
|
#if SOC_PM_SUPPORT_BEACON_WAKEUP
|
|
|
|
s_config.wakeup_triggers |= PMU_WIFI_BEACON_WAKEUP_EN;
|
|
|
|
return ESP_OK;
|
|
|
|
#else
|
|
|
|
return ESP_ERR_NOT_SUPPORTED;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
esp_err_t esp_sleep_disable_wifi_beacon_wakeup(void)
|
|
|
|
{
|
|
|
|
#if SOC_PM_SUPPORT_BEACON_WAKEUP
|
|
|
|
s_config.wakeup_triggers &= (~PMU_WIFI_BEACON_WAKEUP_EN);
|
|
|
|
return ESP_OK;
|
|
|
|
#else
|
|
|
|
return ESP_ERR_NOT_SUPPORTED;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2022-01-12 22:02:16 -05:00
|
|
|
esp_err_t esp_sleep_enable_bt_wakeup(void)
|
|
|
|
{
|
|
|
|
#if SOC_PM_SUPPORT_BT_WAKEUP
|
|
|
|
s_config.wakeup_triggers |= RTC_BT_TRIG_EN;
|
|
|
|
return ESP_OK;
|
|
|
|
#else
|
|
|
|
return ESP_ERR_NOT_SUPPORTED;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
esp_err_t esp_sleep_disable_bt_wakeup(void)
|
|
|
|
{
|
|
|
|
#if SOC_PM_SUPPORT_BT_WAKEUP
|
|
|
|
s_config.wakeup_triggers &= (~RTC_BT_TRIG_EN);
|
|
|
|
return ESP_OK;
|
|
|
|
#else
|
|
|
|
return ESP_ERR_NOT_SUPPORTED;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2019-07-16 05:33:30 -04:00
|
|
|
esp_sleep_wakeup_cause_t esp_sleep_get_wakeup_cause(void)
|
2017-01-27 10:48:00 -05:00
|
|
|
{
|
2021-07-12 22:45:06 -04:00
|
|
|
if (esp_rom_get_reset_reason(0) != RESET_REASON_CORE_DEEP_SLEEP && !s_light_sleep_wakeup) {
|
2017-04-21 00:32:50 -04:00
|
|
|
return ESP_SLEEP_WAKEUP_UNDEFINED;
|
2017-01-27 10:48:00 -05:00
|
|
|
}
|
|
|
|
|
2023-01-28 04:36:45 -05:00
|
|
|
#if SOC_PMU_SUPPORTED
|
2023-01-31 07:11:25 -05:00
|
|
|
uint32_t wakeup_cause = pmu_ll_hp_get_wakeup_cause(&PMU);
|
|
|
|
#else
|
2023-01-03 07:29:08 -05:00
|
|
|
uint32_t wakeup_cause = rtc_cntl_ll_get_wakeup_cause();
|
2023-01-31 07:11:25 -05:00
|
|
|
#endif
|
2020-04-23 00:39:07 -04:00
|
|
|
|
2021-01-12 06:10:21 -05:00
|
|
|
if (wakeup_cause & RTC_TIMER_TRIG_EN) {
|
|
|
|
return ESP_SLEEP_WAKEUP_TIMER;
|
|
|
|
} else if (wakeup_cause & RTC_GPIO_TRIG_EN) {
|
|
|
|
return ESP_SLEEP_WAKEUP_GPIO;
|
|
|
|
} else if (wakeup_cause & (RTC_UART0_TRIG_EN | RTC_UART1_TRIG_EN)) {
|
|
|
|
return ESP_SLEEP_WAKEUP_UART;
|
2023-02-17 07:30:51 -05:00
|
|
|
#if SOC_PM_SUPPORT_EXT0_WAKEUP
|
2021-01-12 06:10:21 -05:00
|
|
|
} else if (wakeup_cause & RTC_EXT0_TRIG_EN) {
|
2017-04-21 00:32:50 -04:00
|
|
|
return ESP_SLEEP_WAKEUP_EXT0;
|
2023-02-17 07:30:51 -05:00
|
|
|
#endif
|
|
|
|
#if SOC_PM_SUPPORT_EXT1_WAKEUP
|
2017-04-11 03:44:43 -04:00
|
|
|
} else if (wakeup_cause & RTC_EXT1_TRIG_EN) {
|
2017-04-21 00:32:50 -04:00
|
|
|
return ESP_SLEEP_WAKEUP_EXT1;
|
2021-01-12 06:10:21 -05:00
|
|
|
#endif
|
2021-06-22 09:53:16 -04:00
|
|
|
#if SOC_PM_SUPPORT_TOUCH_SENSOR_WAKEUP
|
2017-04-11 03:44:43 -04:00
|
|
|
} else if (wakeup_cause & RTC_TOUCH_TRIG_EN) {
|
2017-04-21 00:32:50 -04:00
|
|
|
return ESP_SLEEP_WAKEUP_TOUCHPAD;
|
2021-01-12 06:10:21 -05:00
|
|
|
#endif
|
2023-03-09 01:14:09 -05:00
|
|
|
#if SOC_ULP_FSM_SUPPORTED
|
2017-04-11 03:44:43 -04:00
|
|
|
} else if (wakeup_cause & RTC_ULP_TRIG_EN) {
|
2017-04-21 00:32:50 -04:00
|
|
|
return ESP_SLEEP_WAKEUP_ULP;
|
2020-11-26 03:56:13 -05:00
|
|
|
#endif
|
2021-01-12 06:10:21 -05:00
|
|
|
#if SOC_PM_SUPPORT_WIFI_WAKEUP
|
2020-04-23 00:39:07 -04:00
|
|
|
} else if (wakeup_cause & RTC_WIFI_TRIG_EN) {
|
|
|
|
return ESP_SLEEP_WAKEUP_WIFI;
|
2021-01-12 06:10:21 -05:00
|
|
|
#endif
|
|
|
|
#if SOC_PM_SUPPORT_BT_WAKEUP
|
|
|
|
} else if (wakeup_cause & RTC_BT_TRIG_EN) {
|
|
|
|
return ESP_SLEEP_WAKEUP_BT;
|
|
|
|
#endif
|
2021-12-23 01:12:47 -05:00
|
|
|
#if SOC_RISCV_COPROC_SUPPORTED
|
2020-04-23 00:39:07 -04:00
|
|
|
} else if (wakeup_cause & RTC_COCPU_TRIG_EN) {
|
|
|
|
return ESP_SLEEP_WAKEUP_ULP;
|
|
|
|
} else if (wakeup_cause & RTC_COCPU_TRAP_TRIG_EN) {
|
|
|
|
return ESP_SLEEP_WAKEUP_COCPU_TRAP_TRIG;
|
2023-03-09 01:14:09 -05:00
|
|
|
#endif
|
|
|
|
#if SOC_LP_CORE_SUPPORTED
|
|
|
|
} else if (wakeup_cause & RTC_LP_CORE_TRIG_EN) {
|
|
|
|
return ESP_SLEEP_WAKEUP_ULP;
|
2020-04-23 00:39:07 -04:00
|
|
|
#endif
|
2017-01-27 10:48:00 -05:00
|
|
|
} else {
|
2017-04-21 00:32:50 -04:00
|
|
|
return ESP_SLEEP_WAKEUP_UNDEFINED;
|
2017-01-27 10:48:00 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-15 22:25:55 -05:00
|
|
|
esp_err_t esp_sleep_pd_config(esp_sleep_pd_domain_t domain, esp_sleep_pd_option_t option)
|
2016-12-14 01:20:01 -05:00
|
|
|
{
|
|
|
|
if (domain >= ESP_PD_DOMAIN_MAX || option > ESP_PD_OPTION_AUTO) {
|
|
|
|
return ESP_ERR_INVALID_ARG;
|
|
|
|
}
|
2022-12-15 22:25:55 -05:00
|
|
|
portENTER_CRITICAL_SAFE(&s_config.lock);
|
2023-05-22 02:17:02 -04:00
|
|
|
|
2022-12-15 22:25:55 -05:00
|
|
|
int refs = (option == ESP_PD_OPTION_ON) ? s_config.domain[domain].refs++ \
|
|
|
|
: (option == ESP_PD_OPTION_OFF) ? --s_config.domain[domain].refs \
|
|
|
|
: s_config.domain[domain].refs;
|
|
|
|
if (refs == 0) {
|
|
|
|
s_config.domain[domain].pd_option = option;
|
|
|
|
}
|
|
|
|
portEXIT_CRITICAL_SAFE(&s_config.lock);
|
|
|
|
assert(refs >= 0);
|
2016-12-14 01:20:01 -05:00
|
|
|
return ESP_OK;
|
|
|
|
}
|
|
|
|
|
2023-06-08 05:26:18 -04:00
|
|
|
/**
|
|
|
|
* The modules in the CPU and modem power domains still depend on the top power domain.
|
|
|
|
* To be safe, the CPU and Modem power domains must also be powered off and saved when
|
2023-07-04 00:10:50 -04:00
|
|
|
* the TOP is powered off. If not power down XTAL, power down TOP is meaningless, and
|
|
|
|
* the XTAL clock control of some chips(esp32c6/esp32h2) depends on the top domain.
|
2023-06-08 05:26:18 -04:00
|
|
|
*/
|
|
|
|
#if SOC_PM_SUPPORT_TOP_PD
|
2023-06-25 05:12:43 -04:00
|
|
|
FORCE_INLINE_ATTR bool top_domain_pd_allowed(void) {
|
2024-01-14 22:49:10 -05:00
|
|
|
bool top_pd_allowed = true;
|
2024-04-19 00:12:53 -04:00
|
|
|
#if ESP_SLEEP_POWER_DOWN_CPU
|
2024-01-14 22:49:10 -05:00
|
|
|
top_pd_allowed &= cpu_domain_pd_allowed();
|
|
|
|
#else
|
|
|
|
top_pd_allowed = false;
|
|
|
|
#endif
|
|
|
|
top_pd_allowed &= clock_domain_pd_allowed();
|
|
|
|
top_pd_allowed &= peripheral_domain_pd_allowed();
|
|
|
|
#if SOC_PM_SUPPORT_MODEM_PD
|
|
|
|
top_pd_allowed &= modem_domain_pd_allowed();
|
|
|
|
#endif
|
|
|
|
top_pd_allowed &= (s_config.domain[ESP_PD_DOMAIN_XTAL].pd_option != ESP_PD_OPTION_ON);
|
|
|
|
|
|
|
|
return top_pd_allowed;
|
2023-06-08 05:26:18 -04:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2019-07-16 05:33:30 -04:00
|
|
|
static uint32_t get_power_down_flags(void)
|
2016-12-14 01:20:01 -05:00
|
|
|
{
|
|
|
|
// Where needed, convert AUTO options to ON. Later interpret AUTO as OFF.
|
|
|
|
|
2017-01-11 04:23:23 -05:00
|
|
|
// RTC_SLOW_MEM is needed for the ULP, so keep RTC_SLOW_MEM powered up if ULP
|
|
|
|
// is used and RTC_SLOW_MEM is Auto.
|
|
|
|
// If there is any data placed into .rtc.data or .rtc.bss segments, and
|
|
|
|
// RTC_SLOW_MEM is Auto, keep it powered up as well.
|
|
|
|
|
2022-01-12 02:04:59 -05:00
|
|
|
#if SOC_PM_SUPPORT_RTC_SLOW_MEM_PD && SOC_ULP_SUPPORTED
|
2020-04-23 00:39:07 -04:00
|
|
|
// Labels are defined in the linker script
|
2023-03-31 12:41:40 -04:00
|
|
|
extern int _rtc_slow_length, _rtc_reserved_length;
|
2022-04-24 11:13:48 -04:00
|
|
|
/**
|
|
|
|
* Compiler considers "(size_t) &_rtc_slow_length > 0" to always be true.
|
|
|
|
* So use a volatile variable to prevent compiler from doing this optimization.
|
|
|
|
*/
|
2023-03-31 12:41:40 -04:00
|
|
|
volatile size_t rtc_slow_mem_used = (size_t)&_rtc_slow_length + (size_t)&_rtc_reserved_length;
|
2017-01-11 04:23:23 -05:00
|
|
|
|
2022-12-15 22:25:55 -05:00
|
|
|
if ((s_config.domain[ESP_PD_DOMAIN_RTC_SLOW_MEM].pd_option == ESP_PD_OPTION_AUTO) &&
|
2022-04-24 11:13:48 -04:00
|
|
|
(rtc_slow_mem_used > 0 || (s_config.wakeup_triggers & RTC_ULP_TRIG_EN))) {
|
2022-12-15 22:25:55 -05:00
|
|
|
s_config.domain[ESP_PD_DOMAIN_RTC_SLOW_MEM].pd_option = ESP_PD_OPTION_ON;
|
2016-12-14 01:20:01 -05:00
|
|
|
}
|
2020-11-26 03:56:13 -05:00
|
|
|
#endif
|
2016-12-14 01:20:01 -05:00
|
|
|
|
2022-01-12 02:04:59 -05:00
|
|
|
#if SOC_PM_SUPPORT_RTC_FAST_MEM_PD
|
2020-12-21 00:26:00 -05:00
|
|
|
#if !CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP
|
2020-12-10 01:45:41 -05:00
|
|
|
/* RTC_FAST_MEM is needed for deep sleep stub.
|
|
|
|
If RTC_FAST_MEM is Auto, keep it powered on, so that deep sleep stub can run.
|
|
|
|
In the new chip revision, deep sleep stub will be optional, and this can be changed. */
|
2022-12-15 22:25:55 -05:00
|
|
|
if (s_config.domain[ESP_PD_DOMAIN_RTC_FAST_MEM].pd_option == ESP_PD_OPTION_AUTO) {
|
|
|
|
s_config.domain[ESP_PD_DOMAIN_RTC_FAST_MEM].pd_option = ESP_PD_OPTION_ON;
|
2016-12-14 01:20:01 -05:00
|
|
|
}
|
2020-12-10 01:45:41 -05:00
|
|
|
#else
|
|
|
|
/* If RTC_FAST_MEM is used for heap, force RTC_FAST_MEM to be powered on. */
|
2022-12-15 22:25:55 -05:00
|
|
|
s_config.domain[ESP_PD_DOMAIN_RTC_FAST_MEM].pd_option = ESP_PD_OPTION_ON;
|
2020-12-10 01:45:41 -05:00
|
|
|
#endif
|
2021-12-20 02:09:07 -05:00
|
|
|
#endif
|
2016-12-14 01:20:01 -05:00
|
|
|
|
2021-12-20 02:09:07 -05:00
|
|
|
#if SOC_PM_SUPPORT_RTC_PERIPH_PD
|
2018-08-13 20:42:03 -04:00
|
|
|
// RTC_PERIPH is needed for EXT0 wakeup and GPIO wakeup.
|
2022-08-25 00:27:28 -04:00
|
|
|
// If RTC_PERIPH is left auto (EXT0/GPIO aren't enabled), RTC_PERIPH will be powered off by default.
|
2022-12-15 22:25:55 -05:00
|
|
|
if (s_config.domain[ESP_PD_DOMAIN_RTC_PERIPH].pd_option == ESP_PD_OPTION_AUTO) {
|
2018-08-13 20:42:03 -04:00
|
|
|
if (s_config.wakeup_triggers & (RTC_EXT0_TRIG_EN | RTC_GPIO_TRIG_EN)) {
|
2022-12-15 22:25:55 -05:00
|
|
|
s_config.domain[ESP_PD_DOMAIN_RTC_PERIPH].pd_option = ESP_PD_OPTION_ON;
|
2016-12-14 01:20:01 -05:00
|
|
|
}
|
2022-08-25 00:27:28 -04:00
|
|
|
#if CONFIG_IDF_TARGET_ESP32
|
|
|
|
else if (s_config.wakeup_triggers & (RTC_TOUCH_TRIG_EN | RTC_ULP_TRIG_EN)) {
|
|
|
|
// On ESP32, forcing power up of RTC_PERIPH
|
|
|
|
// prevents ULP timer and touch FSMs from working correctly.
|
2022-12-15 22:25:55 -05:00
|
|
|
s_config.domain[ESP_PD_DOMAIN_RTC_PERIPH].pd_option = ESP_PD_OPTION_OFF;
|
2020-12-29 02:39:52 -05:00
|
|
|
}
|
2023-04-26 01:58:19 -04:00
|
|
|
#endif //CONFIG_IDF_TARGET_ESP32
|
|
|
|
#if SOC_LP_CORE_SUPPORTED
|
|
|
|
else if (s_config.wakeup_triggers & RTC_LP_CORE_TRIG_EN) {
|
|
|
|
// Need to keep RTC_PERIPH on to allow lp core to wakeup during sleep (e.g. from lp timer)
|
|
|
|
s_config.domain[ESP_PD_DOMAIN_RTC_PERIPH].pd_option = ESP_PD_OPTION_ON;
|
|
|
|
}
|
2022-08-25 00:27:28 -04:00
|
|
|
#endif //CONFIG_IDF_TARGET_ESP32
|
2016-12-14 01:20:01 -05:00
|
|
|
}
|
2021-12-20 02:09:07 -05:00
|
|
|
#endif // SOC_PM_SUPPORT_RTC_PERIPH_PD
|
2016-12-14 01:20:01 -05:00
|
|
|
|
2023-01-30 03:37:20 -05:00
|
|
|
/**
|
|
|
|
* VDD_SDIO power domain shall be kept on during the light sleep
|
|
|
|
* when CONFIG_ESP_SLEEP_POWER_DOWN_FLASH is not set and off when it is set.
|
|
|
|
* The application can still force the power domain to remain on by calling
|
|
|
|
* `esp_sleep_pd_config` before getting into light sleep mode.
|
|
|
|
*
|
|
|
|
* In deep sleep mode, the power domain will be turned off, regardless the
|
|
|
|
* value of this field.
|
|
|
|
*/
|
|
|
|
#if SOC_PM_SUPPORT_VDDSDIO_PD
|
2022-12-15 22:25:55 -05:00
|
|
|
if (s_config.domain[ESP_PD_DOMAIN_VDDSDIO].pd_option == ESP_PD_OPTION_AUTO) {
|
2023-01-30 03:37:20 -05:00
|
|
|
#ifndef CONFIG_ESP_SLEEP_POWER_DOWN_FLASH
|
2022-12-15 22:25:55 -05:00
|
|
|
s_config.domain[ESP_PD_DOMAIN_VDDSDIO].pd_option = ESP_PD_OPTION_ON;
|
2023-01-30 03:37:20 -05:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif
|
2020-12-24 08:02:32 -05:00
|
|
|
|
2021-09-06 02:17:43 -04:00
|
|
|
#ifdef CONFIG_IDF_TARGET_ESP32
|
2022-12-15 22:25:55 -05:00
|
|
|
s_config.domain[ESP_PD_DOMAIN_XTAL].pd_option = ESP_PD_OPTION_OFF;
|
2021-09-06 02:17:43 -04:00
|
|
|
#endif
|
2018-04-04 03:05:50 -04:00
|
|
|
|
2016-12-14 01:20:01 -05:00
|
|
|
// Prepare flags based on the selected options
|
2017-04-21 00:32:50 -04:00
|
|
|
uint32_t pd_flags = 0;
|
2022-01-12 02:04:59 -05:00
|
|
|
#if SOC_PM_SUPPORT_RTC_FAST_MEM_PD
|
2022-12-15 22:25:55 -05:00
|
|
|
if (s_config.domain[ESP_PD_DOMAIN_RTC_FAST_MEM].pd_option != ESP_PD_OPTION_ON) {
|
2017-04-11 03:44:43 -04:00
|
|
|
pd_flags |= RTC_SLEEP_PD_RTC_FAST_MEM;
|
2016-12-14 01:20:01 -05:00
|
|
|
}
|
2021-12-20 02:09:07 -05:00
|
|
|
#endif
|
2022-01-12 02:04:59 -05:00
|
|
|
#if SOC_PM_SUPPORT_RTC_SLOW_MEM_PD
|
2022-12-15 22:25:55 -05:00
|
|
|
if (s_config.domain[ESP_PD_DOMAIN_RTC_SLOW_MEM].pd_option != ESP_PD_OPTION_ON) {
|
2017-04-11 03:44:43 -04:00
|
|
|
pd_flags |= RTC_SLEEP_PD_RTC_SLOW_MEM;
|
2016-12-14 01:20:01 -05:00
|
|
|
}
|
2020-11-26 03:56:13 -05:00
|
|
|
#endif
|
2021-12-20 02:09:07 -05:00
|
|
|
#if SOC_PM_SUPPORT_RTC_PERIPH_PD
|
2022-12-15 22:25:55 -05:00
|
|
|
if (s_config.domain[ESP_PD_DOMAIN_RTC_PERIPH].pd_option != ESP_PD_OPTION_ON) {
|
2017-04-11 03:44:43 -04:00
|
|
|
pd_flags |= RTC_SLEEP_PD_RTC_PERIPH;
|
2016-12-14 01:20:01 -05:00
|
|
|
}
|
2021-12-20 02:09:07 -05:00
|
|
|
#endif
|
2020-04-23 00:39:07 -04:00
|
|
|
|
2024-04-19 00:12:53 -04:00
|
|
|
#if SOC_PM_SUPPORT_CPU_PD && ESP_SLEEP_POWER_DOWN_CPU
|
2023-06-08 05:26:18 -04:00
|
|
|
if ((s_config.domain[ESP_PD_DOMAIN_CPU].pd_option != ESP_PD_OPTION_ON) && cpu_domain_pd_allowed()) {
|
2020-12-24 08:02:32 -05:00
|
|
|
pd_flags |= RTC_SLEEP_PD_CPU;
|
|
|
|
}
|
|
|
|
#endif
|
2023-01-30 03:37:20 -05:00
|
|
|
#if SOC_PM_SUPPORT_XTAL32K_PD
|
2022-12-15 22:25:55 -05:00
|
|
|
if (s_config.domain[ESP_PD_DOMAIN_XTAL32K].pd_option != ESP_PD_OPTION_ON) {
|
2023-01-30 03:37:20 -05:00
|
|
|
pd_flags |= PMU_SLEEP_PD_XTAL32K;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#if SOC_PM_SUPPORT_RC32K_PD
|
2022-12-15 22:25:55 -05:00
|
|
|
if (s_config.domain[ESP_PD_DOMAIN_RC32K].pd_option != ESP_PD_OPTION_ON) {
|
2023-01-30 03:37:20 -05:00
|
|
|
pd_flags |= PMU_SLEEP_PD_RC32K;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#if SOC_PM_SUPPORT_RC_FAST_PD
|
2022-12-15 22:25:55 -05:00
|
|
|
if (s_config.domain[ESP_PD_DOMAIN_RC_FAST].pd_option != ESP_PD_OPTION_ON) {
|
2021-08-26 22:38:55 -04:00
|
|
|
pd_flags |= RTC_SLEEP_PD_INT_8M;
|
|
|
|
}
|
2023-01-30 03:37:20 -05:00
|
|
|
#endif
|
2022-12-15 22:25:55 -05:00
|
|
|
if (s_config.domain[ESP_PD_DOMAIN_XTAL].pd_option != ESP_PD_OPTION_ON) {
|
2021-09-06 02:17:43 -04:00
|
|
|
pd_flags |= RTC_SLEEP_PD_XTAL;
|
|
|
|
}
|
2023-02-01 08:34:36 -05:00
|
|
|
#if SOC_PM_SUPPORT_TOP_PD
|
2023-06-08 05:26:18 -04:00
|
|
|
if ((s_config.domain[ESP_PD_DOMAIN_TOP].pd_option != ESP_PD_OPTION_ON) && top_domain_pd_allowed()) {
|
2023-02-01 08:34:36 -05:00
|
|
|
pd_flags |= PMU_SLEEP_PD_TOP;
|
|
|
|
}
|
|
|
|
#endif
|
2022-02-07 21:53:11 -05:00
|
|
|
|
|
|
|
#if SOC_PM_SUPPORT_MODEM_PD
|
2023-11-30 06:26:41 -05:00
|
|
|
if ((s_config.domain[ESP_PD_DOMAIN_MODEM].pd_option != ESP_PD_OPTION_ON) && modem_domain_pd_allowed()
|
|
|
|
#if SOC_PM_MODEM_RETENTION_BY_REGDMA
|
|
|
|
&& clock_domain_pd_allowed()
|
|
|
|
#endif
|
|
|
|
) {
|
2022-09-21 05:19:27 -04:00
|
|
|
pd_flags |= RTC_SLEEP_PD_MODEM;
|
2022-02-07 21:53:11 -05:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2023-01-30 03:37:20 -05:00
|
|
|
#if SOC_PM_SUPPORT_VDDSDIO_PD
|
2022-12-15 22:25:55 -05:00
|
|
|
if (s_config.domain[ESP_PD_DOMAIN_VDDSDIO].pd_option != ESP_PD_OPTION_ON) {
|
2021-02-23 21:53:24 -05:00
|
|
|
pd_flags |= RTC_SLEEP_PD_VDDSDIO;
|
|
|
|
}
|
2023-01-30 03:37:20 -05:00
|
|
|
#endif
|
2021-02-23 21:53:24 -05:00
|
|
|
|
2021-12-20 02:09:07 -05:00
|
|
|
#if ((defined CONFIG_RTC_CLK_SRC_EXT_CRYS) && (defined CONFIG_RTC_EXT_CRYST_ADDIT_CURRENT) && (SOC_PM_SUPPORT_RTC_PERIPH_PD))
|
2018-12-22 01:19:46 -05:00
|
|
|
if ((s_config.wakeup_triggers & (RTC_TOUCH_TRIG_EN | RTC_ULP_TRIG_EN)) == 0) {
|
2021-02-02 23:29:31 -05:00
|
|
|
// If enabled EXT1 only and enable the additional current by touch, should be keep RTC_PERIPH power on.
|
2020-05-10 04:18:50 -04:00
|
|
|
pd_flags &= ~RTC_SLEEP_PD_RTC_PERIPH;
|
2018-12-22 01:19:46 -05:00
|
|
|
}
|
2020-04-23 00:39:07 -04:00
|
|
|
#endif
|
|
|
|
|
2016-12-14 01:20:01 -05:00
|
|
|
return pd_flags;
|
|
|
|
}
|
2018-09-04 04:03:18 -04:00
|
|
|
|
2023-03-09 03:34:01 -05:00
|
|
|
#if CONFIG_IDF_TARGET_ESP32
|
|
|
|
/* APP core of esp32 can't access to RTC FAST MEMORY, do not define it with RTC_IRAM_ATTR */
|
|
|
|
void
|
|
|
|
#else
|
|
|
|
void RTC_IRAM_ATTR
|
|
|
|
#endif
|
|
|
|
esp_deep_sleep_disable_rom_logging(void)
|
2018-09-04 04:03:18 -04:00
|
|
|
{
|
2021-01-26 23:07:05 -05:00
|
|
|
rtc_suppress_rom_log();
|
2018-09-04 04:03:18 -04:00
|
|
|
}
|
2022-05-04 15:19:35 -04:00
|
|
|
|
2022-02-28 05:12:28 -05:00
|
|
|
void esp_sleep_enable_adc_tsens_monitor(bool enable)
|
2022-05-04 15:19:35 -04:00
|
|
|
{
|
|
|
|
s_adc_tsen_enabled = enable;
|
|
|
|
}
|
|
|
|
|
|
|
|
void rtc_sleep_enable_ultra_low(bool enable)
|
|
|
|
{
|
|
|
|
s_ultra_low_enabled = enable;
|
|
|
|
}
|