diff --git a/components/esp32/Kconfig b/components/esp32/Kconfig index ab73fbada..25152dbb9 100644 --- a/components/esp32/Kconfig +++ b/components/esp32/Kconfig @@ -775,6 +775,19 @@ menu "ESP32-specific" bool "Internal 8.5MHz oscillator, divided by 256 (~33kHz)" endchoice + config ESP32_RTC_EXTERNAL_CRYSTAL_ADDITIONAL_CURRENT + bool "Additional current for external 32kHz crystal" + depends on ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL + default "n" + help + Choose which additional current is used for rtc external crystal. + + - With some 32kHz crystal configurations, the X32N and X32P pins may not + have enough drive strength to keep the crystal oscillating during deep sleep. + If this option is enabled, additional current from touchpad 9 is provided + internally to drive the 32kHz crystal. If this option is enabled, deep sleep current + is slightly higher (4-5uA) and the touchpad and ULP wakeup sources are not available. + config ESP32_RTC_CLK_CAL_CYCLES int "Number of cycles for RTC_SLOW_CLK calibration" default 3000 if ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL diff --git a/components/esp32/include/esp_sleep.h b/components/esp32/include/esp_sleep.h index 6ebe79ce3..c21f26add 100644 --- a/components/esp32/include/esp_sleep.h +++ b/components/esp32/include/esp_sleep.h @@ -95,6 +95,7 @@ esp_err_t esp_sleep_disable_wakeup_source(esp_sleep_source_t source); * source is used. * @return * - ESP_OK on success + * - ESP_ERR_NOT_SUPPORTED if additional current by touch (CONFIG_ESP32_RTC_EXTERNAL_CRYSTAL_ADDITIONAL_CURRENT) is enabled. * - ESP_ERR_INVALID_STATE if ULP co-processor is not enabled or if wakeup triggers conflict */ esp_err_t esp_sleep_enable_ulp_wakeup(); @@ -121,6 +122,7 @@ esp_err_t esp_sleep_enable_timer_wakeup(uint64_t time_in_us); * * @return * - ESP_OK on success + * - ESP_ERR_NOT_SUPPORTED if additional current by touch (CONFIG_ESP32_RTC_EXTERNAL_CRYSTAL_ADDITIONAL_CURRENT) is enabled. * - ESP_ERR_INVALID_STATE if wakeup triggers conflict */ esp_err_t esp_sleep_enable_touchpad_wakeup(); diff --git a/components/esp32/sleep_modes.c b/components/esp32/sleep_modes.c index d46036590..3d5109672 100644 --- a/components/esp32/sleep_modes.c +++ b/components/esp32/sleep_modes.c @@ -403,6 +403,9 @@ esp_err_t esp_sleep_disable_wakeup_source(esp_sleep_source_t source) esp_err_t esp_sleep_enable_ulp_wakeup() { +#ifdef CONFIG_ESP32_RTC_EXTERNAL_CRYSTAL_ADDITIONAL_CURRENT + return ESP_ERR_NOT_SUPPORTED; +#endif #ifdef CONFIG_ULP_COPROC_ENABLED if(s_config.wakeup_triggers & RTC_EXT0_TRIG_EN) { ESP_LOGE(TAG, "Conflicting wake-up trigger: ext0"); @@ -436,6 +439,9 @@ static void timer_wakeup_prepare() esp_err_t esp_sleep_enable_touchpad_wakeup() { +#ifdef CONFIG_ESP32_RTC_EXTERNAL_CRYSTAL_ADDITIONAL_CURRENT + return ESP_ERR_NOT_SUPPORTED; +#endif if (s_config.wakeup_triggers & (RTC_EXT0_TRIG_EN)) { ESP_LOGE(TAG, "Conflicting wake-up trigger: ext0"); return ESP_ERR_INVALID_STATE; @@ -695,6 +701,13 @@ static uint32_t get_power_down_flags() if (s_config.pd_options[ESP_PD_DOMAIN_XTAL] != ESP_PD_OPTION_ON) { pd_flags |= RTC_SLEEP_PD_XTAL; } + + if ((s_config.wakeup_triggers & (RTC_TOUCH_TRIG_EN | RTC_ULP_TRIG_EN)) == 0) { + // If enabled EXT1 only and enable the additional current by touch, should be keep RTC_PERIPH power on. +#if ((defined CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL) && (defined CONFIG_ESP32_RTC_EXTERNAL_CRYSTAL_ADDITIONAL_CURRENT)) + pd_flags &= ~RTC_SLEEP_PD_RTC_PERIPH; +#endif + } return pd_flags; } diff --git a/components/soc/esp32/rtc_clk.c b/components/soc/esp32/rtc_clk.c index 9a7278bce..fec28bccb 100644 --- a/components/soc/esp32/rtc_clk.c +++ b/components/soc/esp32/rtc_clk.c @@ -85,7 +85,7 @@ /* Core voltage needs to be increased in two cases: * 1. running at 240 MHz * 2. running with 80MHz Flash frequency - * + * * There is a record in efuse which indicates the proper voltage for these two cases. */ #define RTC_CNTL_DBIAS_HP_VOLT (RTC_CNTL_DBIAS_1V25 - (REG_GET_FIELD(EFUSE_BLK0_RDATA5_REG, EFUSE_RD_VOL_LEVEL_HP_INV))) @@ -116,7 +116,7 @@ static void rtc_clk_32k_enable_common(int dac, int dres, int dbias) { CLEAR_PERI_REG_MASK(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_X32P_RDE | RTC_IO_X32P_RUE | RTC_IO_X32N_RUE | - RTC_IO_X32N_RDE | RTC_IO_X32N_MUX_SEL | RTC_IO_X32P_MUX_SEL); + RTC_IO_X32N_RDE | RTC_IO_X32N_FUN_IE | RTC_IO_X32P_FUN_IE); SET_PERI_REG_MASK(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_X32N_MUX_SEL | RTC_IO_X32P_MUX_SEL); /* Set the parameters of xtal dac --> current @@ -127,7 +127,8 @@ static void rtc_clk_32k_enable_common(int dac, int dres, int dbias) REG_SET_FIELD(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_DRES_XTAL_32K, dres); REG_SET_FIELD(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_DBIAS_XTAL_32K, dbias); - /* TOUCH sensor can provide additional current to external XTAL. +#ifdef CONFIG_ESP32_RTC_EXTERNAL_CRYSTAL_ADDITIONAL_CURRENT + /* TOUCH sensor can provide additional current to external XTAL. In some case, X32N and X32P PAD don't have enough drive capability to start XTAL */ SET_PERI_REG_MASK(RTC_IO_TOUCH_CFG_REG, RTC_IO_TOUCH_XPD_BIAS_M); /* Tie PAD Touch8 to VDD @@ -140,6 +141,7 @@ static void rtc_clk_32k_enable_common(int dac, int dres, int dbias) So the Touch DAC start to drive some current from VDD to TOUCH8(which is also XTAL-N) */ SET_PERI_REG_MASK(RTC_IO_TOUCH_PAD9_REG, RTC_IO_TOUCH_PAD9_XPD_M); +#endif // CONFIG_ESP32_RTC_EXTERNAL_CRYSTAL_ADDITIONAL_CURRENT /* Power up external xtal */ SET_PERI_REG_MASK(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_XPD_XTAL_32K_M); } @@ -150,9 +152,13 @@ void rtc_clk_32k_enable(bool enable) rtc_clk_32k_enable_common(XTAL_32K_DAC_VAL, XTAL_32K_DRES_VAL, XTAL_32K_DBIAS_VAL); } else { /* Disable X32N and X32P pad drive external xtal */ - CLEAR_PERI_REG_MASK(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_XPD_XTAL_32K); + CLEAR_PERI_REG_MASK(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_XPD_XTAL_32K_M); + CLEAR_PERI_REG_MASK(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_X32N_MUX_SEL | RTC_IO_X32P_MUX_SEL); + +#ifdef CONFIG_ESP32_RTC_EXTERNAL_CRYSTAL_ADDITIONAL_CURRENT /* Power down TOUCH */ CLEAR_PERI_REG_MASK(RTC_IO_TOUCH_PAD9_REG, RTC_IO_TOUCH_PAD9_XPD_M); +#endif // CONFIG_ESP32_RTC_EXTERNAL_CRYSTAL_ADDITIONAL_CURRENT } }