Merge branch 'feature/bringup_esp32c6_deepsleep_support_master' into 'master'

esp32c6: bringup deepsleep examples

Closes IDF-6051, IDF-6052, IDF-5349, IDF-5924, and WIFI-5352

See merge request espressif/esp-idf!22300
This commit is contained in:
Wu Zheng Hui 2023-03-03 23:53:10 +08:00
commit 2066977b48
56 changed files with 642 additions and 275 deletions

View File

@ -22,6 +22,10 @@
#include "hal/gpio_hal.h"
#include "esp_rom_gpio.h"
#if (SOC_RTCIO_PIN_COUNT > 0)
#include "hal/rtc_io_hal.h"
#endif
static const char *GPIO_TAG = "gpio";
#define GPIO_CHECK(a, str, ret_val) ESP_RETURN_ON_FALSE(a, ret_val, GPIO_TAG, "%s", str)
@ -730,6 +734,7 @@ esp_err_t gpio_hold_dis(gpio_num_t gpio_num)
return ret;
}
#if !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
void gpio_deep_sleep_hold_en(void)
{
portENTER_CRITICAL(&gpio_context.gpio_spinlock);
@ -743,9 +748,9 @@ void gpio_deep_sleep_hold_dis(void)
gpio_hal_deep_sleep_hold_dis(gpio_context.gpio_hal);
portEXIT_CRITICAL(&gpio_context.gpio_spinlock);
}
#endif //!SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
#if SOC_GPIO_SUPPORT_FORCE_HOLD
esp_err_t IRAM_ATTR gpio_force_hold_all()
{
#if SOC_RTCIO_HOLD_SUPPORTED
@ -767,7 +772,7 @@ esp_err_t IRAM_ATTR gpio_force_unhold_all()
#endif
return ESP_OK;
}
#endif
#endif //SOC_GPIO_SUPPORT_FORCE_HOLD
void gpio_iomux_in(uint32_t gpio, uint32_t signal_idx)
{

View File

@ -374,10 +374,9 @@ esp_err_t gpio_get_drive_capability(gpio_num_t gpio_num, gpio_drive_cap_t *stren
* in output mode: the output level of the GPIO will be locked and can not be changed.
* in input mode: the input read value can still reflect the changes of the input signal.
*
* However, this function cannot be used to hold the state of a digital GPIO during Deep-sleep. Even if this
* function is enabled, the digital GPIO will be reset to its default state when the chip wakes up from
* Deep-sleep. If you want to hold the state of a digital GPIO during Deep-sleep, please call
* `gpio_deep_sleep_hold_en`.
* However, on ESP32/S2/C3/S3/C2, this function cannot be used to hold the state of a digital GPIO during Deep-sleep.
* Even if this function is enabled, the digital GPIO will be reset to its default state when the chip wakes up from
* Deep-sleep. If you want to hold the state of a digital GPIO during Deep-sleep, please call `gpio_deep_sleep_hold_en`.
*
* Power down or call `gpio_hold_dis` will disable this function.
*
@ -408,6 +407,7 @@ esp_err_t gpio_hold_en(gpio_num_t gpio_num);
*/
esp_err_t gpio_hold_dis(gpio_num_t gpio_num);
#if !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
/**
* @brief Enable all digital gpio pads hold function during Deep-sleep.
*
@ -426,6 +426,7 @@ void gpio_deep_sleep_hold_en(void);
* @brief Disable all digital gpio pads hold function during Deep-sleep.
*/
void gpio_deep_sleep_hold_dis(void);
#endif //!SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
/**
* @brief Set pad input to a peripheral signal through the IOMUX.

View File

@ -326,10 +326,9 @@ TEST_CASE("RTCIO_output_hold_test", "[rtcio]")
ESP_LOGI(TAG, "RTCIO hold test over");
}
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C6) // TODO: IDF-5349 Remove when deep sleep is supported on ESP32C6
// It is not necessary to test every rtcio pin, it will take too much ci testing time for deep sleep
// Only tests on s_test_map[TEST_RTCIO_DEEP_SLEEP_PIN_INDEX] pin
// (ESP32: IO25, ESP32S2, S3: IO6) these pads' default configuration is low level
// (ESP32: IO25, ESP32S2, S3: IO6, C6: IO5) these pads' default configuration is low level
#define TEST_RTCIO_DEEP_SLEEP_PIN_INDEX 5
static void rtcio_deep_sleep_hold_test_first_stage(void)
@ -375,5 +374,4 @@ static void rtcio_deep_sleep_hold_test_second_stage(void)
TEST_CASE_MULTIPLE_STAGES("RTCIO_deep_sleep_output_hold_test", "[rtcio]",
rtcio_deep_sleep_hold_test_first_stage,
rtcio_deep_sleep_hold_test_second_stage)
#endif // !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C6, ESP32H2)
#endif // #if SOC_RTCIO_HOLD_SUPPORTED
#endif //SOC_RTCIO_HOLD_SUPPORTED

View File

@ -110,6 +110,7 @@ if(NOT BOOTLOADER_BUILD)
"sleep_cpu.c" # TODO: IDF-6267
"sleep_modes.c" # TODO: IDF-6267
"sleep_wake_stub.c" # TODO: IDF-6267
"sleep_gpio.c" # TODO: IDF-6267
)
endif()
else()

View File

@ -37,6 +37,14 @@ extern "C" {
#define RTC_SLEEP_USE_ADC_TESEN_MONITOR BIT(17)
#define RTC_SLEEP_NO_ULTRA_LOW BIT(18) //!< Avoid using ultra low power in deep sleep, in which RTCIO cannot be used as input, and RTCMEM can't work under high temperature
#if SOC_PM_SUPPORT_EXT0_WAKEUP
#define RTC_EXT0_TRIG_EN PMU_EXT0_WAKEUP_EN //!< EXT0 wakeup
#else
#define RTC_EXT0_TRIG_EN 0
#endif
#if SOC_PM_SUPPORT_EXT1_WAKEUP
#define RTC_EXT1_TRIG_EN PMU_EXT1_WAKEUP_EN //!< EXT1 wakeup
#endif
#define RTC_GPIO_TRIG_EN PMU_GPIO_WAKEUP_EN //!< GPIO wakeup
#define RTC_TIMER_TRIG_EN PMU_LP_TIMER_WAKEUP_EN //!< Timer wakeup
#define RTC_WIFI_TRIG_EN PMU_WIFI_SOC_WAKEUP_EN //!< WIFI wakeup (light sleep only)
@ -60,6 +68,12 @@ extern "C" {
RTC_USB_TRIG_EN | \
RTC_BROWNOUT_DET_TRIG_EN)
#if SOC_PM_SUPPORT_EXT0_WAKEUP
#define PMU_EXT0_WAKEUP_EN BIT(0)
#endif
#if SOC_PM_SUPPORT_EXT1_WAKEUP
#define PMU_EXT1_WAKEUP_EN BIT(1)
#endif
#define PMU_GPIO_WAKEUP_EN BIT(2)
#define PMU_WIFI_BEACON_WAKEUP_EN BIT(3)
@ -82,6 +96,7 @@ extern "C" {
#define PMU_SLEEP_PD_MEM_G1 BIT(7)
#define PMU_SLEEP_PD_MEM_G2 BIT(8)
#define PMU_SLEEP_PD_MEM_G3 BIT(9)
#define PMU_SLEEP_PD_MEM (PMU_SLEEP_PD_MEM_G0|PMU_SLEEP_PD_MEM_G1|PMU_SLEEP_PD_MEM_G2|PMU_SLEEP_PD_MEM_G3)
#define PMU_SLEEP_PD_XTAL BIT(10)
#define PMU_SLEEP_PD_RC_FAST BIT(11)
#define PMU_SLEEP_PD_XTAL32K BIT(12)

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -21,8 +21,7 @@ extern "C" {
*/
void esp_sleep_enable_adc_tsens_monitor(bool enable);
// TODO: IDF-6051, IDF-6052
#if !CONFIG_IDF_TARGET_ESP32H4 && !CONFIG_IDF_TARGET_ESP32C6
#if !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
/**
* @brief Isolate all digital IOs except those that are held during deep sleep
*

View File

@ -193,8 +193,7 @@ touch_pad_t esp_sleep_get_touchpad_wakeup_status(void);
*/
bool esp_sleep_is_valid_wakeup_gpio(gpio_num_t gpio_num);
#if SOC_PM_SUPPORT_EXT_WAKEUP
#if SOC_PM_SUPPORT_EXT0_WAKEUP
/**
* @brief Enable wakeup using a pin
*
@ -223,7 +222,9 @@ bool esp_sleep_is_valid_wakeup_gpio(gpio_num_t gpio_num);
* - ESP_ERR_INVALID_STATE if wakeup triggers conflict
*/
esp_err_t esp_sleep_enable_ext0_wakeup(gpio_num_t gpio_num, int level);
#endif // SOC_PM_SUPPORT_EXT0_WAKEUP
#if SOC_PM_SUPPORT_EXT1_WAKEUP
/**
* @brief Enable wakeup using multiple pins
*
@ -249,6 +250,7 @@ esp_err_t esp_sleep_enable_ext0_wakeup(gpio_num_t gpio_num, int level);
* - ESP32: 0, 2, 4, 12-15, 25-27, 32-39;
* - ESP32-S2: 0-21;
* - ESP32-S3: 0-21.
* - ESP32-C6: 0-7.
* @param mode select logic function used to determine wakeup condition:
* - ESP_EXT1_WAKEUP_ALL_LOW: wake up when all selected GPIOs are low
* - ESP_EXT1_WAKEUP_ANY_HIGH: wake up when any of the selected GPIOs is high
@ -259,7 +261,7 @@ esp_err_t esp_sleep_enable_ext0_wakeup(gpio_num_t gpio_num, int level);
*/
esp_err_t esp_sleep_enable_ext1_wakeup(uint64_t mask, esp_sleep_ext1_wakeup_mode_t mode);
#endif // SOC_PM_SUPPORT_EXT_WAKEUP
#endif // SOC_PM_SUPPORT_EXT1_WAKEUP
#if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP
/**
@ -475,6 +477,11 @@ typedef void (*esp_deep_sleep_wake_stub_fn_t)(void);
*/
void esp_set_deep_sleep_wake_stub(esp_deep_sleep_wake_stub_fn_t new_stub);
/**
* @brief Set wake stub entry to default `esp_wake_stub_entry`
*/
void esp_set_deep_sleep_wake_stub_default_entry(void);
/**
* @brief Get current wake from deep sleep stub
* @return Return current wake from deep sleep stub, or NULL if

View File

@ -14,6 +14,7 @@
#include "soc/soc.h"
#include "soc/rtc.h"
#include "soc/pmu_struct.h"
#include "hal/lp_aon_hal.h"
#include "esp_private/esp_pmu.h"
#define HP(state) (PMU_MODE_HP_ ## state)
@ -152,11 +153,9 @@ const pmu_sleep_config_t* pmu_sleep_config_default(
config->digital = digital_default;
pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(pd_flags);
if (!(pd_flags & PMU_SLEEP_PD_MODEM)){
analog_default.hp_sys.analog.slp_logic_dbias += 2;
}
if (!(pd_flags & PMU_SLEEP_PD_TOP)){
analog_default.hp_sys.analog.slp_logic_dbias += 2;
if (!(pd_flags & PMU_SLEEP_PD_TOP) || !(pd_flags & PMU_SLEEP_PD_MODEM)){
analog_default.hp_sys.analog.xpd = 1;
analog_default.hp_sys.analog.dbias = 2;
}
config->analog = analog_default;
}
@ -200,10 +199,13 @@ static void pmu_sleep_analog_init(pmu_context_t *ctx, const pmu_sleep_analog_con
pmu_ll_hp_set_regulator_dbias (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.dbias);
pmu_ll_hp_set_regulator_driver_bar (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.drv_b);
pmu_ll_lp_set_regulator_slp_xpd (ctx->hal->dev, LP(ACTIVE), analog->lp_sys[LP(ACTIVE)].analog.slp_xpd);
pmu_ll_lp_set_regulator_sleep_dbias(ctx->hal->dev, LP(ACTIVE), analog->lp_sys[LP(ACTIVE)].analog.slp_dbias);
pmu_ll_lp_set_regulator_xpd (ctx->hal->dev, LP(ACTIVE), analog->lp_sys[LP(ACTIVE)].analog.xpd);
pmu_ll_lp_set_regulator_dbias (ctx->hal->dev, LP(ACTIVE), analog->lp_sys[LP(ACTIVE)].analog.dbias);
pmu_ll_lp_set_regulator_driver_bar (ctx->hal->dev, LP(ACTIVE), analog->lp_sys[LP(ACTIVE)].analog.drv_b);
pmu_ll_lp_set_dbg_atten (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.dbg_atten);
pmu_ll_lp_set_current_power_off (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.pd_cur);
pmu_ll_lp_set_bias_sleep_enable (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.bias_sleep);
pmu_ll_lp_set_regulator_xpd (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.xpd);
@ -248,6 +250,9 @@ void pmu_sleep_init(const pmu_sleep_config_t *config, bool dslp)
uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu, bool dslp)
{
assert(PMU_instance()->hal);
lp_aon_hal_inform_wakeup_type(dslp);
pmu_ll_hp_set_wakeup_enable(PMU_instance()->hal->dev, wakeup_opt);
pmu_ll_hp_set_reject_enable(PMU_instance()->hal->dev, reject_opt);

View File

@ -172,14 +172,14 @@ typedef struct {
#define PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(pd_flags) { \
.hp_sys = { \
.analog = { \
.xpd_bias = 0x0, \
.dbg_atten = 0x0, \
.xpd_bias = 0, \
.dbg_atten = 0, \
.pd_cur = 1, \
.bias_sleep = 1, \
.slp_mem_xpd = 1, \
.slp_logic_xpd = 1, \
.slp_mem_dbias = 0x4, \
.slp_logic_dbias = 0x4, \
.slp_mem_dbias = 4, \
.slp_logic_dbias = 4, \
.xpd = 0, \
.dbias = 0, \
.drv_b = 0 \
@ -188,23 +188,23 @@ typedef struct {
.lp_sys[PMU_MODE_LP_ACTIVE] = { \
.analog = { \
.slp_xpd = 0, \
.slp_dbias = 0xc, \
.slp_dbias = 0, \
.xpd = 1, \
.dbias = 0x1a, \
.drv_b = 0x0 \
.dbias = 26, \
.drv_b = 0 \
} \
}, \
.lp_sys[PMU_MODE_LP_SLEEP] = { \
.analog = { \
.xpd_bias = 0, \
.dbg_atten = 0x0, \
.dbg_atten = 0, \
.pd_cur = 1, \
.bias_sleep = 1, \
.xpd = 0, \
.dbias = 0x1c, \
.dbias = 28, \
.slp_xpd = 1, \
.slp_dbias = 0x3, \
.drv_b = 0x0 \
.slp_dbias = 3, \
.drv_b = 0 \
} \
} \
}
@ -213,37 +213,37 @@ typedef struct {
.hp_sys = { \
.analog = { \
.xpd_bias = 0, \
.dbg_atten = 0x3, \
.pd_cur = 1, \
.bias_sleep = 1, \
.dbg_atten = 0, \
.pd_cur = 0, \
.bias_sleep = 0, \
.slp_mem_xpd = 0, \
.slp_logic_xpd = 0, \
.slp_mem_dbias = 0, \
.slp_logic_dbias = 0, \
.xpd = 0, \
.dbias = 0x15, \
.slp_mem_xpd = 1, \
.slp_mem_dbias = 0xc, \
.slp_logic_xpd = 1, \
.slp_logic_dbias = 0x5, \
.drv_b = 0x18c \
.dbias = 0, \
.drv_b = 0 \
} \
}, \
.lp_sys[PMU_MODE_LP_ACTIVE] = { \
.analog = { \
.xpd = 1, \
.dbias = 0x1a, \
.slp_xpd = 0, \
.slp_dbias = 0, \
.drv_b = 0x7 \
.xpd = 1, \
.dbias = 26, \
.drv_b = 0 \
} \
}, \
.lp_sys[PMU_MODE_LP_SLEEP] = { \
.analog = { \
.xpd_bias = 0, \
.dbg_atten = 0xe, \
.dbg_atten = 14, \
.pd_cur = 1, \
.bias_sleep = 1, \
.xpd = 0, \
.dbias = 0, \
.slp_xpd = 1, \
.slp_dbias = 0xe, \
.slp_dbias = 14, \
.drv_b = 0 \
} \
} \

View File

@ -565,7 +565,6 @@ static IRAM_ATTR esp_err_t do_cpu_retention(sleep_cpu_entry_cb_t goto_sleep,
{
RvCoreCriticalSleepFrame * frame = rv_core_critical_regs_save();
if ((frame->pmufunc & 0x3) == 0x1) {
REG_CLR_BIT(SLEEP_MODE_REG, BIT(0)); /* Tell rom to run light sleep wake stub */
REG_WRITE(LIGHT_SLEEP_WAKE_STUB_ADDR_REG, (uint32_t)rv_core_critical_regs_restore);
return (*goto_sleep)(wakeup_opt, reject_opt, lslp_mem_inf_fpu, dslp);
}

View File

@ -21,7 +21,9 @@
#include "hal/gpio_hal.h"
#include "hal/rtc_io_hal.h"
#if !SOC_PMU_SUPPORTED
#if SOC_LP_AON_SUPPORTED
#include "hal/lp_aon_hal.h"
#else
#include "hal/rtc_hal.h"
#endif
@ -107,8 +109,7 @@ void esp_sleep_enable_gpio_switch(bool enable)
}
}
// TODO: IDF-6051, IDF-6052
#if !CONFIG_IDF_TARGET_ESP32H4 && !CONFIG_IDF_TARGET_ESP32C6 && !CONFIG_IDF_TARGET_ESP32H2
#if !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
IRAM_ATTR void esp_sleep_isolate_digital_gpio(void)
{
gpio_hal_context_t gpio_hal = {
@ -146,11 +147,11 @@ IRAM_ATTR void esp_sleep_isolate_digital_gpio(void)
}
}
}
#endif
#endif // !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
void esp_deep_sleep_wakeup_io_reset(void)
{
#if SOC_PM_SUPPORT_EXT_WAKEUP
#if SOC_PM_SUPPORT_EXT1_WAKEUP
uint32_t rtc_io_mask = rtc_hal_ext1_get_wakeup_pins();
// Disable ext1 wakeup before releasing hold, such that wakeup status can reflect the correct wakeup pin
rtc_hal_ext1_clear_wakeup_pins();

View File

@ -25,7 +25,9 @@
#include "driver/rtc_io.h"
#include "hal/rtc_io_hal.h"
#if !SOC_PMU_SUPPORTED
#if SOC_LP_AON_SUPPORTED
#include "hal/lp_aon_hal.h"
#else
#include "hal/rtc_cntl_ll.h"
#include "hal/rtc_hal.h"
#endif
@ -156,12 +158,16 @@ typedef struct {
portMUX_TYPE lock;
uint64_t sleep_duration;
uint32_t wakeup_triggers : 15;
#if SOC_PM_SUPPORT_EXT1_WAKEUP
uint32_t ext1_trigger_mode : 1;
uint32_t ext1_rtc_gpio_mask : 22; //22 is the maximum RTCIO number in all chips
uint32_t ext1_rtc_gpio_mask : 22; // 22 is the maximum RTCIO number in all chips
#endif
#if SOC_PM_SUPPORT_EXT0_WAKEUP
uint32_t ext0_trigger_level : 1;
uint32_t ext0_rtc_gpio_num : 5;
uint32_t gpio_wakeup_mask : 6;
uint32_t gpio_trigger_mode : 6;
#endif
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;
uint32_t sleep_time_adjustment;
uint32_t ccount_ticks_record;
uint32_t sleep_time_overhead_out;
@ -207,8 +213,10 @@ void esp_sleep_periph_use_8m(bool use_or_not)
}
static uint32_t get_power_down_flags(void);
#if SOC_PM_SUPPORT_EXT_WAKEUP
#if SOC_PM_SUPPORT_EXT0_WAKEUP
static void ext0_wakeup_prepare(void);
#endif
#if SOC_PM_SUPPORT_EXT1_WAKEUP
static void ext1_wakeup_prepare(void);
#endif
static void timer_wakeup_prepare(void);
@ -235,14 +243,19 @@ static void RTC_IRAM_ATTR __attribute__((used, noinline)) esp_wake_stub_start(vo
* must be simple enough to ensure that there is no litteral data before the
* wake stub entry, otherwise, the litteral data before the wake stub entry
* will not be CRC checked. */
#if !CONFIG_IDF_TARGET_ESP32C6 // TODO: WIFI-5150
static void __attribute__((section(".rtc.entry.text"))) esp_wake_stub_entry(void)
{
#define _SYM2STR(s) # s
#define SYM2STR(s) _SYM2STR(s)
#ifdef __riscv
__asm__ __volatile__ ("call " SYM2STR(esp_wake_stub_start) "\n");
__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"
);
#else
// call4 has a larger effective addressing range (-524284 to 524288 bytes),
// which is sufficient for instruction addressing in RTC fast memory.
@ -250,7 +263,19 @@ static void __attribute__((section(".rtc.entry.text"))) esp_wake_stub_entry(void
#endif
}
#endif // !CONFIG_IDF_TARGET_ESP32C6 // TODO: WIFI-5150
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);
}
#endif // SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY
/* Wake from deep sleep stub
@ -269,7 +294,13 @@ esp_deep_sleep_wake_stub_fn_t esp_get_deep_sleep_wake_stub(void)
return stub_ptr;
}
void esp_set_deep_sleep_wake_stub(esp_deep_sleep_wake_stub_fn_t new_stub)
#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)
{
#if SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY
wake_stub_fn_handler = new_stub;
@ -433,11 +464,13 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t mo
rtc_clk_cpu_freq_get_config(&cpu_freq_config);
rtc_clk_cpu_freq_set_xtal();
#if SOC_PM_SUPPORT_EXT_WAKEUP
#if SOC_PM_SUPPORT_EXT0_WAKEUP
// Configure pins for external wakeup
if (s_config.wakeup_triggers & RTC_EXT0_TRIG_EN) {
ext0_wakeup_prepare();
}
#endif
#if SOC_PM_SUPPORT_EXT1_WAKEUP
if (s_config.wakeup_triggers & RTC_EXT1_TRIG_EN) {
ext1_wakeup_prepare();
}
@ -529,24 +562,18 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t mo
uint32_t result;
if (deep_sleep) {
// TODO: IDF-6051, IDF-6052
#if !CONFIG_IDF_TARGET_ESP32H4 && !CONFIG_IDF_TARGET_ESP32C6 && !CONFIG_IDF_TARGET_ESP32H2
#if !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
esp_sleep_isolate_digital_gpio();
#endif
#if !CONFIG_IDF_TARGET_ESP32C6 // TODO: IDF-5349
#if SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY
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;
esp_set_deep_sleep_wake_stub_default_entry();
// Enter Deep Sleep
#if SOC_PMU_SUPPORTED
result = call_rtc_sleep_start(reject_triggers, config.power.hp_sys.dig_power.mem_dslp, deep_sleep);
#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);
result = call_rtc_sleep_start(reject_triggers, config.lslp_mem_inf_fpu, deep_sleep);
#endif
#else
#if !CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP
/* If not possible stack is in RTC FAST memory, use the ROM function to calculate the CRC and save ~140 bytes IRAM */
@ -560,9 +587,6 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t mo
#endif
#endif // SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY
#else
result = ESP_OK;
#endif
} else {
/* On esp32c6, only the lp_aon pad hold function can only hold the GPIO state in the active mode.
@ -646,7 +670,14 @@ void IRAM_ATTR esp_deep_sleep_start(void)
// Correct the sleep time
s_config.sleep_time_adjustment = DEEP_SLEEP_TIME_OVERHEAD_US;
#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 \
| PMU_SLEEP_PD_CPU | PMU_SLEEP_PD_MEM | PMU_SLEEP_PD_XTAL | PMU_SLEEP_PD_RC_FAST \
| PMU_SLEEP_PD_XTAL32K |PMU_SLEEP_PD_RC32K;
#else
uint32_t force_pd_flags = RTC_SLEEP_PD_DIG | RTC_SLEEP_PD_VDDSDIO | RTC_SLEEP_PD_INT_8M | RTC_SLEEP_PD_XTAL;
#endif
#if SOC_PM_SUPPORT_WIFI_PD
force_pd_flags |= RTC_SLEEP_PD_WIFI;
@ -928,11 +959,13 @@ esp_err_t esp_sleep_disable_wakeup_source(esp_sleep_source_t source)
} else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_TIMER, RTC_TIMER_TRIG_EN)) {
s_config.wakeup_triggers &= ~RTC_TIMER_TRIG_EN;
s_config.sleep_duration = 0;
#if SOC_PM_SUPPORT_EXT_WAKEUP
#if SOC_PM_SUPPORT_EXT0_WAKEUP
} else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_EXT0, RTC_EXT0_TRIG_EN)) {
s_config.ext0_rtc_gpio_num = 0;
s_config.ext0_trigger_level = 0;
s_config.wakeup_triggers &= ~RTC_EXT0_TRIG_EN;
#endif
#if SOC_PM_SUPPORT_EXT1_WAKEUP
} else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_EXT1, RTC_EXT1_TRIG_EN)) {
s_config.ext1_rtc_gpio_mask = 0;
s_config.ext1_trigger_mode = 0;
@ -1071,8 +1104,7 @@ bool esp_sleep_is_valid_wakeup_gpio(gpio_num_t gpio_num)
#endif // SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
}
#if SOC_PM_SUPPORT_EXT_WAKEUP
#if SOC_PM_SUPPORT_EXT0_WAKEUP
esp_err_t esp_sleep_enable_ext0_wakeup(gpio_num_t gpio_num, int level)
{
if (level < 0 || level > 1) {
@ -1101,7 +1133,9 @@ static void ext0_wakeup_prepare(void)
rtcio_hal_function_select(rtc_gpio_num, RTCIO_FUNC_RTC);
rtcio_hal_input_enable(rtc_gpio_num);
}
#endif // SOC_PM_SUPPORT_EXT0_WAKEUP
#if SOC_PM_SUPPORT_EXT1_WAKEUP
esp_err_t esp_sleep_enable_ext1_wakeup(uint64_t mask, esp_sleep_ext1_wakeup_mode_t mode)
{
if (mode > ESP_EXT1_WAKEUP_ANY_HIGH) {
@ -1185,25 +1219,20 @@ uint64_t esp_sleep_get_ext1_wakeup_status(void)
return gpio_mask;
}
#endif // SOC_PM_SUPPORT_EXT_WAKEUP
#endif // SOC_PM_SUPPORT_EXT1_WAKEUP
#if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP
uint64_t esp_sleep_get_gpio_wakeup_status(void)
{
#if CONFIG_IDF_TARGET_ESP32C6 // TODO: IDF-5349
return 0;
#else
if (esp_sleep_get_wakeup_cause() != ESP_SLEEP_WAKEUP_GPIO) {
return 0;
}
return rtc_hal_gpio_get_wakeup_status();
#endif
}
static void gpio_deep_sleep_wakeup_prepare(void)
{
#if !CONFIG_IDF_TARGET_ESP32C6 // TODO: IDF-5349
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;
@ -1219,7 +1248,6 @@ static void gpio_deep_sleep_wakeup_prepare(void)
}
// Clear state from previous wakeup
rtc_hal_gpio_clear_wakeup_status();
#endif
}
esp_err_t esp_deep_sleep_enable_gpio_wakeup(uint64_t gpio_pin_mask, esp_deepsleep_gpio_wake_up_mode_t mode)
@ -1339,9 +1367,11 @@ esp_sleep_wakeup_cause_t esp_sleep_get_wakeup_cause(void)
return ESP_SLEEP_WAKEUP_GPIO;
} else if (wakeup_cause & (RTC_UART0_TRIG_EN | RTC_UART1_TRIG_EN)) {
return ESP_SLEEP_WAKEUP_UART;
#if SOC_PM_SUPPORT_EXT_WAKEUP
#if SOC_PM_SUPPORT_EXT0_WAKEUP
} else if (wakeup_cause & RTC_EXT0_TRIG_EN) {
return ESP_SLEEP_WAKEUP_EXT0;
#endif
#if SOC_PM_SUPPORT_EXT1_WAKEUP
} else if (wakeup_cause & RTC_EXT1_TRIG_EN) {
return ESP_SLEEP_WAKEUP_EXT1;
#endif

View File

@ -11,6 +11,7 @@
#include "esp_attr.h"
#include "esp_sleep.h"
#include "esp_cpu.h"
#include "soc/soc.h"
#include "soc/rtc.h"
@ -50,31 +51,38 @@
void RTC_IRAM_ATTR esp_wake_stub_sleep(esp_deep_sleep_wake_stub_fn_t new_stub)
{
#if SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY
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 // CONFIG_ESP32S3_RTCDATA_IN_FAST_MEM
esp_rom_set_rtc_wake_addr((esp_rom_wake_func_t)new_stub, rtc_fast_length);
#else
// Set the pointer of the wake stub function.
#if CONFIG_IDF_TARGET_ESP32
// Since the app core of esp32 does not support access to RTC_FAST_MEMORY,
// `esp_set_deep_sleep_wake_stub` is not declared in RTC_FAST_MEMORY,
// so we cannot call it here
REG_WRITE(RTC_ENTRY_ADDR_REG, (uint32_t)new_stub);
#else
esp_set_deep_sleep_wake_stub(new_stub);
#endif
#if SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY
esp_set_deep_sleep_wake_stub_default_entry();
#else
set_rtc_memory_crc();
#endif // SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_MEM
// Go to sleep.
#if SOC_PMU_SUPPORTED
pmu_ll_hp_clear_wakeup_intr_status(&PMU);
pmu_ll_hp_clear_reject_intr_status(&PMU);
pmu_ll_hp_clear_reject_cause(&PMU);
pmu_ll_hp_set_sleep_enable(&PMU);
#else
rtc_cntl_ll_sleep_enable();
#endif
// A few CPU cycles may be necessary for the sleep to start...
while (true) {};
#if __XTENSA__
xt_utils_wait_for_intr();
#else
rv_utils_wait_for_intr();
#endif // __XTENSA__
// never reaches here.
}
@ -87,8 +95,15 @@ void RTC_IRAM_ATTR esp_wake_stub_set_wakeup_time(uint64_t time_in_us)
{
#if SOC_LP_TIMER_SUPPORTED
uint64_t rtc_count_delta = lp_timer_ll_time_to_count(time_in_us);
uint64_t rtc_curr_count = lp_timer_hal_get_cycle_count(0);
lp_timer_hal_set_alarm_target(0, rtc_curr_count + rtc_count_delta);
lp_timer_ll_counter_snapshot(&LP_TIMER);
uint32_t lo = lp_timer_ll_get_counter_value_low(&LP_TIMER, 0);
uint32_t hi = lp_timer_ll_get_counter_value_high(&LP_TIMER, 0);
uint64_t rtc_curr_count = (uint64_t)hi << 32 | lo;
lp_timer_ll_clear_alarm_intr_status(&LP_TIMER);
lp_timer_ll_set_alarm_target(&LP_TIMER, 0, rtc_curr_count + rtc_count_delta);
lp_timer_ll_set_target_enable(&LP_TIMER, 0, true);
#else
uint64_t rtc_count_delta = rtc_cntl_ll_time_to_count(time_in_us);
uint64_t rtc_curr_count = rtc_cntl_ll_get_rtc_time();

View File

@ -178,6 +178,8 @@ typedef void (* esp_rom_wake_func_t)(void);
* @brief Read stored RTC wake function address
*
* Returns pointer to wake address if a value is set in RTC registers, and stored length & CRC all valid.
* valid means that both stored stub length and stored wake function address are four-byte aligned non-zero values
* and the crc check passes
*
* @param None
*
@ -191,8 +193,11 @@ esp_rom_wake_func_t esp_rom_get_rtc_wake_addr(void);
* Set a new RTC wake address function. If a non-NULL function pointer is set then the function
* memory is calculated and stored also.
*
* @param entry_addr Address of function. If NULL, length is ignored and all registers are cleared to 0.
* @param length of function in RTC fast memory. cannot be larger than RTC Fast memory size.
* @param entry_addr Address of function. should be 4-bytes aligned otherwise it will not start from the stub after wake from deepsleep
* if NULL length will be ignored and all registers are cleared to 0.
*
* @param length length of function in RTC fast memory. should be less than RTC Fast memory size and aligned to 4-bytes.
* otherwise all registers are cleared to 0.
*
* @return None
*/

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -175,6 +175,8 @@ typedef void (* esp_rom_wake_func_t)(void);
* @brief Read stored RTC wake function address
*
* Returns pointer to wake address if a value is set in RTC registers, and stored length & CRC all valid.
* valid means that both stored stub length and stored wake function address are four-byte aligned non-zero values
* and the crc check passes
*
* @param None
*
@ -188,8 +190,11 @@ esp_rom_wake_func_t esp_rom_get_rtc_wake_addr(void);
* Set a new RTC wake address function. If a non-NULL function pointer is set then the function
* memory is calculated and stored also.
*
* @param entry_addr Address of function. If NULL, length is ignored and all registers are cleared to 0.
* @param length of function in RTC fast memory. cannot be larger than RTC Fast memory size.
* @param entry_addr Address of function. should be 4-bytes aligned otherwise it will not start from the stub after wake from deepsleep
* if NULL length will be ignored and all registers are cleared to 0.
*
* @param length length of function in RTC fast memory. should be less than RTC Fast memory size and aligned to 4-bytes.
* otherwise all registers are cleared to 0.
*
* @return None
*/

View File

@ -175,6 +175,8 @@ typedef void (* esp_rom_wake_func_t)(void);
* @brief Read stored RTC wake function address
*
* Returns pointer to wake address if a value is set in RTC registers, and stored length & CRC all valid.
* valid means that both stored stub length and stored wake function address are four-byte aligned non-zero values
* and the crc check passes
*
* @param None
*
@ -188,8 +190,11 @@ esp_rom_wake_func_t esp_rom_get_rtc_wake_addr(void);
* Set a new RTC wake address function. If a non-NULL function pointer is set then the function
* memory is calculated and stored also.
*
* @param entry_addr Address of function. If NULL, length is ignored and all registers are cleared to 0.
* @param length of function in RTC fast memory. cannot be larger than RTC Fast memory size.
* @param entry_addr Address of function. should be 4-bytes aligned otherwise it will not start from the stub after wake from deepsleep
* if NULL length will be ignored and all registers are cleared to 0.
*
* @param length length of function in RTC fast memory. should be less than RTC Fast memory size and aligned to 4-bytes.
* otherwise all registers are cleared to 0.
*
* @return None
*/

View File

@ -173,6 +173,8 @@ typedef void (* esp_rom_wake_func_t)(void);
* @brief Read stored RTC wake function address
*
* Returns pointer to wake address if a value is set in RTC registers, and stored length & CRC all valid.
* valid means that both stored stub length and stored wake function address are four-byte aligned non-zero values
* and the crc check passes
*
* @param None
*
@ -186,8 +188,11 @@ esp_rom_wake_func_t esp_rom_get_rtc_wake_addr(void);
* Set a new RTC wake address function. If a non-NULL function pointer is set then the function
* memory is calculated and stored also.
*
* @param entry_addr Address of function. If NULL, length is ignored and all registers are cleared to 0.
* @param length of function in RTC fast memory. cannot be larger than RTC Fast memory size.
* @param entry_addr Address of function. should be 4-bytes aligned otherwise it will not start from the stub after wake from deepsleep
* if NULL length will be ignored and all registers are cleared to 0.
*
* @param length length of function in RTC fast memory. should be less than RTC Fast memory size and aligned to 4-bytes.
* otherwise all registers are cleared to 0.
*
* @return None
*/

View File

@ -17,6 +17,8 @@ SECTIONS
{
. = ALIGN(4);
_rtc_fast_start = ABSOLUTE(.);
_rtc_text_start = ABSOLUTE(.);
*(.rtc.entry.text)
mapping[rtc_text]

View File

@ -541,10 +541,12 @@ void IRAM_ATTR call_start_cpu0(void)
#endif
#endif
#if !CONFIG_IDF_TARGET_ESP32H2 // TODO: IDF-6268
// Need to unhold the IOs that were hold right before entering deep sleep, which are used as wakeup pins
if (rst_reas[0] == RESET_REASON_CORE_DEEP_SLEEP) {
esp_deep_sleep_wakeup_io_reset();
}
#endif
#if !CONFIG_APP_BUILD_TYPE_PURE_RAM_APP
esp_cache_err_int_init();

View File

@ -386,7 +386,7 @@ TEST_CASE_MULTIPLE_STAGES("can set sleep wake stub from stack in RTC RAM", "[dee
#if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
#if SOC_PM_SUPPORT_EXT_WAKEUP
#if SOC_PM_SUPPORT_EXT0_WAKEUP
TEST_CASE("wake up using ext0 (13 high)", "[deepsleep][ignore]")
{
ESP_ERROR_CHECK(rtc_gpio_init(GPIO_NUM_13));
@ -404,7 +404,9 @@ TEST_CASE("wake up using ext0 (13 low)", "[deepsleep][ignore]")
ESP_ERROR_CHECK(esp_sleep_enable_ext0_wakeup(GPIO_NUM_13, ESP_EXT0_WAKEUP_LEVEL_LOW));
esp_deep_sleep_start();
}
#endif // SOC_PM_SUPPORT_EXT0_WAKEUP
#if SOC_PM_SUPPORT_EXT1_WAKEUP
TEST_CASE("wake up using ext1 when RTC_PERIPH is off (13 high)", "[deepsleep][ignore]")
{
// This test needs external pulldown
@ -440,7 +442,7 @@ TEST_CASE("wake up using ext1 when RTC_PERIPH is on (13 low)", "[deepsleep][igno
ESP_ERROR_CHECK(esp_sleep_enable_ext1_wakeup(BIT(GPIO_NUM_13), ESP_EXT1_WAKEUP_ALL_LOW));
esp_deep_sleep_start();
}
#endif // SOC_PM_SUPPORT_EXT_WAKEUP
#endif // SOC_PM_SUPPORT_EXT1_WAKEUP
__attribute__((unused)) static float get_time_ms(void)
{

View File

@ -20,7 +20,8 @@
#include "soc/gpio_periph.h"
#include "soc/gpio_struct.h"
#include "soc/lp_aon_struct.h"
#include "soc/pmu_reg.h"
#include "soc/lp_io_struct.h"
#include "soc/pmu_struct.h"
#include "soc/usb_serial_jtag_reg.h"
#include "soc/pcr_struct.h"
#include "soc/clk_tree_defs.h"
@ -354,26 +355,6 @@ static inline void gpio_ll_get_drive_capability(gpio_dev_t *hw, uint32_t gpio_nu
*strength = (gpio_drive_cap_t)GET_PERI_REG_BITS2(IO_MUX_GPIO0_REG + (gpio_num * 4), FUN_DRV_V, FUN_DRV_S);
}
/**
* @brief Enable all digital gpio pads hold function during Deep-sleep.
*
* @param hw Peripheral GPIO hardware instance address.
*/
static inline void gpio_ll_deep_sleep_hold_en(gpio_dev_t *hw)
{
REG_SET_BIT(PMU_IMM_PAD_HOLD_ALL_REG, PMU_TIE_HIGH_HP_PAD_HOLD_ALL);
}
/**
* @brief Disable all digital gpio pads hold function during Deep-sleep.
*
* @param hw Peripheral GPIO hardware instance address.
*/
static inline void gpio_ll_deep_sleep_hold_dis(gpio_dev_t *hw)
{
REG_SET_BIT(PMU_IMM_PAD_HOLD_ALL_REG, PMU_TIE_LOW_HP_PAD_HOLD_ALL);
}
/**
* @brief Enable gpio pad hold function.
*
@ -396,6 +377,24 @@ static inline void gpio_ll_hold_dis(gpio_dev_t *hw, uint32_t gpio_num)
LP_AON.gpio_hold0.gpio_hold0 &= ~GPIO_HOLD_MASK[gpio_num];
}
/**
* @brief Get digital gpio pad hold status.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number, only support output GPIOs
*
* @note caller must ensure that gpio_num is a digital io pad
*
* @return
* - true digital gpio pad is held
* - false digital gpio pad is unheld
*/
__attribute__((always_inline))
static inline bool gpio_ll_is_digital_io_hold(gpio_dev_t *hw, uint32_t gpio_num)
{
return !!(LP_AON.gpio_hold0.gpio_hold0 & GPIO_HOLD_MASK[gpio_num]);
}
/**
* @brief Set pad input to a peripheral signal through the IOMUX.
*
@ -478,6 +477,26 @@ static inline void gpio_ll_iomux_set_clk_src(soc_module_clk_t src)
}
}
/**
* @brief Force hold digital io pad.
* @note GPIO force hold, whether the chip in sleep mode or wakeup mode.
*/
static inline void gpio_ll_force_hold_all(void)
{
// WT flag, it gets self-cleared after the configuration is done
PMU.imm.pad_hold_all.tie_high_hp_pad_hold_all = 1;
}
/**
* @brief Force unhold digital io pad.
* @note GPIO force unhold, whether the chip in sleep mode or wakeup mode.
*/
static inline void gpio_ll_force_unhold_all(void)
{
// WT flag, it gets self-cleared after the configuration is done
PMU.imm.pad_hold_all.tie_low_hp_pad_hold_all = 1;
}
/**
* @brief Enable GPIO pin to use sleep mode pin functions during light sleep.
*
@ -589,63 +608,6 @@ static inline void gpio_ll_sleep_output_enable(gpio_dev_t *hw, uint32_t gpio_num
PIN_SLP_OUTPUT_ENABLE(IO_MUX_GPIO0_REG + (gpio_num * 4));
}
/**
* @brief Enable GPIO deep-sleep wake-up function.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number.
* @param intr_type GPIO wake-up type. Only GPIO_INTR_LOW_LEVEL or GPIO_INTR_HIGH_LEVEL can be used.
*/
static inline void gpio_ll_deepsleep_wakeup_enable(gpio_dev_t *hw, uint32_t gpio_num, gpio_int_type_t intr_type)
{
HAL_ASSERT(gpio_num <= GPIO_NUM_7 && "gpio larger than 7 does not support deep sleep wake-up function");
LP_AON.ext_wakeup_cntl.ext_wakeup_filter = 1;
uint32_t wakeup_sel_mask = HAL_FORCE_READ_U32_REG_FIELD(LP_AON.ext_wakeup_cntl, ext_wakeup_sel);
wakeup_sel_mask |= BIT(gpio_num);
HAL_FORCE_MODIFY_U32_REG_FIELD(LP_AON.ext_wakeup_cntl, ext_wakeup_sel, wakeup_sel_mask);
bool trigger_level = (intr_type == GPIO_INTR_LOW_LEVEL) ? 0 : 1;
uint32_t wakeup_level_mask = HAL_FORCE_READ_U32_REG_FIELD(LP_AON.ext_wakeup_cntl, ext_wakeup_lv);
if (trigger_level) {
wakeup_level_mask |= BIT(gpio_num);
} else {
wakeup_level_mask &= ~BIT(gpio_num);
}
HAL_FORCE_MODIFY_U32_REG_FIELD(LP_AON.ext_wakeup_cntl, ext_wakeup_lv, wakeup_level_mask);
}
/**
* @brief Disable GPIO deep-sleep wake-up function.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
static inline void gpio_ll_deepsleep_wakeup_disable(gpio_dev_t *hw, uint32_t gpio_num)
{
HAL_ASSERT(gpio_num <= GPIO_NUM_7 && "gpio larger than 7 does not support deep sleep wake-up function");
uint32_t wakeup_sel_mask = HAL_FORCE_READ_U32_REG_FIELD(LP_AON.ext_wakeup_cntl, ext_wakeup_sel);
wakeup_sel_mask &= ~BIT(gpio_num);
HAL_FORCE_MODIFY_U32_REG_FIELD(LP_AON.ext_wakeup_cntl, ext_wakeup_sel, wakeup_sel_mask);
}
/**
* @brief Get the status of whether an IO is used for deep-sleep wake-up.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
* @return True if the pin is enabled to wake up from deep-sleep
*/
static inline bool gpio_ll_deepsleep_wakeup_is_enabled(gpio_dev_t *hw, uint32_t gpio_num)
{
HAL_ASSERT(gpio_num <= GPIO_NUM_7 && "gpio larger than 7 does not support deep sleep wake-up function");
uint32_t wakeup_sel_mask = HAL_FORCE_READ_U32_REG_FIELD(LP_AON.ext_wakeup_cntl, ext_wakeup_sel);
return wakeup_sel_mask & BIT(gpio_num);
}
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,24 @@
/*
* SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "hal/lp_aon_ll.h"
#define rtc_hal_ext1_get_wakeup_status() lp_aon_hal_ext1_get_wakeup_status()
#define rtc_hal_ext1_clear_wakeup_status() lp_aon_hal_ext1_clear_wakeup_status()
#define rtc_hal_ext1_set_wakeup_pins(mask, mode) lp_aon_hal_ext1_set_wakeup_pins(mask, mode)
#define rtc_hal_ext1_clear_wakeup_pins() lp_aon_hal_ext1_clear_wakeup_pins()
#define rtc_hal_ext1_get_wakeup_pins() lp_aon_hal_ext1_get_wakeup_pins()
#define lp_aon_hal_ext1_get_wakeup_status() lp_aon_ll_ext1_get_wakeup_status()
#define lp_aon_hal_ext1_clear_wakeup_status() lp_aon_ll_ext1_clear_wakeup_status()
#define lp_aon_hal_ext1_set_wakeup_pins(mask, mode) lp_aon_ll_ext1_set_wakeup_pins(mask, mode)
#define lp_aon_hal_ext1_clear_wakeup_pins() lp_aon_ll_ext1_clear_wakeup_pins()
#define lp_aon_hal_ext1_get_wakeup_pins() lp_aon_ll_ext1_get_wakeup_pins()
#define lp_aon_hal_inform_wakeup_type(dslp) lp_aon_ll_inform_wakeup_type(dslp)

View File

@ -0,0 +1,97 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
// The LL layer for ESP32-C6 LP_AON register operations
#pragma once
#include <stdlib.h>
#include "soc/soc.h"
#include "soc/lp_aon_struct.h"
#include "hal/misc.h"
#include "esp32c6/rom/rtc.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Get ext1 wakeup source status
* @return The lower 8 bits of the returned value are the bitmap of
* the wakeup source status, bit 0~7 corresponds to LP_IO 0~7
*/
static inline uint32_t lp_aon_ll_ext1_get_wakeup_status(void)
{
return HAL_FORCE_READ_U32_REG_FIELD(LP_AON.ext_wakeup_cntl, ext_wakeup_status);
}
/**
* @brief Clear the ext1 wakeup source status
*/
static inline void lp_aon_ll_ext1_clear_wakeup_status(void)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(LP_AON.ext_wakeup_cntl, ext_wakeup_status_clr, 1);
}
/**
* @brief Set the wake-up LP_IO of the ext1 wake-up source
* @param mask wakeup LP_IO bitmap, bit 0~7 corresponds to LP_IO 0~7
* @param mode 0: Wake the chip when all selected GPIOs go low
* 1: Wake the chip when any of the selected GPIOs go high
*/
static inline void lp_aon_ll_ext1_set_wakeup_pins(uint32_t mask, int mode)
{
uint32_t wakeup_sel_mask = HAL_FORCE_READ_U32_REG_FIELD(LP_AON.ext_wakeup_cntl, ext_wakeup_sel);
wakeup_sel_mask |= mask;
HAL_FORCE_MODIFY_U32_REG_FIELD(LP_AON.ext_wakeup_cntl, ext_wakeup_sel, wakeup_sel_mask);
uint32_t wakeup_level_mask = HAL_FORCE_READ_U32_REG_FIELD(LP_AON.ext_wakeup_cntl, ext_wakeup_lv);
if (mode) {
wakeup_level_mask |= mask;
} else {
wakeup_level_mask &= ~mask;
}
HAL_FORCE_MODIFY_U32_REG_FIELD(LP_AON.ext_wakeup_cntl, ext_wakeup_lv, wakeup_level_mask);
}
/**
* @brief Clear all ext1 wakup-source setting
*/
static inline void lp_aon_ll_ext1_clear_wakeup_pins(void)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(LP_AON.ext_wakeup_cntl, ext_wakeup_sel, 0);
}
/**
* @brief Get ext1 wakeup source setting
* @return The lower 8 bits of the returned value are the bitmap of
* the wakeup source status, bit 0~7 corresponds to LP_IO 0~7
*/
static inline uint32_t lp_aon_ll_ext1_get_wakeup_pins(void)
{
return HAL_FORCE_READ_U32_REG_FIELD(LP_AON.ext_wakeup_cntl, ext_wakeup_sel);
}
/**
* @brief ROM obtains the wake-up type through LP_AON_STORE9_REG[0].
* Set the flag to inform
* @param true: deepsleep false: lightsleep
*/
static inline void lp_aon_ll_inform_wakeup_type(bool dslp)
{
if (dslp) {
REG_SET_BIT(SLEEP_MODE_REG, BIT(0)); /* Tell rom to run deep sleep wake stub */
} else {
REG_CLR_BIT(SLEEP_MODE_REG, BIT(0)); /* Tell rom to run light sleep wake stub */
}
}
#ifdef __cplusplus
}
#endif

View File

@ -13,12 +13,14 @@
#pragma once
#include <stdlib.h>
#include <stdbool.h>
#include "soc/rtc_periph.h"
#include "soc/pcr_struct.h"
#include "soc/rtc_io_struct.h"
#include "soc/lp_aon_struct.h"
#include "soc/pmu_struct.h"
#include "hal/misc.h"
#include "hal/assert.h"
#include "hal/gpio_types.h"
#include "soc/io_mux_reg.h"
@ -28,8 +30,6 @@ extern "C" {
#define RTCIO_LL_PIN_FUNC 0
#define RTCIO_LL_PIN_MASK_ALL ((1 << SOC_RTCIO_PIN_COUNT) - 1)
typedef enum {
RTCIO_FUNC_RTC = 0x0, /*!< The pin controlled by RTC module. */
RTCIO_FUNC_DIGITAL = 0x1, /*!< The pin controlled by DIGITAL module. */
@ -242,22 +242,6 @@ static inline void rtcio_ll_force_hold_disable(int rtcio_num)
LP_AON.gpio_hold0.gpio_hold0 &= ~BIT(rtcio_num);
}
/**
* @brief Enable all LP IO pads hold function during Deep-sleep
*/
static inline void rtcio_ll_deep_sleep_hold_en_all(void)
{
PMU.imm.pad_hold_all.tie_high_lp_pad_hold_all = 1;
}
/**
* @brief Disable all LP IO pads hold function during Deep-sleep
*/
static inline void rtcio_ll_deep_sleep_hold_dis_all(void)
{
PMU.imm.pad_hold_all.tie_low_lp_pad_hold_all = 1;
}
/**
* Enable force hold function for all RTC IO pads
*
@ -268,8 +252,7 @@ static inline void rtcio_ll_deep_sleep_hold_dis_all(void)
*/
static inline void rtcio_ll_force_hold_all(void)
{
// No such a 'hold_all' bit on C6, use bit hold instead
LP_AON.gpio_hold0.gpio_hold0 |= RTCIO_LL_PIN_MASK_ALL;
PMU.imm.pad_hold_all.tie_high_lp_pad_hold_all = 1;
}
/**
@ -279,8 +262,7 @@ static inline void rtcio_ll_force_hold_all(void)
*/
static inline void rtcio_ll_force_unhold_all(void)
{
// No such a 'hold_all' bit on C6, use bit hold instead
LP_AON.gpio_hold0.gpio_hold0 &= ~RTCIO_LL_PIN_MASK_ALL;
PMU.imm.pad_hold_all.tie_low_lp_pad_hold_all = 1;
}
/**
@ -366,6 +348,38 @@ static inline void rtcio_ll_disable_sleep_setting(gpio_num_t gpio_num)
LP_IO.gpio[gpio_num].slp_sel = 0;
}
/**
* @brief Get the status of whether an IO is used for sleep wake-up.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
* @return True if the pin is enabled to wake up from deep-sleep
*/
static inline bool rtcio_ll_wakeup_is_enabled(gpio_num_t gpio_num)
{
HAL_ASSERT(gpio_num <= GPIO_NUM_7 && "gpio larger than 7 does not support deep sleep wake-up function");
// On ESP32-C6, (lp_io pin number) == (gpio pin number)
return LP_IO.pin[gpio_num].wakeup_enable;
}
/**
* @brief Get the rtc io interrupt status
*
* @return bit 0~7 corresponding to 0 ~ SOC_RTCIO_PIN_COUNT.
*/
static inline uint32_t rtcio_ll_get_interrupt_status(void)
{
return (uint32_t)(LP_IO.status.status_interrupt);
}
/**
* @brief Clear all LP IO pads status
*/
static inline void rtcio_ll_clear_interrupt_status(void)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(LP_IO.status_w1tc, status_w1tc, 0xff);
}
#ifdef __cplusplus
}
#endif

View File

@ -20,7 +20,7 @@
#include "soc/gpio_periph.h"
#include "soc/gpio_struct.h"
#include "soc/lp_aon_struct.h"
#include "soc/pmu_reg.h"
#include "soc/pmu_struct.h"
#include "soc/usb_serial_jtag_reg.h"
#include "soc/pcr_struct.h"
#include "soc/clk_tree_defs.h"
@ -398,26 +398,6 @@ static inline void gpio_ll_get_drive_capability(gpio_dev_t *hw, gpio_num_t gpio_
*strength = (gpio_drive_cap_t)GET_PERI_REG_BITS2(IO_MUX_GPIO0_REG + (gpio_num * 4), FUN_DRV_V, FUN_DRV_S);
}
/**
* @brief Enable all digital gpio pad hold function during Deep-sleep.
*
* @param hw Peripheral GPIO hardware instance address.
*/
static inline void gpio_ll_deep_sleep_hold_en(gpio_dev_t *hw)
{
REG_SET_BIT(PMU_IMM_PAD_HOLD_ALL_REG, PMU_TIE_HIGH_HP_PAD_HOLD_ALL);
}
/**
* @brief Disable all digital gpio pad hold function during Deep-sleep.
*
* @param hw Peripheral GPIO hardware instance address.
*/
static inline void gpio_ll_deep_sleep_hold_dis(gpio_dev_t *hw)
{
REG_SET_BIT(PMU_IMM_PAD_HOLD_ALL_REG, PMU_TIE_LOW_HP_PAD_HOLD_ALL);
}
/**
* @brief Enable gpio pad hold function.
*
@ -522,6 +502,28 @@ static inline void gpio_ll_iomux_set_clk_src(soc_module_clk_t src)
}
}
/**
* @brief Force hold all digital(VDDPST2) and lp(VDDPST1) io pads.
* @note GPIO force hold, whether the chip in sleep mode or wakeup mode.
*/
static inline void gpio_ll_force_hold_all(void)
{
// WT flags, they get self-cleared after the configuration is done
PMU.imm.pad_hold_all.tie_high_hp_pad_hold_all = 1;
PMU.imm.pad_hold_all.tie_high_lp_pad_hold_all = 1;
}
/**
* @brief Force unhold all digital(VDDPST2) and lp(VDDPST1) io pads.
* @note GPIO force unhold, whether the chip in sleep mode or wakeup mode.
*/
static inline void gpio_ll_force_unhold_all(void)
{
// WT flags, they get self-cleared after the configuration is done
PMU.imm.pad_hold_all.tie_low_hp_pad_hold_all = 1;
PMU.imm.pad_hold_all.tie_low_lp_pad_hold_all = 1;
}
/**
* @brief Enable GPIO pin to use sleep mode pin functions during light sleep.
*

View File

@ -270,6 +270,22 @@ static inline void gpio_ll_od_enable(gpio_dev_t *hw, uint32_t gpio_num)
hw->pin[gpio_num].pin_pad_driver = 1;
}
/**
* @brief Select a function for the pin in the IOMUX
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
* @param func Function to assign to the pin
*/
static inline __attribute__((always_inline)) void gpio_ll_func_sel(gpio_dev_t *hw, uint8_t gpio_num, uint32_t func)
{
// Disable USB Serial JTAG if pins 18 or pins 19 needs to select an IOMUX function
if (gpio_num == USB_DM_GPIO_NUM || gpio_num == USB_DP_GPIO_NUM) {
CLEAR_PERI_REG_MASK(USB_SERIAL_JTAG_CONF0_REG, USB_SERIAL_JTAG_USB_PAD_ENABLE);
}
PIN_FUNC_SELECT(IO_MUX_GPIO0_REG + (gpio_num * 4), func);
}
/**
* @brief GPIO set output level
*
@ -383,6 +399,21 @@ static inline void gpio_ll_deep_sleep_hold_dis(gpio_dev_t *hw)
SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_CLR_DG_PAD_AUTOHOLD);
}
/**
* @brief Get deep sleep hold status
*
* @param hw Peripheral GPIO hardware instance address.
*
* @return
* - true deep sleep hold is enabled
* - false deep sleep hold is disabled
*/
__attribute__((always_inline))
static inline bool gpio_ll_deep_sleep_hold_is_en(gpio_dev_t *hw)
{
return !GET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_UNHOLD) && GET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_AUTOHOLD_EN_M);
}
/**
* @brief Enable gpio pad hold function.
*
@ -417,6 +448,24 @@ static inline void gpio_ll_hold_dis(gpio_dev_t *hw, uint32_t gpio_num)
}
}
/**
* @brief Get digital gpio pad hold status.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number, only support output GPIOs
*
* @note caller must ensure that gpio_num is a digital io pad
*
* @return
* - true digital gpio pad is held
* - false digital gpio pad is unheld
*/
__attribute__((always_inline))
static inline bool gpio_ll_is_digital_io_hold(gpio_dev_t *hw, uint32_t gpio_num)
{
return GET_PERI_REG_MASK(RTC_CNTL_DIG_PAD_HOLD_REG, BIT(gpio_num));
}
/**
* @brief Set pad input to a peripheral signal through the IOMUX.
*

View File

@ -242,8 +242,8 @@ void gpio_hal_intr_disable(gpio_hal_context_t *hal, uint32_t gpio_num);
* in output mode: the output level of the pad will be force locked and can not be changed.
* in input mode: the input value read will not change, regardless the changes of input signal.
*
* The state of digital gpio cannot be held during Deep-sleep, and it will resume the hold function
* when the chip wakes up from Deep-sleep. If the digital gpio also needs to be held during Deep-sleep,
* On ESP32/S2/C3/S3/C2, the state of digital gpio cannot be held during Deep-sleep, and it will resume the hold
* function when the chip wakes up from Deep-sleep. If the digital gpio also needs to be held during Deep-sleep,
* `gpio_deep_sleep_hold_en` should also be called.
*
* Power down or call gpio_hold_dis will disable this function.
@ -285,6 +285,7 @@ void gpio_hal_intr_disable(gpio_hal_context_t *hal, uint32_t gpio_num);
*/
#define gpio_hal_is_digital_io_hold(hal, gpio_num) gpio_ll_is_digital_io_hold((hal)->dev, gpio_num)
#if !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
/**
* @brief Enable all digital gpio pad hold function during Deep-sleep.
*
@ -315,6 +316,7 @@ void gpio_hal_intr_disable(gpio_hal_context_t *hal, uint32_t gpio_num);
* - false deep sleep hold is disabled
*/
#define gpio_hal_deep_sleep_hold_is_en(hal) gpio_ll_deep_sleep_hold_is_en((hal)->dev)
#endif //!SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
/**
* @brief Set pad input to a peripheral signal through the IOMUX.
@ -448,7 +450,7 @@ void gpio_hal_sleep_pupd_config_apply(gpio_hal_context_t *hal, uint32_t gpio_num
void gpio_hal_sleep_pupd_config_unapply(gpio_hal_context_t *hal, uint32_t gpio_num);
#endif // CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL
#if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP
#if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP && (SOC_RTCIO_PIN_COUNT == 0)
/**
* @brief Enable GPIO deep-sleep wake-up function.
*

View File

@ -39,7 +39,7 @@ typedef struct rtc_cntl_sleep_retent {
#define RTC_HAL_DMA_LINK_NODE_SIZE (16)
#if SOC_PM_SUPPORT_EXT_WAKEUP
#if SOC_PM_SUPPORT_EXT1_WAKEUP
#define rtc_hal_ext1_get_wakeup_status() rtc_cntl_ll_ext1_get_wakeup_status()
@ -51,9 +51,9 @@ typedef struct rtc_cntl_sleep_retent {
#define rtc_hal_ext1_get_wakeup_pins() rtc_cntl_ll_ext1_get_wakeup_pins()
#endif
#endif // SOC_PM_SUPPORT_EXT1_WAKEUP
#if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP
#if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP && (SOC_RTCIO_PIN_COUNT == 0)
#define rtc_hal_gpio_get_wakeup_status() rtc_cntl_ll_gpio_get_wakeup_status()

View File

@ -254,6 +254,36 @@ void rtcio_hal_isolate(int rtc_num);
#endif
#if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP && (SOC_RTCIO_PIN_COUNT > 0)
#define gpio_hal_deepsleep_wakeup_enable(hal, gpio_num, intr_type) rtcio_hal_wakeup_enable(gpio_num, intr_type)
#define gpio_hal_deepsleep_wakeup_disable(hal, gpio_num) rtcio_hal_wakeup_disable(gpio_num)
#define gpio_hal_deepsleep_wakeup_is_enabled(hal, gpio_num) rtcio_hal_wakeup_is_enabled(gpio_num)
#define rtc_hal_gpio_get_wakeup_status() rtcio_hal_get_interrupt_status()
#define rtc_hal_gpio_clear_wakeup_status() rtcio_hal_clear_interrupt_status()
/**
* @brief Get the status of whether an IO is used for sleep wake-up.
*
* @param hw Peripheral GPIO hardware instance address.
* @param rtcio_num GPIO number
* @return True if the pin is enabled to wake up from deep-sleep
*/
#define rtcio_hal_wakeup_is_enabled(rtcio_num) rtcio_ll_wakeup_is_enabled(rtcio_num)
/**
* @brief Get the rtc io interrupt status
*
* @return bit 0~7 corresponding to 0 ~ SOC_RTCIO_PIN_COUNT.
*/
#define rtcio_hal_get_interrupt_status() rtcio_ll_get_interrupt_status()
/**
* @brief Clear all LP IO pads status
*/
#define rtcio_hal_clear_interrupt_status() rtcio_ll_clear_interrupt_status()
#endif //SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP
#ifdef __cplusplus
}
#endif

