1
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
24
25
26
27
28
29
30
31
32
33
34
35
44
51
52
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
100
101
102
103
104
105
106
107
108
109
110
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
152
153
154
158
159
161
181
182
183
184
/* ... */
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>
#include "esp32/rom/rtc.h"
#include "esp_rom_uart.h"
#include "esp_cpu.h"
#include "soc/rtc.h"
#include "soc/rtc_periph.h"
#include "hal/clk_tree_ll.h"
#include "hal/regi2c_ctrl_ll.h"
#include "esp_hw_log.h"
#include "sdkconfig.h"13 includes
/* ... */
#define XTAL_FREQ_EST_CYCLES 10
static soc_xtal_freq_t rtc_clk_xtal_freq_estimate(void);
extern void rtc_clk_cpu_freq_to_xtal(int freq, int div);
static const char* TAG = "rtc_clk_init";
void rtc_clk_init(rtc_clk_config_t cfg)
{
rtc_cpu_freq_config_t old_config, new_config;
/* ... */
if (clk_ll_cpu_get_src() == SOC_CPU_CLK_SRC_PLL) {
/* ... */
rtc_clk_cpu_freq_to_xtal(40, 1);
}{...}
/* ... */
REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_SCK_DCAP, cfg.slow_clk_dcap);
REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DFREQ, cfg.clk_8m_dfreq);
clk_ll_rc_fast_set_divider(cfg.clk_8m_div + 1);
regi2c_ctrl_ll_i2c_reset();
regi2c_ctrl_ll_i2c_bbpll_enable();
regi2c_ctrl_ll_i2c_apll_enable();
soc_xtal_freq_t configured_xtal_freq = cfg.xtal_freq;
soc_xtal_freq_t stored_xtal_freq = rtc_clk_xtal_freq_get();
soc_xtal_freq_t xtal_freq = configured_xtal_freq;
if (configured_xtal_freq == SOC_XTAL_FREQ_AUTO) {
if (stored_xtal_freq != SOC_XTAL_FREQ_AUTO) {
xtal_freq = stored_xtal_freq;
}{...} else {
xtal_freq = rtc_clk_xtal_freq_estimate();
if (xtal_freq == SOC_XTAL_FREQ_AUTO) {
ESP_HW_LOGW(TAG, "Can't estimate XTAL freq, assuming 26MHz");
xtal_freq = SOC_XTAL_FREQ_26M;
}{...}
}{...}
}{...} else if (stored_xtal_freq == SOC_XTAL_FREQ_AUTO) {
/* ... */
soc_xtal_freq_t est_xtal_freq = rtc_clk_xtal_freq_estimate();
if (est_xtal_freq != configured_xtal_freq) {
ESP_HW_LOGW(TAG, "Possibly invalid CONFIG_XTAL_FREQ setting (%dMHz). Detected %dMHz.",
configured_xtal_freq, est_xtal_freq);
}{...}
}{...}
esp_rom_output_tx_wait_idle(0);
rtc_clk_xtal_freq_update(xtal_freq);
rtc_clk_apb_freq_update(xtal_freq * MHZ);
rtc_clk_cpu_freq_get_config(&old_config);
uint32_t freq_before = old_config.freq_mhz;
bool res = rtc_clk_cpu_freq_mhz_to_config(cfg.cpu_freq_mhz, &new_config);
if (!res) {
ESP_HW_LOGE(TAG, "invalid CPU freq value");
abort();
}{...}
rtc_clk_cpu_freq_set_config(&new_config);
clk_ll_ref_tick_set_divider(SOC_CPU_CLK_SRC_XTAL, xtal_freq);
clk_ll_ref_tick_set_divider(SOC_CPU_CLK_SRC_PLL, new_config.freq_mhz);
esp_cpu_set_cycle_count( (uint64_t)esp_cpu_get_cycle_count() * cfg.cpu_freq_mhz / freq_before );
bool need_rc_fast_en = true;
bool need_rc_fast_d256_en = false;
if (cfg.slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) {
rtc_clk_32k_enable(true);
}{...} else if (cfg.slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256) {
need_rc_fast_d256_en = true;
}{...}
rtc_clk_8m_enable(need_rc_fast_en, need_rc_fast_d256_en);
rtc_clk_fast_src_set(cfg.fast_clk_src);
rtc_clk_slow_src_set(cfg.slow_clk_src);
}{ ... }
static soc_xtal_freq_t rtc_clk_xtal_freq_estimate(void)
{
#if CONFIG_IDF_ENV_FPGA
return SOC_XTAL_FREQ_40M;
#endif
soc_xtal_freq_t xtal_freq;
const bool clk_8m_enabled = rtc_clk_8m_enabled();
const bool clk_8md256_enabled = rtc_clk_8md256_enabled();
if (!clk_8md256_enabled) {
rtc_clk_8m_enable(true, true);
}{...}
uint64_t cal_val = rtc_clk_cal_ratio(RTC_CAL_8MD256, XTAL_FREQ_EST_CYCLES);
/* ... */
uint32_t freq_mhz = (cal_val * SOC_CLK_RC_FAST_FREQ_APPROX / MHZ / 256 ) >> RTC_CLK_CAL_FRACT;
/* ... */
switch (freq_mhz) {
case 21 ... 31:
xtal_freq = SOC_XTAL_FREQ_26M;
break;...
case 32 ... 33:
ESP_HW_LOGW(TAG, "Potential bogus XTAL freq: %"PRIu32"MHz, guessing 26MHz", freq_mhz);
xtal_freq = SOC_XTAL_FREQ_26M;
break;...
case 34 ... 35:
ESP_HW_LOGW(TAG, "Potential bogus XTAL freq: %"PRIu32"MHz, guessing 40MHz", freq_mhz);
xtal_freq = SOC_XTAL_FREQ_40M;
break;...
case 36 ... 45:
xtal_freq = SOC_XTAL_FREQ_40M;
break;...
default:
ESP_HW_LOGW(TAG, "Bogus XTAL freq: %"PRIu32"MHz", freq_mhz);
xtal_freq = SOC_XTAL_FREQ_AUTO;
break;...
}{...}
rtc_clk_8m_enable(clk_8m_enabled, clk_8md256_enabled);
return xtal_freq;
}{ ... }