Просмотр исходного кода

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

Closes: IDF-1479
KonstantinKondrashov 5 лет назад
Родитель
Сommit
a259746016
2 измененных файлов с 30 добавлено и 1 удалено
  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.
               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
         int "Bootstrap cycles for external 32kHz crystal"
         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
 
+#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)
 
+/* 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
  * 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;
     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 {
         if (rtc_slow_freq == RTC_SLOW_FREQ_32K_XTAL) {
             /* 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.
             if (SLOW_CLK_CAL_CYCLES > 0) {
                 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");
                     rtc_slow_freq = RTC_SLOW_FREQ_RTC;
                 }