View File

@ -719,6 +719,14 @@ config SOC_PHY_DIG_REGS_MEM_SIZE
int
default 21
config SOC_PM_SUPPORT_EXT0_WAKEUP
bool
default y
config SOC_PM_SUPPORT_EXT1_WAKEUP
bool
default y
config SOC_PM_SUPPORT_EXT_WAKEUP
bool
default y

View File

@ -365,7 +365,10 @@
#define SOC_PHY_DIG_REGS_MEM_SIZE (21*4)
/*-------------------------- Power Management CAPS ---------------------------*/
#define SOC_PM_SUPPORT_EXT_WAKEUP (1)
#define SOC_PM_SUPPORT_EXT0_WAKEUP (1)
#define SOC_PM_SUPPORT_EXT1_WAKEUP (1)
#define SOC_PM_SUPPORT_EXT_WAKEUP (1) /*!<Compatible to the old version of IDF */
#define SOC_PM_SUPPORT_TOUCH_SENSOR_WAKEUP (1) /*!<Supports waking up from touch pad trigger */
#define SOC_PM_SUPPORT_RTC_PERIPH_PD (1)
#define SOC_PM_SUPPORT_RTC_FAST_MEM_PD (1)

View File

@ -171,6 +171,10 @@ config SOC_LP_TIMER_SUPPORTED
bool
default y
config SOC_LP_AON_SUPPORTED
bool
default y
config SOC_XTAL_SUPPORT_40M
bool
default y
@ -403,6 +407,14 @@ config SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK
hex
default 0x000000007FFFFF00
config SOC_GPIO_SUPPORT_FORCE_HOLD
bool
default y
config SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
bool
default y
config SOC_RTCIO_PIN_COUNT
int
default 8
@ -415,6 +427,10 @@ config SOC_RTCIO_HOLD_SUPPORTED
bool
default y
config SOC_RTCIO_WAKE_SUPPORTED
bool
default y
config SOC_DEDIC_GPIO_OUT_CHANNELS_NUM
int
default 8
@ -1035,6 +1051,10 @@ config SOC_PM_SUPPORT_BT_WAKEUP
bool
default y
config SOC_PM_SUPPORT_EXT1_WAKEUP
bool
default y
config SOC_PM_SUPPORT_CPU_PD
bool
default y

