diff --git a/components/esp32/Kconfig b/components/esp32/Kconfig index 1b4e3784b0..7824823a44 100644 --- a/components/esp32/Kconfig +++ b/components/esp32/Kconfig @@ -694,7 +694,8 @@ config ESP32_RTC_CLK_CAL_CYCLES int "Number of cycles for RTC_SLOW_CLK calibration" default 3000 if ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL default 1024 if ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC - range 0 125000 + range 0 27000 if ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL + range 0 32766 if ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC help When the startup code initializes RTC_SLOW_CLK, it can perform calibration by comparing the RTC_SLOW_CLK frequency with main XTAL diff --git a/components/esp32/clk.c b/components/esp32/clk.c index 41b24c6ed9..cfd5e93586 100644 --- a/components/esp32/clk.c +++ b/components/esp32/clk.c @@ -128,7 +128,9 @@ static void select_rtc_slow_clk(rtc_slow_freq_t slow_clk) { uint32_t cal_val = 0; uint32_t wait = 0; - const uint32_t warning_timeout = 3 /* sec */ * 32768 /* Hz */ / (2 * SLOW_CLK_CAL_CYCLES); + uint32_t freq_hz = ((slow_clk == RTC_SLOW_FREQ_32K_XTAL) ? 32768 : 150000); + uint32_t warning_timeout = 3 /* sec */ * freq_hz /* Hz */ / (SLOW_CLK_CAL_CYCLES + 1); + warning_timeout = ((warning_timeout == 0) ? 3 /* sec */ : warning_timeout); bool changing_clock_to_150k = false; do { if (slow_clk == RTC_SLOW_FREQ_32K_XTAL) { @@ -141,11 +143,14 @@ static void select_rtc_slow_clk(rtc_slow_freq_t slow_clk) */ ESP_EARLY_LOGD(TAG, "waiting for 32k oscillator to start up"); rtc_clk_32k_enable(true); - cal_val = rtc_clk_cal(RTC_CAL_32K_XTAL, SLOW_CLK_CAL_CYCLES); - if(cal_val == 0 || cal_val < 15000000L){ - ESP_EARLY_LOGE(TAG, "RTC: Not found External 32 kHz XTAL. Switching to Internal 150 kHz RC chain"); - slow_clk = RTC_SLOW_FREQ_RTC; - changing_clock_to_150k = true; + // 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) { + ESP_EARLY_LOGE(TAG, "RTC: Not found External 32 kHz XTAL. Switching to Internal 150 kHz RC chain"); + slow_clk = RTC_SLOW_FREQ_RTC; + changing_clock_to_150k = true; + } } } rtc_clk_slow_freq_set(slow_clk); diff --git a/components/soc/esp32/rtc_time.c b/components/soc/esp32/rtc_time.c index 94002f79db..6dfb9e1a78 100644 --- a/components/soc/esp32/rtc_time.c +++ b/components/soc/esp32/rtc_time.c @@ -17,6 +17,7 @@ #include "soc/rtc.h" #include "soc/rtc_cntl_reg.h" #include "soc/timer_group_reg.h" +#include "assert.h" #define MHZ (1000000) @@ -35,11 +36,12 @@ /** * @brief Clock calibration function used by rtc_clk_cal and rtc_clk_cal_ratio * @param cal_clk which clock to calibrate - * @param slowclk_cycles number of slow clock cycles to count + * @param slowclk_cycles number of slow clock cycles to count. Max value is 32766. * @return number of XTAL clock cycles within the given number of slow clock cycles */ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles) { + assert(slowclk_cycles < 32767); /* Enable requested clock (150k clock is always on) */ int dig_32k_xtal_state = REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN); if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_state) { @@ -56,16 +58,21 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc /* Figure out how long to wait for calibration to finish */ uint32_t expected_freq; rtc_slow_freq_t slow_freq = REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL); + uint32_t us_timer_max = 0xFFFFFFFF; if (cal_clk == RTC_CAL_32K_XTAL || (cal_clk == RTC_CAL_RTC_MUX && slow_freq == RTC_SLOW_FREQ_32K_XTAL)) { expected_freq = 32768; /* standard 32k XTAL */ + us_timer_max = (uint32_t) (TIMG_RTC_CALI_VALUE / rtc_clk_xtal_freq_get()); } else if (cal_clk == RTC_CAL_8MD256 || (cal_clk == RTC_CAL_RTC_MUX && slow_freq == RTC_SLOW_FREQ_8MD256)) { expected_freq = RTC_FAST_CLK_FREQ_APPROX / 256; } else { expected_freq = 150000; /* 150k internal oscillator */ + us_timer_max = (uint32_t) (TIMG_RTC_CALI_VALUE / rtc_clk_xtal_freq_get()); } uint32_t us_time_estimate = (uint32_t) (((uint64_t) slowclk_cycles) * MHZ / expected_freq); + // The required amount of slowclk_cycles can produce in a counter TIMG a overflow error. Decrease the slowclk_cycles for fix it. + assert(us_time_estimate < us_timer_max); /* Start calibration */ CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START); SET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START);