mirror of
https://github.com/espressif/esp-idf.git
synced 2026-05-28 16:46:31 +03:00
442 lines
16 KiB
C
442 lines
16 KiB
C
/*
|
|
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <sys/lock.h>
|
|
#include <sys/param.h>
|
|
|
|
#include "esp_attr.h"
|
|
#include "esp_system.h"
|
|
#include "esp_sleep.h"
|
|
#include "esp_log.h"
|
|
#include "esp_memory_utils.h"
|
|
#include "soc/soc_caps.h"
|
|
#include "soc/uart_pins.h"
|
|
|
|
#include "sdkconfig.h"
|
|
|
|
#include "driver/gpio.h"
|
|
#include "hal/gpio_hal.h"
|
|
#include "hal/rtc_io_hal.h"
|
|
#include "hal/rtc_io_periph.h"
|
|
#include "soc/uart_pins.h"
|
|
|
|
#include "hal/rtc_hal.h"
|
|
#if SOC_PMU_SUPPORTED
|
|
#include "hal/pmu_ll.h"
|
|
#include "esp_private/esp_pmu.h"
|
|
#else
|
|
#include "soc/rtc.h"
|
|
#include "hal/rtc_cntl_ll.h"
|
|
#endif
|
|
|
|
#include "esp_private/esp_gpio_reserve.h"
|
|
#include "esp_private/gpio.h"
|
|
#include "esp_private/sleep_gpio.h"
|
|
#include "esp_private/spi_flash_os.h"
|
|
#include "esp_private/startup_internal.h"
|
|
#include "bootloader_flash.h"
|
|
|
|
ESP_LOG_ATTR_TAG(TAG, "sleep_gpio");
|
|
|
|
#if SOC_PM_SUPPORT_EXT0_WAKEUP
|
|
#define _IO_WAKEUP_EXT0 RTC_EXT0_TRIG_EN
|
|
#else
|
|
#define _IO_WAKEUP_EXT0 0
|
|
#endif
|
|
#if SOC_PM_SUPPORT_EXT1_WAKEUP
|
|
#define _IO_WAKEUP_EXT1 RTC_EXT1_TRIG_EN
|
|
#else
|
|
#define _IO_WAKEUP_EXT1 0
|
|
#endif
|
|
#define IO_WAKEUP_ENABLED (RTC_GPIO_TRIG_EN | _IO_WAKEUP_EXT0 | _IO_WAKEUP_EXT1)
|
|
|
|
#if CONFIG_IDF_TARGET_ESP32
|
|
/* On ESP32, for IOs with RTC functionality, setting SLP_PU, SLP_PD couldn't change IO status
|
|
* from FUN_PU, FUN_PD to SLP_PU, SLP_PD at sleep.
|
|
*/
|
|
typedef struct gpio_slp_mode_cfg {
|
|
volatile uint32_t fun_pu;
|
|
volatile uint32_t fun_pd;
|
|
} gpio_slp_mode_cfg_t;
|
|
|
|
static DRAM_ATTR gpio_slp_mode_cfg_t gpio_cfg = {};
|
|
|
|
void esp_sleep_gpio_pupd_config_workaround_apply(void)
|
|
{
|
|
/* Record fun_pu and fun_pd state in bitmap */
|
|
for (gpio_num_t gpio_num = GPIO_NUM_0; gpio_num < GPIO_NUM_MAX; gpio_num++) {
|
|
int rtcio_num = rtc_io_num_map[gpio_num];
|
|
if (rtcio_num >= 0 && gpio_ll_sleep_sel_is_enabled(&GPIO, gpio_num)) {
|
|
if (rtcio_ll_is_pullup_enabled(rtcio_num)) {
|
|
gpio_cfg.fun_pu |= BIT(rtcio_num);
|
|
} else {
|
|
gpio_cfg.fun_pu &= ~BIT(rtcio_num);
|
|
}
|
|
if (rtcio_ll_is_pulldown_enabled(rtcio_num)) {
|
|
gpio_cfg.fun_pd |= BIT(rtcio_num);
|
|
} else {
|
|
gpio_cfg.fun_pd &= ~BIT(rtcio_num);
|
|
}
|
|
|
|
if (gpio_ll_sleep_pullup_is_enabled(&GPIO, gpio_num)) {
|
|
rtcio_ll_pullup_enable(rtcio_num);
|
|
} else {
|
|
rtcio_ll_pullup_disable(rtcio_num);
|
|
}
|
|
if (gpio_ll_sleep_pulldown_is_enabled(&GPIO, gpio_num)) {
|
|
rtcio_ll_pulldown_enable(rtcio_num);
|
|
} else {
|
|
rtcio_ll_pulldown_disable(rtcio_num);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void esp_sleep_gpio_pupd_config_workaround_unapply(void)
|
|
{
|
|
/* Restore fun_pu and fun_pd state from bitmap */
|
|
for (gpio_num_t gpio_num = GPIO_NUM_0; gpio_num < GPIO_NUM_MAX; gpio_num++) {
|
|
int rtcio_num = rtc_io_num_map[gpio_num];
|
|
if (rtcio_num >= 0 && gpio_ll_sleep_sel_is_enabled(&GPIO, gpio_num)) {
|
|
if (gpio_cfg.fun_pu & BIT(rtcio_num)) {
|
|
rtcio_ll_pullup_enable(rtcio_num);
|
|
} else {
|
|
rtcio_ll_pullup_disable(rtcio_num);
|
|
}
|
|
if (gpio_cfg.fun_pd & BIT(rtcio_num)) {
|
|
rtcio_ll_pulldown_enable(rtcio_num);
|
|
} else {
|
|
rtcio_ll_pulldown_disable(rtcio_num);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND || CONFIG_PM_SLP_DISABLE_GPIO
|
|
void esp_sleep_config_gpio_isolate(void)
|
|
{
|
|
ESP_EARLY_LOGI(TAG, "Configure to isolate all GPIO pins in sleep state");
|
|
for (gpio_num_t gpio_num = GPIO_NUM_0; gpio_num < GPIO_NUM_MAX; gpio_num++) {
|
|
if (GPIO_IS_VALID_GPIO(gpio_num)) {
|
|
gpio_sleep_set_direction(gpio_num, GPIO_MODE_DISABLE);
|
|
gpio_sleep_set_pull_mode(gpio_num, GPIO_FLOATING);
|
|
}
|
|
}
|
|
|
|
#if CONFIG_ESP_SLEEP_MSPI_NEED_ALL_IO_PU && !SOC_MSPI_HAS_INDEPENT_IOMUX
|
|
gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_CLK), GPIO_PULLUP_ONLY);
|
|
gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_Q), GPIO_PULLUP_ONLY);
|
|
gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_D), GPIO_PULLUP_ONLY);
|
|
gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_HD), GPIO_PULLUP_ONLY);
|
|
gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_WP), GPIO_PULLUP_ONLY);
|
|
#if SOC_SPI_MEM_SUPPORT_FLASH_OPI_MODE
|
|
bool octal_mspi_required = bootloader_flash_is_octal_mode_enabled();
|
|
#if CONFIG_SPIRAM_MODE_OCT
|
|
octal_mspi_required |= true;
|
|
#endif // CONFIG_SPIRAM_MODE_OCT
|
|
if (octal_mspi_required) {
|
|
gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_DQS), GPIO_PULLUP_ONLY);
|
|
gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_D4), GPIO_PULLUP_ONLY);
|
|
gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_D5), GPIO_PULLUP_ONLY);
|
|
gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_D6), GPIO_PULLUP_ONLY);
|
|
gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_D7), GPIO_PULLUP_ONLY);
|
|
}
|
|
#endif // SOC_SPI_MEM_SUPPORT_FLASH_OPI_MODE
|
|
#endif // CONFIG_ESP_SLEEP_MSPI_NEED_ALL_IO_PU
|
|
}
|
|
|
|
void esp_sleep_enable_gpio_switch(bool enable)
|
|
{
|
|
ESP_EARLY_LOGI(TAG, "%s automatic switching of GPIO sleep configuration", enable ? "Enable" : "Disable");
|
|
for (gpio_num_t gpio_num = GPIO_NUM_0; gpio_num < GPIO_NUM_MAX; gpio_num++) {
|
|
if (GPIO_IS_VALID_GPIO(gpio_num)) {
|
|
#if CONFIG_ESP_CONSOLE_UART
|
|
#if CONFIG_ESP_CONSOLE_UART_CUSTOM
|
|
const int uart_tx_gpio = (CONFIG_ESP_CONSOLE_UART_TX_GPIO >= 0) ? CONFIG_ESP_CONSOLE_UART_TX_GPIO : U0TXD_GPIO_NUM;
|
|
const int uart_rx_gpio = (CONFIG_ESP_CONSOLE_UART_RX_GPIO >= 0) ? CONFIG_ESP_CONSOLE_UART_RX_GPIO : U0RXD_GPIO_NUM;
|
|
if ((gpio_num == uart_tx_gpio) || (gpio_num == uart_rx_gpio)) {
|
|
#else
|
|
if ((gpio_num == U0TXD_GPIO_NUM) || (gpio_num == U0RXD_GPIO_NUM)) {
|
|
#endif
|
|
gpio_sleep_sel_dis(gpio_num);
|
|
continue;
|
|
}
|
|
#endif
|
|
/* If the PSRAM is disable in ESP32xx chips equipped with PSRAM, there will be a large current leakage. */
|
|
#if CONFIG_ESP_SLEEP_PSRAM_LEAKAGE_WORKAROUND && CONFIG_SPIRAM & !SOC_MSPI_HAS_INDEPENT_IOMUX
|
|
if (gpio_num == esp_mspi_get_io(ESP_MSPI_IO_CS1)) {
|
|
gpio_sleep_sel_dis(gpio_num);
|
|
continue;
|
|
}
|
|
#endif // CONFIG_ESP_SLEEP_PSRAM_LEAKAGE_WORKAROUND && CONFIG_SPIRAM
|
|
|
|
#if CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND & !SOC_MSPI_HAS_INDEPENT_IOMUX
|
|
if (gpio_num == esp_mspi_get_io(ESP_MSPI_IO_CS0)) {
|
|
gpio_sleep_sel_dis(gpio_num);
|
|
continue;
|
|
}
|
|
#endif // CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND
|
|
|
|
if (enable) {
|
|
gpio_sleep_sel_en(gpio_num);
|
|
} else {
|
|
gpio_sleep_sel_dis(gpio_num);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP || SOC_GPIO_NEED_SOFT_ISOLATE_DURING_PD
|
|
IRAM_ATTR static void sleep_gpio_isolate_one_pin(gpio_num_t gpio_num)
|
|
{
|
|
#if SOC_GPIO_NEED_SOFT_ISOLATE_DURING_PD
|
|
gpio_io_config_t isolate_config = { .pu = 0, .pd = 0, .ie = 0, .oe = 0, .fun_sel = PIN_FUNC_GPIO };
|
|
gpio_ll_set_pad_config_for_sleep_isolate(gpio_num, &isolate_config);
|
|
#else
|
|
gpio_hal_context_t gpio_hal = { .dev = GPIO_HAL_GET_HW(GPIO_PORT_0) };
|
|
gpio_hal_input_disable(&gpio_hal, gpio_num);
|
|
gpio_hal_output_disable(&gpio_hal, gpio_num);
|
|
gpio_hal_pullup_dis(&gpio_hal, gpio_num);
|
|
gpio_hal_pulldown_dis(&gpio_hal, gpio_num);
|
|
gpio_hal_func_sel(&gpio_hal, gpio_num, PIN_FUNC_GPIO);
|
|
#endif
|
|
}
|
|
|
|
#if SOC_GPIO_NEED_SOFT_ISOLATE_DURING_PD
|
|
typedef struct {
|
|
uint64_t backuped;
|
|
uint64_t pu;
|
|
uint64_t pd;
|
|
uint64_t ie;
|
|
uint64_t oe;
|
|
uint8_t fun_sel[GPIO_NUM_MAX];
|
|
} gpio_isolate_backup_t;
|
|
|
|
static DRAM_ATTR gpio_isolate_backup_t s_gpio_isolate_backup;
|
|
|
|
IRAM_ATTR static void sleep_gpio_backup_one_pin(gpio_num_t gpio_num)
|
|
{
|
|
gpio_hal_context_t gpio_hal = { .dev = GPIO_HAL_GET_HW(GPIO_PORT_0) };
|
|
gpio_io_config_t io_config;
|
|
gpio_ll_backup_pad_config_for_sleep_isolate(gpio_num, &io_config);
|
|
if (io_config.pu) {
|
|
s_gpio_isolate_backup.pu |= (1ULL << gpio_num);
|
|
}
|
|
if (io_config.pd) {
|
|
s_gpio_isolate_backup.pd |= (1ULL << gpio_num);
|
|
}
|
|
if (io_config.ie) {
|
|
s_gpio_isolate_backup.ie |= (1ULL << gpio_num);
|
|
}
|
|
if (gpio_ll_output_is_enabled(gpio_hal.dev, gpio_num)) {
|
|
s_gpio_isolate_backup.oe |= (1ULL << gpio_num);
|
|
}
|
|
s_gpio_isolate_backup.fun_sel[gpio_num] = (uint8_t)io_config.fun_sel;
|
|
s_gpio_isolate_backup.backuped |= (1ULL << gpio_num);
|
|
}
|
|
|
|
IRAM_ATTR void esp_sleep_isolate_mspi_gpio(void)
|
|
{
|
|
DRAM_ATTR static const esp_mspi_io_t s_mspi_pins[] = {
|
|
ESP_MSPI_IO_CLK, ESP_MSPI_IO_Q, ESP_MSPI_IO_D, ESP_MSPI_IO_HD, ESP_MSPI_IO_WP
|
|
};
|
|
for (size_t i = 0; i < sizeof(s_mspi_pins) / sizeof(s_mspi_pins[0]); i++) {
|
|
gpio_num_t gpio_num = (gpio_num_t)esp_mspi_get_io(s_mspi_pins[i]);
|
|
sleep_gpio_backup_one_pin(gpio_num);
|
|
#if CONFIG_ESP_SLEEP_MSPI_NEED_ALL_IO_PU && !SOC_MSPI_HAS_INDEPENT_IOMUX
|
|
gpio_hal_context_t gpio_hal = { .dev = GPIO_HAL_GET_HW(GPIO_PORT_0) };
|
|
gpio_hal_pullup_en(&gpio_hal, gpio_num);
|
|
#else
|
|
sleep_gpio_isolate_one_pin(gpio_num);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
IRAM_ATTR void esp_sleep_restore_isolated_digital_gpio(void)
|
|
{
|
|
uint64_t backuped = s_gpio_isolate_backup.backuped;
|
|
while (backuped) {
|
|
gpio_num_t gpio_num = (gpio_num_t)__builtin_ctzll(backuped);
|
|
gpio_io_config_t io_config = {
|
|
.pu = (s_gpio_isolate_backup.pu >> gpio_num) & 0x1,
|
|
.pd = (s_gpio_isolate_backup.pd >> gpio_num) & 0x1,
|
|
.ie = (s_gpio_isolate_backup.ie >> gpio_num) & 0x1,
|
|
.oe = (s_gpio_isolate_backup.oe >> gpio_num) & 0x1,
|
|
.fun_sel = (uint32_t)s_gpio_isolate_backup.fun_sel[gpio_num],
|
|
};
|
|
gpio_ll_set_pad_config_for_sleep_isolate(gpio_num, &io_config);
|
|
backuped &= backuped - 1;
|
|
}
|
|
}
|
|
#endif // SOC_GPIO_NEED_SOFT_ISOLATE_DURING_PD
|
|
|
|
IRAM_ATTR void esp_sleep_isolate_digital_gpio(bool do_backup)
|
|
{
|
|
gpio_hal_context_t gpio_hal = { .dev = GPIO_HAL_GET_HW(GPIO_PORT_0) };
|
|
#if !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
|
|
/* no need to do isolate if digital IOs are not being held in deep sleep */
|
|
if (!gpio_hal_deep_sleep_hold_is_en(&gpio_hal)) {
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
* there is a situation where we cannot isolate digital IO before deep sleep:
|
|
* - task stack is located in external ram(mspi ram), since we will isolate mspi io
|
|
*
|
|
* assert here instead of returning directly, because if digital IO is not isolated,
|
|
* the bottom current of deep sleep will be higher than light sleep, and there is no
|
|
* reason to use deep sleep at this time.
|
|
*/
|
|
assert(esp_ptr_internal(esp_cpu_get_sp()) && "If hold digital IO, the stack of the task calling esp_deep_sleep_start must be in internal ram!");
|
|
|
|
DRAM_ATTR static volatile uint64_t s_pad_mask = SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK;
|
|
uint64_t pad_mask = s_pad_mask;
|
|
#if SOC_GPIO_NEED_SOFT_ISOLATE_DURING_PD
|
|
if (do_backup) {
|
|
s_gpio_isolate_backup.backuped = 0;
|
|
s_gpio_isolate_backup.pu = 0;
|
|
s_gpio_isolate_backup.pd = 0;
|
|
s_gpio_isolate_backup.ie = 0;
|
|
s_gpio_isolate_backup.oe = 0;
|
|
}
|
|
|
|
uint64_t hold_mask = gpio_ll_get_digital_gpio_hold_mask(gpio_hal.dev);
|
|
gpio_io_config_t isolate_config = { .pu = 0, .pd = 0, .ie = 0, .oe = 0, .fun_sel = PIN_FUNC_GPIO };
|
|
|
|
while (pad_mask) {
|
|
gpio_num_t gpio_num = (gpio_num_t)__builtin_ctzll(pad_mask);
|
|
if (!(hold_mask & (1ULL << gpio_num)) &&
|
|
!esp_gpio_is_reserved(BIT64(gpio_num))) {
|
|
if (do_backup) {
|
|
gpio_io_config_t io_config;
|
|
gpio_ll_backup_pad_config_for_sleep_isolate(gpio_num, &io_config);
|
|
if (io_config.pu) {
|
|
s_gpio_isolate_backup.pu |= (1ULL << gpio_num);
|
|
}
|
|
if (io_config.pd) {
|
|
s_gpio_isolate_backup.pd |= (1ULL << gpio_num);
|
|
}
|
|
if (io_config.ie) {
|
|
s_gpio_isolate_backup.ie |= (1ULL << gpio_num);
|
|
}
|
|
if (gpio_ll_output_is_enabled(gpio_hal.dev, gpio_num)) {
|
|
s_gpio_isolate_backup.oe |= (1ULL << gpio_num);
|
|
}
|
|
s_gpio_isolate_backup.fun_sel[gpio_num] = (uint8_t)io_config.fun_sel;
|
|
s_gpio_isolate_backup.backuped |= (1ULL << gpio_num);
|
|
}
|
|
gpio_ll_set_pad_config_for_sleep_isolate(gpio_num, &isolate_config);
|
|
}
|
|
pad_mask &= pad_mask - 1;
|
|
}
|
|
#else
|
|
(void)do_backup;
|
|
while (pad_mask) {
|
|
gpio_num_t gpio_num = (gpio_num_t)__builtin_ctzll(pad_mask);
|
|
if (!gpio_hal_is_digital_io_hold(&gpio_hal, gpio_num) &&
|
|
!esp_gpio_is_reserved(BIT64(gpio_num))) {
|
|
sleep_gpio_isolate_one_pin(gpio_num);
|
|
}
|
|
pad_mask &= pad_mask - 1;
|
|
}
|
|
#endif
|
|
}
|
|
#endif //!SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP || SOC_GPIO_NEED_SOFT_ISOLATE_DURING_PD
|
|
|
|
#if SOC_DEEP_SLEEP_SUPPORTED
|
|
static void esp_deep_sleep_wakeup_io_reset(void)
|
|
{
|
|
#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();
|
|
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;
|
|
}
|
|
#if SOC_RTCIO_HOLD_SUPPORTED
|
|
rtcio_hal_hold_disable(rtcio_num);
|
|
#endif
|
|
rtc_io_mask &= ~BIT(rtcio_num);
|
|
}
|
|
#endif
|
|
|
|
#if SOC_GPIO_SUPPORT_HP_PERIPH_PD_SLEEP_WAKEUP
|
|
gpio_hal_context_t gpio_hal = { .dev = GPIO_HAL_GET_HW(GPIO_PORT_0) };
|
|
uint64_t dslp_io_mask = SOC_GPIO_HP_PERIPH_PD_SLEEP_WAKEABLE_MASK;
|
|
while (dslp_io_mask) {
|
|
int gpio_num = __builtin_ctzll(dslp_io_mask);
|
|
bool wakeup_io_enabled = gpio_hal_wakeup_is_enabled_on_hp_periph_powerdown_sleep(&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_wakeup_disable_on_hp_periph_powerdown_sleep(&gpio_hal, gpio_num);
|
|
gpio_hal_hold_dis(&gpio_hal, gpio_num);
|
|
}
|
|
dslp_io_mask &= dslp_io_mask - 1;
|
|
}
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
ESP_SYSTEM_INIT_FN(esp_sleep_startup_init, SECONDARY, BIT(0), 105)
|
|
{
|
|
#if SOC_DEEP_SLEEP_SUPPORTED
|
|
// Need to unhold the IOs that were hold right before entering deep sleep, which are used as wakeup pins
|
|
#if SOC_PMU_SUPPORTED
|
|
uint32_t io_wakeup_enabled = pmu_ll_hp_get_wakeup_enable(&PMU) & IO_WAKEUP_ENABLED;
|
|
#else
|
|
uint32_t io_wakeup_enabled = rtc_cntl_ll_get_wakeup_enable() & IO_WAKEUP_ENABLED;
|
|
#endif
|
|
if (esp_reset_reason() == ESP_RST_DEEPSLEEP && io_wakeup_enabled) {
|
|
esp_deep_sleep_wakeup_io_reset();
|
|
}
|
|
#endif //#if SOC_DEEP_SLEEP_SUPPORTED
|
|
|
|
#if CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND || CONFIG_PM_SLP_DISABLE_GPIO
|
|
// Configure to isolate (disable the Input/Output/Pullup/Pulldown
|
|
// function of the pin) all GPIO pins in sleep state
|
|
esp_sleep_config_gpio_isolate();
|
|
// Enable automatic switching of GPIO configuration
|
|
esp_sleep_enable_gpio_switch(true);
|
|
#endif
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Convert RTC IO status bit number to GPIO number (for sleep wakeup status translation).
|
|
*
|
|
* @param bit RTC IO intr status bit index (0 to SOC_RTCIO_PIN_COUNT-1).
|
|
* @return GPIO number, or GPIO_NUM_NC if bit is invalid or has no corresponding GPIO.
|
|
*/
|
|
gpio_num_t esp_sleep_wakeup_io_bit2num(uint32_t bit)
|
|
{
|
|
#if SOC_RTCIO_PIN_COUNT > 0
|
|
if (bit >= SOC_RTCIO_PIN_COUNT) {
|
|
return GPIO_NUM_NC;
|
|
}
|
|
for (int gpio = 0; gpio < SOC_GPIO_PIN_COUNT; gpio++) {
|
|
if (rtc_io_num_map[gpio] == (int8_t)bit) {
|
|
return (gpio_num_t)gpio;
|
|
}
|
|
}
|
|
#elif (SOC_RTCIO_PIN_COUNT == 0)
|
|
return (gpio_num_t)bit;
|
|
#endif
|
|
return GPIO_NUM_NC;
|
|
}
|
|
|
|
void esp_sleep_gpio_include(void)
|
|
{
|
|
// Linker hook function, exists to make the linker examine this file
|
|
}
|