View File

@ -68,6 +68,7 @@
#define SOC_PMU_SUPPORTED 1
#define SOC_PAU_SUPPORTED 1
#define SOC_LP_TIMER_SUPPORTED 1
#define SOC_LP_AON_SUPPORTED 1
/*-------------------------- XTAL CAPS ---------------------------------------*/
#define SOC_XTAL_SUPPORT_40M 1
@ -186,11 +187,16 @@
// digital I/O pad powered by VDD3P3_CPU or VDD_SPI(GPIO_NUM_8~GPIO_NUM_30)
#define SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK 0x000000007FFFFF00ULL
// Support to force hold all IOs
#define SOC_GPIO_SUPPORT_FORCE_HOLD (1)
// Support to hold a single digital I/O when the digital domain is powered off
#define SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP (1)
/*-------------------------- RTCIO CAPS --------------------------------------*/
#define SOC_RTCIO_PIN_COUNT 8
#define SOC_RTCIO_INPUT_OUTPUT_SUPPORTED 1
#define SOC_RTCIO_HOLD_SUPPORTED 1
// #define SOC_RTCIO_WAKE_SUPPORTED 1 // TODO: IDF-5645
#define SOC_RTCIO_WAKE_SUPPORTED 1
/*-------------------------- Dedicated GPIO CAPS -----------------------------*/
#define SOC_DEDIC_GPIO_OUT_CHANNELS_NUM (8) /*!< 8 outward channels on each CPU core */
@ -439,6 +445,7 @@
/*-------------------------- Power Management CAPS ----------------------------*/
#define SOC_PM_SUPPORT_WIFI_WAKEUP (1)
#define SOC_PM_SUPPORT_BT_WAKEUP (1)
#define SOC_PM_SUPPORT_EXT1_WAKEUP (1)
#define SOC_PM_SUPPORT_CPU_PD (1)
#define SOC_PM_SUPPORT_MODEM_PD (1)
#define SOC_PM_SUPPORT_XTAL32K_PD (1)

