Browse Source

esp32: Add a Kconfig option- Number of attempts to repeat 32k XTAL calibration

Closes: IDF-1479
KonstantinKondrashov 5 years ago
parent
commit
a259746016
2 changed files with 30 additions and 1 deletions
  1. 10 0
      components/esp32/Kconfig
  2. 20 1
      components/esp32/clk.c

+ 10 - 0
components/esp32/Kconfig

@@ -524,6 +524,16 @@ menu "ESP32-specific"
               In case more value will help improve the definition of the launch of the crystal.
               In case more value will help improve the definition of the launch of the crystal.
               If the crystal could not start, it will be switched to internal RC.
               If the crystal could not start, it will be switched to internal RC.
 
 
+    config ESP32_RTC_XTAL_CAL_RETRY
+        int "Number of attempts to repeat 32k XTAL calibration"
+        default 1
+        depends on ESP32_RTC_CLK_SRC_EXT_CRYS
+        help
+            Number of attempts to repeat 32k XTAL calibration
+            before giving up and switching to the internal RC.
+            Increase this option if the 32k crystal oscillator
+            does not start and switches to internal RC.
+
     config ESP32_RTC_XTAL_BOOTSTRAP_CYCLES
     config ESP32_RTC_XTAL_BOOTSTRAP_CYCLES
         int "Bootstrap cycles for external 32kHz crystal"
         int "Bootstrap cycles for external 32kHz crystal"
         depends on ESP32_RTC_CLK_SRC_EXT_CRYS
         depends on ESP32_RTC_CLK_SRC_EXT_CRYS

+ 20 - 1
components/esp32/clk.c

@@ -41,8 +41,19 @@
  */
  */
 #define SLOW_CLK_CAL_CYCLES     CONFIG_ESP32_RTC_CLK_CAL_CYCLES
 #define SLOW_CLK_CAL_CYCLES     CONFIG_ESP32_RTC_CLK_CAL_CYCLES
 
 
+#ifdef CONFIG_ESP32_RTC_XTAL_CAL_RETRY
+#define RTC_XTAL_CAL_RETRY CONFIG_ESP32_RTC_XTAL_CAL_RETRY
+#else
+#define RTC_XTAL_CAL_RETRY 1
+#endif
+
 #define MHZ (1000000)
 #define MHZ (1000000)
 
 
+/* Lower threshold for a reasonably-looking calibration value for a 32k XTAL.
+ * The ideal value (assuming 32768 Hz frequency) is 1000000/32768*(2**19) = 16*10^6.
+ */
+#define MIN_32K_XTAL_CAL_VAL  15000000L
+
 /* Indicates that this 32k oscillator gets input from external oscillator, rather
 /* Indicates that this 32k oscillator gets input from external oscillator, rather
  * than a crystal.
  * than a crystal.
  */
  */
@@ -172,6 +183,11 @@ static void select_rtc_slow_clk(slow_clk_sel_t slow_clk)
 {
 {
     rtc_slow_freq_t rtc_slow_freq = slow_clk & RTC_CNTL_ANA_CLK_RTC_SEL_V;
     rtc_slow_freq_t rtc_slow_freq = slow_clk & RTC_CNTL_ANA_CLK_RTC_SEL_V;
     uint32_t cal_val = 0;
     uint32_t cal_val = 0;
+    /* number of times to repeat 32k XTAL calibration
+     * before giving up and switching to the internal RC
+     */
+    int retry_32k_xtal = RTC_XTAL_CAL_RETRY;
+
     do {
     do {
         if (rtc_slow_freq == RTC_SLOW_FREQ_32K_XTAL) {
         if (rtc_slow_freq == RTC_SLOW_FREQ_32K_XTAL) {
             /* 32k XTAL oscillator needs to be enabled and running before it can
             /* 32k XTAL oscillator needs to be enabled and running before it can
@@ -190,7 +206,10 @@ static void select_rtc_slow_clk(slow_clk_sel_t slow_clk)
             // When SLOW_CLK_CAL_CYCLES is set to 0, clock calibration will not be performed at startup.
             // When SLOW_CLK_CAL_CYCLES is set to 0, clock calibration will not be performed at startup.
             if (SLOW_CLK_CAL_CYCLES > 0) {
             if (SLOW_CLK_CAL_CYCLES > 0) {
                 cal_val = rtc_clk_cal(RTC_CAL_32K_XTAL, SLOW_CLK_CAL_CYCLES);
                 cal_val = rtc_clk_cal(RTC_CAL_32K_XTAL, SLOW_CLK_CAL_CYCLES);
-                if (cal_val == 0 || cal_val < 15000000L) {
+                if (cal_val == 0 || cal_val < MIN_32K_XTAL_CAL_VAL) {
+                    if (retry_32k_xtal-- > 0) {
+                        continue;
+                    }
                     ESP_EARLY_LOGW(TAG, "32 kHz XTAL not found, switching to internal 150 kHz oscillator");
                     ESP_EARLY_LOGW(TAG, "32 kHz XTAL not found, switching to internal 150 kHz oscillator");
                     rtc_slow_freq = RTC_SLOW_FREQ_RTC;
                     rtc_slow_freq = RTC_SLOW_FREQ_RTC;
                 }
                 }