#include "i2c_rtc_clk.h"
#include "soc_log.h"
#include "sdkconfig.h"
+#include "xtensa/core-macros.h"
+
#define MHZ (1000000)
uint32_t delay_xtal_switch = (rtc_clk_slow_freq_get() == RTC_SLOW_FREQ_RTC) ?
DELAY_CPU_FREQ_SWITCH_TO_XTAL_WITH_150K : DELAY_CPU_FREQ_SWITCH_TO_XTAL_WITH_32K;
ets_delay_us(delay_xtal_switch);
- REG_SET_FIELD(DPORT_CPU_PER_CONF_REG, DPORT_CPUPERIOD_SEL, 0);
+ DPORT_REG_SET_FIELD(DPORT_CPU_PER_CONF_REG, DPORT_CPUPERIOD_SEL, 0);
SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG,
RTC_CNTL_BB_I2C_FORCE_PD | RTC_CNTL_BBPLL_FORCE_PD |
RTC_CNTL_BBPLL_I2C_FORCE_PD);
RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD);
rtc_clk_bbpll_set(xtal_freq, cpu_freq);
if (cpu_freq == RTC_CPU_FREQ_80M) {
- REG_SET_FIELD(DPORT_CPU_PER_CONF_REG, DPORT_CPUPERIOD_SEL, 0);
+ DPORT_REG_SET_FIELD(DPORT_CPU_PER_CONF_REG, DPORT_CPUPERIOD_SEL, 0);
ets_update_cpu_frequency(80);
} else if (cpu_freq == RTC_CPU_FREQ_160M) {
- REG_SET_FIELD(DPORT_CPU_PER_CONF_REG, DPORT_CPUPERIOD_SEL, 1);
+ DPORT_REG_SET_FIELD(DPORT_CPU_PER_CONF_REG, DPORT_CPUPERIOD_SEL, 1);
ets_update_cpu_frequency(160);
} else if (cpu_freq == RTC_CPU_FREQ_240M) {
- REG_SET_FIELD(DPORT_CPU_PER_CONF_REG, DPORT_CPUPERIOD_SEL, 2);
+ DPORT_REG_SET_FIELD(DPORT_CPU_PER_CONF_REG, DPORT_CPUPERIOD_SEL, 2);
ets_update_cpu_frequency(240);
}
REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_SOC_CLK_SEL, RTC_CNTL_SOC_CLK_SEL_PLL);
break;
}
case RTC_CNTL_SOC_CLK_SEL_PLL: {
- uint32_t cpuperiod_sel = REG_GET_FIELD(DPORT_CPU_PER_CONF_REG, DPORT_CPUPERIOD_SEL);
+ uint32_t cpuperiod_sel = DPORT_REG_GET_FIELD(DPORT_CPU_PER_CONF_REG, DPORT_CPUPERIOD_SEL);
if (cpuperiod_sel == 0) {
return RTC_CPU_FREQ_80M;
} else if (cpuperiod_sel == 1) {
uint32_t rtc_clk_apb_freq_get()
{
- return reg_val_to_clk_val(READ_PERI_REG(RTC_APB_FREQ_REG)) << 12;
+ uint32_t freq_hz = reg_val_to_clk_val(READ_PERI_REG(RTC_APB_FREQ_REG)) << 12;
+ // round to the nearest MHz
+ freq_hz += MHZ / 2;
+ uint32_t remainder = freq_hz % MHZ;
+ return freq_hz - remainder;
}
void rtc_clk_init(rtc_clk_config_t cfg)
{
+ rtc_cpu_freq_t cpu_source_before = rtc_clk_cpu_freq_get();
+
/* If we get a TG WDT system reset while running at 240MHz,
* DPORT_CPUPERIOD_SEL register will be reset to 0 resulting in 120MHz
* APB and CPU frequencies after reset. This will cause issues with XTAL
SET_PERI_REG_BITS(ANA_CONFIG_REG, ANA_CONFIG_M, ANA_CONFIG_M, ANA_CONFIG_S);
CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, I2C_APLL_M | I2C_BBPLL_M);
- /* Estimate XTAL frequency if requested */
+ /* Estimate XTAL frequency */
+ rtc_xtal_freq_t est_xtal_freq = rtc_clk_xtal_freq_estimate();
rtc_xtal_freq_t xtal_freq = cfg.xtal_freq;
if (xtal_freq == RTC_XTAL_FREQ_AUTO) {
if (clk_val_is_valid(READ_PERI_REG(RTC_XTAL_FREQ_REG))) {
xtal_freq = rtc_clk_xtal_freq_get();
} else {
/* Not set yet, estimate XTAL frequency based on RTC_FAST_CLK */
- xtal_freq = rtc_clk_xtal_freq_estimate();
+ xtal_freq = est_xtal_freq;
if (xtal_freq == RTC_XTAL_FREQ_AUTO) {
SOC_LOGW(TAG, "Can't estimate XTAL frequency, assuming 26MHz");
xtal_freq = RTC_XTAL_FREQ_26M;
}
}
+ } else if (!clk_val_is_valid(READ_PERI_REG(RTC_XTAL_FREQ_REG))) {
+ /* Exact frequency was set in sdkconfig, but still warn if autodetected
+ * frequency is different. If autodetection failed, worst case we get a
+ * bit of garbage output.
+ */
+ SOC_LOGW(TAG, "Possibly invalid CONFIG_ESP32_XTAL_FREQ setting (%dMHz). Detected %d MHz.",
+ xtal_freq, est_xtal_freq);
}
+ uart_tx_wait_idle(0);
rtc_clk_xtal_freq_update(xtal_freq);
rtc_clk_apb_freq_update(xtal_freq * MHZ);
/* Set CPU frequency */
rtc_clk_cpu_freq_set(cfg.cpu_freq);
+
+ /* Re-calculate the ccount to make time calculation correct. */
+ uint32_t freq_before = rtc_clk_cpu_freq_value(cpu_source_before) / MHZ;
+ uint32_t freq_after = rtc_clk_cpu_freq_value(cfg.cpu_freq) / MHZ;
+ XTHAL_SET_CCOUNT( XTHAL_GET_CCOUNT() * freq_after / freq_before );
/* Slow & fast clocks setup */
if (cfg.slow_freq == RTC_SLOW_FREQ_32K_XTAL) {