View File

@ -379,6 +379,14 @@ config SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK
hex
default 0x000000000FFF807F
config SOC_GPIO_SUPPORT_FORCE_HOLD
bool
default y
config SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
bool
default y
config SOC_DEDIC_GPIO_OUT_CHANNELS_NUM
int
default 8

View File

@ -184,6 +184,11 @@
// digital I/O pad powered by VDD3P3_CPU or VDD_SPI(GPIO_NUM_0~6. GPIO_NUM_15~27)
#define SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK 0x000000000FFF807FULL
// Support to force hold all IOs
#define SOC_GPIO_SUPPORT_FORCE_HOLD (1)
// Support to hold a single digital I/O when the digital domain is powered off
#define SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP (1)
/*-------------------------- Dedicated GPIO CAPS -----------------------------*/
#define SOC_DEDIC_GPIO_OUT_CHANNELS_NUM (8) /*!< 8 outward channels on each CPU core */
#define SOC_DEDIC_GPIO_IN_CHANNELS_NUM (8) /*!< 8 inward channels on each CPU core */

View File

@ -319,6 +319,10 @@ config SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK
hex
default 0x000001FFFFFFFFC0
config SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
bool
default y
config SOC_DEDIC_GPIO_OUT_CHANNELS_NUM
int
default 8

