Răsfoiți Sursa

Merge branch 'bugfix/fix_x32k_startup_slow_bug' into 'master'

bugfix: Fix xtal 32k not oscillate or oscillate too slowly issue for esp32

See merge request espressif/esp-idf!10519
Michael (XIAO Xufeng) 5 ani în urmă
părinte
comite
af992c26bc

+ 4 - 0
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();
     }

+ 1 - 0
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);
 

+ 27 - 10
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 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.
+            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.
+
+            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"

+ 8 - 1
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)

+ 53 - 18
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
     }
 }
 

+ 5 - 3
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)) {

+ 1 - 0
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;
 }

+ 1 - 1
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

+ 1 - 1
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

+ 1 - 1
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