mirror of
				https://github.com/espressif/esp-idf.git
				synced 2025-10-31 13:09:38 +00: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
	 jingli
					jingli