View File

@ -172,6 +172,12 @@
#define SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK 0x0000000003FFE07FULL
#endif
#if CONFIG_IDF_TARGET_ESP32H4_BETA_VERSION_2
// Support to hold a single GPIO when the digital domain is powered off
// ESP32H4-BETA1 only supports hold all in deepsleep
#define SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP (1)
#endif
/*-------------------------- Dedicated GPIO CAPS -----------------------------*/
#define SOC_DEDIC_GPIO_OUT_CHANNELS_NUM (8) /*!< 8 outward channels on each CPU core */
#define SOC_DEDIC_GPIO_IN_CHANNELS_NUM (8) /*!< 8 inward channels on each CPU core */

View File

@ -951,6 +951,14 @@ config SOC_SPI_MEM_SUPPORT_WRAP
bool
default y
config SOC_PM_SUPPORT_EXT0_WAKEUP
bool
default y
config SOC_PM_SUPPORT_EXT1_WAKEUP
bool
default y
config SOC_PM_SUPPORT_EXT_WAKEUP
bool
default y

View File

@ -414,7 +414,10 @@
#define SOC_SPI_MEM_SUPPORT_WRAP (1)
/*-------------------------- Power Management CAPS ---------------------------*/
#define SOC_PM_SUPPORT_EXT_WAKEUP (1)
#define SOC_PM_SUPPORT_EXT0_WAKEUP (1)
#define SOC_PM_SUPPORT_EXT1_WAKEUP (1)
#define SOC_PM_SUPPORT_EXT_WAKEUP (1) /*!<Compatible to the old version of IDF */
#define SOC_PM_SUPPORT_WIFI_WAKEUP (1)
#define SOC_PM_SUPPORT_WIFI_PD (1)
#define SOC_PM_SUPPORT_RTC_PERIPH_PD (1)

