mirror of
https://github.com/espressif/esp-idf.git
synced 2026-05-06 08:37:29 +02:00
Add support for 32k XTAL as RTC_SLOW_CLK source
- RTC_CNTL_SLOWCLK_FREQ define is removed; rtc_clk_slow_freq_get_hz function can be used instead to get an approximate RTC_SLOW_CLK frequency - Clock calibration is performed at startup. The value is saved and used for timekeeping and when entering deep sleep. - When using the 32k XTAL, startup code will wait for the oscillator to start up. This can be possibly optimized by starting a separate task to wait for oscillator startup, and performing clock switch in that task. - Fix a bug that 32k XTAL would be disabled in rtc_clk_init. - Fix a rounding error in rtc_clk_cal, which caused systematic frequency error. - Fix an overflow bug which caused rtc_clk_cal to timeout early if the slow_clk_cycles argument would exceed certain value - Improve 32k XTAL oscillator startup time by introducing bootstrapping code, which uses internal pullup/pulldown resistors on 32K_N/32K_P pins to set better initial conditions for the oscillator.
This commit is contained in:
@@ -31,7 +31,14 @@
|
||||
* once, and TIMG_RTC_CALI_RDY bit is set when counting is done. One-off mode is
|
||||
* enabled using TIMG_RTC_CALI_START bit.
|
||||
*/
|
||||
uint32_t rtc_clk_cal_ratio(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
|
||||
/**
|
||||
* @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
|
||||
* @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)
|
||||
{
|
||||
/* Enable requested clock (150k clock is always on) */
|
||||
if (cal_clk == RTC_CAL_32K_XTAL) {
|
||||
@@ -56,7 +63,7 @@ uint32_t rtc_clk_cal_ratio(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
} else {
|
||||
expected_freq = 150000; /* 150k internal oscillator */
|
||||
}
|
||||
uint32_t us_time_estimate = slowclk_cycles * MHZ / expected_freq;
|
||||
uint32_t us_time_estimate = (uint32_t) (((uint64_t) slowclk_cycles) * MHZ / expected_freq);
|
||||
/* 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);
|
||||
@@ -83,8 +90,13 @@ uint32_t rtc_clk_cal_ratio(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t xtal_cycles = REG_GET_FIELD(TIMG_RTCCALICFG1_REG(0), TIMG_RTC_CALI_VALUE);
|
||||
uint64_t ratio_64 = (xtal_cycles << RTC_CLK_CAL_FRACT) / slowclk_cycles;
|
||||
return REG_GET_FIELD(TIMG_RTCCALICFG1_REG(0), TIMG_RTC_CALI_VALUE);
|
||||
}
|
||||
|
||||
uint32_t rtc_clk_cal_ratio(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
{
|
||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk, slowclk_cycles);
|
||||
uint64_t ratio_64 = ((xtal_cycles << RTC_CLK_CAL_FRACT)) / slowclk_cycles;
|
||||
uint32_t ratio = (uint32_t)(ratio_64 & UINT32_MAX);
|
||||
return ratio;
|
||||
}
|
||||
@@ -92,8 +104,10 @@ uint32_t rtc_clk_cal_ratio(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
{
|
||||
rtc_xtal_freq_t xtal_freq = rtc_clk_xtal_freq_get();
|
||||
uint32_t ratio = rtc_clk_cal_ratio(cal_clk, slowclk_cycles);
|
||||
uint32_t period = ratio / xtal_freq;
|
||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk, slowclk_cycles);
|
||||
uint64_t divider = ((uint64_t)xtal_freq) * slowclk_cycles;
|
||||
uint64_t period_64 = ((xtal_cycles << RTC_CLK_CAL_FRACT) + divider / 2 - 1) / divider;
|
||||
uint32_t period = (uint32_t)(period_64 & UINT32_MAX);
|
||||
return period;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user