diff --git a/Documentation/platforms/xtensa/esp32s3/boards/esp32s3-devkit/index.rst b/Documentation/platforms/xtensa/esp32s3/boards/esp32s3-devkit/index.rst index 061ab406d0..631c5aab42 100644 --- a/Documentation/platforms/xtensa/esp32s3/boards/esp32s3-devkit/index.rst +++ b/Documentation/platforms/xtensa/esp32s3/boards/esp32s3-devkit/index.rst @@ -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 + (0) PM EXT1 Wakeup Trigger Mode + Before switching PM status, you need to query the current PM status:: nsh> pmconfig diff --git a/Documentation/platforms/xtensa/esp32s3/index.rst b/Documentation/platforms/xtensa/esp32s3/index.rst index 8b414f1de2..76b6be36e2 100644 --- a/Documentation/platforms/xtensa/esp32s3/index.rst +++ b/Documentation/platforms/xtensa/esp32s3/index.rst @@ -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 ----- diff --git a/arch/xtensa/src/esp32s3/esp32s3_pm.c b/arch/xtensa/src/esp32s3/esp32s3_pm.c index bb019a53fd..20647acd69 100644 --- a/arch/xtensa/src/esp32s3/esp32s3_pm.c +++ b/arch/xtensa/src/esp32s3/esp32s3_pm.c @@ -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(); } diff --git a/arch/xtensa/src/esp32s3/esp32s3_rtc.c b/arch/xtensa/src/esp32s3/esp32s3_rtc.c index 7f64bf4b15..1ec45adc91 100644 --- a/arch/xtensa/src/esp32s3/esp32s3_rtc.c +++ b/arch/xtensa/src/esp32s3/esp32s3_rtc.c @@ -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 * diff --git a/arch/xtensa/src/esp32s3/esp32s3_rtc.h b/arch/xtensa/src/esp32s3/esp32s3_rtc.h index aaa54bfffb..32763e3538 100644 --- a/arch/xtensa/src/esp32s3/esp32s3_rtc.h +++ b/arch/xtensa/src/esp32s3/esp32s3_rtc.h @@ -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 * diff --git a/boards/xtensa/esp32s3/common/Kconfig b/boards/xtensa/esp32s3/common/Kconfig index 6948cee207..ed43926c6a 100644 --- a/boards/xtensa/esp32s3/common/Kconfig +++ b/boards/xtensa/esp32s3/common/Kconfig @@ -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