Select one of the symbols to view example projects that use it.
 
Outline
#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"
TAG
esp_clk_tree_calibrated_freq_t
esp_clk_tree_calibrated_freq_t
s_calibrated_freq
#define RTC_SLOW_CLK_CAL_CYCLES
#define DEFAULT_32K_CLK_CAL_CYCLES
#define DEFAULT_RC_FAST_CAL_CYCLES
clk_tree_rtc_slow_calibration(uint32_t)
esp_clk_tree_rc_fast_d256_get_freq_hz(esp_clk_tree_src_freq_precision_t)
esp_clk_tree_xtal32k_get_freq_hz(esp_clk_tree_src_freq_precision_t)
esp_clk_tree_lp_slow_get_freq_hz(esp_clk_tree_src_freq_precision_t)
esp_clk_tree_rc_fast_get_freq_hz(esp_clk_tree_src_freq_precision_t)
esp_clk_tree_lp_fast_get_freq_hz(esp_clk_tree_src_freq_precision_t)
Files
loading...
SourceVuESP-IDF Framework and ExamplesESP-IDFcomponents/esp_hw_support/port/esp_clk_tree_common.c
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
/* * 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 includes static const char *TAG = "esp_clk_tree_common"; typedef struct esp_clk_tree_calibrated_freq_t esp_clk_tree_calibrated_freq_t; struct esp_clk_tree_calibrated_freq_t { #if SOC_CLK_RC_FAST_D256_SUPPORTED uint32_t rc_fast_d256; #elif SOC_CLK_RC_FAST_SUPPORT_CALIBRATION // && !SOC_CLK_RC_FAST_D256_SUPPORTED uint32_t rc_fast; #endif #if SOC_CLK_XTAL32K_SUPPORTED uint32_t xtal32k; #endif #if SOC_CLK_OSC_SLOW_SUPPORTED uint32_t osc_slow; #endif }{ ... }; // TODO: Better to implement a spinlock for the static variables static esp_clk_tree_calibrated_freq_t s_calibrated_freq = {}; /* Number of cycles for RTC_SLOW_CLK calibration */ #define RTC_SLOW_CLK_CAL_CYCLES CONFIG_RTC_CLK_CAL_CYCLES /* Number of cycles for ~32kHz clocks calibration (rc_fast_d256, xtal32k, osc_slow, rc32k) */ #define DEFAULT_32K_CLK_CAL_CYCLES 100 /* Number of cycles for RC_FAST calibration */ #define DEFAULT_RC_FAST_CAL_CYCLES 10000 // 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 *//* ... */ static uint32_t clk_tree_rtc_slow_calibration(uint32_t slowclk_cycles) { uint32_t cal_val = 0; if (slowclk_cycles > 0) { cal_val = rtc_clk_cal(RTC_CAL_RTC_MUX, slowclk_cycles); }{...} else { const uint64_t cal_dividend = (1ULL << RTC_CLK_CAL_FRACT) * 1000000ULL; uint32_t source_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_CLK esp_clk_slowclk_cal_set(cal_val); }{...} return cal_val; }{ ... } #if SOC_CLK_RC_FAST_D256_SUPPORTED uint32_t esp_clk_tree_rc_fast_d256_get_freq_hz(esp_clk_tree_src_freq_precision_t precision) { switch (precision) { case ESP_CLK_TREE_SRC_FREQ_PRECISION_APPROX: return SOC_CLK_RC_FAST_D256_FREQ_APPROX;... case ESP_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)); }{...} return s_calibrated_freq.rc_fast_d256;... case ESP_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)); return s_calibrated_freq.rc_fast_d256;... default: return 0;... }{...} }{ ... } /* ... */#endif #if SOC_CLK_XTAL32K_SUPPORTED uint32_t esp_clk_tree_xtal32k_get_freq_hz(esp_clk_tree_src_freq_precision_t precision) { switch (precision) { case ESP_CLK_TREE_SRC_FREQ_PRECISION_APPROX: return SOC_CLK_XTAL32K_FREQ_APPROX;... case ESP_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)); }{...} return s_calibrated_freq.xtal32k;... case ESP_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)); return s_calibrated_freq.xtal32k;... default: return 0;... }{...} }{ ... } /* ... */#endif #if SOC_CLK_OSC_SLOW_SUPPORTED uint32_t esp_clk_tree_osc_slow_get_freq_hz(esp_clk_tree_src_freq_precision_t precision) { switch (precision) { case ESP_CLK_TREE_SRC_FREQ_PRECISION_APPROX: return SOC_CLK_OSC_SLOW_FREQ_APPROX;... case ESP_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)); }{...} return s_calibrated_freq.osc_slow;... case ESP_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)); return s_calibrated_freq.osc_slow;... default: return 0;... }{...} }{...} /* ... */#endif uint32_t esp_clk_tree_lp_slow_get_freq_hz(esp_clk_tree_src_freq_precision_t precision) { switch (precision) { case ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED: // This returns calibrated (if CONFIG_xxx_RTC_CLK_CAL_CYCLES) value stored in RTC storage register return rtc_clk_freq_cal(clk_ll_rtc_slow_load_cal());... case ESP_CLK_TREE_SRC_FREQ_PRECISION_APPROX: return clk_hal_lp_slow_get_freq_hz();... case ESP_CLK_TREE_SRC_FREQ_PRECISION_EXACT: return rtc_clk_freq_cal(clk_tree_rtc_slow_calibration(RTC_SLOW_CLK_CAL_CYCLES));... default: return 0;... }{...} }{ ... } uint32_t esp_clk_tree_rc_fast_get_freq_hz(esp_clk_tree_src_freq_precision_t precision) { #if SOC_CLK_RC_FAST_SUPPORT_CALIBRATION if (precision == ESP_CLK_TREE_SRC_FREQ_PRECISION_APPROX) { return SOC_CLK_RC_FAST_FREQ_APPROX; }{...} #if SOC_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) return esp_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 value if (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)); }{...} return s_calibrated_freq.rc_fast;/* ... */ #endif //SOC_CLK_RC_FAST_D256_SUPPORTED/* ... */ #else //!SOC_CLK_RC_FAST_SUPPORT_CALIBRATION if (precision != ESP_CLK_TREE_SRC_FREQ_PRECISION_APPROX) { // No way of getting exact rc_fast freq ESP_HW_LOGW(TAG, "unable to get the exact freq of rc_fast_clk, returning its approx. freq value"); }{...} return SOC_CLK_RC_FAST_FREQ_APPROX;/* ... */ #endif //SOC_CLK_RC_FAST_SUPPORT_CALIBRATION }{ ... } uint32_t esp_clk_tree_lp_fast_get_freq_hz(esp_clk_tree_src_freq_precision_t precision) { switch (clk_ll_rtc_fast_get_src()) { case SOC_RTC_FAST_CLK_SRC_XTAL_DIV: #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 //SOC_RTC_FAST_CLK_SRC_XTAL_D4 return clk_hal_xtal_get_freq_mhz() * MHZ >> 2; #elif CONFIG_IDF_TARGET_ESP32P4 //SOC_RTC_FAST_CLK_SRC_XTAL return clk_hal_xtal_get_freq_mhz() * MHZ; #else //SOC_RTC_FAST_CLK_SRC_XTAL_D2 return clk_hal_xtal_get_freq_mhz() * MHZ >> 1; #endif... case SOC_RTC_FAST_CLK_SRC_RC_FAST: return esp_clk_tree_rc_fast_get_freq_hz(precision) / clk_ll_rc_fast_get_divider(); #if SOC_CLK_LP_FAST_SUPPORT_LP_PLL... case SOC_RTC_FAST_CLK_SRC_LP_PLL: return clk_ll_lp_pll_get_freq_mhz() * MHZ;/* ... */ #endif #if SOC_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_DIV case SOC_RTC_FAST_CLK_SRC_XTAL: return clk_hal_xtal_get_freq_mhz() * MHZ;/* ... */ #endif default: // Invalid clock source assert(false); return 0;... }{...} }{ ... }
Details
Show:
from
Types: Columns:
This file uses the notable symbols shown below. Click anywhere in the file to view more details.