]> granicus.if.org Git - esp-idf/blobdiff - components/soc/esp32/rtc_clk.c
fix(global, log): fix `esp_log(_early)_timestamp` readings after startup by correct...
[esp-idf] / components / soc / esp32 / rtc_clk.c
index 676b9f33cebfa78c45db511033b522a41f3f7d8e..e3e007898df55e69efa2cb1ec240a077ce7a84a9 100644 (file)
@@ -29,6 +29,8 @@
 #include "i2c_rtc_clk.h"
 #include "soc_log.h"
 #include "sdkconfig.h"
+#include "xtensa/core-macros.h"
+
 
 #define MHZ (1000000)
 
@@ -332,7 +334,7 @@ void rtc_clk_cpu_freq_set(rtc_cpu_freq_t cpu_freq)
     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);
@@ -361,13 +363,13 @@ void rtc_clk_cpu_freq_set(rtc_cpu_freq_t cpu_freq)
                 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);
@@ -392,7 +394,7 @@ rtc_cpu_freq_t rtc_clk_cpu_freq_get()
             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) {
@@ -499,12 +501,18 @@ void rtc_clk_apb_freq_update(uint32_t apb_freq)
 
 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
@@ -536,7 +544,8 @@ void rtc_clk_init(rtc_clk_config_t cfg)
     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))) {
@@ -544,17 +553,30 @@ void rtc_clk_init(rtc_clk_config_t cfg)
             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) {