diff --git a/components/driver/esp32/touch_sensor.c b/components/driver/esp32/touch_sensor.c index 9f61299944..5e8215e73c 100644 --- a/components/driver/esp32/touch_sensor.c +++ b/components/driver/esp32/touch_sensor.c @@ -287,6 +287,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 46ed3d7130..f9855bc9dc 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 4c815dddab..10c72be32d 100644 --- a/components/esp32/Kconfig +++ b/components/esp32/Kconfig @@ -570,18 +570,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/esp_hw_support/CMakeLists.txt b/components/esp_hw_support/CMakeLists.txt index ab097c4f69..987abe80ee 100644 --- a/components/esp_hw_support/CMakeLists.txt +++ b/components/esp_hw_support/CMakeLists.txt @@ -1,7 +1,14 @@ +idf_build_get_property(target IDF_TARGET) + +set(requires soc) +if(${target} STREQUAL "esp32") + list(APPEND requires efuse) +endif() + idf_component_register(SRCS "compare_set.c" "cpu_util.c" INCLUDE_DIRS include - REQUIRES soc + REQUIRES ${requires} LDFRAGMENTS linker.lf) idf_build_get_property(target IDF_TARGET) diff --git a/components/esp_hw_support/port/esp32/rtc_clk.c b/components/esp_hw_support/port/esp32/rtc_clk.c index bd65f5ae5c..2dac3a9c93 100644 --- a/components/esp_hw_support/port/esp32/rtc_clk.c +++ b/components/esp_hw_support/port/esp32/rtc_clk.c @@ -19,6 +19,7 @@ #include "esp32/rom/ets_sys.h" // for ets_update_cpu_frequency #include "esp32/rom/rtc.h" #include "esp_rom_gpio.h" +#include "esp_efuse.h" #include "soc/rtc.h" #include "soc/rtc_periph.h" #include "soc/sens_periph.h" @@ -58,7 +59,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 @@ -127,20 +128,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); } @@ -155,9 +178,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/components/esp_system/sleep_modes.c b/components/esp_system/sleep_modes.c index 9882bdcbbc..e23149d511 100644 --- a/components/esp_system/sleep_modes.c +++ b/components/esp_system/sleep_modes.c @@ -542,9 +542,10 @@ esp_err_t esp_sleep_disable_wakeup_source(esp_sleep_source_t source) esp_err_t esp_sleep_enable_ulp_wakeup(void) { #if CONFIG_IDF_TARGET_ESP32 -#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 // CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT +#endif #ifdef CONFIG_ESP32_ULP_COPROC_ENABLED if(s_config.wakeup_triggers & RTC_EXT0_TRIG_EN) { ESP_LOGE(TAG, "Conflicting wake-up trigger: ext0"); @@ -596,7 +597,8 @@ static void touch_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/hal/esp32/include/hal/touch_sensor_ll.h b/components/hal/esp32/include/hal/touch_sensor_ll.h index b65120b684..0b876039b0 100644 --- a/components/hal/esp32/include/hal/touch_sensor_ll.h +++ b/components/hal/esp32/include/hal/touch_sensor_ll.h @@ -233,6 +233,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/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 a56f3613b4..f406b6e7de 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