From 6e9d60ef70703795b03f0e5f4fc82291cb75362c Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 21 Apr 2017 10:33:58 +0800 Subject: [PATCH] rtc_clk_init: handle case when XTAL frequency has already been set MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On first reset, ROM code writes the estimated XTAL frequency into RTC_APB_FREQ_REG (aka STORE5). If the application doesn’t specify exact XTAL frequency (which is always the case for now), rtc_clk_init will guess what kind of XTAL is used (26M or 40M), based on the estimated frequency. Later, detected frequency is written into RTC_XTAL_FREQ_REG (aka STORE4). When the application switches clock source to PLL, APB frequency changes and RTC_APB_FREQ_REG is updated. If the application encounters an RTC WDT reset, RTC_APB_FREQ_REG will not be updated prior to reset. Once the application starts up again, it will attempt to auto-detect XTAL frequency based on RTC_APB_FREQ_REG, which now has value of 80000000. This will fail, and rtc_clk_xtal_freq_estimate will fall back to the default value of 26 MHz. Due to an incorrect XTAL frequency, PLL initialization will also take incorrect path, and PLL will run at a different frequency. Depending on the application this may cause just garbage output on UART or a crash (if WiFi is used). --- components/soc/esp32/rtc_clk.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/components/soc/esp32/rtc_clk.c b/components/soc/esp32/rtc_clk.c index 79b56f993..bc7eacc9d 100644 --- a/components/soc/esp32/rtc_clk.c +++ b/components/soc/esp32/rtc_clk.c @@ -488,10 +488,16 @@ void rtc_clk_init(rtc_clk_config_t cfg) /* Estimate XTAL frequency if requested */ rtc_xtal_freq_t xtal_freq = cfg.xtal_freq; if (xtal_freq == RTC_XTAL_FREQ_AUTO) { - xtal_freq = rtc_clk_xtal_freq_estimate(); - if (xtal_freq == RTC_XTAL_FREQ_AUTO) { - SOC_LOGW(TAG, "Can't estimate XTAL frequency, assuming 26MHz"); - xtal_freq = RTC_XTAL_FREQ_26M; + if (clk_val_is_valid(READ_PERI_REG(RTC_XTAL_FREQ_REG))) { + /* XTAL frequency has already been set, use existing value */ + xtal_freq = rtc_clk_xtal_freq_get(); + } else { + /* Not set yet, estimate XTAL frequency based on RTC_FAST_CLK */ + xtal_freq = rtc_clk_xtal_freq_estimate(); + if (xtal_freq == RTC_XTAL_FREQ_AUTO) { + SOC_LOGW(TAG, "Can't estimate XTAL frequency, assuming 26MHz"); + xtal_freq = RTC_XTAL_FREQ_26M; + } } } rtc_clk_xtal_freq_update(xtal_freq);