View File

@ -983,6 +983,14 @@ config SOC_AES_SUPPORT_AES_256
bool
default y
config SOC_PM_SUPPORT_EXT0_WAKEUP
bool
default y
config SOC_PM_SUPPORT_EXT1_WAKEUP
bool
default y
config SOC_PM_SUPPORT_EXT_WAKEUP
bool
default y

View File

@ -404,7 +404,10 @@
/*-------------------------- Power Management CAPS ---------------------------*/
#define SOC_PM_SUPPORT_EXT_WAKEUP (1)
#define SOC_PM_SUPPORT_EXT0_WAKEUP (1)
#define SOC_PM_SUPPORT_EXT1_WAKEUP (1)
#define SOC_PM_SUPPORT_EXT_WAKEUP (1) /*!<Compatible to the old version of IDF */
#define SOC_PM_SUPPORT_WIFI_WAKEUP (1)
#define SOC_PM_SUPPORT_BT_WAKEUP (1)
#define SOC_PM_SUPPORT_TOUCH_SENSOR_WAKEUP (1) /*!<Supports waking up from touch pad trigger */

View File

@ -36,7 +36,6 @@ api-reference/network/esp-wifi-mesh
api-reference/network/esp_smartconfig
api-reference/network/esp_wifi
api-reference/network/index
api-reference/system/sleep_modes
api-reference/system/ulp_macros
api-reference/system/ulp
api-reference/system/efuse

