Merge branch 'bugfix/wakeup_io_hold_unhold_in_sleep_v4.4' into 'release/v4.4'

gpio: Fix deep sleep wakeup IOs unable to unhold after wakeup (v4.4)

See merge request espressif/esp-idf!22670
This commit is contained in:
morris 2023-04-21 10:51:05 +08:00
commit 9516e80f61
27 changed files with 360 additions and 204 deletions

View File

@ -690,10 +690,10 @@ void gpio_deep_sleep_hold_dis(void)
#if SOC_GPIO_SUPPORT_FORCE_HOLD
esp_err_t gpio_force_hold_all()
esp_err_t IRAM_ATTR gpio_force_hold_all()
{
#if SOC_RTCIO_HOLD_SUPPORTED
rtc_gpio_force_hold_all();
rtc_gpio_force_hold_en_all();
#endif
portENTER_CRITICAL(&gpio_context.gpio_spinlock);
gpio_hal_force_hold_all(gpio_context.gpio_hal);
@ -701,14 +701,14 @@ esp_err_t gpio_force_hold_all()
return ESP_OK;
}
esp_err_t gpio_force_unhold_all()
esp_err_t IRAM_ATTR gpio_force_unhold_all()
{
#if SOC_RTCIO_HOLD_SUPPORTED
rtc_gpio_force_hold_dis_all();
#endif
portENTER_CRITICAL(&gpio_context.gpio_spinlock);
gpio_hal_force_unhold_all();
portEXIT_CRITICAL(&gpio_context.gpio_spinlock);
#if SOC_RTCIO_HOLD_SUPPORTED
rtc_gpio_force_hold_dis_all();
#endif
return ESP_OK;
}
#endif

View File

