arch/xtensa/esp32s3: Add EXT1 wakeup support in power management
Some checks failed
Build Documentation / build-html (push) Has been cancelled

Introduce EXT1 wakeup functionality to the ESP32-S3 power management
subsystem. With this feature, the ESP32-S3 can wake up from PM_STANDBY
or PM_SLEEP when one or more RTC GPIOs trigger the EXT1 condition.

Changes include:
- Added EXT1 wakeup configuration and preparation logic in rtc code.
- Integrated EXT1 handling in pmstandby() and pmsleep().
- New board-level Kconfig options under ESP32-S3 DevKit menu:
  - CONFIG_PM_EXT1_WAKEUP: enable EXT1 wakeup support
  - CONFIG_PM_EXT1_WAKEUP_RTC_GPIO<n>: select RTC GPIOs as wake sources
  - CONFIG_PM_EXT1_WAKEUP_TRIGGER_MODE: choose wakeup on HIGH or LOW level
- Fixing Kconfig style
- Fixing comments standard
- Adding PM documentation for esp32s3-devkit

Impact:
- No build impact unless CONFIG_PM_EXT1_WAKEUP is enabled.
- When enabled, ESP32-S3 can wake from low-power states via RTC GPIOs.
- No new public API introduced; controlled via board Kconfig.

Tested on ESP32-S3 DevKit:
- Configured GPIO4 and GPIO5 as EXT1 wake sources.
- Verified wakeup from light sleep and deep sleep on external signals.
- Wakeup reason correctly reported as EXT1.

Signed-off-by: Thiago Finelon <thiago.sfinelon@gmail.com>
This commit is contained in:
Thiago Finelon
2025-08-20 15:50:27 -03:00
committed by Alan C. Assis
parent 67d0b975a5
commit e87c43b798
6 changed files with 341 additions and 0 deletions

View File

@@ -637,6 +637,16 @@ Enables PM support. You can define standby mode and sleep mode delay time::
(20) PM_SLEEP delay (seconds)
(0) PM_SLEEP delay (nanoseconds)
You can also define an EXT1 wakeup for both sleep modes by selecting which RTC
GPIO will be used and the logic level that will trigger it::
$ make menuconfig
-> Board Selection
-> [*] PM EXT1 Wakeup
PM EXT1 Wakeup Sources --->
[ ] RTC_GPIO<N>
(0) PM EXT1 Wakeup Trigger Mode
Before switching PM status, you need to query the current PM status::
nsh> pmconfig

View File

@@ -610,6 +610,18 @@ using WPA2.
The ``dhcpd_start`` is necessary to let your board to associate an IP to your smartphone.
Power Management
================
.. tip:: Boards usually expose a pm defconfig which enables power management
features. On ESP32-S3, different low power modes can be used to reduce power
consumption depending on the application.
When using this board configuration profile, two wakeup sources are available:
- Timer (mandatory) : Every time the board enters sleep mode, a timer is started. Once the defined time is reached, the board wakes up.
- EXT1 (optional): The board wakes up whenever the selected EXT1 GPIO is asserted to the configured level.
PSRAM
-----

View File

