diff --git a/components/driver/esp32/touch_sensor.c b/components/driver/esp32/touch_sensor.c index ebf454df17..eb3030feaa 100644 --- a/components/driver/esp32/touch_sensor.c +++ b/components/driver/esp32/touch_sensor.c @@ -289,6 +289,10 @@ esp_err_t touch_pad_config(touch_pad_t touch_num, uint16_t threshold) esp_err_t touch_pad_init(void) { +#ifdef CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT_V2 + ESP_LOGE(TOUCH_TAG, "Touch Pad can't work because it provides current to external XTAL"); + return ESP_ERR_NOT_SUPPORTED; +#endif // CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT_V2 if (rtc_touch_mux == NULL) { rtc_touch_mux = xSemaphoreCreateMutex(); } diff --git a/components/driver/include/driver/touch_sensor_common.h b/components/driver/include/driver/touch_sensor_common.h index a114b03da2..3ff2dcd5ba 100644 --- a/components/driver/include/driver/touch_sensor_common.h +++ b/components/driver/include/driver/touch_sensor_common.h @@ -28,6 +28,7 @@ extern "C" { * @return * - ESP_OK Success * - ESP_ERR_NO_MEM Touch pad init error + * - ESP_ERR_NOT_SUPPORTED Touch pad is providing current to external XTAL */ esp_err_t touch_pad_init(void); diff --git a/components/esp32/Kconfig b/components/esp32/Kconfig index eafd3426a7..019d9cb698 100644 --- a/components/esp32/Kconfig +++ b/components/esp32/Kconfig @@ -564,18 +564,35 @@ menu "ESP32-specific" bool "Internal 8.5MHz oscillator, divided by 256 (~33kHz)" endchoice - config ESP32_RTC_EXT_CRYST_ADDIT_CURRENT - bool "Additional current for external 32kHz crystal" + choice ESP32_RTC_EXT_CRYST_ADDIT_CURRENT_METHOD + prompt "Additional current for external 32kHz crystal" depends on ESP32_RTC_CLK_SRC_EXT_CRYS - default "n" + depends on ESP32_REV_MIN <= 1 + default ESP32_RTC_EXT_CRYST_ADDIT_CURRENT_NONE 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. Choose the method to provide + additional current from touchpad 9 to the external 32kHz crystal. Note that + the deep sleep current is slightly high (4-5uA) and the touchpad and the + wakeup sources of both touchpad and ULP are not available in method 1 and method 2. - - 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. + This problem is fixed in ESP32 ECO 3, so this workaround is not needed. Setting the + project configuration to minimum revision ECO3 will disable this option, , allow + all wakeup sources, and save some code size. + + - "None" option will not provide additional current to external crystal + - "Method 1" option can't ensure 100% to solve the external 32k crystal start failed + issue, but the touchpad can work in this method. + - "Method 2" option can solve the external 32k issue, but the touchpad can't work + in this method. + + config ESP32_RTC_EXT_CRYST_ADDIT_CURRENT_NONE + bool "None" + config ESP32_RTC_EXT_CRYST_ADDIT_CURRENT + bool "Method 1" + config ESP32_RTC_EXT_CRYST_ADDIT_CURRENT_V2 + bool "Method 2" + endchoice config ESP32_RTC_CLK_CAL_CYCLES int "Number of cycles for RTC_SLOW_CLK calibration" diff --git a/components/esp32/sleep_modes.c b/components/esp32/sleep_modes.c index 0f8fc7a736..1bac8f1ef0 100644 --- a/components/esp32/sleep_modes.c +++ b/components/esp32/sleep_modes.c @@ -419,7 +419,8 @@ esp_err_t esp_sleep_disable_wakeup_source(esp_sleep_source_t source) esp_err_t esp_sleep_enable_ulp_wakeup(void) { -#ifdef CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT +#if ((defined CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT) || (defined CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT_V2)) + ESP_LOGE(TAG, "Failed to enable wakeup when provide current to external 32kHz crystal"); return ESP_ERR_NOT_SUPPORTED; #endif #ifdef CONFIG_ESP32_ULP_COPROC_ENABLED @@ -455,7 +456,8 @@ static void timer_wakeup_prepare(void) esp_err_t esp_sleep_enable_touchpad_wakeup(void) { -#ifdef CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT +#if ((defined CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT) || (defined CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT_V2)) + ESP_LOGE(TAG, "Failed to enable wakeup when provide current to external 32kHz crystal"); return ESP_ERR_NOT_SUPPORTED; #endif if (s_config.wakeup_triggers & (RTC_EXT0_TRIG_EN)) { diff --git a/components/soc/CMakeLists.txt b/components/soc/CMakeLists.txt index a786c90b80..f7ecfd4d1b 100644 --- a/components/soc/CMakeLists.txt +++ b/components/soc/CMakeLists.txt @@ -38,8 +38,14 @@ if(NOT BOOTLOADER_BUILD) list(APPEND srcs "src/regi2c_ctrl.c") endif() +set(priv_requires ${target}) +if(${target} STREQUAL "esp32") + # For RTC_EXT_CRYST_ADDIT_CURRENT to get chip revision in rtc_clk.c + list(APPEND priv_requires efuse) +endif() + idf_component_register(SRCS ${srcs} - PRIV_REQUIRES ${target} + PRIV_REQUIRES ${priv_requires} LDFRAGMENTS linker.lf) if(CONFIG_IDF_TARGET_ESP32) diff --git a/components/soc/src/esp32/include/hal/touch_sensor_ll.h b/components/soc/src/esp32/include/hal/touch_sensor_ll.h index e6bf271087..ea829226b0 100644 --- a/components/soc/src/esp32/include/hal/touch_sensor_ll.h +++ b/components/soc/src/esp32/include/hal/touch_sensor_ll.h @@ -237,6 +237,7 @@ static inline void touch_ll_get_tie_option(touch_pad_t touch_num, touch_tie_opt_ */ static inline void touch_ll_set_fsm_mode(touch_fsm_mode_t mode) { + SENS.sar_touch_ctrl2.touch_start_fsm_en = 1; SENS.sar_touch_ctrl2.touch_start_en = 0; SENS.sar_touch_ctrl2.touch_start_force = mode; } diff --git a/components/soc/src/esp32/rtc_clk.c b/components/soc/src/esp32/rtc_clk.c index 574cf6d0f7..4790b48cec 100644 --- a/components/soc/src/esp32/rtc_clk.c +++ b/components/soc/src/esp32/rtc_clk.c @@ -20,6 +20,7 @@ #include "esp32/rom/rtc.h" #include "esp32/rom/uart.h" #include "esp32/rom/gpio.h" +#include "esp_efuse.h" #include "soc/rtc.h" #include "soc/rtc_periph.h" #include "soc/sens_periph.h" @@ -57,7 +58,7 @@ #define APLL_CAL_DELAY_2 0x3f #define APLL_CAL_DELAY_3 0x1f -#define XTAL_32K_DAC_VAL 3 +#define XTAL_32K_DAC_VAL 1 #define XTAL_32K_DRES_VAL 3 #define XTAL_32K_DBIAS_VAL 0 @@ -126,20 +127,42 @@ static void rtc_clk_32k_enable_common(int dac, int dres, int dbias) REG_SET_FIELD(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_DBIAS_XTAL_32K, dbias); #ifdef CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_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 - NOTE: TOUCH8 and TOUCH9 register settings are reversed except for DAC, so we set RTC_IO_TOUCH_PAD9_REG here instead - */ - SET_PERI_REG_MASK(RTC_IO_TOUCH_PAD9_REG, RTC_IO_TOUCH_PAD9_TIE_OPT_M); - /* Set the current used to compensate TOUCH PAD8 */ - SET_PERI_REG_BITS(RTC_IO_TOUCH_PAD8_REG, RTC_IO_TOUCH_PAD8_DAC, 4, RTC_IO_TOUCH_PAD8_DAC_S); - /* Power up TOUCH8 - 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_EXT_CRYST_ADDIT_CURRENT + uint8_t chip_ver = esp_efuse_get_chip_ver(); + // version0 and version1 need provide additional current to external XTAL. + if(chip_ver == 0 || chip_ver == 1) { + /* 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 + NOTE: TOUCH8 and TOUCH9 register settings are reversed except for DAC, so we set RTC_IO_TOUCH_PAD9_REG here instead*/ + SET_PERI_REG_MASK(RTC_IO_TOUCH_PAD9_REG, RTC_IO_TOUCH_PAD9_TIE_OPT_M); + /* Set the current used to compensate TOUCH PAD8 */ + SET_PERI_REG_BITS(RTC_IO_TOUCH_PAD8_REG, RTC_IO_TOUCH_PAD8_DAC, 4, RTC_IO_TOUCH_PAD8_DAC_S); + /* Power up TOUCH8 + 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); + } +#elif defined CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT_V2 + uint8_t chip_ver = esp_efuse_get_chip_ver(); + if(chip_ver == 0 || chip_ver == 1) { + /* 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); + SET_PERI_REG_BITS(RTC_IO_TOUCH_CFG_REG, RTC_IO_TOUCH_DCUR, 3, RTC_IO_TOUCH_DCUR_S); + CLEAR_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_START_FSM_EN_M); + /* Tie PAD Touch8 to VDD + NOTE: TOUCH8 and TOUCH9 register settings are reversed except for DAC, so we set RTC_IO_TOUCH_PAD9_REG here instead + */ + SET_PERI_REG_MASK(RTC_IO_TOUCH_PAD9_REG, RTC_IO_TOUCH_PAD9_TIE_OPT_M); + /* Set the current used to compensate TOUCH PAD8 */ + SET_PERI_REG_BITS(RTC_IO_TOUCH_PAD8_REG, RTC_IO_TOUCH_PAD8_DAC, 1, RTC_IO_TOUCH_PAD8_DAC_S); + /* Power up TOUCH8 + 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); + CLEAR_PERI_REG_MASK(RTC_IO_TOUCH_PAD9_REG, RTC_IO_TOUCH_PAD9_START_M); + } +#endif /* Power up external xtal */ SET_PERI_REG_MASK(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_XPD_XTAL_32K_M); } @@ -154,9 +177,21 @@ void rtc_clk_32k_enable(bool enable) CLEAR_PERI_REG_MASK(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_X32N_MUX_SEL | RTC_IO_X32P_MUX_SEL); #ifdef CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT - /* Power down TOUCH */ - CLEAR_PERI_REG_MASK(RTC_IO_TOUCH_PAD9_REG, RTC_IO_TOUCH_PAD9_XPD_M); -#endif // CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT + uint8_t chip_ver = esp_efuse_get_chip_ver(); + if(chip_ver == 0 || chip_ver == 1) { + /* Power down TOUCH */ + CLEAR_PERI_REG_MASK(RTC_IO_TOUCH_PAD9_REG, RTC_IO_TOUCH_PAD9_XPD_M); + } +#elif defined CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT_V2 + uint8_t chip_ver = esp_efuse_get_chip_ver(); + if(chip_ver == 0 || chip_ver == 1) { + /* Power down TOUCH */ + CLEAR_PERI_REG_MASK(RTC_IO_TOUCH_CFG_REG, RTC_IO_TOUCH_XPD_BIAS_M); + SET_PERI_REG_BITS(RTC_IO_TOUCH_CFG_REG, RTC_IO_TOUCH_DCUR, 0, RTC_IO_TOUCH_DCUR_S); + CLEAR_PERI_REG_MASK(RTC_IO_TOUCH_PAD9_REG, RTC_IO_TOUCH_PAD9_XPD_M); + SET_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_START_FSM_EN_M); + } +#endif } } diff --git a/examples/peripherals/touch_pad_interrupt/main/esp32/tp_interrupt_main.c b/examples/peripherals/touch_pad_interrupt/main/esp32/tp_interrupt_main.c index 76552239d9..0c0187c498 100644 --- a/examples/peripherals/touch_pad_interrupt/main/esp32/tp_interrupt_main.c +++ b/examples/peripherals/touch_pad_interrupt/main/esp32/tp_interrupt_main.c @@ -151,7 +151,7 @@ void app_main(void) { // Initialize touch pad peripheral, it will start a timer to run a filter ESP_LOGI(TAG, "Initializing touch pad"); - touch_pad_init(); + ESP_ERROR_CHECK(touch_pad_init()); // If use interrupt trigger mode, should set touch sensor FSM mode at 'TOUCH_FSM_MODE_TIMER'. touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER); // Set reference voltage for charging/discharging diff --git a/examples/peripherals/touch_pad_read/main/esp32/tp_read_main.c b/examples/peripherals/touch_pad_read/main/esp32/tp_read_main.c index a3093b3982..4ab44003c8 100644 --- a/examples/peripherals/touch_pad_read/main/esp32/tp_read_main.c +++ b/examples/peripherals/touch_pad_read/main/esp32/tp_read_main.c @@ -57,7 +57,7 @@ void app_main(void) { // Initialize touch pad peripheral. // The default fsm mode is software trigger mode. - touch_pad_init(); + ESP_ERROR_CHECK(touch_pad_init()); // Set reference voltage for charging/discharging // In this case, the high reference valtage will be 2.7V - 1V = 1.7V // The low reference voltage will be 0.5 diff --git a/examples/system/deep_sleep/main/deep_sleep_example_main.c b/examples/system/deep_sleep/main/deep_sleep_example_main.c index 721a7e9c7e..cee9cbc5a2 100644 --- a/examples/system/deep_sleep/main/deep_sleep_example_main.c +++ b/examples/system/deep_sleep/main/deep_sleep_example_main.c @@ -159,7 +159,7 @@ void app_main(void) #if CONFIG_IDF_TARGET_ESP32 // Initialize touch pad peripheral. // The default fsm mode is software trigger mode. - touch_pad_init(); + ESP_ERROR_CHECK(touch_pad_init()); // If use touch pad wake up, should set touch sensor FSM mode at 'TOUCH_FSM_MODE_TIMER'. touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER); // Set reference voltage for charging/discharging