@ -364,16 +364,21 @@ esp_err_t gpio_get_drive_capability(gpio_num_t gpio_num, gpio_drive_cap_t *stren
/**
* @brief Enable gpio pad hold function.
*
* When the pin is set to hold, the state is latched at that moment and will not change no matter how the internal
* signals change or how the IO MUX/GPIO configuration is modified (including input enable, output enable,
* output value, function, and drive strength values). It can be used to retain the pin state through a
* core reset and system reset triggered by watchdog time-out or Deep-sleep events.
*
* The gpio pad hold function works in both input and output modes, but must be output-capable gpios.
* If pad hold enabled:
* 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.
* in input mode: input read value can still reflect the changes of the input signal.
*
* The state of digital gpio cannot be held during Deep-sleep, and it will resume the hold function
* The state of the digital gpio cannot be held during Deep-sleep, and it will resume to hold at its default pin state
* 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.
* Power down or call `gpio_hold_dis` will disable this function.
*
* @param gpio_num GPIO number, only support output-capable GPIOs
*
@ -403,19 +408,21 @@ esp_err_t gpio_hold_en(gpio_num_t gpio_num);
esp_err_t gpio_hold_dis(gpio_num_t gpio_num);
/**
* @brief Enable all digital gpio pad hold function during Deep-sleep.
* @brief Enable all digital gpio pads hold function during Deep-sleep.
*
* When the chip is in Deep-sleep mode, all digital gpio will hold the state before sleep, and when the chip is woken up,
* the status of digital gpio will not be held. Note that the pad hold feature only works when the chip is in Deep-sleep mode,
* when not in sleep mode, the digital gpio state can be changed even you have called this function.
* Enabling this feature makes all digital gpio pads be at the holding state during Deep-sleep. The state of each pad
* holds is its active configuration (not pad's sleep configuration!).
*
* Power down or call gpio_hold_dis will disable this function, otherwise, the digital gpio hold feature works as long as the chip enter Deep-sleep.
* Note that this pad hold feature only works when the chip is in Deep-sleep mode. When the chip is in active mode,
* the digital gpio state can be changed freely even you have called this function.
*
* After this API is being called, the digital gpio Deep-sleep hold feature will work during every sleep process. You
* should call `gpio_deep_sleep_hold_dis` to disable this feature.
*/
void gpio_deep_sleep_hold_en(void);
/**
* @brief Disable all digital gpio pad hold function during Deep-sleep.
*
* @brief Disable all digital gpio pads hold function during Deep-sleep.
*/
void gpio_deep_sleep_hold_dis(void);
@ -437,14 +444,21 @@ void gpio_iomux_out(uint8_t gpio_num, int func, bool oen_inv);
#if SOC_GPIO_SUPPORT_FORCE_HOLD
/**
* @brief Force hold digital and rtc gpio pad.
* @note GPIO force hold, whether the chip in sleep mode or wakeup mode.
* @brief Force hold all digital and rtc gpio pads.
*
* GPIO force hold, no matter the chip in active mode or sleep modes.
*
* This function will immediately cause all pads to latch the current values of input enable, output enable,
* output value, function, and drive strength values.
*
* @warning This function will hold flash and UART pins as well. Therefore, this function, and all code run afterwards
* (till calling `gpio_force_unhold_all` to disable this feature), MUST be placed in internal RAM as holding the flash
* pins will halt SPI flash operation, and holding the UART pins will halt any UART logging.
* */
esp_err_t gpio_force_hold_all(void);
/**
* @brief Force unhold digital and rtc gpio pad.
* @note GPIO force unhold, whether the chip in sleep mode or wakeup mode.
* @brief Force unhold all digital and rtc gpio pads.
* */
esp_err_t gpio_force_unhold_all(void);
#endif

View File

@ -269,7 +269,7 @@ esp_err_t rtc_gpio_isolate(gpio_num_t gpio_num);
* Force hold signal is enabled before going into deep sleep for pins which
* are used for EXT1 wakeup.
*/
esp_err_t rtc_gpio_force_hold_all(void);
esp_err_t rtc_gpio_force_hold_en_all(void);
/**
* @brief Disable force hold signal for all RTC IOs

View File

@ -21,7 +21,7 @@
#include "esp_log.h"
#include "soc/rtc_io_periph.h"
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3, ESP32C3)
#if SOC_RTCIO_PIN_COUNT > 0
#define RTCIO_CHECK(condition) TEST_ASSERT_MESSAGE((condition == ESP_OK), "ret is not ESP_OK")
#define RTCIO_VERIFY(condition, msg) TEST_ASSERT_MESSAGE((condition), msg)
@ -77,6 +77,32 @@ const int s_test_map[TEST_GPIO_PIN_COUNT] = {
GPIO_NUM_20, //GPIO20
GPIO_NUM_21, //GPIO21
};
#elif defined CONFIG_IDF_TARGET_ESP32S3
#define TEST_GPIO_PIN_COUNT 21
const int s_test_map[TEST_GPIO_PIN_COUNT] = {
// GPIO_NUM_0, //GPIO0 // Workaround: GPIO0 is strap pin, can not be used pullup/pulldown test.
GPIO_NUM_1, //GPIO1
GPIO_NUM_2, //GPIO2
GPIO_NUM_3, //GPIO3
GPIO_NUM_4, //GPIO4
GPIO_NUM_5, //GPIO5
GPIO_NUM_6, //GPIO6
GPIO_NUM_7, //GPIO7
GPIO_NUM_8, //GPIO8
GPIO_NUM_9, //GPIO9
GPIO_NUM_10, //GPIO10
GPIO_NUM_11, //GPIO11
GPIO_NUM_12, //GPIO12
GPIO_NUM_13, //GPIO13
GPIO_NUM_14, //GPIO14
GPIO_NUM_15, //GPIO15
GPIO_NUM_16, //GPIO16
GPIO_NUM_17, //GPIO17
GPIO_NUM_18, //GPIO18
GPIO_NUM_19, //GPIO19
GPIO_NUM_20, //GPIO20
GPIO_NUM_21, //GPIO21
};
#endif
/*
@ -276,4 +302,52 @@ TEST_CASE("RTCIO output hold test", "[rtcio]")
ESP_LOGI(TAG, "RTCIO hold test over");
}
#endif
// 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
#define TEST_RTCIO_DEEP_SLEEP_PIN_INDEX 5
static void rtcio_deep_sleep_hold_test_first_stage(void)
{
printf("configure rtcio pin to hold during deep sleep");
int io_num = s_test_map[TEST_RTCIO_DEEP_SLEEP_PIN_INDEX];
TEST_ESP_OK(esp_sleep_enable_timer_wakeup(2000000));
gpio_config_t io_conf = {
.intr_type = GPIO_INTR_DISABLE,
.mode = GPIO_MODE_INPUT_OUTPUT,
.pin_bit_mask = (1ULL << io_num),
.pull_down_en = 0,
.pull_up_en = 0,
};
gpio_config(&io_conf);
gpio_set_level(io_num, 1);
// Enable global persistence
TEST_ESP_OK(gpio_hold_en(io_num));
esp_deep_sleep_start();
}
static void rtcio_deep_sleep_hold_test_second_stage(void)
{
int io_num = s_test_map[TEST_RTCIO_DEEP_SLEEP_PIN_INDEX];
// Check reset reason is waking up from deepsleep
TEST_ASSERT_EQUAL(ESP_RST_DEEPSLEEP, esp_reset_reason());
// Pin should stay at high level after the deep sleep
TEST_ASSERT_EQUAL_INT(1, gpio_get_level(io_num));
gpio_hold_dis(io_num);
}
/*
* Test rtcio hold function during deep sleep.
* This test case can only check the hold state after waking up from deep sleep
* If you want to check that the rtcio hold function works properly during deep sleep,
* please use logic analyzer or oscillscope
*/
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 // SOC_RTCIO_PIN_COUNT > 0

View File

@ -15,7 +15,7 @@ extern "C" {
/**
* @file sleep_gpio.h
*
* This file contains declarations of GPIO related functions in light sleep mode.
* This file contains declarations of GPIO related functions in sleep modes.
*/
#if CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL
@ -41,6 +41,11 @@ void gpio_sleep_mode_config_unapply(void);
#endif // CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL
/**
* @brief Call once in startup to disable the wakeup IO pins and release their holding state after waking up from Deep-sleep
*/
void esp_deep_sleep_wakeup_io_reset(void);
#ifdef __cplusplus
}
#endif

View File

@ -234,25 +234,25 @@ esp_err_t esp_sleep_enable_ext1_wakeup(uint64_t mask, esp_sleep_ext1_wakeup_mode
* This function enables an IO pin to wake the chip from deep sleep
*
* @note This function does not modify pin configuration. The pins are
* configured in esp_sleep_start, immediately before
* entering sleep mode.
* configured inside esp_deep_sleep_start, immediately before entering sleep mode.
*
* @note You don't need to care to pull-up or pull-down before using this
* function, because this will be done in esp_sleep_start based on
* param mask you give. BTW, when you use low level to wake up the
* chip, we strongly recommand you to add external registors(pull-up).
* function, because this will be set internally in esp_deep_sleep_start
* based on the wakeup mode. BTW, when you use low level to wake up the
* chip, we strongly recommend you to add external resistors (pull-up).
*
* @param gpio_pin_mask Bit mask of GPIO numbers which will cause wakeup. Only GPIOs
* which are have RTC functionality can be used in this bit map.
* which have RTC functionality (pads that powered by VDD3P3_RTC) can be used in this bit map.
* @param mode Select logic function used to determine wakeup condition:
* - ESP_GPIO_WAKEUP_GPIO_LOW: wake up when the gpio turn to low.
* - ESP_GPIO_WAKEUP_GPIO_HIGH: wake up when the gpio turn to high.
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG if gpio num is more than 5 or mode is invalid,
* - ESP_ERR_INVALID_ARG if the mask contains any invalid deep sleep wakeup pin or wakeup mode is invalid
*/
esp_err_t esp_deep_sleep_enable_gpio_wakeup(uint64_t gpio_pin_mask, esp_deepsleep_gpio_wake_up_mode_t mode);
#endif
/**
* @brief Enable wakeup from light sleep using GPIOs
*

View File

@ -19,6 +19,8 @@
#include "driver/gpio.h"
#include "hal/gpio_hal.h"
#include "hal/rtc_io_hal.h"
#include "hal/rtc_hal.h"
#include "esp_private/gpio.h"
#include "esp_private/sleep_gpio.h"
#include "esp_private/spi_flash_os.h"
@ -133,3 +135,37 @@ IRAM_ATTR void esp_sleep_isolate_digital_gpio(void)
}
}
#endif
void esp_deep_sleep_wakeup_io_reset(void)
{
#if SOC_PM_SUPPORT_EXT_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();
for (int gpio_num = 0; gpio_num < SOC_GPIO_PIN_COUNT && rtc_io_mask != 0; ++gpio_num) {
int rtcio_num = rtc_io_num_map[gpio_num];
if ((rtc_io_mask & BIT(rtcio_num)) == 0) {
continue;
}
rtcio_hal_hold_disable(rtcio_num);
rtc_io_mask &= ~BIT(rtcio_num);
}
#endif
#if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP
uint32_t dl_io_mask = SOC_GPIO_DEEP_SLEEP_WAKEUP_VALID_GPIO_MASK;
gpio_hal_context_t gpio_hal = {
.dev = GPIO_HAL_GET_HW(GPIO_PORT_0)
};
while (dl_io_mask) {
int gpio_num = __builtin_ffs(dl_io_mask) - 1;
bool wakeup_io_enabled = gpio_hal_deepsleep_wakeup_is_enabled(&gpio_hal, gpio_num);
if (wakeup_io_enabled) {
// Disable the wakeup before releasing hold, such that wakeup status can reflect the correct wakeup pin
gpio_hal_deepsleep_wakeup_disable(&gpio_hal, gpio_num);
gpio_hal_hold_dis(&gpio_hal, gpio_num);
}
dl_io_mask &= ~BIT(gpio_num);
}
#endif
}

View File

@ -201,7 +201,7 @@ static void timer_wakeup_prepare(void);
static void touch_wakeup_prepare(void);
#endif
#if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP
static void esp_deep_sleep_wakeup_prepare(void);
static void gpio_deep_sleep_wakeup_prepare(void);
#endif
#if SOC_PM_SUPPORT_DEEPSLEEP_VERIFY_STUB_ONLY
@ -417,8 +417,8 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags)
#endif
#if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP
if (s_config.wakeup_triggers & RTC_GPIO_TRIG_EN) {
esp_deep_sleep_wakeup_prepare();
if (deep_sleep && (s_config.wakeup_triggers & RTC_GPIO_TRIG_EN)) {
gpio_deep_sleep_wakeup_prepare();
}
#endif
@ -1100,7 +1100,7 @@ static void ext1_wakeup_prepare(void)
}
// Clear state from previous wakeup
rtc_hal_ext1_clear_wakeup_pins();
rtc_hal_ext1_clear_wakeup_status();
// Set RTC IO pins and mode (any high, all low) to be used for wakeup
rtc_hal_ext1_set_wakeup_pins(s_config.ext1_rtc_gpio_mask, s_config.ext1_trigger_mode);
}
@ -1110,7 +1110,7 @@ uint64_t esp_sleep_get_ext1_wakeup_status(void)
if (esp_sleep_get_wakeup_cause() != ESP_SLEEP_WAKEUP_EXT1) {
return 0;
}
uint32_t status = rtc_hal_ext1_get_wakeup_pins();
uint32_t status = rtc_hal_ext1_get_wakeup_status();
// Translate bit map of RTC IO numbers into the bit map of GPIO numbers
uint64_t gpio_mask = 0;
for (int gpio = 0; gpio < GPIO_PIN_COUNT; ++gpio) {
@ -1135,10 +1135,10 @@ uint64_t esp_sleep_get_gpio_wakeup_status(void)
return 0;
}
return rtc_hal_gpio_get_wakeup_pins();
return rtc_hal_gpio_get_wakeup_status();
}
static void esp_deep_sleep_wakeup_prepare(void)
static void gpio_deep_sleep_wakeup_prepare(void)
{
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) {
@ -1151,9 +1151,10 @@ static void esp_deep_sleep_wakeup_prepare(void)
ESP_ERROR_CHECK(gpio_pullup_en(gpio_idx));
ESP_ERROR_CHECK(gpio_pulldown_dis(gpio_idx));
}
rtc_hal_gpio_set_wakeup_pins();
ESP_ERROR_CHECK(gpio_hold_en(gpio_idx));
}
// Clear state from previous wakeup
rtc_hal_gpio_clear_wakeup_status();
}
esp_err_t esp_deep_sleep_enable_gpio_wakeup(uint64_t gpio_pin_mask, esp_deepsleep_gpio_wake_up_mode_t mode)
@ -1169,7 +1170,7 @@ esp_err_t esp_deep_sleep_enable_gpio_wakeup(uint64_t gpio_pin_mask, esp_deepslee
continue;
}
if (!esp_sleep_is_valid_wakeup_gpio(gpio_idx)) {
ESP_LOGE(TAG, "invalid mask, please ensure gpio number is no more than 5");
ESP_LOGE(TAG, "gpio %d is an invalid deep sleep wakeup IO", gpio_idx);
return ESP_ERR_INVALID_ARG;
}
err = gpio_deep_sleep_wakeup_enable(gpio_idx, intr_type);
@ -1182,7 +1183,6 @@ esp_err_t esp_deep_sleep_enable_gpio_wakeup(uint64_t gpio_pin_mask, esp_deepslee
}
}
s_config.wakeup_triggers |= RTC_GPIO_TRIG_EN;
rtc_hal_gpio_clear_wakeup_pins();
return err;
}

View File

@ -66,8 +66,7 @@
#include "esp_private/crosscore_int.h"
#include "esp_flash_encrypt.h"
#include "hal/rtc_io_hal.h"
#include "hal/gpio_hal.h"
#include "esp_private/sleep_gpio.h"
#include "hal/wdt_hal.h"
#include "soc/rtc.h"
#include "soc/efuse_reg.h"
@ -536,11 +535,10 @@ void IRAM_ATTR call_start_cpu0(void)
#endif
#endif
#if SOC_RTCIO_HOLD_SUPPORTED
rtcio_hal_unhold_all();
#else
gpio_hal_force_unhold_all();
#endif
// 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();
}
esp_cache_err_int_init();

View File

@ -20,12 +20,12 @@ static inline void rtc_cntl_ll_set_wakeup_timer(uint64_t t)
WRITE_PERI_REG(RTC_CNTL_SLP_TIMER1_REG, t >> 32);
}
static inline void rtc_cntl_ll_ext1_clear_wakeup_pins(void)
static inline void rtc_cntl_ll_ext1_clear_wakeup_status(void)
{
REG_SET_BIT(RTC_CNTL_EXT_WAKEUP1_REG, RTC_CNTL_EXT_WAKEUP1_STATUS_CLR);
}
static inline uint32_t rtc_cntl_ll_ext1_get_wakeup_pins(void)
static inline uint32_t rtc_cntl_ll_ext1_get_wakeup_status(void)
{
return REG_GET_FIELD(RTC_CNTL_EXT_WAKEUP1_STATUS_REG, RTC_CNTL_EXT_WAKEUP1_STATUS);
}
@ -37,6 +37,16 @@ static inline void rtc_cntl_ll_ext1_set_wakeup_pins(uint32_t mask, int mode)
mode, RTC_CNTL_EXT_WAKEUP1_LV_S);
}
static inline void rtc_cntl_ll_ext1_clear_wakeup_pins(void)
{
CLEAR_PERI_REG_MASK(RTC_CNTL_EXT_WAKEUP1_REG, RTC_CNTL_EXT_WAKEUP1_SEL_M);
}
static inline uint32_t rtc_cntl_ll_ext1_get_wakeup_pins(void)
{
return REG_GET_FIELD(RTC_CNTL_EXT_WAKEUP1_REG, RTC_CNTL_EXT_WAKEUP1_SEL);
}
static inline void rtc_cntl_ll_ulp_wakeup_enable(void)
{
SET_PERI_REG_MASK(RTC_CNTL_STATE0_REG, RTC_CNTL_ULP_CP_WAKEUP_FORCE_EN);

View File

@ -209,7 +209,7 @@ static inline void rtcio_ll_pulldown_disable(int rtcio_num)
}
/**
* Enable force hold function for RTC IO pad.
* Enable force hold function on an RTC IO pad.
*
* Enabling HOLD function will cause the pad to lock current status, such as,
* input/output enable, input/output value, function, drive strength values.
@ -225,7 +225,7 @@ static inline void rtcio_ll_force_hold_enable(int rtcio_num)
}
/**
* Disable hold function on an RTC IO pad
* Disable hold function on an RTC IO pad.
*
* @note If disable the pad hold, the status of pad maybe changed in sleep mode.
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
@ -237,7 +237,7 @@ static inline void rtcio_ll_force_hold_disable(int rtcio_num)
}
/**
* Enable force hold function for RTC IO pad.
* Enable force hold function on all RTC IO pads.
*
* Enabling HOLD function will cause the pad to lock current status, such as,
* input/output enable, input/output value, function, drive strength values.
@ -252,7 +252,7 @@ static inline void rtcio_ll_force_hold_all(void)
}
/**
* Disable hold function on an RTC IO pad
* Disable hold function on all RTC IO pads.
*
* @note If disable the pad hold, the status of pad maybe changed in sleep mode.
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).

View File

@ -475,9 +475,9 @@ static inline void gpio_ll_force_hold_all(gpio_dev_t *hw)
static inline void gpio_ll_force_unhold_all(void)
{
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_HOLD);
CLEAR_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_PAD_FORCE_HOLD_M);
SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_UNHOLD);
SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_CLR_DG_PAD_AUTOHOLD);
CLEAR_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_PAD_FORCE_HOLD_M);
}
/**
@ -626,6 +626,22 @@ static inline void gpio_ll_deepsleep_wakeup_disable(gpio_dev_t *hw, gpio_num_t g
CLEAR_PERI_REG_MASK(RTC_CNTL_GPIO_WAKEUP_REG, RTC_CNTL_GPIO_PIN0_INT_TYPE_S - gpio_num * 3);
}
/**
* @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)
{
if (gpio_num > GPIO_NUM_5) {
abort(); // gpio lager than 5 doesn't support.
}
return GET_PERI_REG_MASK(RTC_CNTL_GPIO_WAKEUP_REG, 1 << (RTC_CNTL_GPIO_PIN0_WAKEUP_ENABLE_S - gpio_num));
}
#ifdef __cplusplus
}
#endif

View File

@ -32,19 +32,15 @@ static inline void rtc_cntl_ll_set_wakeup_timer(uint64_t t)
SET_PERI_REG_MASK(RTC_CNTL_SLP_TIMER1_REG, RTC_CNTL_MAIN_TIMER_ALARM_EN_M);
}
static inline uint32_t rtc_cntl_ll_gpio_get_wakeup_pins(void)
static inline uint32_t rtc_cntl_ll_gpio_get_wakeup_status(void)
{
return GET_PERI_REG_MASK(RTC_CNTL_GPIO_WAKEUP_REG, RTC_CNTL_GPIO_WAKEUP_STATUS);
}
static inline void rtc_cntl_ll_gpio_set_wakeup_pins(void)
{
REG_CLR_BIT(RTC_CNTL_GPIO_WAKEUP_REG, RTC_CNTL_GPIO_WAKEUP_STATUS_CLR);
}
static inline void rtc_cntl_ll_gpio_clear_wakeup_pins(void)
static inline void rtc_cntl_ll_gpio_clear_wakeup_status(void)
{
REG_SET_BIT(RTC_CNTL_GPIO_WAKEUP_REG, RTC_CNTL_GPIO_WAKEUP_STATUS_CLR);
REG_CLR_BIT(RTC_CNTL_GPIO_WAKEUP_REG, RTC_CNTL_GPIO_WAKEUP_STATUS_CLR);
}
static inline void rtc_cntl_ll_set_cpu_retention_link_addr(uint32_t addr)

View File

@ -14,12 +14,14 @@
#pragma once
#include <stdlib.h>
#include <stdbool.h>
#include "soc/soc.h"
#include "soc/gpio_periph.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/gpio_struct.h"
#include "hal/gpio_types.h"
#include "stdlib.h"
#include "hal/assert.h"
#ifdef __cplusplus
extern "C" {
@ -431,9 +433,9 @@ static inline void gpio_ll_force_hold_all(gpio_dev_t *hw)
static inline void gpio_ll_force_unhold_all(void)
{
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_HOLD);
CLEAR_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_PAD_FORCE_HOLD_M);
SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_UNHOLD);
SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_CLR_DG_PAD_AUTOHOLD);
CLEAR_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_PAD_FORCE_HOLD_M);
}
/**
@ -555,15 +557,14 @@ static inline void gpio_ll_sleep_output_enable(gpio_dev_t *hw, gpio_num_t gpio_n
*/
static inline void gpio_ll_deepsleep_wakeup_enable(gpio_dev_t *hw, gpio_num_t gpio_num, gpio_int_type_t intr_type)
{
if (gpio_num > GPIO_NUM_5) {
abort(); // gpio lager than 5 doesn't support.
}
HAL_ASSERT((gpio_num >= GPIO_NUM_7 && gpio_num <= GPIO_NUM_12) &&
"only gpio7~12 support deep sleep wake-up function");
REG_SET_BIT(RTC_CNTL_GPIO_WAKEUP_REG, RTC_CNTL_GPIO_PIN_CLK_GATE);
REG_SET_BIT(RTC_CNTL_EXT_WAKEUP_CONF_REG, RTC_CNTL_GPIO_WAKEUP_FILTER);
SET_PERI_REG_MASK(RTC_CNTL_GPIO_WAKEUP_REG, 1 << (RTC_CNTL_GPIO_PIN0_WAKEUP_ENABLE_S - gpio_num));
SET_PERI_REG_MASK(RTC_CNTL_GPIO_WAKEUP_REG, 1 << (RTC_CNTL_GPIO_PIN0_WAKEUP_ENABLE_S - (gpio_num - 7)));
uint32_t reg = REG_READ(RTC_CNTL_GPIO_WAKEUP_REG);
reg &= (~(RTC_CNTL_GPIO_PIN0_INT_TYPE_V << (RTC_CNTL_GPIO_PIN0_INT_TYPE_S - gpio_num * 3)));
reg |= (intr_type << (RTC_CNTL_GPIO_PIN0_INT_TYPE_S - gpio_num * 3));
reg &= (~(RTC_CNTL_GPIO_PIN0_INT_TYPE_V << (RTC_CNTL_GPIO_PIN0_INT_TYPE_S - (gpio_num - 7) * 3)));
reg |= (intr_type << (RTC_CNTL_GPIO_PIN0_INT_TYPE_S - (gpio_num - 7) * 3));
REG_WRITE(RTC_CNTL_GPIO_WAKEUP_REG, reg);
}
@ -575,11 +576,26 @@ static inline void gpio_ll_deepsleep_wakeup_enable(gpio_dev_t *hw, gpio_num_t gp
*/
static inline void gpio_ll_deepsleep_wakeup_disable(gpio_dev_t *hw, gpio_num_t gpio_num)
{
if (gpio_num > GPIO_NUM_5) {
abort(); // gpio lager than 5 doesn't support.
}
CLEAR_PERI_REG_MASK(RTC_CNTL_GPIO_WAKEUP_REG, 1 << (RTC_CNTL_GPIO_PIN0_WAKEUP_ENABLE_S - gpio_num));
CLEAR_PERI_REG_MASK(RTC_CNTL_GPIO_WAKEUP_REG, RTC_CNTL_GPIO_PIN0_INT_TYPE_S - gpio_num * 3);
HAL_ASSERT((gpio_num >= GPIO_NUM_7 && gpio_num <= GPIO_NUM_12) &&
"only gpio7~12 support deep sleep wake-up function");
CLEAR_PERI_REG_MASK(RTC_CNTL_GPIO_WAKEUP_REG, 1 << (RTC_CNTL_GPIO_PIN0_WAKEUP_ENABLE_S - (gpio_num - 7)));
CLEAR_PERI_REG_MASK(RTC_CNTL_GPIO_WAKEUP_REG, RTC_CNTL_GPIO_PIN0_INT_TYPE_S - (gpio_num - 7) * 3);
}
/**
* @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_num <= GPIO_NUM_12) &&
"only gpio7~12 support deep sleep wake-up function");
return GET_PERI_REG_MASK(RTC_CNTL_GPIO_WAKEUP_REG, 1 << (RTC_CNTL_GPIO_PIN0_WAKEUP_ENABLE_S - (gpio_num - 7)));
}
#ifdef __cplusplus

View File

@ -32,19 +32,15 @@ static inline void rtc_cntl_ll_set_wakeup_timer(uint64_t t)
SET_PERI_REG_MASK(RTC_CNTL_SLP_TIMER1_REG, RTC_CNTL_MAIN_TIMER_ALARM_EN_M);
}
static inline uint32_t rtc_cntl_ll_gpio_get_wakeup_pins(void)
static inline uint32_t rtc_cntl_ll_gpio_get_wakeup_status(void)
{
return GET_PERI_REG_MASK(RTC_CNTL_GPIO_WAKEUP_REG, RTC_CNTL_GPIO_WAKEUP_STATUS);
}
static inline void rtc_cntl_ll_gpio_set_wakeup_pins(void)
{
REG_CLR_BIT(RTC_CNTL_GPIO_WAKEUP_REG, RTC_CNTL_GPIO_WAKEUP_STATUS_CLR);
}
static inline void rtc_cntl_ll_gpio_clear_wakeup_pins(void)
static inline void rtc_cntl_ll_gpio_clear_wakeup_status(void)
{
REG_SET_BIT(RTC_CNTL_GPIO_WAKEUP_REG, RTC_CNTL_GPIO_WAKEUP_STATUS_CLR);
REG_CLR_BIT(RTC_CNTL_GPIO_WAKEUP_REG, RTC_CNTL_GPIO_WAKEUP_STATUS_CLR);
}
static inline void rtc_cntl_ll_enable_cpu_retention(uint32_t addr)

View File

@ -23,7 +23,12 @@ static inline void rtc_cntl_ll_set_wakeup_timer(uint64_t t)
SET_PERI_REG_MASK(RTC_CNTL_SLP_TIMER1_REG, RTC_CNTL_MAIN_TIMER_ALARM_EN_M);
}
static inline uint32_t rtc_cntl_ll_ext1_get_wakeup_pins(void)
static inline void rtc_cntl_ll_ext1_clear_wakeup_status(void)
{
REG_SET_BIT(RTC_CNTL_EXT_WAKEUP1_REG, RTC_CNTL_EXT_WAKEUP1_STATUS_CLR);
}
static inline uint32_t rtc_cntl_ll_ext1_get_wakeup_status(void)
{
return REG_GET_FIELD(RTC_CNTL_EXT_WAKEUP1_STATUS_REG, RTC_CNTL_EXT_WAKEUP1_STATUS);
}
@ -37,7 +42,12 @@ static inline void rtc_cntl_ll_ext1_set_wakeup_pins(uint32_t mask, int mode)
static inline void rtc_cntl_ll_ext1_clear_wakeup_pins(void)
{
REG_SET_BIT(RTC_CNTL_EXT_WAKEUP1_REG, RTC_CNTL_EXT_WAKEUP1_STATUS_CLR);
CLEAR_PERI_REG_MASK(RTC_CNTL_EXT_WAKEUP1_REG, RTC_CNTL_EXT_WAKEUP1_SEL_M);
}
static inline uint32_t rtc_cntl_ll_ext1_get_wakeup_pins(void)
{
return REG_GET_FIELD(RTC_CNTL_EXT_WAKEUP1_REG, RTC_CNTL_EXT_WAKEUP1_SEL);
}
static inline void rtc_cntl_ll_ulp_int_clear(void)

View File

@ -220,7 +220,7 @@ static inline void rtcio_ll_pulldown_disable(int rtcio_num)
}
/**
* Enable force hold function for RTC IO pad.
* Enable force hold function on an RTC IO pad.
*
* Enabling HOLD function will cause the pad to lock current status, such as,
* input/output enable, input/output value, function, drive strength values.
@ -235,7 +235,7 @@ static inline void rtcio_ll_force_hold_enable(int rtcio_num)
}
/**
* Disable hold function on an RTC IO pad
* Disable hold function on an RTC IO pad.
*
* @note If disable the pad hold, the status of pad maybe changed in sleep mode.
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
@ -246,7 +246,7 @@ static inline void rtcio_ll_force_hold_disable(int rtcio_num)
}
/**
* Enable force hold function for RTC IO pad.
* Enable force hold function on all RTC IO pads.
*
* Enabling HOLD function will cause the pad to lock current status, such as,
* input/output enable, input/output value, function, drive strength values.
@ -261,7 +261,7 @@ static inline void rtcio_ll_force_hold_all(void)
}
/**
* Disable hold function on an RTC IO pad
* Disable hold function on all RTC IO pads.
*
* @note If disable the pad hold, the status of pad maybe changed in sleep mode.
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).

View File

@ -27,7 +27,12 @@ static inline void rtc_cntl_ll_set_wakeup_timer(uint64_t t)
SET_PERI_REG_MASK(RTC_CNTL_SLP_TIMER1_REG, RTC_CNTL_MAIN_TIMER_ALARM_EN_M);
}
static inline uint32_t rtc_cntl_ll_ext1_get_wakeup_pins(void)
static inline void rtc_cntl_ll_ext1_clear_wakeup_status(void)
{
REG_SET_BIT(RTC_CNTL_EXT_WAKEUP1_REG, RTC_CNTL_EXT_WAKEUP1_STATUS_CLR);
}
static inline uint32_t rtc_cntl_ll_ext1_get_wakeup_status(void)
{
return REG_GET_FIELD(RTC_CNTL_EXT_WAKEUP1_STATUS_REG, RTC_CNTL_EXT_WAKEUP1_STATUS);
}
@ -41,7 +46,12 @@ static inline void rtc_cntl_ll_ext1_set_wakeup_pins(uint32_t mask, int mode)
static inline void rtc_cntl_ll_ext1_clear_wakeup_pins(void)
{
REG_SET_BIT(RTC_CNTL_EXT_WAKEUP1_REG, RTC_CNTL_EXT_WAKEUP1_STATUS_CLR);
CLEAR_PERI_REG_MASK(RTC_CNTL_EXT_WAKEUP1_REG, RTC_CNTL_EXT_WAKEUP1_SEL_M);
}
static inline uint32_t rtc_cntl_ll_ext1_get_wakeup_pins(void)
{
return REG_GET_FIELD(RTC_CNTL_EXT_WAKEUP1_REG, RTC_CNTL_EXT_WAKEUP1_SEL);
}
static inline void rtc_cntl_ll_set_tagmem_retention_link_addr(uint32_t link_addr)

View File

@ -228,7 +228,7 @@ static inline void rtcio_ll_pulldown_disable(int rtcio_num)
}
/**
* Enable force hold function for RTC IO pad.
* Enable force hold function on an RTC IO pad.
*
* Enabling HOLD function will cause the pad to lock current status, such as,
* input/output enable, input/output value, function, drive strength values.
@ -243,7 +243,7 @@ static inline void rtcio_ll_force_hold_enable(int rtcio_num)
}
/**
* Disable hold function on an RTC IO pad
* Disable hold function on an RTC IO pad.
*
* @note If disable the pad hold, the status of pad maybe changed in sleep mode.
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
@ -254,7 +254,7 @@ static inline void rtcio_ll_force_hold_disable(int rtcio_num)
}
/**
* Enable force hold function for RTC IO pad.
* Enable force hold function on all RTC IO pads.
*
* Enabling HOLD function will cause the pad to lock current status, such as,
* input/output enable, input/output value, function, drive strength values.
@ -269,7 +269,7 @@ static inline void rtcio_ll_force_hold_all(void)
}
/**
* Disable hold function on an RTC IO pad
* Disable hold function on all RTC IO pads.
*
* @note If disable the pad hold, the status of pad maybe changed in sleep mode.
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).

View File

@ -358,7 +358,7 @@ void gpio_hal_intr_disable(gpio_hal_context_t *hal, gpio_num_t gpio_num);
#if SOC_GPIO_SUPPORT_FORCE_HOLD
/**
* @brief Force hold digital gpio pad.
* @brief Force hold all digital gpio pads (including those powered by VDD3P3_RTC power domain).
* @note GPIO force hold, whether the chip in sleep mode or wakeup mode.
*
* @param hal Context of the HAL layer
@ -366,7 +366,7 @@ void gpio_hal_intr_disable(gpio_hal_context_t *hal, gpio_num_t gpio_num);
#define gpio_hal_force_hold_all(hal) gpio_ll_force_hold_all((hal)->dev)
/**
* @brief Force unhold digital gpio pad.
* @brief Force unhold all digital gpio pads (including those powered by VDD3P3_RTC power domain).
* @note GPIO force unhold, whether the chip in sleep mode or wakeup mode.
*
* @param hal Context of the HAL layer
@ -498,6 +498,15 @@ void gpio_hal_sleep_pupd_config_unapply(gpio_hal_context_t *hal, gpio_num_t gpio
*/
#define gpio_hal_is_valid_deepsleep_wakeup_gpio(gpio_num) (gpio_num <= GPIO_NUM_5)
/**
* @brief Get the status of whether an IO is used for deep-sleep wake-up.
*
* @param hal Context of the HAL layer
* @param gpio_num GPIO number
*
* @return True if the pin is enabled to wake up from deep-sleep
*/
#define gpio_hal_deepsleep_wakeup_is_enabled(hal, gpio_num) gpio_ll_deepsleep_wakeup_is_enabled((hal)->dev, gpio_num)
#endif //SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP
/**

View File

@ -48,21 +48,23 @@ typedef struct rtc_cntl_sleep_retent {
#if SOC_PM_SUPPORT_EXT_WAKEUP
#define rtc_hal_ext1_get_wakeup_pins() rtc_cntl_ll_ext1_get_wakeup_pins()
#define rtc_hal_ext1_get_wakeup_status() rtc_cntl_ll_ext1_get_wakeup_status()
#define rtc_hal_ext1_clear_wakeup_status() rtc_cntl_ll_ext1_clear_wakeup_status()
#define rtc_hal_ext1_set_wakeup_pins(mask, mode) rtc_cntl_ll_ext1_set_wakeup_pins(mask, mode)
#define rtc_hal_ext1_clear_wakeup_pins() rtc_cntl_ll_ext1_clear_wakeup_pins()
#define rtc_hal_ext1_get_wakeup_pins() rtc_cntl_ll_ext1_get_wakeup_pins()
#endif
#if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP
#define rtc_hal_gpio_get_wakeup_pins() rtc_cntl_ll_gpio_get_wakeup_pins()
#define rtc_hal_gpio_get_wakeup_status() rtc_cntl_ll_gpio_get_wakeup_status()
#define rtc_hal_gpio_clear_wakeup_pins() rtc_cntl_ll_gpio_clear_wakeup_pins()
#define rtc_hal_gpio_set_wakeup_pins() rtc_cntl_ll_gpio_set_wakeup_pins()
#define rtc_hal_gpio_clear_wakeup_status() rtc_cntl_ll_gpio_clear_wakeup_status()
#endif

View File

@ -173,7 +173,7 @@ void rtcio_hal_set_direction_in_sleep(int rtcio_num, rtc_gpio_mode_t mode);
#if SOC_RTCIO_HOLD_SUPPORTED
/**
* Enable force hold function for RTC IO pad.
* Enable force hold function on an RTC IO pad.
*
* Enabling HOLD function will cause the pad to lock current status, such as,
* input/output enable, input/output value, function, drive strength values.
@ -185,7 +185,7 @@ void rtcio_hal_set_direction_in_sleep(int rtcio_num, rtc_gpio_mode_t mode);
#define rtcio_hal_hold_enable(rtcio_num) rtcio_ll_force_hold_enable(rtcio_num)
/**
* Disable hold function on an RTC IO pad
* Disable hold function on an RTC IO pad.
*
* @note If disable the pad hold, the status of pad maybe changed in sleep mode.
* @param rtcio_num The index of rtcio. 0 ~ SOC_RTCIO_PIN_COUNT.
@ -193,7 +193,7 @@ void rtcio_hal_set_direction_in_sleep(int rtcio_num, rtc_gpio_mode_t mode);
#define rtcio_hal_hold_disable(rtcio_num) rtcio_ll_force_hold_disable(rtcio_num)
/**
* Enable force hold function for RTC IO pads.
* Enable force hold function on all RTC IO pads.
*
* Enabling HOLD function will cause the pad to lock current status, such as,
* input/output enable, input/output value, function, drive strength values.
@ -205,7 +205,7 @@ void rtcio_hal_set_direction_in_sleep(int rtcio_num, rtc_gpio_mode_t mode);
#define rtcio_hal_hold_all() rtcio_ll_force_hold_all()
/**
* Disable hold function on an RTC IO pads.
* Disable hold function on all RTC IO pads.
*
* @note If disable the pad hold, the status of pad maybe changed in sleep mode.
* @param rtcio_num The index of rtcio. 0 ~ SOC_RTCIO_PIN_COUNT.

View File

@ -1,70 +0,0 @@
// Copyright 2010-2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
//RTC GPIO channels
#define RTCIO_GPIO36_CHANNEL 0 //RTCIO_CHANNEL_0
#define RTCIO_CHANNEL_0_GPIO_NUM 36
#define RTCIO_GPIO37_CHANNEL 1 //RTCIO_CHANNEL_1
#define RTCIO_CHANNEL_1_GPIO_NUM 37
#define RTCIO_GPIO38_CHANNEL 2 //RTCIO_CHANNEL_2
#define RTCIO_CHANNEL_2_GPIO_NUM 38
#define RTCIO_GPIO39_CHANNEL 3 //RTCIO_CHANNEL_3
#define RTCIO_CHANNEL_3_GPIO_NUM 39
#define RTCIO_GPIO34_CHANNEL 4 //RTCIO_CHANNEL_4
#define RTCIO_CHANNEL_4_GPIO_NUM 34
#define RTCIO_GPIO35_CHANNEL 5 //RTCIO_CHANNEL_5
#define RTCIO_CHANNEL_5_GPIO_NUM 35
#define RTCIO_GPIO25_CHANNEL 6 //RTCIO_CHANNEL_6
#define RTCIO_CHANNEL_6_GPIO_NUM 25
#define RTCIO_GPIO26_CHANNEL 7 //RTCIO_CHANNEL_7
#define RTCIO_CHANNEL_7_GPIO_NUM 26
#define RTCIO_GPIO33_CHANNEL 8 //RTCIO_CHANNEL_8
#define RTCIO_CHANNEL_8_GPIO_NUM 33
#define RTCIO_GPIO32_CHANNEL 9 //RTCIO_CHANNEL_9
#define RTCIO_CHANNEL_9_GPIO_NUM 32
#define RTCIO_GPIO4_CHANNEL 10 //RTCIO_CHANNEL_10
#define RTCIO_CHANNEL_10_GPIO_NUM 4
#define RTCIO_GPIO0_CHANNEL 11 //RTCIO_CHANNEL_11
#define RTCIO_CHANNEL_11_GPIO_NUM 0
#define RTCIO_GPIO2_CHANNEL 12 //RTCIO_CHANNEL_12
#define RTCIO_CHANNEL_12_GPIO_NUM 2
#define RTCIO_GPIO15_CHANNEL 13 //RTCIO_CHANNEL_13
#define RTCIO_CHANNEL_13_GPIO_NUM 15
#define RTCIO_GPIO13_CHANNEL 14 //RTCIO_CHANNEL_14
#define RTCIO_CHANNEL_14_GPIO_NUM 13
#define RTCIO_GPIO12_CHANNEL 15 //RTCIO_CHANNEL_15
#define RTCIO_CHANNEL_15_GPIO_NUM 12
#define RTCIO_GPIO14_CHANNEL 16 //RTCIO_CHANNEL_16
#define RTCIO_CHANNEL_16_GPIO_NUM 14
#define RTCIO_GPIO27_CHANNEL 17 //RTCIO_CHANNEL_17
#define RTCIO_CHANNEL_17_GPIO_NUM 27

View File

@ -99,10 +99,13 @@ This wakeup mode doesn't require RTC peripherals or RTC memories to be powered o
This wakeup source is implemented by the RTC controller. As such, RTC peripherals and RTC memories can be powered down in this mode. However, if RTC peripherals are powered down, internal pullup and pulldown resistors will be disabled. To use internal pullup or pulldown resistors, request RTC peripherals power domain to be kept on during sleep, and configure pullup/pulldown resistors using ``rtc_gpio_`` functions, before entering sleep::
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
gpio_pullup_dis(gpio_num);
gpio_pulldown_en(gpio_num);
rtc_gpio_pullup_dis(gpio_num);
rtc_gpio_pulldown_en(gpio_num);
.. warning:: After wake up from sleep, IO pad(s) used for wakeup will be configured as RTC IO. Before using these pads as digital GPIOs, reconfigure them using ``rtc_gpio_deinit(gpio_num)`` function.
.. warning::
- To use the EXT1 wakeup, the IO pad(s) are configured as RTC IO. Thus if these pads want to be used as digital GPIOs after waking up from sleep, ``rtc_gpio_deinit(gpio_num)`` function needs to be called first.
- If the RTC peripherals are configured to be powered down (which is by default), the wakeup IOs will be set to holding state before entering sleep. Therefore, after waking up from Light-sleep, please call `rtc_gpio_hold_dis` to disable the hold function to perform any pin re-configuration. For Deep-sleep wakeup, this is already being handled at the application startup stage.
:cpp:func:`esp_sleep_enable_ext1_wakeup` function can be used to enable this wakeup source.
@ -142,6 +145,14 @@ This wakeup mode doesn't require RTC peripherals or RTC memories to be powered o
esp_sleep_pd_config(ESP_PD_DOMAIN_VDDSDIO, ESP_PD_OPTION_ON);
.. only:: not SOC_RTCIO_WAKE_SUPPORTED
GPIO Wakeup
^^^^^^^^^^^
Any IO can be used as the external input to wakeup the chip from Light-sleep. Each pin can be individually configured to trigger wakeup on high or low level using :cpp:func:`gpio_wakeup_enable` function. Then :cpp:func:`esp_sleep_enable_gpio_wakeup` function should be called to enable this wakeup source.
Additionally, IOs that are powered by the VDD3P3_RTC power domain can be used to wakeup the chip from Deep-sleep. The wakeup pin and wakeup trigger level can be configured by calling :cpp:func:`esp_deep_sleep_enable_gpio_wakeup`. The function will enable the Deep-sleep wakeup for the selected pin.
UART wakeup (light sleep only)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -5,28 +5,36 @@
(See the README.md file in the upper level 'examples' directory for more information about examples.)
The [deep sleep mode](https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/system/sleep_modes.html#sleep-modes) of the ESP32 is a power saving mode that causes the CPU, majority of RAM, and digital peripherals that are clocked from APB_CLK to be powered off. Deep sleep mode can be exited using one of multiple [wake up sources](https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/system/sleep_modes.html#wakeup-sources). This example demonstrates how to use the [`esp_sleep.h`](https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/system/sleep_modes.html#api-reference) API to enter deep sleep mode, then wake up form different sources.
The [deep sleep mode](https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/system/sleep_modes.html#sleep-modes) is a power saving mode that causes the CPU, majority of RAM, and digital peripherals that are clocked from APB_CLK to be powered off. Deep sleep mode can be exited using one of multiple [wake up sources](https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/system/sleep_modes.html#wakeup-sources). This example demonstrates how to use the [`esp_sleep.h`](https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/system/sleep_modes.html#api-reference) API to enter deep sleep mode, then wake up form different sources.
The following wake up sources are demonstrated in this example (refer to the [Wakeup Sources documentation](https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/system/sleep_modes.html#wakeup-sources) for more details regarding wake up sources):
1. **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.
2. **EXT1:** External wake up 1 which is tied to multiple RTC GPIOs. This example use GPIO2 and GPIO4 to trigger a wake up with any one of the two pins are HIGH.
3. **Touch:** Touch pad sensor interrupt. This example uses touch pads connected to GPIO32, GPIO33 in ESP32 or GPIO9 in ESP32-S2 to trigger a wake up when any of the pads are pressed.
4. **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.
- **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.)
- **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.
Note: Some wake up sources can be disabled via configuration (see section on [project configuration](#Configure-the-project))
Warning: On ESP32, touch wake up source cannot be used together with EXT0 or ULP wake up source. If they co-exist, IDF will give a runtime error and the program will crash. By default in this example, touch wake up is enabled, and the other two are disabled. You can switch to enable the other wake up sources via menuconfig.
In this example, the `CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP` Kconfig option is used, which allows you to reduce the boot time of the bootloader during waking up from deep sleep. The bootloader stores in rtc memory the address of a running partition and uses it when it wakes up. This example allows you to skip all image checks and speed up the boot.
## How to use example
### Hardware Required
This example should be able to run on any commonly available ESP32 development board without any extra hardware if only **Timer** and **ULP** wake up sources are used. However, the following extra connections will be required for the remaining wake up sources.
This example should be able to run on any commonly available ESP32 series development board without any extra hardware if only **Timer** and **ULP** wake up sources are used. However, the following extra connections will be required for the remaining wake up sources.
- **EXT0:** Connect GPIO25 in ESP32 or GPIO3 in ESP32-S2/S3 to HIGH to trigger a wake up.
- **EXT1:** GPIO2 and GPIO4 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 pins may trigger a wake up.
- **Touch:** GPIO32, GPIO33 in ESP32 or GPIO9 in ESP32-S2 should be connected to touch sensors (see [Touch Sensor Application Note](https://github.com/espressif/esp-iot-solution/blob/release/v1.0/documents/touch_pad_solution/touch_sensor_design_en.md)).
- **GPIO:** If `EXAMPLE_GPIO_WAKEUP_HIGH_LEVEL` is selected in menuconfig, then connect `EXAMPLE_GPIO_WAKEUP_PIN` to HIGH to trigger a wake up; Otherwise, connect `EXAMPLE_GPIO_WAKEUP_PIN` to LOW to trigger a wake up.
- **Touch:** GPIO32, GPIO33 in ESP32 or GPIO9 in ESP32-S2/S3 should be connected to touch sensors (see [Touch Sensor Application Note](https://github.com/espressif/esp-iot-solution/blob/release/v1.0/documents/touch_pad_solution/touch_sensor_design_en.md)).
### Configure the project
@ -35,7 +43,12 @@ idf.py menuconfig
```
* **Touch wake up** can be enabled/disabled via `Example configuration > Enable touch wake up`
* **ULT wake up** can be enabled/disabled via `Example configuration > Enable temperature monitoring by ULP`
* **EXT0 wake up** can be enabled/disabled via `Example configuration > Enable wakeup from GPIO (ext0)`
* **EXT1 wake up** can be enabled/disabled via `Example configuration > Enable wakeup from GPIO (ext1)`
* **GPIO wake up** can be enabled/disabled via `Example configuration > Enable wakeup from GPIO`
Trigger pin can be chosen via `Example configuration > GPIO wakeup configuration > Enable wakeup from GPIO`
Trigger level can be selected via `Example configuration > GPIO wakeup configuration > Enable GPIO high-level wakeup`
* **ULP wake up** can be enabled/disabled via `Example configuration > Enable temperature monitoring by ULP`
Wake up sources that are unused or unconnected should be disabled in configuration to prevent inadvertent triggering of wake up as a result of floating pins.

View File

@ -5,8 +5,11 @@ menu "Example Configuration"
default y
depends on IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
help
This option enables wake up from deep sleep using touch pads
TOUCH8 and TOUCH9, which correspond to GPIO33 and GPIO32.
This option enables wake up from deep sleep using touch pads.
ESP32 - TOUCH8 and TOUCH9, which correspond to GPIO33 and GPIO32.
ESP32S2/S3 - TOUCH9, which corresponds to GPIO9.
Note: On ESP32, touch wakeup source can not be used together with ext0 wakeup source.
config EXAMPLE_ULP_TEMPERATURE_WAKEUP
bool "Enable temperature monitoring by ULP"
@ -21,12 +24,15 @@ menu "Example Configuration"
config EXAMPLE_EXT0_WAKEUP
bool "Enable wakeup from GPIO (ext0)"
default y
default y if !IDF_TARGET_ESP32
default n if IDF_TARGET_ESP32
depends on !IDF_TARGET_ESP32C3
help
This option enables wake up from deep sleep from GPIO3. 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
pins may trigger a wake up.
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.
Note that floating pins may trigger a wake up.
Note: On ESP32, ext0 wakeup source can not be used together with touch wakeup source.
config EXAMPLE_EXT1_WAKEUP
bool "Enable wakeup from GPIO (ext1)"

View File

@ -182,19 +182,23 @@ void app_main(void)
const int wakeup_time_sec = 20;
printf("Enabling timer wakeup, %ds\n", wakeup_time_sec);
esp_sleep_enable_timer_wakeup(wakeup_time_sec * 1000000);
ESP_ERROR_CHECK(esp_sleep_enable_timer_wakeup(wakeup_time_sec * 1000000));
#if CONFIG_EXAMPLE_EXT0_WAKEUP
#if CONFIG_IDF_TARGET_ESP32
const int ext_wakeup_pin_0 = 25;
#else
const int ext_wakeup_pin_0 = 3;
#endif
printf("Enabling EXT0 wakeup on pin GPIO%d\n", ext_wakeup_pin_0);
esp_sleep_enable_ext0_wakeup(ext_wakeup_pin_0, 1);
ESP_ERROR_CHECK(esp_sleep_enable_ext0_wakeup(ext_wakeup_pin_0, 1));
// Configure pullup/downs via RTCIO to tie wakeup pins to inactive level during deepsleep.
// EXT0 resides in the same power domain (RTC_PERIPH) as the RTC IO pullup/downs.
// No need to keep that power domain explicitly, unlike EXT1.
rtc_gpio_pullup_dis(ext_wakeup_pin_0);
rtc_gpio_pulldown_en(ext_wakeup_pin_0);
ESP_ERROR_CHECK(rtc_gpio_pullup_dis(ext_wakeup_pin_0));
ESP_ERROR_CHECK(rtc_gpio_pulldown_en(ext_wakeup_pin_0));
#endif // CONFIG_EXAMPLE_EXT0_WAKEUP
#ifdef CONFIG_EXAMPLE_EXT1_WAKEUP
const int ext_wakeup_pin_1 = 2;
@ -203,17 +207,17 @@ void app_main(void)
const uint64_t ext_wakeup_pin_2_mask = 1ULL << ext_wakeup_pin_2;
printf("Enabling EXT1 wakeup on pins GPIO%d, GPIO%d\n", ext_wakeup_pin_1, ext_wakeup_pin_2);
esp_sleep_enable_ext1_wakeup(ext_wakeup_pin_1_mask | ext_wakeup_pin_2_mask, ESP_EXT1_WAKEUP_ANY_HIGH);
ESP_ERROR_CHECK(esp_sleep_enable_ext1_wakeup(ext_wakeup_pin_1_mask | ext_wakeup_pin_2_mask, ESP_EXT1_WAKEUP_ANY_HIGH));
/* If there are no external pull-up/downs, tie wakeup pins to inactive level with internal pull-up/downs via RTC IO
* 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
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
rtc_gpio_pullup_dis(ext_wakeup_pin_1);
rtc_gpio_pulldown_en(ext_wakeup_pin_1);
rtc_gpio_pullup_dis(ext_wakeup_pin_2);
rtc_gpio_pulldown_en(ext_wakeup_pin_2);
ESP_ERROR_CHECK(esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON));
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));
ESP_ERROR_CHECK(rtc_gpio_pulldown_en(ext_wakeup_pin_2));
# endif //CONFIG_EXAMPLE_EXT1_USE_INTERNAL_PULLUPS
#endif // CONFIG_EXAMPLE_EXT1_WAKEUP
@ -288,8 +292,8 @@ void app_main(void)
TOUCH_PAD_NUM9, touch_value, (uint32_t)(touch_value * 0.1));
#endif
printf("Enabling touch pad wakeup\n");
esp_sleep_enable_touchpad_wakeup();
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
ESP_ERROR_CHECK(esp_sleep_enable_touchpad_wakeup());
ESP_ERROR_CHECK(esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON));
#endif // CONFIG_EXAMPLE_TOUCH_WAKEUP
#ifdef CONFIG_EXAMPLE_ULP_TEMPERATURE_WAKEUP