/* * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 *//* ... */#include"esp_private/esp_clk_tree_common.h"#include"hal/clk_tree_hal.h"#include"hal/clk_tree_ll.h"#include"soc/rtc.h"#include"esp_private/esp_clk.h"#include"soc/clk_tree_defs.h"#include"soc/soc_caps.h"#include"sdkconfig.h"#include"esp_hw_log.h"9 includesstaticconstchar*TAG="esp_clk_tree_common";typedefstructesp_clk_tree_calibrated_freq_tesp_clk_tree_calibrated_freq_t;structesp_clk_tree_calibrated_freq_t{#ifSOC_CLK_RC_FAST_D256_SUPPORTEDuint32_trc_fast_d256;#elifSOC_CLK_RC_FAST_SUPPORT_CALIBRATION// && !SOC_CLK_RC_FAST_D256_SUPPORTEDuint32_trc_fast;#endif#ifSOC_CLK_XTAL32K_SUPPORTEDuint32_txtal32k;#endif#ifSOC_CLK_OSC_SLOW_SUPPORTEDuint32_tosc_slow;#endif}{ ... };// TODO: Better to implement a spinlock for the static variablesstaticesp_clk_tree_calibrated_freq_ts_calibrated_freq={};/* Number of cycles for RTC_SLOW_CLK calibration */#defineRTC_SLOW_CLK_CAL_CYCLESCONFIG_RTC_CLK_CAL_CYCLES/* Number of cycles for ~32kHz clocks calibration (rc_fast_d256, xtal32k, osc_slow, rc32k) */#defineDEFAULT_32K_CLK_CAL_CYCLES100/* Number of cycles for RC_FAST calibration */#defineDEFAULT_RC_FAST_CAL_CYCLES10000// RC_FAST has a higher frequency, therefore, requires more cycles to get an accurate value// Usually we calibrate on the divider of the RC_FAST clock, the cal_cycles is divided by// the divider factor internally in rtc_clk_cal, so the time to spend on calibrating RC_FAST// is always (10000 / f_rc_fast)/** * Performs a frequency calibration to RTC slow clock * * slowclk_cycles Number of slow clock cycles to count. * If slowclk_cycles = 0, calibration will not be performed. Clock's theoretical value will be used. * * Returns the number of XTAL clock cycles within the given number of slow clock cycles * It returns 0 if calibration failed, i.e. clock is not running *//* ... */staticuint32_tclk_tree_rtc_slow_calibration(uint32_tslowclk_cycles){uint32_tcal_val=0;if(slowclk_cycles>0){cal_val=rtc_clk_cal(RTC_CAL_RTC_MUX,slowclk_cycles);}{...}else{constuint64_tcal_dividend=(1ULL<<RTC_CLK_CAL_FRACT)*1000000ULL;uint32_tsource_approx_freq=clk_hal_lp_slow_get_freq_hz();assert(source_approx_freq);cal_val=(uint32_t)(cal_dividend/source_approx_freq);}{...}if(cal_val){ESP_EARLY_LOGD(TAG,"RTC_SLOW_CLK calibration value: %"PRIu32,cal_val);// Update the calibration value of RTC_SLOW_CLKesp_clk_slowclk_cal_set(cal_val);}{...}returncal_val;}{ ... }#ifSOC_CLK_RC_FAST_D256_SUPPORTEDuint32_tesp_clk_tree_rc_fast_d256_get_freq_hz(esp_clk_tree_src_freq_precision_tprecision){switch(precision){caseESP_CLK_TREE_SRC_FREQ_PRECISION_APPROX:returnSOC_CLK_RC_FAST_D256_FREQ_APPROX;...caseESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED:if(!s_calibrated_freq.rc_fast_d256){s_calibrated_freq.rc_fast_d256=rtc_clk_freq_cal(rtc_clk_cal(RTC_CAL_8MD256,DEFAULT_32K_CLK_CAL_CYCLES));}{...}returns_calibrated_freq.rc_fast_d256;...caseESP_CLK_TREE_SRC_FREQ_PRECISION_EXACT:s_calibrated_freq.rc_fast_d256=rtc_clk_freq_cal(rtc_clk_cal(RTC_CAL_8MD256,DEFAULT_32K_CLK_CAL_CYCLES));returns_calibrated_freq.rc_fast_d256;...default:return0;...}{...}}{ ... }/* ... */#endif#ifSOC_CLK_XTAL32K_SUPPORTEDuint32_tesp_clk_tree_xtal32k_get_freq_hz(esp_clk_tree_src_freq_precision_tprecision){switch(precision){caseESP_CLK_TREE_SRC_FREQ_PRECISION_APPROX:returnSOC_CLK_XTAL32K_FREQ_APPROX;...caseESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED:if(!s_calibrated_freq.xtal32k){s_calibrated_freq.xtal32k=rtc_clk_freq_cal(rtc_clk_cal(RTC_CAL_32K_XTAL,DEFAULT_32K_CLK_CAL_CYCLES));}{...}returns_calibrated_freq.xtal32k;...caseESP_CLK_TREE_SRC_FREQ_PRECISION_EXACT:s_calibrated_freq.xtal32k=rtc_clk_freq_cal(rtc_clk_cal(RTC_CAL_32K_XTAL,DEFAULT_32K_CLK_CAL_CYCLES));returns_calibrated_freq.xtal32k;...default:return0;...}{...}}{ ... }/* ... */#endif#ifSOC_CLK_OSC_SLOW_SUPPORTEDuint32_tesp_clk_tree_osc_slow_get_freq_hz(esp_clk_tree_src_freq_precision_tprecision){switch(precision){caseESP_CLK_TREE_SRC_FREQ_PRECISION_APPROX:returnSOC_CLK_OSC_SLOW_FREQ_APPROX;...caseESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED:if(!s_calibrated_freq.osc_slow){s_calibrated_freq.osc_slow=rtc_clk_freq_cal(rtc_clk_cal(RTC_CAL_32K_OSC_SLOW,DEFAULT_32K_CLK_CAL_CYCLES));}{...}returns_calibrated_freq.osc_slow;...caseESP_CLK_TREE_SRC_FREQ_PRECISION_EXACT:s_calibrated_freq.osc_slow=rtc_clk_freq_cal(rtc_clk_cal(RTC_CAL_32K_OSC_SLOW,DEFAULT_32K_CLK_CAL_CYCLES));returns_calibrated_freq.osc_slow;...default:return0;...}{...}}{...}/* ... */#endifuint32_tesp_clk_tree_lp_slow_get_freq_hz(esp_clk_tree_src_freq_precision_tprecision){switch(precision){caseESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED:// This returns calibrated (if CONFIG_xxx_RTC_CLK_CAL_CYCLES) value stored in RTC storage registerreturnrtc_clk_freq_cal(clk_ll_rtc_slow_load_cal());...caseESP_CLK_TREE_SRC_FREQ_PRECISION_APPROX:returnclk_hal_lp_slow_get_freq_hz();...caseESP_CLK_TREE_SRC_FREQ_PRECISION_EXACT:returnrtc_clk_freq_cal(clk_tree_rtc_slow_calibration(RTC_SLOW_CLK_CAL_CYCLES));...default:return0;...}{...}}{ ... }uint32_tesp_clk_tree_rc_fast_get_freq_hz(esp_clk_tree_src_freq_precision_tprecision){#ifSOC_CLK_RC_FAST_SUPPORT_CALIBRATIONif(precision==ESP_CLK_TREE_SRC_FREQ_PRECISION_APPROX){returnSOC_CLK_RC_FAST_FREQ_APPROX;}{...}#ifSOC_CLK_RC_FAST_D256_SUPPORTED// If RC_FAST_D256 clock exists, calibration on a slow freq clock is much faster (less slow clock cycles need to wait)returnesp_clk_tree_rc_fast_d256_get_freq_hz(precision)<<8;/* ... */#else// Calibrate directly on the RC_FAST clock requires much more slow clock cycles to get an accurate freq valueif(precision!=ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED||!s_calibrated_freq.rc_fast){s_calibrated_freq.rc_fast=rtc_clk_freq_cal(rtc_clk_cal(RTC_CAL_RC_FAST,DEFAULT_RC_FAST_CAL_CYCLES));}{...}returns_calibrated_freq.rc_fast;/* ... */#endif//SOC_CLK_RC_FAST_D256_SUPPORTED/* ... */#else//!SOC_CLK_RC_FAST_SUPPORT_CALIBRATIONif(precision!=ESP_CLK_TREE_SRC_FREQ_PRECISION_APPROX){// No way of getting exact rc_fast freqESP_HW_LOGW(TAG,"unable to get the exact freq of rc_fast_clk, returning its approx. freq value");}{...}returnSOC_CLK_RC_FAST_FREQ_APPROX;/* ... */#endif//SOC_CLK_RC_FAST_SUPPORT_CALIBRATION}{ ... }uint32_tesp_clk_tree_lp_fast_get_freq_hz(esp_clk_tree_src_freq_precision_tprecision){switch(clk_ll_rtc_fast_get_src()){caseSOC_RTC_FAST_CLK_SRC_XTAL_DIV:#ifCONFIG_IDF_TARGET_ESP32||CONFIG_IDF_TARGET_ESP32S2//SOC_RTC_FAST_CLK_SRC_XTAL_D4returnclk_hal_xtal_get_freq_mhz()*MHZ>>2;#elifCONFIG_IDF_TARGET_ESP32P4//SOC_RTC_FAST_CLK_SRC_XTALreturnclk_hal_xtal_get_freq_mhz()*MHZ;#else//SOC_RTC_FAST_CLK_SRC_XTAL_D2returnclk_hal_xtal_get_freq_mhz()*MHZ>>1;#endif...caseSOC_RTC_FAST_CLK_SRC_RC_FAST:returnesp_clk_tree_rc_fast_get_freq_hz(precision)/clk_ll_rc_fast_get_divider();#ifSOC_CLK_LP_FAST_SUPPORT_LP_PLL...caseSOC_RTC_FAST_CLK_SRC_LP_PLL:returnclk_ll_lp_pll_get_freq_mhz()*MHZ;/* ... */#endif#ifSOC_CLK_LP_FAST_SUPPORT_XTAL&&!CONFIG_IDF_TARGET_ESP32P4// On P4 SOC_RTC_FAST_CLK_SRC_XTAL is an alias for SOC_RTC_FAST_CLK_SRC_XTAL_DIVcaseSOC_RTC_FAST_CLK_SRC_XTAL:returnclk_hal_xtal_get_freq_mhz()*MHZ;/* ... */#endifdefault:// Invalid clock sourceassert(false);return0;...}{...}}{ ... }
Details
Show: from
Types: Columns:
All items filtered out
All items filtered out
This file uses the notable symbols shown below. Click anywhere in the file to view more details.