@@ -49,6 +49,7 @@
#include "hardware/esp32s3_gpio.h"
#include "esp32s3_rtc.h"
#include "esp32s3_rtc_gpio.h"
#include "esp32s3_pm.h"
#include "soc/periph_defs.h"
@@ -91,6 +92,8 @@
#define RTC_VDDSDIO_TIEH_1_8V 0 /* TIEH field value for 1.8V VDDSDIO */
#define RTC_VDDSDIO_TIEH_3_3V 1 /* TIEH field value for 3.3V VDDSDIO */
#define RTC_EXT0_TRIG_EN BIT(0) /* External wakeup source 0 */
#define RTC_EXT1_TRIG_EN BIT(1) /* External wakeup source 1 */
#define RTC_GPIO_TRIG_EN BIT(2) /* GPIO wakeup */
#define RTC_TIMER_TRIG_EN BIT(3) /* Timer wakeup */
#define RTC_WIFI_TRIG_EN BIT(5) /* Wi-Fi wakeup (light sleep only) */
@@ -429,6 +432,40 @@ static uint32_t IRAM_ATTR esp32s3_get_power_down_flags(void)
return pd_flags;
}
/****************************************************************************
* Name: esp32s3_ext1_wakeup_prepare
*
* Description:
* Configure gpio to wake-up
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
static void IRAM_ATTR esp32s3_ext1_wakeup_prepare(void)
{
static bool ext1_rtc_gpio_mask_configured = false;
if (ext1_rtc_gpio_mask_configured == false)
{
for (int i = 0; i < RTC_GPIO_NUMBER; i++)
{
if (g_config.ext1_rtc_gpio_mask & BIT(i))
{
esp32s3_configrtcio(i, RTC_INPUT_FUNCTION_RTCIO);
}
}
ext1_rtc_gpio_mask_configured = true;
}
esp32s3_rtc_ext1_prepare(g_config.ext1_trigger_mode,
g_config.ext1_rtc_gpio_mask);
}
/****************************************************************************
* Name: esp32s3_timer_wakeup_prepare
*
@@ -596,6 +633,11 @@ static int IRAM_ATTR esp32s3_sleep_start(uint32_t pd_flags)
esp32s3_timer_wakeup_prepare();
}
if (g_config.wakeup_triggers & RTC_EXT1_TRIG_EN)
{
esp32s3_ext1_wakeup_prepare();
}
result = esp32s3_rtc_sleep_start(g_config.wakeup_triggers, 0);
/* Restore CPU frequency */
@@ -865,6 +907,94 @@ void IRAM_ATTR esp32s3_periph_inform_out_sleep_overhead(uint32_t us)
}
}
/****************************************************************************
* Name: esp32s3_sleep_enable_ext1_wakeup
*
* Description:
* Enable wakeup by ext1 gpio
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
void IRAM_ATTR esp32s3_sleep_enable_ext1_wakeup(void)
{
g_config.wakeup_triggers |= RTC_EXT1_TRIG_EN;
#ifdef CONFIG_PM_EXT1_WAKEUP_TRIGGER_MODE
g_config.ext1_trigger_mode = CONFIG_PM_EXT1_WAKEUP_TRIGGER_MODE;
#endif
g_config.ext1_rtc_gpio_mask = 0U;
#ifdef CONFIG_PM_EXT1_WAKEUP_RTC_GPIO0
g_config.ext1_rtc_gpio_mask |= BIT(RTCIO_CHANNEL_0_GPIO_NUM);
#endif
#ifdef CONFIG_PM_EXT1_WAKEUP_RTC_GPIO1
g_config.ext1_rtc_gpio_mask |= BIT(RTCIO_CHANNEL_1_GPIO_NUM);
#endif
#ifdef CONFIG_PM_EXT1_WAKEUP_RTC_GPIO2
g_config.ext1_rtc_gpio_mask |= BIT(RTCIO_CHANNEL_2_GPIO_NUM);
#endif
#ifdef CONFIG_PM_EXT1_WAKEUP_RTC_GPIO3
g_config.ext1_rtc_gpio_mask |= BIT(RTCIO_CHANNEL_3_GPIO_NUM);
#endif
#ifdef CONFIG_PM_EXT1_WAKEUP_RTC_GPIO4
g_config.ext1_rtc_gpio_mask |= BIT(RTCIO_CHANNEL_4_GPIO_NUM);
#endif
#ifdef CONFIG_PM_EXT1_WAKEUP_RTC_GPIO5
g_config.ext1_rtc_gpio_mask |= BIT(RTCIO_CHANNEL_5_GPIO_NUM);
#endif
#ifdef CONFIG_PM_EXT1_WAKEUP_RTC_GPIO6
g_config.ext1_rtc_gpio_mask |= BIT(RTCIO_CHANNEL_6_GPIO_NUM);
#endif
#ifdef CONFIG_PM_EXT1_WAKEUP_RTC_GPIO7
g_config.ext1_rtc_gpio_mask |= BIT(RTCIO_CHANNEL_7_GPIO_NUM);
#endif
#ifdef CONFIG_PM_EXT1_WAKEUP_RTC_GPIO8
g_config.ext1_rtc_gpio_mask |= BIT(RTCIO_CHANNEL_8_GPIO_NUM);
#endif
#ifdef CONFIG_PM_EXT1_WAKEUP_RTC_GPIO9
g_config.ext1_rtc_gpio_mask |= BIT(RTCIO_CHANNEL_9_GPIO_NUM);
#endif
#ifdef CONFIG_PM_EXT1_WAKEUP_RTC_GPIO10
g_config.ext1_rtc_gpio_mask |= BIT(RTCIO_CHANNEL_10_GPIO_NUM);
#endif
#ifdef CONFIG_PM_EXT1_WAKEUP_RTC_GPIO11
g_config.ext1_rtc_gpio_mask |= BIT(RTCIO_CHANNEL_11_GPIO_NUM);
#endif
#ifdef CONFIG_PM_EXT1_WAKEUP_RTC_GPIO12
g_config.ext1_rtc_gpio_mask |= BIT(RTCIO_CHANNEL_12_GPIO_NUM);
#endif
#ifdef CONFIG_PM_EXT1_WAKEUP_RTC_GPIO13
g_config.ext1_rtc_gpio_mask |= BIT(RTCIO_CHANNEL_13_GPIO_NUM);
#endif
#ifdef CONFIG_PM_EXT1_WAKEUP_RTC_GPIO14
g_config.ext1_rtc_gpio_mask |= BIT(RTCIO_CHANNEL_14_GPIO_NUM);
#endif
#ifdef CONFIG_PM_EXT1_WAKEUP_RTC_GPIO15
g_config.ext1_rtc_gpio_mask |= BIT(RTCIO_CHANNEL_15_GPIO_NUM);
#endif
#ifdef CONFIG_PM_EXT1_WAKEUP_RTC_GPIO16
g_config.ext1_rtc_gpio_mask |= BIT(RTCIO_CHANNEL_16_GPIO_NUM);
#endif
#ifdef CONFIG_PM_EXT1_WAKEUP_RTC_GPIO17
g_config.ext1_rtc_gpio_mask |= BIT(RTCIO_CHANNEL_17_GPIO_NUM);
#endif
#ifdef CONFIG_PM_EXT1_WAKEUP_RTC_GPIO18
g_config.ext1_rtc_gpio_mask |= BIT(RTCIO_CHANNEL_18_GPIO_NUM);
#endif
#ifdef CONFIG_PM_EXT1_WAKEUP_RTC_GPIO19
g_config.ext1_rtc_gpio_mask |= BIT(RTCIO_CHANNEL_19_GPIO_NUM);
#endif
#ifdef CONFIG_PM_EXT1_WAKEUP_RTC_GPIO20
g_config.ext1_rtc_gpio_mask |= BIT(RTCIO_CHANNEL_20_GPIO_NUM);
#endif
}
/****************************************************************************
* Name: esp32s3_sleep_enable_timer_wakeup
*
@@ -1025,6 +1155,10 @@ void esp32s3_pmstandby(uint64_t time_in_us)
{
uint64_t rtc_diff_us;
#ifdef CONFIG_PM_EXT1_WAKEUP
esp32s3_sleep_enable_ext1_wakeup();
#endif
/* Don't power down XTAL - powering it up takes different time on. */
esp32s3_sleep_enable_timer_wakeup(time_in_us);
@@ -1094,6 +1228,10 @@ void IRAM_ATTR esp32s3_deep_sleep_start(void)
void esp32s3_pmsleep(uint64_t time_in_us)
{
#ifdef CONFIG_PM_EXT1_WAKEUP
esp32s3_sleep_enable_ext1_wakeup();
#endif
esp32s3_sleep_enable_timer_wakeup(time_in_us);
esp32s3_deep_sleep_start();
}