View File

@ -42,7 +42,7 @@ Dynamic frequency scaling (DFS) and automatic light sleep can be enabled in an a
In light sleep, peripherals are clock gated, and interrupts (from GPIOs and internal peripherals) will not be generated. A wakeup source described in the :doc:`sleep_modes` documentation can be used to trigger wakeup from the light sleep state.
.. only:: SOC_PM_SUPPORT_EXT_WAKEUP
.. only:: SOC_PM_SUPPORT_EXT0_WAKEUP or SOC_PM_SUPPORT_EXT1_WAKEUP
For example, the EXT0 and EXT1 wakeup sources can be used to wake up the chip via a GPIO.

View File

@ -71,7 +71,7 @@ RTC peripherals or RTC memories don't need to be powered on during sleep in this
:cpp:func:`esp_sleep_enable_touchpad_wakeup` function can be used to enable this wakeup source.
.. only:: SOC_PM_SUPPORT_EXT_WAKEUP
.. only:: SOC_PM_SUPPORT_EXT0_WAKEUP or SOC_PM_SUPPORT_EXT1_WAKEUP
External Wakeup (ext0)
^^^^^^^^^^^^^^^^^^^^^^
@ -127,11 +127,11 @@ RTC peripherals or RTC memories don't need to be powered on during sleep in this
GPIO Wakeup (Light-sleep Only)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. only:: SOC_PM_SUPPORT_EXT_WAKEUP
.. only:: (SOC_PM_SUPPORT_EXT0_WAKEUP or SOC_PM_SUPPORT_EXT1_WAKEUP)
In addition to EXT0 and EXT1 wakeup sources described above, one more method of wakeup from external inputs is available in Light-sleep mode. With this wakeup source, each pin can be individually configured to trigger wakeup on high or low level using :cpp:func:`gpio_wakeup_enable` function. Unlike EXT0 and EXT1 wakeup sources, which can only be used with RTC IOs, this wakeup source can be used with any IO (RTC or digital).
.. only:: not SOC_PM_SUPPORT_EXT_WAKEUP
.. only:: not (SOC_PM_SUPPORT_EXT0_WAKEUP or SOC_PM_SUPPORT_EXT1_WAKEUP)
One more method of wakeup from external inputs is available in Light-sleep mode. With this wakeup source, each pin can be individually configured to trigger wakeup on high or low level using :cpp:func:`gpio_wakeup_enable` function. This wakeup source can be used with any IO (RTC or digital).
@ -257,7 +257,7 @@ Checking Sleep Wakeup Cause
For touchpad, it is possible to identify which touch pin has caused wakeup using :cpp:func:`esp_sleep_get_touchpad_wakeup_status` functions.
.. only:: SOC_PM_SUPPORT_EXT_WAKEUP
.. only:: SOC_PM_SUPPORT_EXT1_WAKEUP
For ext1 wakeup sources, it is possible to identify which touch pin has caused wakeup using :cpp:func:`esp_sleep_get_ext1_wakeup_status` functions.

View File

@ -42,7 +42,7 @@ ESP-IDF 中集成的电源管理算法可以根据应用程序组件的需求,
Light-sleep 状态下,外设设有时钟门控,不会产生来自 GPIO 和内部外设的中断。:doc:`sleep_modes` 文档中所提到的唤醒源可用于从 Light-sleep 状态触发唤醒。
.. only:: SOC_PM_SUPPORT_EXT_WAKEUP
.. only:: SOC_PM_SUPPORT_EXT0_WAKEUP or SOC_PM_SUPPORT_EXT1_WAKEUP
例如EXT0 和 EXT1 唤醒源可以通过 GPIO 唤醒芯片。

View File

