mirror of
https://github.com/espressif/esp-idf.git
synced 2025-07-30 10:47:19 +02:00
esp_hw_support/clk_cali: fix xtal32k error detect
This commit is contained in:
@ -117,10 +117,22 @@ uint32_t rtc_clk_cal_ratio(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
|||||||
return ratio;
|
return ratio;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool rtc_clk_cal_32k_valid(rtc_xtal_freq_t xtal_freq, uint32_t slowclk_cycles, uint64_t actual_xtal_cycles)
|
||||||
|
{
|
||||||
|
uint64_t expected_xtal_cycles = (xtal_freq * 1000000ULL * slowclk_cycles) >> 15; // xtal_freq(hz) * slowclk_cycles / 32768
|
||||||
|
uint64_t delta = expected_xtal_cycles / 2000; // 5/10000
|
||||||
|
return (actual_xtal_cycles >= (expected_xtal_cycles - delta)) && (actual_xtal_cycles <= (expected_xtal_cycles + delta));
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t rtc_clk_cal(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();
|
rtc_xtal_freq_t xtal_freq = rtc_clk_xtal_freq_get();
|
||||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk, slowclk_cycles);
|
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk, slowclk_cycles);
|
||||||
|
|
||||||
|
if ((cal_clk == RTC_CAL_32K_XTAL) && !rtc_clk_cal_32k_valid(xtal_freq, slowclk_cycles, xtal_cycles)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t divider = ((uint64_t)xtal_freq) * 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;
|
uint64_t period_64 = ((xtal_cycles << RTC_CLK_CAL_FRACT) + divider / 2 - 1) / divider;
|
||||||
uint32_t period = (uint32_t)(period_64 & UINT32_MAX);
|
uint32_t period = (uint32_t)(period_64 & UINT32_MAX);
|
||||||
|
@ -129,10 +129,22 @@ uint32_t rtc_clk_cal_ratio(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
|||||||
return ratio;
|
return ratio;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool rtc_clk_cal_32k_valid(rtc_xtal_freq_t xtal_freq, uint32_t slowclk_cycles, uint64_t actual_xtal_cycles)
|
||||||
|
{
|
||||||
|
uint64_t expected_xtal_cycles = (xtal_freq * 1000000ULL * slowclk_cycles) >> 15; // xtal_freq(hz) * slowclk_cycles / 32768
|
||||||
|
uint64_t delta = expected_xtal_cycles / 2000; // 5/10000
|
||||||
|
return (actual_xtal_cycles >= (expected_xtal_cycles - delta)) && (actual_xtal_cycles <= (expected_xtal_cycles + delta));
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t rtc_clk_cal(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();
|
rtc_xtal_freq_t xtal_freq = rtc_clk_xtal_freq_get();
|
||||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk, slowclk_cycles);
|
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk, slowclk_cycles);
|
||||||
|
|
||||||
|
if ((cal_clk == RTC_CAL_32K_XTAL) && !rtc_clk_cal_32k_valid(xtal_freq, slowclk_cycles, xtal_cycles)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t divider = ((uint64_t)xtal_freq) * 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;
|
uint64_t period_64 = ((xtal_cycles << RTC_CLK_CAL_FRACT) + divider / 2 - 1) / divider;
|
||||||
uint32_t period = (uint32_t)(period_64 & UINT32_MAX);
|
uint32_t period = (uint32_t)(period_64 & UINT32_MAX);
|
||||||
|
@ -191,11 +191,22 @@ uint32_t rtc_clk_cal_ratio(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
|||||||
return ratio;
|
return ratio;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool rtc_clk_cal_32k_valid(rtc_xtal_freq_t xtal_freq, uint32_t slowclk_cycles, uint64_t actual_xtal_cycles)
|
||||||
|
{
|
||||||
|
uint64_t expected_xtal_cycles = (xtal_freq * 1000000ULL * slowclk_cycles) >> 15; // xtal_freq(hz) * slowclk_cycles / 32768
|
||||||
|
uint64_t delta = expected_xtal_cycles / 2000; // 5/10000
|
||||||
|
return (actual_xtal_cycles >= (expected_xtal_cycles - delta)) && (actual_xtal_cycles <= (expected_xtal_cycles + delta));
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t rtc_clk_cal(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)
|
||||||
{
|
{
|
||||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk, slowclk_cycles, RTC_TIME_CAL_ONEOFF_MODE);
|
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk, slowclk_cycles, RTC_TIME_CAL_ONEOFF_MODE);
|
||||||
uint32_t period = rtc_clk_xtal_to_slowclk(xtal_cycles, slowclk_cycles);
|
|
||||||
return period;
|
if ((cal_clk == RTC_CAL_32K_XTAL) && !rtc_clk_cal_32k_valid(rtc_clk_xtal_freq_get(), slowclk_cycles, xtal_cycles)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rtc_clk_xtal_to_slowclk(xtal_cycles, slowclk_cycles);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t rtc_clk_cal_cycling(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
uint32_t rtc_clk_cal_cycling(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||||
|
@ -128,10 +128,22 @@ uint32_t rtc_clk_cal_ratio(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
|||||||
return ratio;
|
return ratio;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool rtc_clk_cal_32k_valid(rtc_xtal_freq_t xtal_freq, uint32_t slowclk_cycles, uint64_t actual_xtal_cycles)
|
||||||
|
{
|
||||||
|
uint64_t expected_xtal_cycles = (xtal_freq * 1000000ULL * slowclk_cycles) >> 15; // xtal_freq(hz) * slowclk_cycles / 32768
|
||||||
|
uint64_t delta = expected_xtal_cycles / 2000; // 5/10000
|
||||||
|
return (actual_xtal_cycles >= (expected_xtal_cycles - delta)) && (actual_xtal_cycles <= (expected_xtal_cycles + delta));
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t rtc_clk_cal(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();
|
rtc_xtal_freq_t xtal_freq = rtc_clk_xtal_freq_get();
|
||||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk, slowclk_cycles);
|
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk, slowclk_cycles);
|
||||||
|
|
||||||
|
if ((cal_clk == RTC_CAL_32K_XTAL) && !rtc_clk_cal_32k_valid(xtal_freq, slowclk_cycles, xtal_cycles)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t divider = ((uint64_t)xtal_freq) * 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;
|
uint64_t period_64 = ((xtal_cycles << RTC_CLK_CAL_FRACT) + divider / 2 - 1) / divider;
|
||||||
uint32_t period = (uint32_t)(period_64 & UINT32_MAX);
|
uint32_t period = (uint32_t)(period_64 & UINT32_MAX);
|
||||||
|
@ -403,6 +403,11 @@ uint32_t rtc_clk_apb_freq_get(void);
|
|||||||
* 32k XTAL is being calibrated, but the oscillator has not started up (due to
|
* 32k XTAL is being calibrated, but the oscillator has not started up (due to
|
||||||
* incorrect loading capacitance, board design issue, or lack of 32 XTAL on board).
|
* incorrect loading capacitance, board design issue, or lack of 32 XTAL on board).
|
||||||
*
|
*
|
||||||
|
* @note When 32k CLK is being calibrated, this function will check the accuracy
|
||||||
|
* of the clock. Since the xtal 32k or ext osc 32k is generally very stable, if
|
||||||
|
* the check fails, then consider this an invalid 32k clock and return 0. This
|
||||||
|
* check can filter some jamming signal.
|
||||||
|
*
|
||||||
* @param cal_clk clock to be measured
|
* @param cal_clk clock to be measured
|
||||||
* @param slow_clk_cycles number of slow clock cycles to average
|
* @param slow_clk_cycles number of slow clock cycles to average
|
||||||
* @return average slow clock period in microseconds, Q13.19 fixed point format,
|
* @return average slow clock period in microseconds, Q13.19 fixed point format,
|
||||||
|
@ -509,6 +509,11 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles);
|
|||||||
* 32k XTAL is being calibrated, but the oscillator has not started up (due to
|
* 32k XTAL is being calibrated, but the oscillator has not started up (due to
|
||||||
* incorrect loading capacitance, board design issue, or lack of 32 XTAL on board).
|
* incorrect loading capacitance, board design issue, or lack of 32 XTAL on board).
|
||||||
*
|
*
|
||||||
|
* @note When 32k CLK is being calibrated, this function will check the accuracy
|
||||||
|
* of the clock. Since the xtal 32k or ext osc 32k is generally very stable, if
|
||||||
|
* the check fails, then consider this an invalid 32k clock and return 0. This
|
||||||
|
* check can filter some jamming signal.
|
||||||
|
*
|
||||||
* @param cal_clk clock to be measured
|
* @param cal_clk clock to be measured
|
||||||
* @param slow_clk_cycles number of slow clock cycles to average
|
* @param slow_clk_cycles number of slow clock cycles to average
|
||||||
* @return average slow clock period in microseconds, Q13.19 fixed point format,
|
* @return average slow clock period in microseconds, Q13.19 fixed point format,
|
||||||
|
@ -539,6 +539,11 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles, ui
|
|||||||
* 32k XTAL is being calibrated, but the oscillator has not started up (due to
|
* 32k XTAL is being calibrated, but the oscillator has not started up (due to
|
||||||
* incorrect loading capacitance, board design issue, or lack of 32 XTAL on board).
|
* incorrect loading capacitance, board design issue, or lack of 32 XTAL on board).
|
||||||
*
|
*
|
||||||
|
* @note When 32k CLK is being calibrated, this function will check the accuracy
|
||||||
|
* of the clock. Since the xtal 32k or ext osc 32k is generally very stable, if
|
||||||
|
* the check fails, then consider this an invalid 32k clock and return 0. This
|
||||||
|
* check can filter some jamming signal.
|
||||||
|
*
|
||||||
* @param cal_clk clock to be measured
|
* @param cal_clk clock to be measured
|
||||||
* @param slow_clk_cycles number of slow clock cycles to average
|
* @param slow_clk_cycles number of slow clock cycles to average
|
||||||
* @return average slow clock period in microseconds, Q13.19 fixed point format,
|
* @return average slow clock period in microseconds, Q13.19 fixed point format,
|
||||||
|
@ -503,6 +503,11 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles);
|
|||||||
* 32k XTAL is being calibrated, but the oscillator has not started up (due to
|
* 32k XTAL is being calibrated, but the oscillator has not started up (due to
|
||||||
* incorrect loading capacitance, board design issue, or lack of 32 XTAL on board).
|
* incorrect loading capacitance, board design issue, or lack of 32 XTAL on board).
|
||||||
*
|
*
|
||||||
|
* @note When 32k CLK is being calibrated, this function will check the accuracy
|
||||||
|
* of the clock. Since the xtal 32k or ext osc 32k is generally very stable, if
|
||||||
|
* the check fails, then consider this an invalid 32k clock and return 0. This
|
||||||
|
* check can filter some jamming signal.
|
||||||
|
*
|
||||||
* @param cal_clk clock to be measured
|
* @param cal_clk clock to be measured
|
||||||
* @param slow_clk_cycles number of slow clock cycles to average
|
* @param slow_clk_cycles number of slow clock cycles to average
|
||||||
* @return average slow clock period in microseconds, Q13.19 fixed point format,
|
* @return average slow clock period in microseconds, Q13.19 fixed point format,
|
||||||
|
Reference in New Issue
Block a user