View File

@@ -2431,6 +2431,18 @@ int IRAM_ATTR esp32s3_rtc_sleep_start(uint32_t wakeup_opt,
return reject;
}
void esp32s3_rtc_ext1_prepare(uint32_t trigger_mode, uint32_t rtc_gpio_mask)
{
if (rtc_gpio_mask > 0)
{
modifyreg32(RTC_CNTL_RTC_EXT_WAKEUP1_REG, 0 ,
RTC_CNTL_EXT_WAKEUP1_STATUS_CLR | rtc_gpio_mask);
modifyreg32(RTC_CNTL_RTC_EXT_WAKEUP_CONF_REG, 0,
(trigger_mode << RTC_CNTL_EXT_WAKEUP1_LV_S) | \
RTC_CNTL_GPIO_WAKEUP_FILTER);
}
}
/****************************************************************************
* Name: esp32s3_rtc_clk_cpu_freq_set_config
*

View File

@@ -514,6 +514,23 @@ int esp_rtc_clk_get_cpu_freq(void);
void esp32s3_rtc_sleep_init(uint32_t flags);
/****************************************************************************
* Name: esp32s3_rtc_ext1_prepare
*
* Description:
* Configure RTC_EXT1 wakeup sources
*
* Input Parameters:
* trigger_mode - trigger mode for RTC_EXT1 wakeup sources
* rtc_gpio_mask - mask of GPIOs to be used as RTC_EXT1 wakeup sources
*
* Returned Value:
* None
*
****************************************************************************/
void esp32s3_rtc_ext1_prepare(uint32_t trigger_mode, uint32_t rtc_gpio_mask);
/****************************************************************************
* Name: esp32s3_rtc_sleep_start
*

View File

@@ -80,6 +80,158 @@ endchoice # ESP32S3_SPIFLASH_FS
if PM
config PM_EXT1_WAKEUP
bool "PM EXT1 Wakeup"
default n
---help---
Enable EXT1 wakeup functionality.
This allows the system to wake up from PM_STANDBY or PM_SLEEP
when a GPIO pin configured as an EXT1 wakeup source is triggered.
if PM_EXT1_WAKEUP
menu "PM EXT1 Wakeup Sources"
config PM_EXT1_WAKEUP_RTC_GPIO0
bool "RTC_GPIO0"
default n
---help---
Enable RTC GPIO0 as an EXT1 wakeup source.
config PM_EXT1_WAKEUP_RTC_GPIO1
bool "RTC_GPIO1"
default n
---help---
Enable RTC GPIO1 as an EXT1 wakeup source.
config PM_EXT1_WAKEUP_RTC_GPIO2
bool "RTC_GPIO2"
default n
---help---
Enable RTC GPIO2 as an EXT1 wakeup source.
config PM_EXT1_WAKEUP_RTC_GPIO3
bool "RTC_GPIO3"
default n
---help---
Enable RTC GPIO3 as an EXT1 wakeup source.
config PM_EXT1_WAKEUP_RTC_GPIO4
bool "RTC_GPIO4"
default n
---help---
Enable RTC GPIO4 as an EXT1 wakeup source.
config PM_EXT1_WAKEUP_RTC_GPIO5
bool "RTC_GPIO5"
default n
---help---
Enable RTC GPIO5 as an EXT1 wakeup source.
config PM_EXT1_WAKEUP_RTC_GPIO6
bool "RTC_GPIO6"
default n
---help---
Enable RTC GPIO6 as an EXT1 wakeup source.
config PM_EXT1_WAKEUP_RTC_GPIO7
bool "RTC_GPIO7"
default n
---help---
Enable RTC GPIO7 as an EXT1 wakeup source.
config PM_EXT1_WAKEUP_RTC_GPIO8
bool "RTC_GPIO8"
default n
---help---
Enable RTC GPIO8 as an EXT1 wakeup source.
config PM_EXT1_WAKEUP_RTC_GPIO9
bool "RTC_GPIO9"
default n
---help---
Enable RTC GPIO9 as an EXT1 wakeup source.
config PM_EXT1_WAKEUP_RTC_GPIO10
bool "RTC_GPIO10"
default n
---help---
Enable RTC GPIO10 as an EXT1 wakeup source.
config PM_EXT1_WAKEUP_RTC_GPIO11
bool "RTC_GPIO11"
default n
---help---
Enable RTC GPIO11 as an EXT1 wakeup source.
config PM_EXT1_WAKEUP_RTC_GPIO12
bool "RTC_GPIO12"
default n
---help---
Enable RTC GPIO12 as an EXT1 wakeup source.
config PM_EXT1_WAKEUP_RTC_GPIO13
bool "RTC_GPIO13"
default n
---help---
Enable RTC GPIO13 as an EXT1 wakeup source.
config PM_EXT1_WAKEUP_RTC_GPIO14
bool "RTC_GPIO14"
default n
---help---
Enable RTC GPIO14 as an EXT1 wakeup source.
config PM_EXT1_WAKEUP_RTC_GPIO15
bool "RTC_GPIO15"
default n
---help---
Enable RTC GPIO15 as an EXT1 wakeup source.
config PM_EXT1_WAKEUP_RTC_GPIO16
bool "RTC_GPIO16"
default n
---help---
Enable RTC GPIO16 as an EXT1 wakeup source.
config PM_EXT1_WAKEUP_RTC_GPIO17
bool "RTC_GPIO17"
default n
---help---
Enable RTC GPIO17 as an EXT1 wakeup source.
config PM_EXT1_WAKEUP_RTC_GPIO18
bool "RTC_GPIO18"
default n
---help---
Enable RTC GPIO18 as an EXT1 wakeup source.
config PM_EXT1_WAKEUP_RTC_GPIO19
bool "RTC_GPIO19"
default n
---help---
Enable RTC GPIO19 as an EXT1 wakeup source.
config PM_EXT1_WAKEUP_RTC_GPIO20
bool "RTC_GPIO20"
default n
---help---
Enable RTC GPIO20 as an EXT1 wakeup source.
endmenu # PM_EXT1_WAKEUP_SOURCES
config PM_EXT1_WAKEUP_TRIGGER_MODE
int "PM EXT1 Wakeup Trigger Mode"
range 0 1
default 0
---help---
Select EXT1 wakeup mode:
0 = Wakeup when any selected GPIO is LOW
1 = Wakeup when any selected GPIO is HIGH
endif # PM_EXT1_WAKEUP
config PM_ALARM_SEC
int "PM_STANDBY delay (seconds)"
default 15