@ -71,7 +71,7 @@ RTC 控制器中内嵌定时器,可用于在预定义的时间到达后唤醒
可调用 :cpp:func:`esp_sleep_enable_touchpad_wakeup` 函数来启用该唤醒源。
.. only:: SOC_PM_SUPPORT_EXT_WAKEUP
.. only:: SOC_PM_SUPPORT_EXT0_WAKEUP or SOC_PM_SUPPORT_EXT1_WAKEUP
外部唤醒 (ext0)
^^^^^^^^^^^^^^^^^^^^^^
@ -127,11 +127,11 @@ RTC 控制器中内嵌定时器,可用于在预定义的时间到达后唤醒
GPIO 唤醒(仅适用于 Light-sleep 模式)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. only:: SOC_PM_SUPPORT_EXT_WAKEUP
.. only:: SOC_PM_SUPPORT_EXT0_WAKEUP or SOC_PM_SUPPORT_EXT1_WAKEUP
除了上述 EXT0 和 EXT1 唤醒源之外,还有一种从外部唤醒 Light-sleep 模式的方法——使用函数 :cpp:func:`gpio_wakeup_enable`。启用该唤醒源后可将每个管脚单独配置为在高电平或低电平时唤醒。EXT0 和 EXT1 唤醒源只能用于 RTC IO但此唤醒源既可以用于 RTC IO可也用于数字 IO。
.. only:: not SOC_PM_SUPPORT_EXT_WAKEUP
.. only:: not (SOC_PM_SUPPORT_EXT0_WAKEUP or SOC_PM_SUPPORT_EXT1_WAKEUP)
此外,还有一种从外部唤醒 Light-sleep 模式的方法。启用该唤醒源后,可将每个管脚单独配置为在高电平或低电平时调用 :cpp:func:`gpio_wakeup_enable` 函数触发唤醒。此唤醒源既可以用于 RTC IO可也用于数字 IO。
@ -257,7 +257,7 @@ UART 输出处理
对于触摸传感器唤醒源,可以调用函数 :cpp:func:`esp_sleep_get_touchpad_wakeup_status` 来确认触发唤醒的触摸管脚。
.. only:: SOC_PM_SUPPORT_EXT_WAKEUP
.. only:: SOC_PM_SUPPORT_EXT1_WAKEUP
对于 ext1 唤醒源,可以调用函数 :cpp:func:`esp_sleep_get_ext1_wakeup_status` 来确认触发唤醒的触摸管脚。

View File

@ -216,7 +216,7 @@ static int deep_sleep(int argc, char **argv)
ESP_LOGI(TAG, "Enabling wakeup on GPIO%d, wakeup on %s level",
io_num, level ? "HIGH" : "LOW");
#if SOC_PM_SUPPORT_EXT_WAKEUP
#if SOC_PM_SUPPORT_EXT1_WAKEUP
ESP_ERROR_CHECK( esp_sleep_enable_ext1_wakeup(1ULL << io_num, level) );
#endif
}

View File

@ -40,13 +40,13 @@ examples/system/console/basic:
examples/system/deep_sleep:
disable:
- if: IDF_TARGET in ["esp32c2", "esp32c6", "esp32h2"]
- if: IDF_TARGET in ["esp32c2", "esp32h2"]
temporary: true
reason: target(s) not supported yet
reason: target(s) not supported yet # IDF-5432 / IDF-6268
examples/system/deep_sleep_wake_stub:
disable:
- if: IDF_TARGET in ["esp32c2", "esp32c6", "esp32h2"]
- if: IDF_TARGET in ["esp32c2", "esp32h2"]
temporary: true
reason: target(s) is not supported yet

View File

@ -224,7 +224,7 @@ static void register_tasks(void)
static struct {
struct arg_int *wakeup_time;
#if SOC_PM_SUPPORT_EXT_WAKEUP
#if SOC_PM_SUPPORT_EXT0_WAKEUP || SOC_PM_SUPPORT_EXT1_WAKEUP
struct arg_int *wakeup_gpio_num;
struct arg_int *wakeup_gpio_level;
#endif
@ -245,7 +245,7 @@ static int deep_sleep(int argc, char **argv)
ESP_ERROR_CHECK( esp_sleep_enable_timer_wakeup(timeout) );
}
#if SOC_PM_SUPPORT_EXT_WAKEUP
#if SOC_PM_SUPPORT_EXT1_WAKEUP
if (deep_sleep_args.wakeup_gpio_num->count) {
int io_num = deep_sleep_args.wakeup_gpio_num->ival[0];
if (!esp_sleep_is_valid_wakeup_gpio(io_num)) {
@ -266,7 +266,7 @@ static int deep_sleep(int argc, char **argv)
ESP_ERROR_CHECK( esp_sleep_enable_ext1_wakeup(1ULL << io_num, level) );
ESP_LOGE(TAG, "GPIO wakeup from deep sleep currently unsupported on ESP32-C3");
}
#endif // SOC_PM_SUPPORT_EXT_WAKEUP
#endif // SOC_PM_SUPPORT_EXT1_WAKEUP
#if CONFIG_IDF_TARGET_ESP32
rtc_gpio_isolate(GPIO_NUM_12);
@ -280,7 +280,7 @@ static void register_deep_sleep(void)
int num_args = 1;
deep_sleep_args.wakeup_time =
arg_int0("t", "time", "<t>", "Wake up time, ms");
#if SOC_PM_SUPPORT_EXT_WAKEUP
#if SOC_PM_SUPPORT_EXT0_WAKEUP || SOC_PM_SUPPORT_EXT1_WAKEUP
deep_sleep_args.wakeup_gpio_num =
arg_int0(NULL, "io", "<n>",
"If specified, wakeup using GPIO with given number");
@ -293,7 +293,7 @@ static void register_deep_sleep(void)
const esp_console_cmd_t cmd = {
.command = "deep_sleep",
.help = "Enter deep sleep mode. "
#if SOC_PM_SUPPORT_EXT_WAKEUP
#if SOC_PM_SUPPORT_EXT0_WAKEUP || SOC_PM_SUPPORT_EXT1_WAKEUP
"Two wakeup modes are supported: timer and GPIO. "
#else
"Timer wakeup mode is supported. "

View File

@ -1,5 +1,5 @@
| Supported Targets | ESP32 | ESP32-C3 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- |
| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- |
# Deep Sleep Example
@ -11,7 +11,7 @@ The following wake up sources are demonstrated in this example (refer to the [Wa
- **Timer:** An RTC timer that can be programmed to trigger a wake up after a preset time. This example will trigger a wake up every 20 seconds.
- **EXT0:** External wake up 0 can trigger wakeup when one predefined RTC GPIO is at a predefined logic level. This example uses GPIO25 in ESP32 or GPIO3 in ESP32-S2/S3 to trigger a wake up when the pin is HIGH. (This wake up source is only available on ESP32, ESP32-S2, and ESP32-S3.)
- **EXT1:** External wake up 1 which is tied to multiple RTC GPIOs. This example uses GPIO2 and GPIO4 to trigger a wake up with any one of the two pins are HIGH. (This wake up source is only available on ESP32, ESP32-S2, and ESP32-S3.)
- **EXT1:** External wake up 1 which is tied to multiple RTC GPIOs. This example uses GPIO2 and GPIO4 to trigger a wake up with any one of the two pins are HIGH. (This wake up source is available on ESP32, ESP32-S2, ESP32-S3 and ESP32-C6.)
- **GPIO:** Pads powered by VDD3P3_RTC can be used to trigger a wake up from deep sleep. You may choose the pin and trigger level in menuconfig. (This wake up source is unavailable on ESP32, ESP32-S2, and ESP32-S3.)
- **Touch:** Touch pad sensor interrupt. This example uses touch pads connected to GPIO32, GPIO33 in ESP32 or GPIO9 in ESP32-S2/S3 to trigger a wake up when any of the pads are pressed.
- **ULP:** Ultra Low Power Coprocessor which can continue to run during deep sleep. This example utilizes the ULP and constantly sample the chip's temperature and trigger a wake up if the chips temperature exceeds ~5 degrees Celsius.

View File

@ -15,7 +15,7 @@ menu "Example Configuration"
bool "Enable wakeup from GPIO (ext0)"
default y if !IDF_TARGET_ESP32
default n if IDF_TARGET_ESP32
depends on SOC_PM_SUPPORT_EXT_WAKEUP
depends on SOC_PM_SUPPORT_EXT0_WAKEUP
help
This option enables wake up from deep sleep from GPIO25(ESP32)/GPIO3(ESP32S2,S3). The pin should be
connected to LOW to avoid being in a floating state. When triggering a wake up, connect the pin to HIGH.
@ -26,7 +26,7 @@ menu "Example Configuration"
config EXAMPLE_EXT1_WAKEUP
bool "Enable wakeup from GPIO (ext1)"
default y
depends on SOC_PM_SUPPORT_EXT_WAKEUP
depends on SOC_PM_SUPPORT_EXT1_WAKEUP
help
This option enables wake up from deep sleep from GPIO2 and GPIO4. They should be connected to LOW to avoid
floating pins. When triggering a wake up, connect one or both of the pins to HIGH. Note that floating
@ -62,6 +62,7 @@ menu "Example Configuration"
int "Enable wakeup from GPIO"
default 0 if !IDF_TARGET_ESP32H4_BETA_VERSION_2
default 7 if IDF_TARGET_ESP32H4_BETA_VERSION_2
range 0 7 if IDF_TARGET_ESP32C6
range 0 5 if !IDF_TARGET_ESP32H4_BETA_VERSION_2
range 7 12 if IDF_TARGET_ESP32H4_BETA_VERSION_2

View File

@ -133,7 +133,9 @@ void app_main(void)
* during deepsleep. However, RTC IO relies on the RTC_PERIPH power domain. Keeping this power domain on will
* increase some power comsumption. */
# if CONFIG_EXAMPLE_EXT1_USE_INTERNAL_PULLUPS
#if SOC_PM_SUPPORT_RTC_PERIPH_PD
ESP_ERROR_CHECK(esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON));
#endif
ESP_ERROR_CHECK(rtc_gpio_pullup_dis(ext_wakeup_pin_1));
ESP_ERROR_CHECK(rtc_gpio_pulldown_en(ext_wakeup_pin_1));
ESP_ERROR_CHECK(rtc_gpio_pullup_dis(ext_wakeup_pin_2));

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import logging
@ -12,7 +12,7 @@ touch_wake_up_support = ['esp32', 'esp32s2']
CONFIGS = [
pytest.param('esp32_singlecore', marks=[pytest.mark.esp32]),
pytest.param('basic', marks=[pytest.mark.esp32, pytest.mark.esp32s2, pytest.mark.esp32s3, pytest.mark.esp32c3]),
pytest.param('basic', marks=[pytest.mark.esp32, pytest.mark.esp32s2, pytest.mark.esp32s3, pytest.mark.esp32c3, pytest.mark.esp32c6]),
]

View File

@ -1,5 +1,5 @@
| Supported Targets | ESP32 | ESP32-C3 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- |
| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- |
# Deep Sleep Wake Stub Example

View File

@ -43,7 +43,6 @@ void app_main(void)
rtc_gpio_isolate(GPIO_NUM_12);
#endif
// Set the wake stub function
esp_set_deep_sleep_wake_stub(&wake_stub_example);
printf("Entering deep sleep\n");

View File

@ -12,6 +12,7 @@ from pytest_embedded import Dut
@pytest.mark.esp32s2
@pytest.mark.esp32s3
@pytest.mark.esp32c3
@pytest.mark.esp32c6
@pytest.mark.generic
@pytest.mark.parametrize('config', ['default',], indirect=True)
def test_deep_sleep_wake_stub(config: str, dut: Dut) -> None: