From abb6bb11813080fd3d62641a811c9c635dc561da Mon Sep 17 00:00:00 2001 From: jingli Date: Sat, 7 May 2022 21:52:56 +0800 Subject: [PATCH] esp_hw_support/sleep: fix cannot enable sleep reject in some cases When enable sleep reject before this fix, we have two limitations: 1. it must be light sleep 2. RTC GPIO wakeup source must be set We require light sleep because `esp_deep_sleep_start` function has been declared with "noreturn" attribute, So developers don't expect that this function may return (due to an error or a sleep reject). But the requirement for RTC GPIO wakeup source is not reasonable for all chips. This requirement exists because ESP32 only supports RTC GPIO and SDIO sleep reject sources. But later chips support all sleep reject sources. This fix brings the following changes: for ESP32: RTC GPIO and SDIO sleep reject sources can be enabled when corresponding wakeup source is set. for later chips: all sleep reject sources can be enabled when corresponding wakeup source is set. --- .../esp_hw_support/port/esp32/rtc_sleep.c | 3 +++ components/esp_hw_support/sleep_modes.c | 13 ++++++----- components/soc/esp32/include/soc/rtc.h | 12 +++++++++- components/soc/esp32c2/include/soc/rtc.h | 17 ++++++++++++-- components/soc/esp32c3/include/soc/rtc.h | 17 ++++++++++++-- components/soc/esp32h2/include/soc/rtc.h | 17 ++++++++++++-- components/soc/esp32s2/include/soc/rtc.h | 23 +++++++++++++++++-- components/soc/esp32s3/include/soc/rtc.h | 23 +++++++++++++++++-- 8 files changed, 108 insertions(+), 17 deletions(-) diff --git a/components/esp_hw_support/port/esp32/rtc_sleep.c b/components/esp_hw_support/port/esp32/rtc_sleep.c index dff1b49acd..cbac7d74e0 100644 --- a/components/esp_hw_support/port/esp32/rtc_sleep.c +++ b/components/esp_hw_support/port/esp32/rtc_sleep.c @@ -201,6 +201,9 @@ void rtc_sleep_init(rtc_sleep_config_t cfg) REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DBIAS_WAK, cfg.rtc_dbias_wak); REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, cfg.dig_dbias_wak); REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_SLP, cfg.dig_dbias_slp); + + REG_SET_FIELD(RTC_CNTL_SLP_REJECT_CONF_REG, RTC_CNTL_DEEP_SLP_REJECT_EN, cfg.deep_slp_reject); + REG_SET_FIELD(RTC_CNTL_SLP_REJECT_CONF_REG, RTC_CNTL_LIGHT_SLP_REJECT_EN, cfg.light_slp_reject); } void rtc_sleep_low_init(uint32_t slowclk_period) diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index dbd589a169..2ac1905760 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -357,6 +357,11 @@ inline static uint32_t call_rtc_sleep_start(uint32_t reject_triggers, uint32_t l //TODO: IDF-4813 bool esp_no_sleep = false; +inline static bool is_light_sleep(uint32_t pd_flags) +{ + return (pd_flags & RTC_SLEEP_PD_DIG) == 0; +} + static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags) { #if CONFIG_IDF_TARGET_ESP32S3 @@ -433,15 +438,11 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags) } #endif uint32_t reject_triggers = 0; - if ((pd_flags & RTC_SLEEP_PD_DIG) == 0 && (s_config.wakeup_triggers & RTC_GPIO_TRIG_EN)) { + if (is_light_sleep(pd_flags)) { /* Light sleep, enable sleep reject for faster return from this function, * in case the wakeup is already triggerred. */ -#if CONFIG_IDF_TARGET_ESP32 - reject_triggers = RTC_CNTL_LIGHT_SLP_REJECT_EN_M | RTC_CNTL_GPIO_REJECT_EN_M; -#else - reject_triggers = s_config.wakeup_triggers; -#endif + reject_triggers = s_config.wakeup_triggers & RTC_SLEEP_REJECT_MASK; } // Enter sleep diff --git a/components/soc/esp32/include/soc/rtc.h b/components/soc/esp32/include/soc/rtc.h index 1ca2c4707d..e768f8c8e9 100644 --- a/components/soc/esp32/include/soc/rtc.h +++ b/components/soc/esp32/include/soc/rtc.h @@ -515,6 +515,8 @@ typedef struct rtc_sleep_config_s { uint32_t lslp_meminf_pd : 1; //!< remove all peripheral force power up flags uint32_t vddsdio_pd_en : 1; //!< power down VDDSDIO regulator uint32_t xtal_fpu : 1; //!< keep main XTAL powered up in sleep + uint32_t deep_slp_reject : 1; //!< enable deep sleep reject + uint32_t light_slp_reject : 1; //!< enable light sleep reject } rtc_sleep_config_t; /** @@ -548,7 +550,9 @@ typedef struct rtc_sleep_config_s { : RTC_CNTL_DBIAS_0V90, \ .lslp_meminf_pd = 1, \ .vddsdio_pd_en = ((sleep_flags) & RTC_SLEEP_PD_VDDSDIO) ? 1 : 0, \ - .xtal_fpu = ((sleep_flags) & RTC_SLEEP_PD_XTAL) ? 0 : 1 \ + .xtal_fpu = ((sleep_flags) & RTC_SLEEP_PD_XTAL) ? 0 : 1, \ + .deep_slp_reject = 1, \ + .light_slp_reject = 1 \ }; #define RTC_SLEEP_PD_DIG BIT(0) //!< Deep sleep (power down digital domain) @@ -615,6 +619,12 @@ void rtc_sleep_set_wakeup_time(uint64_t t); #define RTC_ULP_TRIG_EN BIT(9) //!< ULP wakeup #define RTC_BT_TRIG_EN BIT(10) //!< BT wakeup (light sleep only) +/** + * RTC_SLEEP_REJECT_MASK records sleep reject sources supported by chip + * esp32 only supports GPIO and SDIO sleep reject sources + */ +#define RTC_SLEEP_REJECT_MASK (RTC_GPIO_TRIG_EN | RTC_SDIO_TRIG_EN) + /** * @brief Enter deep or light sleep mode * diff --git a/components/soc/esp32c2/include/soc/rtc.h b/components/soc/esp32c2/include/soc/rtc.h index 35616e179e..72df334bcd 100644 --- a/components/soc/esp32c2/include/soc/rtc.h +++ b/components/soc/esp32c2/include/soc/rtc.h @@ -610,8 +610,8 @@ typedef struct { uint32_t rtc_dbias_slp : 5; //!< set bias for RTC domain, in sleep mode uint32_t vddsdio_pd_en : 1; //!< power down VDDSDIO regulator uint32_t xtal_fpu : 1; //!< keep main XTAL powered up in sleep - uint32_t deep_slp_reject : 1; - uint32_t light_slp_reject : 1; + uint32_t deep_slp_reject : 1; //!< enable deep sleep reject + uint32_t light_slp_reject : 1; //!< enable light sleep reject } rtc_sleep_config_t; /** @@ -707,6 +707,19 @@ void rtc_sleep_set_wakeup_time(uint64_t t); #define RTC_USB_TRIG_EN BIT(14) #define RTC_BROWNOUT_DET_TRIG_EN BIT(16) +/** + * RTC_SLEEP_REJECT_MASK records sleep reject sources supported by chip + */ +#define RTC_SLEEP_REJECT_MASK (RTC_GPIO_TRIG_EN | \ + RTC_TIMER_TRIG_EN | \ + RTC_WIFI_TRIG_EN | \ + RTC_UART0_TRIG_EN | \ + RTC_UART1_TRIG_EN | \ + RTC_BT_TRIG_EN | \ + RTC_XTAL32K_DEAD_TRIG_EN | \ + RTC_USB_TRIG_EN | \ + RTC_BROWNOUT_DET_TRIG_EN) + /** * @brief Enter deep or light sleep mode * diff --git a/components/soc/esp32c3/include/soc/rtc.h b/components/soc/esp32c3/include/soc/rtc.h index 2fbf1431d0..5acd321588 100644 --- a/components/soc/esp32c3/include/soc/rtc.h +++ b/components/soc/esp32c3/include/soc/rtc.h @@ -626,8 +626,8 @@ typedef struct { uint32_t rtc_dbias_slp : 5; //!< set bias for RTC domain, in sleep mode uint32_t vddsdio_pd_en : 1; //!< power down VDDSDIO regulator uint32_t xtal_fpu : 1; //!< keep main XTAL powered up in sleep - uint32_t deep_slp_reject : 1; - uint32_t light_slp_reject : 1; + uint32_t deep_slp_reject : 1; //!< enable deep sleep reject + uint32_t light_slp_reject : 1; //!< enable light sleep reject } rtc_sleep_config_t; /** @@ -723,6 +723,19 @@ void rtc_sleep_set_wakeup_time(uint64_t t); #define RTC_USB_TRIG_EN BIT(14) #define RTC_BROWNOUT_DET_TRIG_EN BIT(16) +/** + * RTC_SLEEP_REJECT_MASK records sleep reject sources supported by chip + */ +#define RTC_SLEEP_REJECT_MASK (RTC_GPIO_TRIG_EN | \ + RTC_TIMER_TRIG_EN | \ + RTC_WIFI_TRIG_EN | \ + RTC_UART0_TRIG_EN | \ + RTC_UART1_TRIG_EN | \ + RTC_BT_TRIG_EN | \ + RTC_XTAL32K_DEAD_TRIG_EN | \ + RTC_USB_TRIG_EN | \ + RTC_BROWNOUT_DET_TRIG_EN) + /** * @brief Enter deep or light sleep mode * diff --git a/components/soc/esp32h2/include/soc/rtc.h b/components/soc/esp32h2/include/soc/rtc.h index 5bfaf03e37..ae64da5df1 100644 --- a/components/soc/esp32h2/include/soc/rtc.h +++ b/components/soc/esp32h2/include/soc/rtc.h @@ -642,8 +642,8 @@ typedef struct { uint32_t rtc_dbias_slp : 5; //!< set bias for RTC domain, in sleep mode uint32_t vddsdio_pd_en : 1; //!< power down VDDSDIO regulator uint32_t xtal_fpu : 1; //!< keep main XTAL powered up in sleep - uint32_t deep_slp_reject : 1; - uint32_t light_slp_reject : 1; + uint32_t deep_slp_reject : 1; //!< enable deep sleep reject + uint32_t light_slp_reject : 1; //!< enable light sleep reject } rtc_sleep_config_t; /** @@ -739,6 +739,19 @@ void rtc_sleep_set_wakeup_time(uint64_t t); #define RTC_USB_TRIG_EN BIT(14) #define RTC_BROWNOUT_DET_TRIG_EN BIT(16) +/** + * RTC_SLEEP_REJECT_MASK records sleep reject sources supported by chip + */ +#define RTC_SLEEP_REJECT_MASK (RTC_GPIO_TRIG_EN | \ + RTC_TIMER_TRIG_EN | \ + RTC_WIFI_TRIG_EN | \ + RTC_UART0_TRIG_EN | \ + RTC_UART1_TRIG_EN | \ + RTC_BT_TRIG_EN | \ + RTC_XTAL32K_DEAD_TRIG_EN | \ + RTC_USB_TRIG_EN | \ + RTC_BROWNOUT_DET_TRIG_EN) + /** * @brief Enter deep or light sleep mode * diff --git a/components/soc/esp32s2/include/soc/rtc.h b/components/soc/esp32s2/include/soc/rtc.h index 91cad6f860..b33be653cb 100644 --- a/components/soc/esp32s2/include/soc/rtc.h +++ b/components/soc/esp32s2/include/soc/rtc.h @@ -683,8 +683,8 @@ typedef struct { uint32_t rtc_dbias_slp : 3; //!< set bias for RTC domain, in sleep mode uint32_t vddsdio_pd_en : 1; //!< power down VDDSDIO regulator uint32_t xtal_fpu : 1; //!< keep main XTAL powered up in sleep - uint32_t deep_slp_reject : 1; - uint32_t light_slp_reject : 1; + uint32_t deep_slp_reject : 1; //!< enable deep sleep reject + uint32_t light_slp_reject : 1; //!< enable light sleep reject } rtc_sleep_config_t; /** @@ -775,6 +775,25 @@ void rtc_sleep_low_init(uint32_t slowclk_period); #define RTC_COCPU_TRAP_TRIG_EN BIT(13) #define RTC_USB_TRIG_EN BIT(14) +/** + * RTC_SLEEP_REJECT_MASK records sleep reject sources supported by chip + */ +#define RTC_SLEEP_REJECT_MASK (RTC_EXT0_TRIG_EN | \ + RTC_EXT1_TRIG_EN | \ + RTC_GPIO_TRIG_EN | \ + RTC_TIMER_TRIG_EN | \ + RTC_SDIO_TRIG_EN | \ + RTC_WIFI_TRIG_EN | \ + RTC_UART0_TRIG_EN | \ + RTC_UART1_TRIG_EN | \ + RTC_TOUCH_TRIG_EN | \ + RTC_ULP_TRIG_EN | \ + RTC_BT_TRIG_EN | \ + RTC_COCPU_TRIG_EN | \ + RTC_XTAL32K_DEAD_TRIG_EN | \ + RTC_COCPU_TRAP_TRIG_EN | \ + RTC_USB_TRIG_EN) + /** * @brief Enter deep or light sleep mode * diff --git a/components/soc/esp32s3/include/soc/rtc.h b/components/soc/esp32s3/include/soc/rtc.h index c5e5b764cb..52ccfe77b4 100644 --- a/components/soc/esp32s3/include/soc/rtc.h +++ b/components/soc/esp32s3/include/soc/rtc.h @@ -633,8 +633,8 @@ typedef struct { uint32_t rtc_dbias_slp : 5; //!< set bias for RTC domain, in sleep mode uint32_t vddsdio_pd_en : 1; //!< power down VDDSDIO regulator uint32_t xtal_fpu : 1; //!< keep main XTAL powered up in sleep - uint32_t deep_slp_reject : 1; - uint32_t light_slp_reject : 1; + uint32_t deep_slp_reject : 1; //!< enable deep sleep reject + uint32_t light_slp_reject : 1; //!< enable light sleep reject } rtc_sleep_config_t; /** @@ -737,6 +737,25 @@ void rtc_sleep_set_wakeup_time(uint64_t t); #define RTC_COCPU_TRAP_TRIG_EN BIT(13) #define RTC_USB_TRIG_EN BIT(14) +/** + * RTC_SLEEP_REJECT_MASK records sleep reject sources supported by chip + */ +#define RTC_SLEEP_REJECT_MASK (RTC_EXT0_TRIG_EN | \ + RTC_EXT1_TRIG_EN | \ + RTC_GPIO_TRIG_EN | \ + RTC_TIMER_TRIG_EN | \ + RTC_SDIO_TRIG_EN | \ + RTC_WIFI_TRIG_EN | \ + RTC_UART0_TRIG_EN | \ + RTC_UART1_TRIG_EN | \ + RTC_TOUCH_TRIG_EN | \ + RTC_ULP_TRIG_EN | \ + RTC_BT_TRIG_EN | \ + RTC_COCPU_TRIG_EN | \ + RTC_XTAL32K_DEAD_TRIG_EN | \ + RTC_COCPU_TRAP_TRIG_EN | \ + RTC_USB_TRIG_EN) + /** * @brief Enter deep or light sleep mode *