mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 11:10:54 +03:00
Merge branch 'refactor/rtc_cal_clk' into 'master'
refactor(clk): add soc_clk_calibration_clk_src_t for all targets Closes IDF-11790 See merge request espressif/esp-idf!40737
This commit is contained in:
@@ -89,14 +89,9 @@ typedef struct rtc_cpu_freq_config_s {
|
||||
uint32_t freq_mhz; //!< CPU clock frequency
|
||||
} rtc_cpu_freq_config_t;
|
||||
|
||||
/**
|
||||
* @brief Clock source to be calibrated using rtc_clk_cal function
|
||||
*/
|
||||
typedef enum {
|
||||
RTC_CAL_RTC_MUX = 0, //!< Currently selected RTC SLOW_CLK
|
||||
RTC_CAL_8MD256 = 1, //!< Internal 8 MHz RC oscillator, divided by 256
|
||||
RTC_CAL_32K_XTAL = 2 //!< External 32 kHz XTAL
|
||||
} rtc_cal_sel_t;
|
||||
#define RTC_CAL_RTC_MUX _Pragma ("GCC warning \"'RTC_CAL_RTC_MUX' macro is deprecated\"") CLK_CAL_RTC_SLOW
|
||||
#define RTC_CAL_8MD256 _Pragma ("GCC warning \"'RTC_CAL_8MD256' macro is deprecated\"") CLK_CAL_RC_FAST_D256
|
||||
#define RTC_CAL_32K_XTAL _Pragma ("GCC warning \"'RTC_CAL_32K_XTAL' macro is deprecated\"") CLK_CAL_32K_XTAL
|
||||
|
||||
/**
|
||||
* Initialization parameters for rtc_clk_init
|
||||
@@ -397,21 +392,21 @@ uint32_t rtc_clk_apb_freq_get(void);
|
||||
* the check fails, then consider this an invalid 32k clock and return 0. This
|
||||
* check can filter some jamming signal.
|
||||
*
|
||||
* @param cal_clk clock to be measured
|
||||
* @param cal_clk_sel clock to be measured
|
||||
* @param slow_clk_cycles number of slow clock cycles to average
|
||||
* @return average slow clock period in microseconds, Q13.19 fixed point format,
|
||||
* or 0 if calibration has timed out
|
||||
*/
|
||||
uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slow_clk_cycles);
|
||||
uint32_t rtc_clk_cal(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slow_clk_cycles);
|
||||
|
||||
/**
|
||||
* @brief Measure ratio between XTAL frequency and RTC slow clock frequency
|
||||
* @param cal_clk slow clock to be measured
|
||||
* @param cal_clk_sel slow clock to be measured
|
||||
* @param slow_clk_cycles number of slow clock cycles to average
|
||||
* @return average ratio between XTAL frequency and slow clock frequency,
|
||||
* Q13.19 fixed point format, or 0 if calibration has timed out.
|
||||
*/
|
||||
uint32_t rtc_clk_cal_ratio(rtc_cal_sel_t cal_clk, uint32_t slow_clk_cycles);
|
||||
uint32_t rtc_clk_cal_ratio(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slow_clk_cycles);
|
||||
|
||||
/**
|
||||
* @brief Convert time interval from microseconds to RTC_SLOW_CLK cycles
|
||||
|
||||
@@ -150,7 +150,7 @@ static soc_xtal_freq_t rtc_clk_xtal_freq_estimate(void)
|
||||
rtc_clk_8m_enable(true, true);
|
||||
}
|
||||
|
||||
uint64_t cal_val = rtc_clk_cal_ratio(RTC_CAL_8MD256, XTAL_FREQ_EST_CYCLES);
|
||||
uint64_t cal_val = rtc_clk_cal_ratio(CLK_CAL_RC_FAST_D256, XTAL_FREQ_EST_CYCLES);
|
||||
/* cal_val contains period of 8M/256 clock in XTAL clock cycles
|
||||
* (shifted by RTC_CLK_CAL_FRACT bits).
|
||||
* Xtal frequency will be (cal_val * 8M / 256) / 2^19
|
||||
|
||||
@@ -30,37 +30,38 @@ static const char *TAG = "rtc_time";
|
||||
|
||||
/**
|
||||
* @brief Clock calibration function used by rtc_clk_cal and rtc_clk_cal_ratio
|
||||
* @param cal_clk which clock to calibrate
|
||||
* @param cal_clk_sel which clock to calculate frequency
|
||||
* @param slowclk_cycles number of slow clock cycles to count. Max value is 32766.
|
||||
* @return number of XTAL clock cycles within the given number of slow clock cycles
|
||||
*/
|
||||
static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
static uint32_t rtc_clk_cal_internal(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slowclk_cycles)
|
||||
{
|
||||
assert(slowclk_cycles < 32767);
|
||||
/* Enable requested clock (150k clock is always on) */
|
||||
|
||||
/* Enable requested clock (rtc slow clock is always on) */
|
||||
bool dig_32k_xtal_enabled = clk_ll_xtal32k_digi_is_enabled();
|
||||
if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
if (cal_clk_sel == CLK_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
clk_ll_xtal32k_digi_enable();
|
||||
}
|
||||
|
||||
bool rc_fast_enabled = clk_ll_rc_fast_is_enabled();
|
||||
bool rc_fast_d256_enabled = clk_ll_rc_fast_d256_is_enabled();
|
||||
if (cal_clk == RTC_CAL_8MD256) {
|
||||
if (cal_clk_sel == CLK_CAL_RC_FAST_D256) {
|
||||
rtc_clk_8m_enable(true, true);
|
||||
clk_ll_rc_fast_d256_digi_enable();
|
||||
}
|
||||
/* Prepare calibration */
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_CLK_SEL, cal_clk);
|
||||
clk_ll_freq_calulation_set_target(cal_clk_sel);
|
||||
CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING);
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_MAX, slowclk_cycles);
|
||||
/* Figure out how long to wait for calibration to finish */
|
||||
uint32_t expected_freq;
|
||||
soc_rtc_slow_clk_src_t slow_clk_src = rtc_clk_slow_src_get();
|
||||
if (cal_clk == RTC_CAL_32K_XTAL ||
|
||||
(cal_clk == RTC_CAL_RTC_MUX && slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K)) {
|
||||
if (cal_clk_sel == CLK_CAL_32K_XTAL ||
|
||||
(cal_clk_sel == CLK_CAL_RTC_SLOW && slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K)) {
|
||||
expected_freq = SOC_CLK_XTAL32K_FREQ_APPROX; /* standard 32k XTAL */
|
||||
} else if (cal_clk == RTC_CAL_8MD256 ||
|
||||
(cal_clk == RTC_CAL_RTC_MUX && slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256)) {
|
||||
} else if (cal_clk_sel == CLK_CAL_RC_FAST_D256 ||
|
||||
(cal_clk_sel == CLK_CAL_RTC_SLOW && slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256)) {
|
||||
expected_freq = SOC_CLK_RC_FAST_D256_FREQ_APPROX;
|
||||
} else {
|
||||
expected_freq = SOC_CLK_RC_SLOW_FREQ_APPROX; /* 150k internal oscillator */
|
||||
@@ -94,11 +95,11 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
|
||||
}
|
||||
|
||||
/* if dig_32k_xtal was originally off and enabled due to calibration, then set back to off state */
|
||||
if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
if (cal_clk_sel == CLK_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
clk_ll_xtal32k_digi_disable();
|
||||
}
|
||||
|
||||
if (cal_clk == RTC_CAL_8MD256) {
|
||||
if (cal_clk_sel == CLK_CAL_RC_FAST_D256) {
|
||||
clk_ll_rc_fast_d256_digi_disable();
|
||||
rtc_clk_8m_enable(rc_fast_enabled, rc_fast_d256_enabled);
|
||||
}
|
||||
@@ -110,10 +111,10 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
|
||||
return REG_GET_FIELD(TIMG_RTCCALICFG1_REG(0), TIMG_RTC_CALI_VALUE);
|
||||
}
|
||||
|
||||
uint32_t rtc_clk_cal_ratio(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
uint32_t rtc_clk_cal_ratio(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slowclk_cycles)
|
||||
{
|
||||
assert(slowclk_cycles);
|
||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk, slowclk_cycles);
|
||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk_sel, slowclk_cycles);
|
||||
uint64_t ratio_64 = ((xtal_cycles << RTC_CLK_CAL_FRACT)) / slowclk_cycles;
|
||||
uint32_t ratio = (uint32_t)(ratio_64 & UINT32_MAX);
|
||||
return ratio;
|
||||
@@ -126,13 +127,13 @@ static inline bool rtc_clk_cal_32k_valid(uint32_t xtal_freq, uint32_t slowclk_cy
|
||||
return (actual_xtal_cycles >= (expected_xtal_cycles - delta)) && (actual_xtal_cycles <= (expected_xtal_cycles + delta));
|
||||
}
|
||||
|
||||
uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
uint32_t rtc_clk_cal(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slowclk_cycles)
|
||||
{
|
||||
assert(slowclk_cycles);
|
||||
soc_xtal_freq_t xtal_freq = rtc_clk_xtal_freq_get();
|
||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk, slowclk_cycles);
|
||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk_sel, slowclk_cycles);
|
||||
|
||||
if ((cal_clk == RTC_CAL_32K_XTAL) && !rtc_clk_cal_32k_valid((uint32_t)xtal_freq, slowclk_cycles, xtal_cycles)) {
|
||||
if ((cal_clk_sel == CLK_CAL_32K_XTAL) && !rtc_clk_cal_32k_valid((uint32_t)xtal_freq, slowclk_cycles, xtal_cycles)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -165,7 +166,7 @@ void rtc_clk_wait_for_slow_cycle(void)
|
||||
{
|
||||
REG_CLR_BIT(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING | TIMG_RTC_CALI_START);
|
||||
REG_CLR_BIT(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_RDY);
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_CLK_SEL, RTC_CAL_RTC_MUX);
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_CLK_SEL, CLK_CAL_RTC_SLOW);
|
||||
/* Request to run calibration for 0 slow clock cycles.
|
||||
* RDY bit will be set on the nearest slow clock cycle.
|
||||
*/
|
||||
|
||||
@@ -155,17 +155,10 @@ typedef struct rtc_cpu_freq_config_s {
|
||||
#define RTC_VDDSDIO_TIEH_1_8V 0 //!< TIEH field value for 1.8V VDDSDIO
|
||||
#define RTC_VDDSDIO_TIEH_3_3V 1 //!< TIEH field value for 3.3V VDDSDIO
|
||||
|
||||
/**
|
||||
* @brief Clock source to be calibrated using rtc_clk_cal function
|
||||
*/
|
||||
typedef enum {
|
||||
RTC_CAL_RTC_MUX = 0, //!< Currently selected RTC SLOW_CLK
|
||||
RTC_CAL_8MD256 = 1, //!< Internal 8 MHz RC oscillator, divided by 256
|
||||
RTC_CAL_32K_OSC_SLOW = 2, //!< External 32.768 KHz CLK
|
||||
|
||||
// deprecated name
|
||||
RTC_CAL_EXT_32K __attribute__((deprecated)) = RTC_CAL_32K_OSC_SLOW,
|
||||
} rtc_cal_sel_t;
|
||||
#define RTC_CAL_RTC_MUX _Pragma ("GCC warning \"'RTC_CAL_RTC_MUX' macro is deprecated\"") CLK_CAL_RTC_SLOW
|
||||
#define RTC_CAL_8MD256 _Pragma ("GCC warning \"'RTC_CAL_8MD256' macro is deprecated\"") CLK_CAL_RC_FAST_D256
|
||||
#define RTC_CAL_32K_OSC_SLOW _Pragma ("GCC warning \"'RTC_CAL_32K_OSC_SLOW' macro is deprecated\"") CLK_CAL_32K_OSC_SLOW
|
||||
#define RTC_CAL_INTERNAL_OSC _Pragma ("GCC warning \"'RTC_CAL_INTERNAL_OSC' macro is deprecated\"") CLK_CAL_RC_SLOW
|
||||
|
||||
/**
|
||||
* Initialization parameters for rtc_clk_init
|
||||
@@ -409,8 +402,6 @@ void rtc_clk_apb_freq_update(uint32_t apb_freq);
|
||||
*/
|
||||
uint32_t rtc_clk_apb_freq_get(void);
|
||||
|
||||
uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles);
|
||||
|
||||
/**
|
||||
* @brief Measure RTC slow clock's period, based on main XTAL frequency
|
||||
*
|
||||
@@ -424,21 +415,21 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles);
|
||||
* the check fails, then consider this an invalid 32k clock and return 0. This
|
||||
* check can filter some jamming signal.
|
||||
*
|
||||
* @param cal_clk clock to be measured
|
||||
* @param cal_clk_sel clock to be measured
|
||||
* @param slow_clk_cycles number of slow clock cycles to average
|
||||
* @return average slow clock period in microseconds, Q13.19 fixed point format,
|
||||
* or 0 if calibration has timed out
|
||||
*/
|
||||
uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slow_clk_cycles);
|
||||
uint32_t rtc_clk_cal(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slow_clk_cycles);
|
||||
|
||||
/**
|
||||
* @brief Measure ratio between XTAL frequency and RTC slow clock frequency
|
||||
* @param cal_clk slow clock to be measured
|
||||
* @param cal_clk_sel slow clock to be measured
|
||||
* @param slow_clk_cycles number of slow clock cycles to average
|
||||
* @return average ratio between XTAL frequency and slow clock frequency,
|
||||
* Q13.19 fixed point format, or 0 if calibration has timed out.
|
||||
*/
|
||||
uint32_t rtc_clk_cal_ratio(rtc_cal_sel_t cal_clk, uint32_t slow_clk_cycles);
|
||||
uint32_t rtc_clk_cal_ratio(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slow_clk_cycles);
|
||||
|
||||
/**
|
||||
* @brief Convert time interval from microseconds to RTC_SLOW_CLK cycles
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -154,16 +154,9 @@ static void calibrate_ocode(void)
|
||||
4. wait o-code calibration done flag(odone_flag & bg_odone_flag) or timeout;
|
||||
5. set cpu to old-config.
|
||||
*/
|
||||
soc_rtc_slow_clk_src_t slow_clk_src = rtc_clk_slow_src_get();
|
||||
rtc_cal_sel_t cal_clk = RTC_CAL_RTC_MUX;
|
||||
if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_OSC_SLOW) {
|
||||
cal_clk = RTC_CAL_32K_OSC_SLOW;
|
||||
} else if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256) {
|
||||
cal_clk = RTC_CAL_8MD256;
|
||||
}
|
||||
|
||||
uint64_t max_delay_time_us = 10000;
|
||||
uint32_t slow_clk_period = rtc_clk_cal(cal_clk, 100);
|
||||
uint32_t slow_clk_period = rtc_clk_cal(CLK_CAL_RTC_SLOW, 100);
|
||||
uint64_t max_delay_cycle = rtc_time_us_to_slowclk(max_delay_time_us, slow_clk_period);
|
||||
uint64_t cycle0 = rtc_time_get();
|
||||
uint64_t timeout_cycle = cycle0 + max_delay_cycle;
|
||||
@@ -259,7 +252,7 @@ uint32_t get_rtc_dbias_by_efuse(uint8_t dbias_scheme_ver, uint32_t dig_dbias)
|
||||
static void set_rtc_dig_dbias()
|
||||
{
|
||||
/*
|
||||
1. a reasonable dig_dbias which by scaning pvt to make 120 CPU run successful stored in efuse;
|
||||
1. a reasonable dig_dbias which by scanning pvt to make 120 CPU run successful stored in efuse;
|
||||
2. a reasonable rtc_dbias can be calculated by a certion formula.
|
||||
*/
|
||||
uint32_t rtc_dbias = 31, dig_dbias = 26;
|
||||
|
||||
@@ -29,34 +29,32 @@
|
||||
|
||||
/**
|
||||
* @brief Clock calibration function used by rtc_clk_cal and rtc_clk_cal_ratio
|
||||
* @param cal_clk which clock to calibrate
|
||||
* @param cal_clk_sel which clock to calculate frequency
|
||||
* @param slowclk_cycles number of slow clock cycles to count
|
||||
* @return number of XTAL clock cycles within the given number of slow clock cycles
|
||||
*/
|
||||
uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
static uint32_t rtc_clk_cal_internal(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slowclk_cycles)
|
||||
{
|
||||
/* On ESP32-C2, choosing RTC_CAL_RTC_MUX results in calibration of
|
||||
* the 150k RTC clock regardless of the currently selected SLOW_CLK.
|
||||
* On the ESP32, it used the currently selected SLOW_CLK.
|
||||
* The following code emulates ESP32 behavior:
|
||||
*/
|
||||
if (cal_clk == RTC_CAL_RTC_MUX) {
|
||||
if (cal_clk_sel == CLK_CAL_RTC_SLOW) {
|
||||
soc_rtc_slow_clk_src_t slow_clk_src = rtc_clk_slow_src_get();
|
||||
if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_OSC_SLOW) {
|
||||
cal_clk = RTC_CAL_32K_OSC_SLOW;
|
||||
if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC_SLOW) {
|
||||
cal_clk_sel = CLK_CAL_RC_SLOW;
|
||||
} else if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_OSC_SLOW) {
|
||||
cal_clk_sel = CLK_CAL_32K_OSC_SLOW;
|
||||
} else if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256) {
|
||||
cal_clk = RTC_CAL_8MD256;
|
||||
cal_clk_sel = CLK_CAL_RC_FAST_D256;
|
||||
}
|
||||
}
|
||||
|
||||
/* Enable requested clock (150k clock is always on) */
|
||||
bool dig_ext_clk_enabled = clk_ll_xtal32k_digi_is_enabled();
|
||||
if (cal_clk == RTC_CAL_32K_OSC_SLOW && !dig_ext_clk_enabled) {
|
||||
if (cal_clk_sel == CLK_CAL_32K_OSC_SLOW && !dig_ext_clk_enabled) {
|
||||
clk_ll_xtal32k_digi_enable();
|
||||
}
|
||||
|
||||
bool rc_fast_enabled = clk_ll_rc_fast_is_enabled();
|
||||
bool rc_fast_d256_enabled = clk_ll_rc_fast_d256_is_enabled();
|
||||
if (cal_clk == RTC_CAL_8MD256) {
|
||||
if (cal_clk_sel == CLK_CAL_RC_FAST_D256) {
|
||||
rtc_clk_8m_enable(true, true);
|
||||
clk_ll_rc_fast_d256_digi_enable();
|
||||
}
|
||||
@@ -74,17 +72,17 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
}
|
||||
|
||||
/* Prepare calibration */
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_CLK_SEL, cal_clk);
|
||||
clk_ll_freq_calulation_set_target(cal_clk_sel);
|
||||
CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING);
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_MAX, slowclk_cycles);
|
||||
/* Figure out how long to wait for calibration to finish */
|
||||
|
||||
/* Set timeout reg and expect time delay*/
|
||||
uint32_t expected_freq;
|
||||
if (cal_clk == RTC_CAL_32K_OSC_SLOW) {
|
||||
if (cal_clk_sel == CLK_CAL_32K_OSC_SLOW) {
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_SLOW_CLK_X32K_CAL_TIMEOUT_THRES(slowclk_cycles));
|
||||
expected_freq = SOC_CLK_OSC_SLOW_FREQ_APPROX;
|
||||
} else if (cal_clk == RTC_CAL_8MD256) {
|
||||
} else if (cal_clk_sel == CLK_CAL_RC_FAST_D256) {
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_SLOW_CLK_8MD256_CAL_TIMEOUT_THRES(slowclk_cycles));
|
||||
expected_freq = SOC_CLK_RC_FAST_D256_FREQ_APPROX;
|
||||
} else {
|
||||
@@ -112,11 +110,11 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START);
|
||||
|
||||
/* if dig_ext_clk was originally off and enabled due to calibration, then set back to off state */
|
||||
if (cal_clk == RTC_CAL_32K_OSC_SLOW && !dig_ext_clk_enabled) {
|
||||
if (cal_clk_sel == CLK_CAL_32K_OSC_SLOW && !dig_ext_clk_enabled) {
|
||||
clk_ll_xtal32k_digi_disable();
|
||||
}
|
||||
|
||||
if (cal_clk == RTC_CAL_8MD256) {
|
||||
if (cal_clk_sel == CLK_CAL_RC_FAST_D256) {
|
||||
clk_ll_rc_fast_d256_digi_disable();
|
||||
rtc_clk_8m_enable(rc_fast_enabled, rc_fast_d256_enabled);
|
||||
}
|
||||
@@ -124,10 +122,10 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
return cal_val;
|
||||
}
|
||||
|
||||
uint32_t rtc_clk_cal_ratio(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
uint32_t rtc_clk_cal_ratio(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slowclk_cycles)
|
||||
{
|
||||
assert(slowclk_cycles);
|
||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk, slowclk_cycles);
|
||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk_sel, slowclk_cycles);
|
||||
uint64_t ratio_64 = ((xtal_cycles << RTC_CLK_CAL_FRACT)) / slowclk_cycles;
|
||||
uint32_t ratio = (uint32_t)(ratio_64 & UINT32_MAX);
|
||||
return ratio;
|
||||
@@ -140,13 +138,13 @@ static inline bool rtc_clk_cal_32k_valid(uint32_t xtal_freq, uint32_t slowclk_cy
|
||||
return (actual_xtal_cycles >= (expected_xtal_cycles - delta)) && (actual_xtal_cycles <= (expected_xtal_cycles + delta));
|
||||
}
|
||||
|
||||
uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
uint32_t rtc_clk_cal(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slowclk_cycles)
|
||||
{
|
||||
assert(slowclk_cycles);
|
||||
soc_xtal_freq_t xtal_freq = rtc_clk_xtal_freq_get();
|
||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk, slowclk_cycles);
|
||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk_sel, slowclk_cycles);
|
||||
|
||||
if ((cal_clk == RTC_CAL_32K_OSC_SLOW) && !rtc_clk_cal_32k_valid((uint32_t)xtal_freq, slowclk_cycles, xtal_cycles)) {
|
||||
if ((cal_clk_sel == CLK_CAL_32K_OSC_SLOW) && !rtc_clk_cal_32k_valid((uint32_t)xtal_freq, slowclk_cycles, xtal_cycles)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -157,15 +157,10 @@ typedef struct rtc_cpu_freq_config_s {
|
||||
#define RTC_VDDSDIO_TIEH_1_8V 0 //!< TIEH field value for 1.8V VDDSDIO
|
||||
#define RTC_VDDSDIO_TIEH_3_3V 1 //!< TIEH field value for 3.3V VDDSDIO
|
||||
|
||||
/**
|
||||
* @brief Clock source to be calibrated using rtc_clk_cal function
|
||||
*/
|
||||
typedef enum {
|
||||
RTC_CAL_RTC_MUX = 0, //!< Currently selected RTC SLOW_CLK
|
||||
RTC_CAL_8MD256 = 1, //!< Internal 8 MHz RC oscillator, divided by 256
|
||||
RTC_CAL_32K_XTAL = 2, //!< External 32 kHz XTAL
|
||||
RTC_CAL_INTERNAL_OSC = 3 //!< Internal 150 kHz oscillator
|
||||
} rtc_cal_sel_t;
|
||||
#define RTC_CAL_RTC_MUX _Pragma ("GCC warning \"'RTC_CAL_RTC_MUX' macro is deprecated\"") CLK_CAL_RTC_SLOW
|
||||
#define RTC_CAL_8MD256 _Pragma ("GCC warning \"'RTC_CAL_8MD256' macro is deprecated\"") CLK_CAL_RC_FAST_D256
|
||||
#define RTC_CAL_32K_XTAL _Pragma ("GCC warning \"'RTC_CAL_32K_XTAL' macro is deprecated\"") CLK_CAL_32K_XTAL
|
||||
#define RTC_CAL_INTERNAL_OSC _Pragma ("GCC warning \"'RTC_CAL_INTERNAL_OSC' macro is deprecated\"") CLK_CAL_RC_SLOW
|
||||
|
||||
/**
|
||||
* Initialization parameters for rtc_clk_init
|
||||
@@ -437,8 +432,6 @@ void rtc_clk_apb_freq_update(uint32_t apb_freq);
|
||||
*/
|
||||
uint32_t rtc_clk_apb_freq_get(void);
|
||||
|
||||
uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles);
|
||||
|
||||
/**
|
||||
* @brief Measure RTC slow clock's period, based on main XTAL frequency
|
||||
*
|
||||
@@ -452,21 +445,21 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles);
|
||||
* the check fails, then consider this an invalid 32k clock and return 0. This
|
||||
* check can filter some jamming signal.
|
||||
*
|
||||
* @param cal_clk clock to be measured
|
||||
* @param cal_clk_sel clock to be measured
|
||||
* @param slow_clk_cycles number of slow clock cycles to average
|
||||
* @return average slow clock period in microseconds, Q13.19 fixed point format,
|
||||
* or 0 if calibration has timed out
|
||||
*/
|
||||
uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slow_clk_cycles);
|
||||
uint32_t rtc_clk_cal(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slow_clk_cycles);
|
||||
|
||||
/**
|
||||
* @brief Measure ratio between XTAL frequency and RTC slow clock frequency
|
||||
* @param cal_clk slow clock to be measured
|
||||
* @param cal_clk_sel slow clock to be measured
|
||||
* @param slow_clk_cycles number of slow clock cycles to average
|
||||
* @return average ratio between XTAL frequency and slow clock frequency,
|
||||
* Q13.19 fixed point format, or 0 if calibration has timed out.
|
||||
*/
|
||||
uint32_t rtc_clk_cal_ratio(rtc_cal_sel_t cal_clk, uint32_t slow_clk_cycles);
|
||||
uint32_t rtc_clk_cal_ratio(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slow_clk_cycles);
|
||||
|
||||
/**
|
||||
* @brief Convert time interval from microseconds to RTC_SLOW_CLK cycles
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -190,16 +190,9 @@ static void calibrate_ocode(void)
|
||||
4. wait o-code calibration done flag(odone_flag & bg_odone_flag) or timeout;
|
||||
5. set cpu to old-config.
|
||||
*/
|
||||
soc_rtc_slow_clk_src_t slow_clk_src = rtc_clk_slow_src_get();
|
||||
rtc_cal_sel_t cal_clk = RTC_CAL_RTC_MUX;
|
||||
if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) {
|
||||
cal_clk = RTC_CAL_32K_XTAL;
|
||||
} else if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256) {
|
||||
cal_clk = RTC_CAL_8MD256;
|
||||
}
|
||||
|
||||
uint64_t max_delay_time_us = 10000;
|
||||
uint32_t slow_clk_period = rtc_clk_cal(cal_clk, 100);
|
||||
uint32_t slow_clk_period = rtc_clk_cal(CLK_CAL_RTC_SLOW, 100);
|
||||
uint64_t max_delay_cycle = rtc_time_us_to_slowclk(max_delay_time_us, slow_clk_period);
|
||||
uint64_t cycle0 = rtc_time_get();
|
||||
uint64_t timeout_cycle = cycle0 + max_delay_cycle;
|
||||
|
||||
@@ -29,37 +29,32 @@
|
||||
|
||||
/**
|
||||
* @brief Clock calibration function used by rtc_clk_cal and rtc_clk_cal_ratio
|
||||
* @param cal_clk which clock to calibrate
|
||||
* @param cal_clk_sel which clock to calibrate
|
||||
* @param slowclk_cycles number of slow clock cycles to count
|
||||
* @return number of XTAL clock cycles within the given number of slow clock cycles
|
||||
*/
|
||||
uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
static uint32_t rtc_clk_cal_internal(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slowclk_cycles)
|
||||
{
|
||||
/* On ESP32C3, choosing RTC_CAL_RTC_MUX results in calibration of
|
||||
* the 150k RTC clock regardless of the currently selected SLOW_CLK.
|
||||
* On the ESP32, it used the currently selected SLOW_CLK.
|
||||
* The following code emulates ESP32 behavior:
|
||||
*/
|
||||
if (cal_clk == RTC_CAL_RTC_MUX) {
|
||||
if (cal_clk_sel == CLK_CAL_RTC_SLOW) {
|
||||
soc_rtc_slow_clk_src_t slow_clk_src = rtc_clk_slow_src_get();
|
||||
if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) {
|
||||
cal_clk = RTC_CAL_32K_XTAL;
|
||||
if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC_SLOW) {
|
||||
cal_clk_sel = CLK_CAL_RC_SLOW;
|
||||
} else if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) {
|
||||
cal_clk_sel = CLK_CAL_32K_XTAL;
|
||||
} else if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256) {
|
||||
cal_clk = RTC_CAL_8MD256;
|
||||
cal_clk_sel = CLK_CAL_RC_FAST_D256;
|
||||
}
|
||||
} else if (cal_clk == RTC_CAL_INTERNAL_OSC) {
|
||||
cal_clk = RTC_CAL_RTC_MUX;
|
||||
}
|
||||
|
||||
/* Enable requested clock (150k clock is always on) */
|
||||
bool dig_32k_xtal_enabled = clk_ll_xtal32k_digi_is_enabled();
|
||||
if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
if (cal_clk_sel == CLK_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
clk_ll_xtal32k_digi_enable();
|
||||
}
|
||||
|
||||
bool rc_fast_enabled = clk_ll_rc_fast_is_enabled();
|
||||
bool rc_fast_d256_enabled = clk_ll_rc_fast_d256_is_enabled();
|
||||
if (cal_clk == RTC_CAL_8MD256) {
|
||||
if (cal_clk_sel == CLK_CAL_RC_FAST_D256) {
|
||||
rtc_clk_8m_enable(true, true);
|
||||
clk_ll_rc_fast_d256_digi_enable();
|
||||
}
|
||||
@@ -77,17 +72,17 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
}
|
||||
|
||||
/* Prepare calibration */
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_CLK_SEL, cal_clk);
|
||||
clk_ll_freq_calulation_set_target(cal_clk_sel);
|
||||
CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING);
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_MAX, slowclk_cycles);
|
||||
/* Figure out how long to wait for calibration to finish */
|
||||
|
||||
/* Set timeout reg and expect time delay*/
|
||||
uint32_t expected_freq;
|
||||
if (cal_clk == RTC_CAL_32K_XTAL) {
|
||||
if (cal_clk_sel == CLK_CAL_32K_XTAL) {
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_SLOW_CLK_X32K_CAL_TIMEOUT_THRES(slowclk_cycles));
|
||||
expected_freq = SOC_CLK_XTAL32K_FREQ_APPROX;
|
||||
} else if (cal_clk == RTC_CAL_8MD256) {
|
||||
} else if (cal_clk_sel == CLK_CAL_RC_FAST_D256) {
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_SLOW_CLK_8MD256_CAL_TIMEOUT_THRES(slowclk_cycles));
|
||||
expected_freq = SOC_CLK_RC_FAST_D256_FREQ_APPROX;
|
||||
} else {
|
||||
@@ -115,11 +110,11 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START);
|
||||
|
||||
/* if dig_32k_xtal was originally off and enabled due to calibration, then set back to off state */
|
||||
if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
if (cal_clk_sel == CLK_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
clk_ll_xtal32k_digi_disable();
|
||||
}
|
||||
|
||||
if (cal_clk == RTC_CAL_8MD256) {
|
||||
if (cal_clk_sel == CLK_CAL_RC_FAST_D256) {
|
||||
clk_ll_rc_fast_d256_digi_disable();
|
||||
rtc_clk_8m_enable(rc_fast_enabled, rc_fast_d256_enabled);
|
||||
}
|
||||
@@ -127,10 +122,10 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
return cal_val;
|
||||
}
|
||||
|
||||
uint32_t rtc_clk_cal_ratio(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
uint32_t rtc_clk_cal_ratio(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slowclk_cycles)
|
||||
{
|
||||
assert(slowclk_cycles);
|
||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk, slowclk_cycles);
|
||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk_sel, slowclk_cycles);
|
||||
uint64_t ratio_64 = ((xtal_cycles << RTC_CLK_CAL_FRACT)) / slowclk_cycles;
|
||||
uint32_t ratio = (uint32_t)(ratio_64 & UINT32_MAX);
|
||||
return ratio;
|
||||
@@ -143,13 +138,13 @@ static bool rtc_clk_cal_32k_valid(uint32_t xtal_freq, uint32_t slowclk_cycles, u
|
||||
return (actual_xtal_cycles >= (expected_xtal_cycles - delta)) && (actual_xtal_cycles <= (expected_xtal_cycles + delta));
|
||||
}
|
||||
|
||||
uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
uint32_t rtc_clk_cal(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slowclk_cycles)
|
||||
{
|
||||
assert(slowclk_cycles);
|
||||
soc_xtal_freq_t xtal_freq = rtc_clk_xtal_freq_get();
|
||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk, slowclk_cycles);
|
||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk_sel, slowclk_cycles);
|
||||
|
||||
if ((cal_clk == RTC_CAL_32K_XTAL) && !rtc_clk_cal_32k_valid((uint32_t)xtal_freq, slowclk_cycles, xtal_cycles)) {
|
||||
if ((cal_clk_sel == CLK_CAL_32K_XTAL) && !rtc_clk_cal_32k_valid((uint32_t)xtal_freq, slowclk_cycles, xtal_cycles)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -114,19 +114,11 @@ typedef struct rtc_cpu_freq_config_s {
|
||||
#define RTC_VDDSDIO_TIEH_1_8V 0 //!< TIEH field value for 1.8V VDDSDIO
|
||||
#define RTC_VDDSDIO_TIEH_3_3V 1 //!< TIEH field value for 3.3V VDDSDIO
|
||||
|
||||
/**
|
||||
* @brief Clock source to be calibrated using rtc_clk_cal function
|
||||
*
|
||||
* @note On ESP32C5, the enum values somehow reflects the register field values of PCR_32K_SEL.
|
||||
*/
|
||||
typedef enum {
|
||||
RTC_CAL_RTC_MUX = -1, //!< Currently selected RTC_SLOW_CLK
|
||||
RTC_CAL_32K_XTAL = 1, //!< External 32kHz XTAL, as one type of 32k clock
|
||||
RTC_CAL_32K_OSC_SLOW = 2, //!< External slow clock signal input by lp_pad_gpio0, as one type of 32k clock
|
||||
RTC_CAL_RC_SLOW = 3, //!< Internal 150kHz RC oscillator
|
||||
RTC_CAL_RC_FAST = 4, //!< Internal 20MHz RC oscillator
|
||||
RTC_CAL_INVALID_CLK, //!< Clock not available to calibrate
|
||||
} rtc_cal_sel_t;
|
||||
#define RTC_CAL_RTC_MUX _Pragma ("GCC warning \"'RTC_CAL_RTC_MUX' macro is deprecated\"") CLK_CAL_RTC_SLOW
|
||||
#define RTC_CAL_32K_XTAL _Pragma ("GCC warning \"'RTC_CAL_32K_XTAL' macro is deprecated\"") CLK_CAL_32K_XTAL
|
||||
#define RTC_CAL_32K_OSC_SLOW _Pragma ("GCC warning \"'RTC_CAL_32K_OSC_SLOW' macro is deprecated\"") CLK_CAL_32K_OSC_SLOW
|
||||
#define RTC_CAL_RC_SLOW _Pragma ("GCC warning \"'RTC_CAL_RC_SLOW' macro is deprecated\"") CLK_CAL_RC_SLOW
|
||||
#define RTC_CAL_RC_FAST _Pragma ("GCC warning \"'RTC_CAL_RC_FAST' macro is deprecated\"") CLK_CAL_RC_FAST
|
||||
|
||||
/**
|
||||
* Initialization parameters for rtc_clk_init
|
||||
@@ -352,12 +344,12 @@ uint32_t rtc_clk_apb_freq_get(void);
|
||||
* the check fails, then consider this an invalid 32k clock and return 0. This
|
||||
* check can filter some jamming signal.
|
||||
*
|
||||
* @param cal_clk clock to be measured
|
||||
* @param cal_clk_sel clock to be measured
|
||||
* @param slow_clk_cycles number of slow clock cycles to average
|
||||
* @return average slow clock period in microseconds, Q13.19 fixed point format,
|
||||
* or 0 if calibration has timed out
|
||||
*/
|
||||
uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slow_clk_cycles);
|
||||
uint32_t rtc_clk_cal(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slow_clk_cycles);
|
||||
|
||||
/**
|
||||
* @brief Convert time interval from microseconds to RTC_SLOW_CLK cycles
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -38,16 +38,9 @@ static void IRAM_ATTR NOINLINE_ATTR calibrate_ocode(void)
|
||||
4. wait o-code calibration done flag(odone_flag & bg_odone_flag) or timeout;
|
||||
5. set cpu to old-config.
|
||||
*/
|
||||
soc_rtc_slow_clk_src_t slow_clk_src = rtc_clk_slow_src_get();
|
||||
rtc_cal_sel_t cal_clk = RTC_CAL_RTC_MUX;
|
||||
if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_OSC_SLOW) {
|
||||
cal_clk = RTC_CAL_32K_OSC_SLOW;
|
||||
} else if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) {
|
||||
cal_clk = RTC_CAL_32K_XTAL;
|
||||
}
|
||||
|
||||
uint64_t max_delay_time_us = 10000;
|
||||
uint32_t slow_clk_period = rtc_clk_cal(cal_clk, 100);
|
||||
uint32_t slow_clk_period = rtc_clk_cal(CLK_CAL_RTC_SLOW, 100);
|
||||
uint64_t max_delay_cycle = rtc_time_us_to_slowclk(max_delay_time_us, slow_clk_period);
|
||||
uint64_t cycle0 = rtc_time_get();
|
||||
uint64_t timeout_cycle = cycle0 + max_delay_cycle;
|
||||
|
||||
@@ -19,44 +19,46 @@
|
||||
|
||||
__attribute__((unused)) static const char *TAG = "rtc_time";
|
||||
|
||||
/* Calibration of RTC_SLOW_CLK is performed using a special feature of TIMG0.
|
||||
#define CLK_CAL_TIMEOUT_THRES(cal_clk_sel, cycles) ((cal_clk_sel == CLK_CAL_32K_XTAL || cal_clk_sel == CLK_CAL_32K_OSC_SLOW) ? (cycles << 12) : (cycles << 10))
|
||||
|
||||
/**
|
||||
* @brief Clock frequency calculation function used by rtc_clk_cal
|
||||
*
|
||||
* Calculation of clock frequency is performed using a special feature of TIMG0.
|
||||
* This feature counts the number of XTAL clock cycles within a given number of
|
||||
* RTC_SLOW_CLK cycles.
|
||||
* clock cycles.
|
||||
*
|
||||
* @param cal_clk_sel which clock to calculate frequency
|
||||
* @param slowclk_cycles number of slow clock cycles to count
|
||||
* @return number of XTAL clock cycles within the given number of slow clock cycles
|
||||
*/
|
||||
|
||||
#define CLK_CAL_TIMEOUT_THRES(cal_clk, cycles) ((cal_clk == RTC_CAL_32K_XTAL || cal_clk == RTC_CAL_32K_OSC_SLOW) ? (cycles << 12) : (cycles << 10))
|
||||
|
||||
static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
static uint32_t rtc_clk_cal_internal(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slowclk_cycles)
|
||||
{
|
||||
assert(slowclk_cycles < TIMG_RTC_CALI_MAX_V);
|
||||
|
||||
if (cal_clk == RTC_CAL_RTC_MUX) {
|
||||
if (cal_clk_sel == CLK_CAL_RTC_SLOW) {
|
||||
soc_rtc_slow_clk_src_t slow_clk_src = rtc_clk_slow_src_get();
|
||||
if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC_SLOW) {
|
||||
cal_clk = RTC_CAL_RC_SLOW;
|
||||
cal_clk_sel = CLK_CAL_RC_SLOW;
|
||||
} else if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) {
|
||||
cal_clk = RTC_CAL_32K_XTAL;
|
||||
cal_clk_sel = CLK_CAL_32K_XTAL;
|
||||
} else if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_OSC_SLOW) {
|
||||
cal_clk = RTC_CAL_32K_OSC_SLOW;
|
||||
cal_clk_sel = CLK_CAL_32K_OSC_SLOW;
|
||||
}
|
||||
}
|
||||
if (cal_clk < 0 || cal_clk >= RTC_CAL_INVALID_CLK) {
|
||||
ESP_EARLY_LOGE(TAG, "clock not supported to be calibrated");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Enable requested clock (150k clock is always on) */
|
||||
// All clocks on/off takes time to be stable, so we shouldn't frequently enable/disable the clock
|
||||
// Only enable if originally was disabled, and set back to the disable state after calibration is done
|
||||
// If the clock is already on, then do nothing
|
||||
bool dig_32k_xtal_enabled = clk_ll_xtal32k_digi_is_enabled();
|
||||
if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
clk_ll_xtal32k_digi_enable();
|
||||
if (cal_clk_sel == CLK_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
clk_ll_xtal32k_digi_enable();
|
||||
}
|
||||
|
||||
bool rc_fast_enabled = clk_ll_rc_fast_is_enabled();
|
||||
bool dig_rc_fast_enabled = clk_ll_rc_fast_digi_is_enabled();
|
||||
if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
if (cal_clk_sel == CLK_CAL_RC_FAST) {
|
||||
if (!rc_fast_enabled) {
|
||||
rtc_clk_8m_enable(true);
|
||||
}
|
||||
@@ -79,8 +81,8 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
|
||||
}
|
||||
|
||||
/* Prepare calibration */
|
||||
REG_SET_FIELD(PCR_CTRL_32K_CONF_REG, PCR_32K_SEL, cal_clk);
|
||||
if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
clk_ll_freq_calulation_set_target(cal_clk_sel);
|
||||
if (cal_clk_sel == CLK_CAL_RC_FAST) {
|
||||
clk_ll_rc_fast_tick_conf();
|
||||
}
|
||||
CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING);
|
||||
@@ -88,11 +90,11 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
|
||||
/* Figure out how long to wait for calibration to finish */
|
||||
|
||||
/* Set timeout reg and expect time delay*/
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, CLK_CAL_TIMEOUT_THRES(cal_clk, slowclk_cycles));
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, CLK_CAL_TIMEOUT_THRES(cal_clk_sel, slowclk_cycles));
|
||||
uint32_t expected_freq;
|
||||
if (cal_clk == RTC_CAL_32K_XTAL || cal_clk == RTC_CAL_32K_OSC_SLOW) {
|
||||
if (cal_clk_sel == CLK_CAL_32K_XTAL || cal_clk_sel == CLK_CAL_32K_OSC_SLOW) {
|
||||
expected_freq = SOC_CLK_XTAL32K_FREQ_APPROX;
|
||||
} else if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
} else if (cal_clk_sel == CLK_CAL_RC_FAST) {
|
||||
expected_freq = SOC_CLK_RC_FAST_FREQ_APPROX >> CLK_LL_RC_FAST_CALIB_TICK_DIV_BITS;
|
||||
} else {
|
||||
expected_freq = SOC_CLK_RC_SLOW_FREQ_APPROX;
|
||||
@@ -111,7 +113,7 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
|
||||
|
||||
/*The Fosc CLK of calibration circuit is divided by a factor, k.
|
||||
So we need to multiply the frequency of the FOSC by k times.*/
|
||||
if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
if (cal_clk_sel == CLK_CAL_RC_FAST) {
|
||||
cal_val = cal_val >> CLK_LL_RC_FAST_CALIB_TICK_DIV_BITS;
|
||||
}
|
||||
break;
|
||||
@@ -125,11 +127,11 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
|
||||
|
||||
clk_ll_enable_timergroup_rtc_calibration_clock(false);
|
||||
/* if dig_32k_xtal was originally off and enabled due to calibration, then set back to off state */
|
||||
if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
if (cal_clk_sel == CLK_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
clk_ll_xtal32k_digi_disable();
|
||||
}
|
||||
|
||||
if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
if (cal_clk_sel == CLK_CAL_RC_FAST) {
|
||||
if (!dig_rc_fast_enabled) {
|
||||
rtc_dig_clk8m_disable();
|
||||
}
|
||||
@@ -148,19 +150,19 @@ static bool rtc_clk_cal_32k_valid(uint32_t xtal_freq, uint32_t slowclk_cycles, u
|
||||
return (actual_xtal_cycles >= (expected_xtal_cycles - delta)) && (actual_xtal_cycles <= (expected_xtal_cycles + delta));
|
||||
}
|
||||
|
||||
uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
uint32_t rtc_clk_cal(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slowclk_cycles)
|
||||
{
|
||||
/*The Fosc CLK of calibration circuit is divided by a factor, k.
|
||||
So we need to divide the calibrate cycles of the FOSC by k to
|
||||
avoid excessive calibration time.*/
|
||||
if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
if (cal_clk_sel == CLK_CAL_RC_FAST) {
|
||||
slowclk_cycles = slowclk_cycles >> CLK_LL_RC_FAST_CALIB_TICK_DIV_BITS;
|
||||
}
|
||||
assert(slowclk_cycles);
|
||||
|
||||
soc_xtal_freq_t xtal_freq = rtc_clk_xtal_freq_get();
|
||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk, slowclk_cycles);
|
||||
if (cal_clk == RTC_CAL_32K_XTAL && !rtc_clk_cal_32k_valid((uint32_t)xtal_freq, slowclk_cycles, xtal_cycles)) {
|
||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk_sel, slowclk_cycles);
|
||||
if (cal_clk_sel == CLK_CAL_32K_XTAL && !rtc_clk_cal_32k_valid((uint32_t)xtal_freq, slowclk_cycles, xtal_cycles)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,24 +12,13 @@ choice RTC_CLK_SRC
|
||||
config RTC_CLK_SRC_EXT_OSC
|
||||
bool "External 32 kHz oscillator at 32K_XP pin"
|
||||
select ESP_SYSTEM_RTC_EXT_OSC
|
||||
config RTC_CLK_SRC_INT_RC32K
|
||||
bool "Internal 32 kHz RC oscillator (NOT RECOMMENDED TO USE, READ DOCS FIRST)"
|
||||
depends on RTC_CLK_SRC_USE_DANGEROUS_RC32K_ALLOWED
|
||||
help
|
||||
To be able to select this option, please select `RTC_CLK_SRC_USE_DANGEROUS_RC32K_ALLOWED` first.
|
||||
This option will be removed in IDF v6.0.
|
||||
endchoice
|
||||
|
||||
config RTC_CLK_SRC_USE_DANGEROUS_RC32K_ALLOWED
|
||||
bool "Confirm to use the unrecommended 32 kHz RC oscillator (READ DOCS FIRST)"
|
||||
help
|
||||
Internal RC32K clock is unstable at extreme temperatures and is not recommended for use.
|
||||
|
||||
config RTC_CLK_CAL_CYCLES
|
||||
int "Number of cycles for RTC_SLOW_CLK calibration"
|
||||
default 3000 if RTC_CLK_SRC_EXT_CRYS || RTC_CLK_SRC_EXT_OSC || RTC_CLK_SRC_INT_RC32K
|
||||
default 3000 if RTC_CLK_SRC_EXT_CRYS || RTC_CLK_SRC_EXT_OSC
|
||||
default 1024 if RTC_CLK_SRC_INT_RC
|
||||
range 0 8190 if RTC_CLK_SRC_EXT_CRYS || RTC_CLK_SRC_EXT_OSC || RTC_CLK_SRC_INT_RC32K
|
||||
range 0 8190 if RTC_CLK_SRC_EXT_CRYS || RTC_CLK_SRC_EXT_OSC
|
||||
range 0 32766 if RTC_CLK_SRC_INT_RC
|
||||
help
|
||||
When the startup code initializes RTC_SLOW_CLK, it can perform
|
||||
|
||||
@@ -120,22 +120,12 @@ typedef struct rtc_cpu_freq_config_s {
|
||||
#define RTC_VDDSDIO_TIEH_1_8V 0 //!< TIEH field value for 1.8V VDDSDIO
|
||||
#define RTC_VDDSDIO_TIEH_3_3V 1 //!< TIEH field value for 3.3V VDDSDIO
|
||||
|
||||
|
||||
/**
|
||||
* @brief Clock source to be calibrated using rtc_clk_cal function
|
||||
*
|
||||
* @note On previous targets, the enum values somehow reflects the register field values of TIMG_RTC_CALI_CLK_SEL
|
||||
* However, this is not true on ESP32C6. The conversion to register field values is explicitly done in
|
||||
* rtc_clk_cal_internal
|
||||
*/
|
||||
typedef enum {
|
||||
RTC_CAL_RTC_MUX = -1, //!< Currently selected RTC_SLOW_CLK
|
||||
RTC_CAL_RC_SLOW = SOC_RTC_SLOW_CLK_SRC_RC_SLOW, //!< Internal 150kHz RC oscillator
|
||||
RTC_CAL_RC32K = SOC_RTC_SLOW_CLK_SRC_RC32K, //!< Internal 32kHz RC oscillator, as one type of 32k clock
|
||||
RTC_CAL_32K_XTAL = SOC_RTC_SLOW_CLK_SRC_XTAL32K, //!< External 32kHz XTAL, as one type of 32k clock
|
||||
RTC_CAL_32K_OSC_SLOW = SOC_RTC_SLOW_CLK_SRC_OSC_SLOW, //!< External slow clock signal input by lp_pad_gpio0, as one type of 32k clock
|
||||
RTC_CAL_RC_FAST //!< Internal 20MHz RC oscillator
|
||||
} rtc_cal_sel_t;
|
||||
#define RTC_CAL_RTC_MUX _Pragma ("GCC warning \"'RTC_CAL_RTC_MUX' macro is deprecated\"") CLK_CAL_RTC_SLOW
|
||||
#define RTC_CAL_RC_SLOW _Pragma ("GCC warning \"'RTC_CAL_RC_SLOW' macro is deprecated\"") CLK_CAL_RC_SLOW
|
||||
#define RTC_CAL_RC32K _Pragma ("GCC warning \"'RTC_CAL_RC32K' macro is deprecated\"") CLK_CAL_RC32K
|
||||
#define RTC_CAL_32K_XTAL _Pragma ("GCC warning \"'RTC_CAL_32K_XTAL' macro is deprecated\"") CLK_CAL_32K_XTAL
|
||||
#define RTC_CAL_32K_OSC_SLOW _Pragma ("GCC warning \"'RTC_CAL_32K_OSC_SLOW' macro is deprecated\"") CLK_CAL_32K_OSC_SLOW
|
||||
#define RTC_CAL_RC_FAST _Pragma ("GCC warning \"'RTC_CAL_RC_FAST' macro is deprecated\"") CLK_CAL_RC_FAST
|
||||
|
||||
/**
|
||||
* Initialization parameters for rtc_clk_init
|
||||
@@ -381,12 +371,12 @@ uint32_t rtc_clk_apb_freq_get(void);
|
||||
* the check fails, then consider this an invalid 32k clock and return 0. This
|
||||
* check can filter some jamming signal.
|
||||
*
|
||||
* @param cal_clk clock to be measured
|
||||
* @param cal_clk_sel clock to be measured
|
||||
* @param slow_clk_cycles number of slow clock cycles to average
|
||||
* @return average slow clock period in microseconds, Q13.19 fixed point format,
|
||||
* or 0 if calibration has timed out
|
||||
*/
|
||||
uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slow_clk_cycles);
|
||||
uint32_t rtc_clk_cal(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slow_clk_cycles);
|
||||
|
||||
/**
|
||||
* @brief Convert time interval from microseconds to RTC_SLOW_CLK cycles
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -37,16 +37,9 @@ static void calibrate_ocode(void)
|
||||
4. wait o-code calibration done flag(odone_flag & bg_odone_flag) or timeout;
|
||||
5. set cpu to old-config.
|
||||
*/
|
||||
soc_rtc_slow_clk_src_t slow_clk_src = rtc_clk_slow_src_get();
|
||||
rtc_cal_sel_t cal_clk = RTC_CAL_RTC_MUX;
|
||||
if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_OSC_SLOW) {
|
||||
cal_clk = RTC_CAL_32K_OSC_SLOW;
|
||||
} else if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) {
|
||||
cal_clk = RTC_CAL_32K_XTAL;
|
||||
}
|
||||
|
||||
uint64_t max_delay_time_us = 10000;
|
||||
uint32_t slow_clk_period = rtc_clk_cal(cal_clk, 100);
|
||||
uint32_t slow_clk_period = rtc_clk_cal(CLK_CAL_RTC_SLOW, 100);
|
||||
uint64_t max_delay_cycle = rtc_time_us_to_slowclk(max_delay_time_us, slow_clk_period);
|
||||
uint64_t cycle0 = rtc_time_get();
|
||||
uint64_t timeout_cycle = cycle0 + max_delay_cycle;
|
||||
|
||||
@@ -20,31 +20,10 @@
|
||||
|
||||
__attribute__((unused)) static const char *TAG = "rtc_time";
|
||||
|
||||
/* Calibration of RTC_SLOW_CLK is performed using a special feature of TIMG0.
|
||||
* This feature counts the number of XTAL clock cycles within a given number of
|
||||
* RTC_SLOW_CLK cycles.
|
||||
*
|
||||
* Slow clock calibration feature has two modes of operation: one-off and cycling.
|
||||
* In cycling mode (which is enabled by default on SoC reset), counting of XTAL
|
||||
* cycles within RTC_SLOW_CLK cycle is done continuously. Cycling mode is enabled
|
||||
* using TIMG_RTC_CALI_START_CYCLING bit. In one-off mode counting is performed
|
||||
* once, and TIMG_RTC_CALI_RDY bit is set when counting is done. One-off mode is
|
||||
* enabled using TIMG_RTC_CALI_START bit.
|
||||
*/
|
||||
|
||||
/* On ESP32C6, TIMG_RTC_CALI_CLK_SEL can config to 0, 1, 2, 3
|
||||
* 0 or 3: calibrate RC_SLOW clock
|
||||
* 1: calibrate RC_FAST clock
|
||||
* 2: calibrate 32K clock, which 32k depends on reg_32k_sel: 0: Internal 32 kHz RC oscillator, 1: External 32 kHz XTAL, 2: External 32kHz clock input by lp_pad_gpio0
|
||||
*/
|
||||
#define TIMG_RTC_CALI_CLK_SEL_RC_SLOW 0
|
||||
#define TIMG_RTC_CALI_CLK_SEL_RC_FAST 1
|
||||
#define TIMG_RTC_CALI_CLK_SEL_32K 2
|
||||
|
||||
/**
|
||||
* @brief Clock calibration function used by rtc_clk_cal
|
||||
* @brief Clock frequency calculation function used by rtc_clk_cal
|
||||
*
|
||||
* Calibration of RTC_SLOW_CLK is performed using a special feature of TIMG0.
|
||||
* Calculation of RTC_SLOW_CLK is performed using a special feature of TIMG0.
|
||||
* This feature counts the number of XTAL clock cycles within a given number of
|
||||
* RTC_SLOW_CLK cycles.
|
||||
*
|
||||
@@ -55,42 +34,39 @@ __attribute__((unused)) static const char *TAG = "rtc_time";
|
||||
* once, and TIMG_RTC_CALI_RDY bit is set when counting is done. One-off mode is
|
||||
* enabled using TIMG_RTC_CALI_START bit.
|
||||
*
|
||||
* @param cal_clk which clock to calibrate
|
||||
* @param cal_clk_sel which clock to calculate frequency
|
||||
* @param slowclk_cycles number of slow clock cycles to count
|
||||
* @return number of XTAL clock cycles within the given number of slow clock cycles
|
||||
*/
|
||||
static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
static uint32_t rtc_clk_cal_internal(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slowclk_cycles)
|
||||
{
|
||||
assert(slowclk_cycles < TIMG_RTC_CALI_MAX_V);
|
||||
|
||||
uint32_t cali_clk_sel = 0;
|
||||
soc_rtc_slow_clk_src_t slow_clk_src = rtc_clk_slow_src_get();
|
||||
soc_rtc_slow_clk_src_t old_32k_cal_clk_sel = clk_ll_32k_calibration_get_target();
|
||||
if (cal_clk == RTC_CAL_RTC_MUX) {
|
||||
cal_clk = (rtc_cal_sel_t)slow_clk_src;
|
||||
if (cal_clk_sel == CLK_CAL_RTC_SLOW) {
|
||||
soc_rtc_slow_clk_src_t slow_clk_src = rtc_clk_slow_src_get();
|
||||
if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC_SLOW) {
|
||||
cal_clk_sel = CLK_CAL_RC_SLOW;
|
||||
} else if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_OSC_SLOW) {
|
||||
cal_clk_sel = CLK_CAL_32K_OSC_SLOW;
|
||||
} else if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) {
|
||||
cal_clk_sel = CLK_CAL_32K_XTAL;
|
||||
} else if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC32K) {
|
||||
cal_clk_sel = CLK_CAL_RC32K;
|
||||
}
|
||||
}
|
||||
if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
cali_clk_sel = TIMG_RTC_CALI_CLK_SEL_RC_FAST;
|
||||
} else if (cal_clk == RTC_CAL_RC_SLOW) {
|
||||
cali_clk_sel = TIMG_RTC_CALI_CLK_SEL_RC_SLOW;
|
||||
} else {
|
||||
cali_clk_sel = TIMG_RTC_CALI_CLK_SEL_32K;
|
||||
clk_ll_32k_calibration_set_target((soc_rtc_slow_clk_src_t)cal_clk);
|
||||
}
|
||||
|
||||
|
||||
/* Enable requested clock (150k clock is always on) */
|
||||
// All clocks on/off takes time to be stable, so we shouldn't frequently enable/disable the clock
|
||||
// Only enable if originally was disabled, and set back to the disable state after calibration is done
|
||||
// If the clock is already on, then do nothing
|
||||
bool dig_32k_xtal_enabled = clk_ll_xtal32k_digi_is_enabled();
|
||||
if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
clk_ll_xtal32k_digi_enable();
|
||||
if (cal_clk_sel == CLK_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
clk_ll_xtal32k_digi_enable();
|
||||
}
|
||||
|
||||
bool rc_fast_enabled = clk_ll_rc_fast_is_enabled();
|
||||
bool dig_rc_fast_enabled = clk_ll_rc_fast_digi_is_enabled();
|
||||
if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
if (cal_clk_sel == CLK_CAL_RC_FAST) {
|
||||
if (!rc_fast_enabled) {
|
||||
rtc_clk_8m_enable(true);
|
||||
}
|
||||
@@ -101,7 +77,7 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
|
||||
|
||||
bool rc32k_enabled = clk_ll_rc32k_is_enabled();
|
||||
bool dig_rc32k_enabled = clk_ll_rc32k_digi_is_enabled();
|
||||
if (cal_clk == RTC_CAL_RC32K) {
|
||||
if (cal_clk_sel == CLK_CAL_RC32K) {
|
||||
if (!rc32k_enabled) {
|
||||
rtc_clk_rc32k_enable(true);
|
||||
}
|
||||
@@ -124,8 +100,8 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
|
||||
}
|
||||
|
||||
/* Prepare calibration */
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_CLK_SEL, cali_clk_sel);
|
||||
if (cali_clk_sel == TIMG_RTC_CALI_CLK_SEL_RC_FAST) {
|
||||
clk_ll_freq_calulation_set_target(cal_clk_sel);
|
||||
if (cal_clk_sel == CLK_CAL_RC_FAST) {
|
||||
clk_ll_rc_fast_tick_conf();
|
||||
}
|
||||
CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING);
|
||||
@@ -134,10 +110,10 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
|
||||
|
||||
/* Set timeout reg and expect time delay*/
|
||||
uint32_t expected_freq;
|
||||
if (cali_clk_sel == TIMG_RTC_CALI_CLK_SEL_32K) {
|
||||
if (cal_clk_sel == CLK_CAL_32K_XTAL || cal_clk_sel == CLK_CAL_32K_OSC_SLOW || cal_clk_sel == CLK_CAL_RC32K) {
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_SLOW_CLK_32K_CAL_TIMEOUT_THRES(slowclk_cycles));
|
||||
expected_freq = SOC_CLK_XTAL32K_FREQ_APPROX;
|
||||
} else if (cali_clk_sel == TIMG_RTC_CALI_CLK_SEL_RC_FAST) {
|
||||
} else if (cal_clk_sel == CLK_CAL_RC_FAST) {
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_FAST_CLK_20M_CAL_TIMEOUT_THRES(slowclk_cycles));
|
||||
expected_freq = SOC_CLK_RC_FAST_FREQ_APPROX;
|
||||
if (ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 1)) {
|
||||
@@ -165,7 +141,7 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
|
||||
And the 32-divider belongs to REF_TICK module, so we need to enable its clock during
|
||||
calibration. */
|
||||
if (ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 1)) {
|
||||
if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
if (cal_clk_sel == CLK_CAL_RC_FAST) {
|
||||
cal_val = cal_val >> CLK_LL_RC_FAST_CALIB_TICK_DIV_BITS;
|
||||
CLEAR_PERI_REG_MASK(PCR_CTRL_TICK_CONF_REG, PCR_TICK_ENABLE);
|
||||
}
|
||||
@@ -180,11 +156,11 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
|
||||
CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START);
|
||||
|
||||
/* if dig_32k_xtal was originally off and enabled due to calibration, then set back to off state */
|
||||
if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
if (cal_clk_sel == CLK_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
clk_ll_xtal32k_digi_disable();
|
||||
}
|
||||
|
||||
if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
if (cal_clk_sel == CLK_CAL_RC_FAST) {
|
||||
if (!dig_rc_fast_enabled) {
|
||||
rtc_dig_clk8m_disable();
|
||||
}
|
||||
@@ -193,7 +169,7 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
|
||||
}
|
||||
}
|
||||
|
||||
if (cal_clk == RTC_CAL_RC32K) {
|
||||
if (cal_clk_sel == CLK_CAL_RC32K) {
|
||||
if (!dig_rc32k_enabled) {
|
||||
clk_ll_rc32k_digi_disable();
|
||||
}
|
||||
@@ -202,11 +178,6 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
|
||||
}
|
||||
}
|
||||
|
||||
// Always set back the calibration 32kHz clock selection
|
||||
if (old_32k_cal_clk_sel != SOC_RTC_SLOW_CLK_SRC_INVALID) {
|
||||
clk_ll_32k_calibration_set_target(old_32k_cal_clk_sel);
|
||||
}
|
||||
|
||||
return cal_val;
|
||||
}
|
||||
|
||||
@@ -217,7 +188,7 @@ static bool rtc_clk_cal_32k_valid(uint32_t xtal_freq, uint32_t slowclk_cycles, u
|
||||
return (actual_xtal_cycles >= (expected_xtal_cycles - delta)) && (actual_xtal_cycles <= (expected_xtal_cycles + delta));
|
||||
}
|
||||
|
||||
uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
uint32_t rtc_clk_cal(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slowclk_cycles)
|
||||
{
|
||||
assert(slowclk_cycles);
|
||||
soc_xtal_freq_t xtal_freq = rtc_clk_xtal_freq_get();
|
||||
@@ -226,15 +197,15 @@ uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
So we need to divide the calibrate cycles of the FOSC for ECO1 and above chips by 32 to
|
||||
avoid excessive calibration time.*/
|
||||
if (ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 1)) {
|
||||
if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
if (cal_clk_sel == CLK_CAL_RC_FAST) {
|
||||
slowclk_cycles = slowclk_cycles >> CLK_LL_RC_FAST_CALIB_TICK_DIV_BITS;
|
||||
SET_PERI_REG_MASK(PCR_CTRL_TICK_CONF_REG, PCR_TICK_ENABLE);
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk, slowclk_cycles);
|
||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk_sel, slowclk_cycles);
|
||||
|
||||
if (cal_clk == RTC_CAL_32K_XTAL && !rtc_clk_cal_32k_valid((uint32_t)xtal_freq, slowclk_cycles, xtal_cycles)) {
|
||||
if (cal_clk_sel == CLK_CAL_32K_XTAL && !rtc_clk_cal_32k_valid((uint32_t)xtal_freq, slowclk_cycles, xtal_cycles)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -114,19 +114,11 @@ typedef struct rtc_cpu_freq_config_s {
|
||||
#define RTC_VDDSDIO_TIEH_1_8V 0 //!< TIEH field value for 1.8V VDDSDIO
|
||||
#define RTC_VDDSDIO_TIEH_3_3V 1 //!< TIEH field value for 3.3V VDDSDIO
|
||||
|
||||
/**
|
||||
* @brief Clock source to be calibrated using rtc_clk_cal function
|
||||
*
|
||||
* @note On ESP32C61, the enum values somehow reflects the register field values of PCR_32K_SEL.
|
||||
*/
|
||||
typedef enum {
|
||||
RTC_CAL_RTC_MUX = -1, //!< Currently selected RTC_SLOW_CLK
|
||||
RTC_CAL_32K_XTAL = 1, //!< External 32kHz XTAL, as one type of 32k clock
|
||||
RTC_CAL_32K_OSC_SLOW = 2, //!< External slow clock signal input by lp_pad_gpio0, as one type of 32k clock
|
||||
RTC_CAL_RC_SLOW = 3, //!< Internal 150kHz RC oscillator
|
||||
RTC_CAL_RC_FAST = 4, //!< Internal 20MHz RC oscillator
|
||||
RTC_CAL_INVALID_CLK, //!< Clock not available to calibrate
|
||||
} rtc_cal_sel_t;
|
||||
#define RTC_CAL_RTC_MUX _Pragma ("GCC warning \"'RTC_CAL_RTC_MUX' macro is deprecated\"") CLK_CAL_RTC_SLOW
|
||||
#define RTC_CAL_32K_XTAL _Pragma ("GCC warning \"'RTC_CAL_32K_XTAL' macro is deprecated\"") CLK_CAL_32K_XTAL
|
||||
#define RTC_CAL_32K_OSC_SLOW _Pragma ("GCC warning \"'RTC_CAL_32K_OSC_SLOW' macro is deprecated\"") CLK_CAL_32K_OSC_SLOW
|
||||
#define RTC_CAL_RC_SLOW _Pragma ("GCC warning \"'RTC_CAL_RC_SLOW' macro is deprecated\"") CLK_CAL_RC_SLOW
|
||||
#define RTC_CAL_RC_FAST _Pragma ("GCC warning \"'RTC_CAL_RC_FAST' macro is deprecated\"") CLK_CAL_RC_FAST
|
||||
|
||||
/**
|
||||
* Initialization parameters for rtc_clk_init
|
||||
@@ -350,12 +342,12 @@ uint32_t rtc_clk_apb_freq_get(void);
|
||||
* the check fails, then consider this an invalid 32k clock and return 0. This
|
||||
* check can filter some jamming signal.
|
||||
*
|
||||
* @param cal_clk clock to be measured
|
||||
* @param cal_clk_sel clock to be measured
|
||||
* @param slow_clk_cycles number of slow clock cycles to average
|
||||
* @return average slow clock period in microseconds, Q13.19 fixed point format,
|
||||
* or 0 if calibration has timed out
|
||||
*/
|
||||
uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slow_clk_cycles);
|
||||
uint32_t rtc_clk_cal(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slow_clk_cycles);
|
||||
|
||||
/**
|
||||
* @brief Convert time interval from microseconds to RTC_SLOW_CLK cycles
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -37,16 +37,9 @@ static void IRAM_ATTR NOINLINE_ATTR calibrate_ocode(void)
|
||||
4. wait o-code calibration done flag(odone_flag & bg_odone_flag) or timeout;
|
||||
5. set cpu to old-config.
|
||||
*/
|
||||
soc_rtc_slow_clk_src_t slow_clk_src = rtc_clk_slow_src_get();
|
||||
rtc_cal_sel_t cal_clk = RTC_CAL_RTC_MUX;
|
||||
if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_OSC_SLOW) {
|
||||
cal_clk = RTC_CAL_32K_OSC_SLOW;
|
||||
} else if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) {
|
||||
cal_clk = RTC_CAL_32K_XTAL;
|
||||
}
|
||||
|
||||
uint64_t max_delay_time_us = 10000;
|
||||
uint32_t slow_clk_period = rtc_clk_cal(cal_clk, 100);
|
||||
uint32_t slow_clk_period = rtc_clk_cal(CLK_CAL_RTC_SLOW, 100);
|
||||
uint64_t max_delay_cycle = rtc_time_us_to_slowclk(max_delay_time_us, slow_clk_period);
|
||||
uint64_t cycle0 = rtc_time_get();
|
||||
uint64_t timeout_cycle = cycle0 + max_delay_cycle;
|
||||
|
||||
@@ -18,44 +18,46 @@
|
||||
|
||||
__attribute__((unused)) static const char *TAG = "rtc_time";
|
||||
|
||||
/* Calibration of RTC_SLOW_CLK is performed using a special feature of TIMG0.
|
||||
#define CLK_CAL_TIMEOUT_THRES(cal_clk_sel, cycles) ((cal_clk_sel == CLK_CAL_32K_XTAL || cal_clk_sel == CLK_CAL_32K_OSC_SLOW) ? (cycles << 12) : (cycles << 10))
|
||||
|
||||
/**
|
||||
* @brief Clock frequency calculation function used by rtc_clk_cal
|
||||
*
|
||||
* Calculation of clock frequency is performed using a special feature of TIMG0.
|
||||
* This feature counts the number of XTAL clock cycles within a given number of
|
||||
* RTC_SLOW_CLK cycles.
|
||||
* clock cycles.
|
||||
*
|
||||
* @param cal_clk_sel which clock to calculate frequency
|
||||
* @param slowclk_cycles number of slow clock cycles to count
|
||||
* @return number of XTAL clock cycles within the given number of slow clock cycles
|
||||
*/
|
||||
|
||||
#define CLK_CAL_TIMEOUT_THRES(cal_clk, cycles) ((cal_clk == RTC_CAL_32K_XTAL || cal_clk == RTC_CAL_32K_OSC_SLOW) ? (cycles << 12) : (cycles << 10))
|
||||
|
||||
static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
static uint32_t rtc_clk_cal_internal(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slowclk_cycles)
|
||||
{
|
||||
assert(slowclk_cycles < TIMG_RTC_CALI_MAX_V);
|
||||
|
||||
if (cal_clk == RTC_CAL_RTC_MUX) {
|
||||
if (cal_clk_sel == CLK_CAL_RTC_SLOW) {
|
||||
soc_rtc_slow_clk_src_t slow_clk_src = rtc_clk_slow_src_get();
|
||||
if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC_SLOW) {
|
||||
cal_clk = RTC_CAL_RC_SLOW;
|
||||
cal_clk_sel = CLK_CAL_RC_SLOW;
|
||||
} else if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) {
|
||||
cal_clk = RTC_CAL_32K_XTAL;
|
||||
cal_clk_sel = CLK_CAL_32K_XTAL;
|
||||
} else if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_OSC_SLOW) {
|
||||
cal_clk = RTC_CAL_32K_OSC_SLOW;
|
||||
cal_clk_sel = CLK_CAL_32K_OSC_SLOW;
|
||||
}
|
||||
}
|
||||
if (cal_clk < 0 || cal_clk >= RTC_CAL_INVALID_CLK) {
|
||||
ESP_EARLY_LOGE(TAG, "clock not supported to be calibrated");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Enable requested clock (150k clock is always on) */
|
||||
// All clocks on/off takes time to be stable, so we shouldn't frequently enable/disable the clock
|
||||
// Only enable if originally was disabled, and set back to the disable state after calibration is done
|
||||
// If the clock is already on, then do nothing
|
||||
bool dig_32k_xtal_enabled = clk_ll_xtal32k_digi_is_enabled();
|
||||
if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
clk_ll_xtal32k_digi_enable();
|
||||
if (cal_clk_sel == CLK_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
clk_ll_xtal32k_digi_enable();
|
||||
}
|
||||
|
||||
bool rc_fast_enabled = clk_ll_rc_fast_is_enabled();
|
||||
bool dig_rc_fast_enabled = clk_ll_rc_fast_digi_is_enabled();
|
||||
if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
if (cal_clk_sel == CLK_CAL_RC_FAST) {
|
||||
if (!rc_fast_enabled) {
|
||||
rtc_clk_8m_enable(true);
|
||||
}
|
||||
@@ -78,8 +80,8 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
|
||||
}
|
||||
|
||||
/* Prepare calibration */
|
||||
REG_SET_FIELD(PCR_CTRL_32K_CONF_REG, PCR_32K_SEL, cal_clk);
|
||||
if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
clk_ll_freq_calulation_set_target(cal_clk_sel);
|
||||
if (cal_clk_sel == CLK_CAL_RC_FAST) {
|
||||
clk_ll_rc_fast_tick_conf();
|
||||
}
|
||||
CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING);
|
||||
@@ -87,11 +89,11 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
|
||||
/* Figure out how long to wait for calibration to finish */
|
||||
|
||||
/* Set timeout reg and expect time delay*/
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, CLK_CAL_TIMEOUT_THRES(cal_clk, slowclk_cycles));
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, CLK_CAL_TIMEOUT_THRES(cal_clk_sel, slowclk_cycles));
|
||||
uint32_t expected_freq;
|
||||
if (cal_clk == RTC_CAL_32K_XTAL || cal_clk == RTC_CAL_32K_OSC_SLOW) {
|
||||
if (cal_clk_sel == CLK_CAL_32K_XTAL || cal_clk_sel == CLK_CAL_32K_OSC_SLOW) {
|
||||
expected_freq = SOC_CLK_XTAL32K_FREQ_APPROX;
|
||||
} else if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
} else if (cal_clk_sel == CLK_CAL_RC_FAST) {
|
||||
expected_freq = SOC_CLK_RC_FAST_FREQ_APPROX >> CLK_LL_RC_FAST_CALIB_TICK_DIV_BITS;
|
||||
} else {
|
||||
expected_freq = SOC_CLK_RC_SLOW_FREQ_APPROX;
|
||||
@@ -110,7 +112,7 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
|
||||
|
||||
/*The Fosc CLK of calibration circuit is divided by a factor, k.
|
||||
So we need to multiply the frequency of the FOSC by k times.*/
|
||||
if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
if (cal_clk_sel == CLK_CAL_RC_FAST) {
|
||||
cal_val = cal_val >> CLK_LL_RC_FAST_CALIB_TICK_DIV_BITS;
|
||||
}
|
||||
break;
|
||||
@@ -123,11 +125,11 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
|
||||
CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START);
|
||||
|
||||
/* if dig_32k_xtal was originally off and enabled due to calibration, then set back to off state */
|
||||
if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
if (cal_clk_sel == CLK_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
clk_ll_xtal32k_digi_disable();
|
||||
}
|
||||
|
||||
if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
if (cal_clk_sel == CLK_CAL_RC_FAST) {
|
||||
if (!dig_rc_fast_enabled) {
|
||||
rtc_dig_clk8m_disable();
|
||||
}
|
||||
@@ -146,20 +148,20 @@ static bool rtc_clk_cal_32k_valid(uint32_t xtal_freq, uint32_t slowclk_cycles, u
|
||||
return (actual_xtal_cycles >= (expected_xtal_cycles - delta)) && (actual_xtal_cycles <= (expected_xtal_cycles + delta));
|
||||
}
|
||||
|
||||
uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
uint32_t rtc_clk_cal(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slowclk_cycles)
|
||||
{
|
||||
/*The Fosc CLK of calibration circuit is divided by a factor, k.
|
||||
So we need to divide the calibrate cycles of the FOSC by k to
|
||||
avoid excessive calibration time.*/
|
||||
if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
if (cal_clk_sel == CLK_CAL_RC_FAST) {
|
||||
slowclk_cycles = slowclk_cycles >> CLK_LL_RC_FAST_CALIB_TICK_DIV_BITS;
|
||||
}
|
||||
assert(slowclk_cycles);
|
||||
|
||||
soc_xtal_freq_t xtal_freq = rtc_clk_xtal_freq_get();
|
||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk, slowclk_cycles);
|
||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk_sel, slowclk_cycles);
|
||||
|
||||
if (cal_clk == RTC_CAL_32K_XTAL && !rtc_clk_cal_32k_valid((uint32_t)xtal_freq, slowclk_cycles, xtal_cycles)) {
|
||||
if (cal_clk_sel == CLK_CAL_32K_XTAL && !rtc_clk_cal_32k_valid((uint32_t)xtal_freq, slowclk_cycles, xtal_cycles)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -123,21 +123,12 @@ typedef struct rtc_cpu_freq_config_s {
|
||||
#define RTC_VDDSDIO_TIEH_1_8V 0 //!< TIEH field value for 1.8V VDDSDIO
|
||||
#define RTC_VDDSDIO_TIEH_3_3V 1 //!< TIEH field value for 3.3V VDDSDIO
|
||||
|
||||
/**
|
||||
* @brief Clock source to be calibrated using rtc_clk_cal function
|
||||
*
|
||||
* @note On previous targets, the enum values somehow reflects the register field values of TIMG_RTC_CALI_CLK_SEL
|
||||
* However, this is not true on ESP32H2. The conversion to register field values is explicitly done in
|
||||
* rtc_clk_cal_internal
|
||||
*/
|
||||
typedef enum {
|
||||
RTC_CAL_RTC_MUX = -1, //!< Currently selected RTC_SLOW_CLK
|
||||
RTC_CAL_RC_SLOW = SOC_RTC_SLOW_CLK_SRC_RC_SLOW, //!< Internal 150kHz RC oscillator
|
||||
RTC_CAL_RC32K = SOC_RTC_SLOW_CLK_SRC_RC32K, //!< Internal 32kHz RC oscillator, as one type of 32k clock
|
||||
RTC_CAL_32K_XTAL = SOC_RTC_SLOW_CLK_SRC_XTAL32K, //!< External 32kHz XTAL, as one type of 32k clock
|
||||
RTC_CAL_32K_OSC_SLOW = SOC_RTC_SLOW_CLK_SRC_OSC_SLOW, //!< External slow clock signal input by lp_pad_gpiox, as one type of 32k clock
|
||||
RTC_CAL_RC_FAST //!< Internal 8MHz RC oscillator
|
||||
} rtc_cal_sel_t;
|
||||
#define RTC_CAL_RTC_MUX _Pragma ("GCC warning \"'RTC_CAL_RTC_MUX' macro is deprecated\"") CLK_CAL_RTC_SLOW
|
||||
#define RTC_CAL_RC_SLOW _Pragma ("GCC warning \"'RTC_CAL_RC_SLOW' macro is deprecated\"") CLK_CAL_RC_SLOW
|
||||
#define RTC_CAL_RC32K _Pragma ("GCC warning \"'RTC_CAL_RC32K' macro is deprecated\"") CLK_CAL_RC32K
|
||||
#define RTC_CAL_32K_XTAL _Pragma ("GCC warning \"'RTC_CAL_32K_XTAL' macro is deprecated\"") CLK_CAL_32K_XTAL
|
||||
#define RTC_CAL_32K_OSC_SLOW _Pragma ("GCC warning \"'RTC_CAL_32K_OSC_SLOW' macro is deprecated\"") CLK_CAL_32K_OSC_SLOW
|
||||
#define RTC_CAL_RC_FAST _Pragma ("GCC warning \"'RTC_CAL_RC_FAST' macro is deprecated\"") CLK_CAL_RC_FAST
|
||||
|
||||
/**
|
||||
* Initialization parameters for rtc_clk_init
|
||||
@@ -379,12 +370,12 @@ uint32_t rtc_clk_apb_freq_get(void);
|
||||
* 32k XTAL is being calibrated, but the oscillator has not started up (due to
|
||||
* incorrect loading capacitance, board design issue, or lack of 32 XTAL on board).
|
||||
*
|
||||
* @param cal_clk clock to be measured
|
||||
* @param cal_clk_sel clock to be measured
|
||||
* @param slow_clk_cycles number of slow clock cycles to average
|
||||
* @return average slow clock period in microseconds, Q13.19 fixed point format,
|
||||
* or 0 if calibration has timed out
|
||||
*/
|
||||
uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slow_clk_cycles);
|
||||
uint32_t rtc_clk_cal(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slow_clk_cycles);
|
||||
|
||||
/**
|
||||
* @brief Convert time interval from microseconds to RTC_SLOW_CLK cycles
|
||||
|
||||
@@ -20,31 +20,10 @@
|
||||
|
||||
__attribute__((unused)) static const char *TAG = "rtc_time";
|
||||
|
||||
/* Calibration of RTC_SLOW_CLK is performed using a special feature of TIMG0.
|
||||
* This feature counts the number of XTAL clock cycles within a given number of
|
||||
* RTC_SLOW_CLK cycles.
|
||||
*
|
||||
* Slow clock calibration feature has two modes of operation: one-off and cycling.
|
||||
* In cycling mode (which is enabled by default on SoC reset), counting of XTAL
|
||||
* cycles within RTC_SLOW_CLK cycle is done continuously. Cycling mode is enabled
|
||||
* using TIMG_RTC_CALI_START_CYCLING bit. In one-off mode counting is performed
|
||||
* once, and TIMG_RTC_CALI_RDY bit is set when counting is done. One-off mode is
|
||||
* enabled using TIMG_RTC_CALI_START bit.
|
||||
*/
|
||||
|
||||
/* On ESP32H2, TIMG_RTC_CALI_CLK_SEL can config to 0, 1, 2, 3
|
||||
* 0 or 3: calibrate RC_SLOW clock
|
||||
* 1: calibrate RC_FAST clock
|
||||
* 2: calibrate 32K clock, which 32k depends on reg_32k_sel: 0: Internal 32 kHz RC oscillator, 1: External 32 kHz XTAL, 2: External 32kHz clock input by gpio13
|
||||
*/
|
||||
#define TIMG_RTC_CALI_CLK_SEL_RC_SLOW 0
|
||||
#define TIMG_RTC_CALI_CLK_SEL_RC_FAST 1
|
||||
#define TIMG_RTC_CALI_CLK_SEL_32K 2
|
||||
|
||||
/**
|
||||
* @brief Clock calibration function used by rtc_clk_cal
|
||||
* @brief Clock frequency calculation function used by rtc_clk_cal
|
||||
*
|
||||
* Calibration of RTC_SLOW_CLK is performed using a special feature of TIMG0.
|
||||
* Calculation of RTC_SLOW_CLK is performed using a special feature of TIMG0.
|
||||
* This feature counts the number of XTAL clock cycles within a given number of
|
||||
* RTC_SLOW_CLK cycles.
|
||||
*
|
||||
@@ -55,42 +34,39 @@ __attribute__((unused)) static const char *TAG = "rtc_time";
|
||||
* once, and TIMG_RTC_CALI_RDY bit is set when counting is done. One-off mode is
|
||||
* enabled using TIMG_RTC_CALI_START bit.
|
||||
*
|
||||
* @param cal_clk which clock to calibrate
|
||||
* @param cal_clk_sel which clock to calculate frequency
|
||||
* @param slowclk_cycles number of slow clock cycles to count
|
||||
* @return number of XTAL clock cycles within the given number of slow clock cycles
|
||||
*/
|
||||
static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
static uint32_t rtc_clk_cal_internal(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slowclk_cycles)
|
||||
{
|
||||
assert(slowclk_cycles < TIMG_RTC_CALI_MAX_V);
|
||||
|
||||
uint32_t cali_clk_sel = 0;
|
||||
soc_rtc_slow_clk_src_t slow_clk_src = rtc_clk_slow_src_get();
|
||||
soc_rtc_slow_clk_src_t old_32k_cal_clk_sel = clk_ll_32k_calibration_get_target();
|
||||
if (cal_clk == RTC_CAL_RTC_MUX) {
|
||||
cal_clk = (rtc_cal_sel_t)slow_clk_src;
|
||||
if (cal_clk_sel == CLK_CAL_RTC_SLOW) {
|
||||
soc_rtc_slow_clk_src_t slow_clk_src = rtc_clk_slow_src_get();
|
||||
if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC_SLOW) {
|
||||
cal_clk_sel = CLK_CAL_RC_SLOW;
|
||||
} else if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_OSC_SLOW) {
|
||||
cal_clk_sel = CLK_CAL_32K_OSC_SLOW;
|
||||
} else if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) {
|
||||
cal_clk_sel = CLK_CAL_32K_XTAL;
|
||||
} else if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC32K) {
|
||||
cal_clk_sel = CLK_CAL_RC32K;
|
||||
}
|
||||
}
|
||||
if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
cali_clk_sel = TIMG_RTC_CALI_CLK_SEL_RC_FAST;
|
||||
} else if (cal_clk == RTC_CAL_RC_SLOW) {
|
||||
cali_clk_sel = TIMG_RTC_CALI_CLK_SEL_RC_SLOW;
|
||||
} else {
|
||||
cali_clk_sel = TIMG_RTC_CALI_CLK_SEL_32K;
|
||||
clk_ll_32k_calibration_set_target((soc_rtc_slow_clk_src_t)cal_clk);
|
||||
}
|
||||
|
||||
|
||||
/* Enable requested clock (150k clock is always on) */
|
||||
// All clocks on/off takes time to be stable, so we shouldn't frequently enable/disable the clock
|
||||
// Only enable if originally was disabled, and set back to the disable state after calibration is done
|
||||
// If the clock is already on, then do nothing
|
||||
bool dig_32k_xtal_enabled = clk_ll_xtal32k_digi_is_enabled();
|
||||
if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
clk_ll_xtal32k_digi_enable();
|
||||
if (cal_clk_sel == CLK_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
clk_ll_xtal32k_digi_enable();
|
||||
}
|
||||
|
||||
bool rc_fast_enabled = clk_ll_rc_fast_is_enabled();
|
||||
bool dig_rc_fast_enabled = clk_ll_rc_fast_digi_is_enabled();
|
||||
if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
if (cal_clk_sel == CLK_CAL_RC_FAST) {
|
||||
if (!rc_fast_enabled) {
|
||||
rtc_clk_8m_enable(true);
|
||||
}
|
||||
@@ -101,7 +77,7 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
|
||||
|
||||
bool rc32k_enabled = clk_ll_rc32k_is_enabled();
|
||||
bool dig_rc32k_enabled = clk_ll_rc32k_digi_is_enabled();
|
||||
if (cal_clk == RTC_CAL_RC32K) {
|
||||
if (cal_clk_sel == CLK_CAL_RC32K) {
|
||||
if (!rc32k_enabled) {
|
||||
rtc_clk_rc32k_enable(true);
|
||||
}
|
||||
@@ -124,8 +100,8 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
|
||||
}
|
||||
|
||||
/* Prepare calibration */
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_CLK_SEL, cali_clk_sel);
|
||||
if (cali_clk_sel == TIMG_RTC_CALI_CLK_SEL_RC_FAST) {
|
||||
clk_ll_freq_calulation_set_target(cal_clk_sel);
|
||||
if (cal_clk_sel == CLK_CAL_RC_FAST) {
|
||||
clk_ll_rc_fast_tick_conf();
|
||||
}
|
||||
CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING);
|
||||
@@ -134,10 +110,10 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
|
||||
|
||||
/* Set timeout reg and expect time delay*/
|
||||
uint32_t expected_freq;
|
||||
if (cali_clk_sel == TIMG_RTC_CALI_CLK_SEL_32K) {
|
||||
if (cal_clk_sel == CLK_CAL_32K_XTAL || cal_clk_sel == CLK_CAL_32K_OSC_SLOW || cal_clk_sel == CLK_CAL_RC32K) {
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_SLOW_CLK_32K_CAL_TIMEOUT_THRES(slowclk_cycles));
|
||||
expected_freq = SOC_CLK_XTAL32K_FREQ_APPROX;
|
||||
} else if (cali_clk_sel == TIMG_RTC_CALI_CLK_SEL_RC_FAST) {
|
||||
} else if (cal_clk_sel == CLK_CAL_RC_FAST) {
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_FAST_CLK_8M_CAL_TIMEOUT_THRES(slowclk_cycles));
|
||||
expected_freq = SOC_CLK_RC_FAST_FREQ_APPROX;
|
||||
if (ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 2)) {
|
||||
@@ -165,7 +141,7 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
|
||||
And the 32-divider belongs to REF_TICK module, so we need to enable its clock during
|
||||
calibration. */
|
||||
if (ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 2)) {
|
||||
if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
if (cal_clk_sel == CLK_CAL_RC_FAST) {
|
||||
cal_val = cal_val >> CLK_LL_RC_FAST_CALIB_TICK_DIV_BITS;
|
||||
CLEAR_PERI_REG_MASK(PCR_CTRL_TICK_CONF_REG, PCR_TICK_ENABLE);
|
||||
}
|
||||
@@ -180,11 +156,11 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
|
||||
CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START);
|
||||
|
||||
/* if dig_32k_xtal was originally off and enabled due to calibration, then set back to off state */
|
||||
if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
if (cal_clk_sel == CLK_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
clk_ll_xtal32k_digi_disable();
|
||||
}
|
||||
|
||||
if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
if (cal_clk_sel == CLK_CAL_RC_FAST) {
|
||||
if (!dig_rc_fast_enabled) {
|
||||
rtc_dig_clk8m_disable();
|
||||
}
|
||||
@@ -193,7 +169,7 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
|
||||
}
|
||||
}
|
||||
|
||||
if (cal_clk == RTC_CAL_RC32K) {
|
||||
if (cal_clk_sel == CLK_CAL_RC32K) {
|
||||
if (!dig_rc32k_enabled) {
|
||||
clk_ll_rc32k_digi_disable();
|
||||
}
|
||||
@@ -202,11 +178,6 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
|
||||
}
|
||||
}
|
||||
|
||||
// Always set back the calibration 32kHz clock selection
|
||||
if (old_32k_cal_clk_sel != SOC_RTC_SLOW_CLK_SRC_INVALID) {
|
||||
clk_ll_32k_calibration_set_target(old_32k_cal_clk_sel);
|
||||
}
|
||||
|
||||
return cal_val;
|
||||
}
|
||||
|
||||
@@ -217,7 +188,7 @@ static bool rtc_clk_cal_32k_valid(uint32_t xtal_freq, uint32_t slowclk_cycles, u
|
||||
return (actual_xtal_cycles >= (expected_xtal_cycles - delta)) && (actual_xtal_cycles <= (expected_xtal_cycles + delta));
|
||||
}
|
||||
|
||||
uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
uint32_t rtc_clk_cal(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slowclk_cycles)
|
||||
{
|
||||
assert(slowclk_cycles);
|
||||
soc_xtal_freq_t xtal_freq = rtc_clk_xtal_freq_get();
|
||||
@@ -226,15 +197,15 @@ uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
So we need to divide the calibrate cycles of the FOSC for ECO1 and above chips by 32 to
|
||||
avoid excessive calibration time.*/
|
||||
if (ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 2)) {
|
||||
if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
if (cal_clk_sel == CLK_CAL_RC_FAST) {
|
||||
slowclk_cycles = slowclk_cycles >> CLK_LL_RC_FAST_CALIB_TICK_DIV_BITS;
|
||||
SET_PERI_REG_MASK(PCR_CTRL_TICK_CONF_REG, PCR_TICK_ENABLE);
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk, slowclk_cycles);
|
||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk_sel, slowclk_cycles);
|
||||
|
||||
if (cal_clk == RTC_CAL_32K_XTAL && !rtc_clk_cal_32k_valid((uint32_t)xtal_freq, slowclk_cycles, xtal_cycles)) {
|
||||
if (cal_clk_sel == CLK_CAL_32K_XTAL && !rtc_clk_cal_32k_valid((uint32_t)xtal_freq, slowclk_cycles, xtal_cycles)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -105,20 +105,6 @@ typedef struct rtc_cpu_freq_config_s {
|
||||
|
||||
#define RTC_CLK_CAL_FRACT 19 //!< Number of fractional bits in values returned by rtc_clk_cal
|
||||
|
||||
/**
|
||||
* @brief Clock source to be calibrated using rtc_clk_cal function
|
||||
*
|
||||
* @note On previous targets, the enum values somehow reflects the register field values of TIMG_RTC_CALI_CLK_SEL
|
||||
* However, this is not true on ESP32H21. The conversion to register field values is explicitly done internally
|
||||
*/
|
||||
typedef enum {
|
||||
RTC_CAL_RTC_MUX = -1, //!< Currently selected RTC_SLOW_CLK
|
||||
RTC_CAL_RC_SLOW = CLK_CAL_RC_SLOW, //!< Internal 600kHz RC oscillator
|
||||
RTC_CAL_32K_XTAL = CLK_CAL_32K_XTAL, //!< External 32kHz XTAL, as one type of 32k clock
|
||||
RTC_CAL_32K_OSC_SLOW = CLK_CAL_32K_OSC_SLOW, //!< External slow clock signal input by gpio11, as one type of 32k clock
|
||||
RTC_CAL_RC_FAST = CLK_CAL_RC_FAST, //!< Internal 20MHz RC oscillator
|
||||
} rtc_cal_sel_t;
|
||||
|
||||
/**
|
||||
* Initialization parameters for rtc_clk_init
|
||||
*/
|
||||
@@ -328,12 +314,12 @@ uint32_t rtc_clk_apb_freq_get(void);
|
||||
* the check fails, then consider this an invalid 32k clock and return 0. This
|
||||
* check can filter some jamming signal.
|
||||
*
|
||||
* @param cal_clk clock to be measured
|
||||
* @param cal_clk_sel clock to be measured
|
||||
* @param slow_clk_cycles number of slow clock cycles to average
|
||||
* @return average slow clock period in microseconds, Q13.19 fixed point format,
|
||||
* or 0 if calibration has timed out
|
||||
*/
|
||||
uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slow_clk_cycles);
|
||||
uint32_t rtc_clk_cal(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slow_clk_cycles);
|
||||
|
||||
/**
|
||||
* @brief Convert time interval from microseconds to RTC_SLOW_CLK cycles
|
||||
|
||||
@@ -18,31 +18,38 @@
|
||||
|
||||
__attribute__((unused)) static const char *TAG = "rtc_time";
|
||||
|
||||
/* Calibration of RTC_SLOW_CLK is performed using a special feature of TIMG0.
|
||||
* This feature counts the number of XTAL clock cycles within a given number of
|
||||
* RTC_SLOW_CLK cycles.
|
||||
*/
|
||||
|
||||
#define RTC_SLOW_CLK_600K_CAL_TIMEOUT_THRES(cycles) (cycles << 10)
|
||||
#define RTC_SLOW_CLK_32K_CAL_TIMEOUT_THRES(cycles) (cycles << 12)
|
||||
#define RTC_FAST_CLK_20M_CAL_TIMEOUT_THRES(cycles) (TIMG_RTC_CALI_TIMEOUT_THRES_V) // Just use the max timeout thres value
|
||||
|
||||
static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
/**
|
||||
* @brief Clock frequency calculation function used by rtc_clk_cal
|
||||
*
|
||||
* Calculation of clock frequency is performed using a special feature of TIMG0.
|
||||
* This feature counts the number of XTAL clock cycles within a given number of
|
||||
* clock cycles.
|
||||
*
|
||||
* @param cal_clk_sel which clock to calculate frequency
|
||||
* @param slowclk_cycles number of slow clock cycles to count
|
||||
* @return number of XTAL clock cycles within the given number of slow clock cycles
|
||||
*/
|
||||
static uint32_t rtc_clk_cal_internal(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slowclk_cycles)
|
||||
{
|
||||
assert(slowclk_cycles < TIMG_RTC_CALI_MAX_V);
|
||||
|
||||
bool is_cal_clk_rtc_slow = false;
|
||||
soc_rtc_slow_clk_src_t slow_clk_src = rtc_clk_slow_src_get();
|
||||
soc_clk_calibration_clk_src_t cali_clk_sel = (soc_clk_calibration_clk_src_t)cal_clk;
|
||||
if (cal_clk == RTC_CAL_RTC_MUX) {
|
||||
if (cal_clk_sel == CLK_CAL_RTC_SLOW) {
|
||||
is_cal_clk_rtc_slow = true;
|
||||
switch (slow_clk_src) {
|
||||
case SOC_RTC_SLOW_CLK_SRC_RC_SLOW_D4:
|
||||
cali_clk_sel = CLK_CAL_RC_SLOW;
|
||||
cal_clk_sel = CLK_CAL_RC_SLOW;
|
||||
break;
|
||||
case SOC_RTC_SLOW_CLK_SRC_XTAL32K:
|
||||
cali_clk_sel = CLK_CAL_32K_XTAL;
|
||||
cal_clk_sel = CLK_CAL_32K_XTAL;
|
||||
break;
|
||||
case SOC_RTC_SLOW_CLK_SRC_OSC_SLOW:
|
||||
cali_clk_sel = CLK_CAL_32K_OSC_SLOW;
|
||||
cal_clk_sel = CLK_CAL_32K_OSC_SLOW;
|
||||
break;
|
||||
default:
|
||||
ESP_EARLY_LOGE(TAG, "clock not supported to be calibrated");
|
||||
@@ -55,13 +62,13 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
|
||||
// Only enable if originally was disabled, and set back to the disable state after calibration is done
|
||||
// If the clock is already on, then do nothing
|
||||
bool dig_32k_xtal_enabled = clk_ll_xtal32k_digi_is_enabled();
|
||||
if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
if (cal_clk_sel == CLK_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
clk_ll_xtal32k_digi_enable();
|
||||
}
|
||||
|
||||
bool rc_fast_enabled = clk_ll_rc_fast_is_enabled();
|
||||
bool dig_rc_fast_enabled = clk_ll_rc_fast_digi_is_enabled();
|
||||
if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
if (cal_clk_sel == CLK_CAL_RC_FAST) {
|
||||
if (!rc_fast_enabled) {
|
||||
rtc_clk_8m_enable(true);
|
||||
}
|
||||
@@ -84,8 +91,8 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
|
||||
}
|
||||
|
||||
/* Prepare calibration */
|
||||
clk_ll_calibration_set_target(cali_clk_sel);
|
||||
if (cali_clk_sel == CLK_CAL_RC_FAST) {
|
||||
clk_ll_freq_calulation_set_target(cal_clk_sel);
|
||||
if (cal_clk_sel == CLK_CAL_RC_FAST) {
|
||||
clk_ll_rc_fast_tick_conf();
|
||||
}
|
||||
CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING);
|
||||
@@ -94,10 +101,10 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
|
||||
|
||||
/* Set timeout reg and expect time delay*/
|
||||
uint32_t expected_freq;
|
||||
if (cali_clk_sel == CLK_CAL_32K_XTAL || cali_clk_sel == CLK_CAL_32K_OSC_SLOW) {
|
||||
if (cal_clk_sel == CLK_CAL_32K_XTAL || cal_clk_sel == CLK_CAL_32K_OSC_SLOW) {
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_SLOW_CLK_32K_CAL_TIMEOUT_THRES(slowclk_cycles));
|
||||
expected_freq = SOC_CLK_XTAL32K_FREQ_APPROX;
|
||||
} else if (cali_clk_sel == CLK_CAL_RC_FAST) {
|
||||
} else if (cal_clk_sel == CLK_CAL_RC_FAST) {
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_FAST_CLK_20M_CAL_TIMEOUT_THRES(slowclk_cycles));
|
||||
expected_freq = SOC_CLK_RC_FAST_FREQ_APPROX >> CLK_LL_RC_FAST_CALIB_TICK_DIV_BITS;
|
||||
} else {
|
||||
@@ -118,7 +125,7 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
|
||||
|
||||
/* The Fosc CLK of calibration circuit is divided by a factor, k.
|
||||
So we need to multiply the frequency of the FOSC by k times. */
|
||||
if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
if (cal_clk_sel == CLK_CAL_RC_FAST) {
|
||||
cal_val = cal_val >> CLK_LL_RC_FAST_CALIB_TICK_DIV_BITS;
|
||||
}
|
||||
break;
|
||||
@@ -131,11 +138,11 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
|
||||
CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START);
|
||||
|
||||
/* if dig_32k_xtal was originally off and enabled due to calibration, then set back to off state */
|
||||
if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
if (cal_clk_sel == CLK_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
clk_ll_xtal32k_digi_disable();
|
||||
}
|
||||
|
||||
if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
if (cal_clk_sel == CLK_CAL_RC_FAST) {
|
||||
if (!dig_rc_fast_enabled) {
|
||||
rtc_dig_clk8m_disable();
|
||||
}
|
||||
@@ -144,7 +151,7 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
|
||||
}
|
||||
}
|
||||
|
||||
if (cal_clk == RTC_CAL_RTC_MUX && slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC_SLOW_D4) {
|
||||
if (is_cal_clk_rtc_slow && slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC_SLOW_D4) {
|
||||
// calibration was done on RC_SLOW clock, but rtc_slow_clk src is RC_SLOW_D4, so we need to multiply the cal_val by 4
|
||||
cal_val *= 4;
|
||||
}
|
||||
@@ -159,20 +166,20 @@ static bool rtc_clk_cal_32k_valid(uint32_t xtal_freq, uint32_t slowclk_cycles, u
|
||||
return (actual_xtal_cycles >= (expected_xtal_cycles - delta)) && (actual_xtal_cycles <= (expected_xtal_cycles + delta));
|
||||
}
|
||||
|
||||
uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
uint32_t rtc_clk_cal(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slowclk_cycles)
|
||||
{
|
||||
/* The Fosc CLK of calibration circuit is divided by a factor, k.
|
||||
So we need to divide the calibrate cycles of the FOSC by k to
|
||||
avoid excessive calibration time. */
|
||||
if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
if (cal_clk_sel == CLK_CAL_RC_FAST) {
|
||||
slowclk_cycles = slowclk_cycles >> CLK_LL_RC_FAST_CALIB_TICK_DIV_BITS;
|
||||
}
|
||||
assert(slowclk_cycles);
|
||||
|
||||
soc_xtal_freq_t xtal_freq = rtc_clk_xtal_freq_get();
|
||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk, slowclk_cycles);
|
||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk_sel, slowclk_cycles);
|
||||
|
||||
if (cal_clk == RTC_CAL_32K_XTAL && !rtc_clk_cal_32k_valid((uint32_t)xtal_freq, slowclk_cycles, xtal_cycles)) {
|
||||
if (cal_clk_sel == CLK_CAL_32K_XTAL && !rtc_clk_cal_32k_valid((uint32_t)xtal_freq, slowclk_cycles, xtal_cycles)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -105,20 +105,6 @@ typedef struct rtc_cpu_freq_config_s {
|
||||
|
||||
#define RTC_CLK_CAL_FRACT 19 //!< Number of fractional bits in values returned by rtc_clk_cal
|
||||
|
||||
/**
|
||||
* @brief Clock source to be calibrated using rtc_clk_cal function
|
||||
*
|
||||
* @note On previous targets, the enum values somehow reflects the register field values of TIMG_RTC_CALI_CLK_SEL
|
||||
* However, this is not true on ESP32H4. The conversion to register field values is explicitly done internally
|
||||
*/
|
||||
typedef enum {
|
||||
RTC_CAL_RTC_MUX = -1, //!< Currently selected RTC_SLOW_CLK
|
||||
RTC_CAL_RC_SLOW = CLK_CAL_RC_SLOW, //!< Internal 600kHz RC oscillator
|
||||
RTC_CAL_32K_XTAL = CLK_CAL_32K_XTAL, //!< External 32kHz XTAL, as one type of 32k clock
|
||||
RTC_CAL_32K_OSC_SLOW = CLK_CAL_32K_OSC_SLOW, //!< External slow clock signal input by gpio5, as one type of 32k clock
|
||||
RTC_CAL_RC_FAST = CLK_CAL_RC_FAST, //!< Internal 20MHz RC oscillator
|
||||
} rtc_cal_sel_t;
|
||||
|
||||
/**
|
||||
* Initialization parameters for rtc_clk_init
|
||||
*/
|
||||
@@ -341,12 +327,12 @@ uint32_t rtc_clk_apb_freq_get(void);
|
||||
* the check fails, then consider this an invalid 32k clock and return 0. This
|
||||
* check can filter some jamming signal.
|
||||
*
|
||||
* @param cal_clk clock to be measured
|
||||
* @param cal_clk_sel clock to be measured
|
||||
* @param slow_clk_cycles number of slow clock cycles to average
|
||||
* @return average slow clock period in microseconds, Q13.19 fixed point format,
|
||||
* or 0 if calibration has timed out
|
||||
*/
|
||||
uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slow_clk_cycles);
|
||||
uint32_t rtc_clk_cal(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slow_clk_cycles);
|
||||
|
||||
/**
|
||||
* @brief Convert time interval from microseconds to RTC_SLOW_CLK cycles
|
||||
|
||||
@@ -19,29 +19,41 @@ static const char *TAG = "rtc_time";
|
||||
|
||||
#define RTC_SLOW_CLK_600K_CAL_TIMEOUT_THRES(cycles) (cycles << 10)
|
||||
#define RTC_SLOW_CLK_32K_CAL_TIMEOUT_THRES(cycles) (cycles << 12)
|
||||
#define RTC_FAST_CLK_20M_CAL_TIMEOUT_THRES(cycles) (TIMG_RTC_CALI_TIMEOUT_THRES_V) // Just use the max timeout thres value
|
||||
#define RTC_FAST_CLK_20M_CAL_TIMEOUT_THRES(cycles) (TIMG_RTC_CALI_TIMEOUT_THRES_V) // Just use the max timeout thres value
|
||||
|
||||
// Calibration can only be performed on relatively slow speed clock signal. Therefore, for high-speed clocks,
|
||||
// calibration is performed on their DIV_CLKs. The divider is configurable. We set:
|
||||
#define CLK_CAL_DIV_VAL(cal_clk) \
|
||||
((cal_clk == RTC_CAL_RC_FAST) ? 32 : 1)
|
||||
#define CLK_CAL_DIV_VAL(cal_clk_sel) \
|
||||
((cal_clk_sel == CLK_CAL_RC_FAST) ? 32 : 1)
|
||||
|
||||
static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
/**
|
||||
* @brief Clock frequency calculation function used by rtc_clk_cal
|
||||
*
|
||||
* Calculation of clock frequency is performed using a special feature of TIMG0.
|
||||
* This feature counts the number of XTAL clock cycles within a given number of
|
||||
* clock cycles.
|
||||
*
|
||||
* @param cal_clk_sel which clock to calculate frequency
|
||||
* @param slowclk_cycles number of slow clock cycles to count
|
||||
* @return number of XTAL clock cycles within the given number of slow clock cycles
|
||||
*/
|
||||
static uint32_t rtc_clk_cal_internal(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slowclk_cycles)
|
||||
{
|
||||
assert(slowclk_cycles < TIMG_RTC_CALI_MAX_V);
|
||||
|
||||
bool is_cal_clk_rtc_slow = false;
|
||||
soc_rtc_slow_clk_src_t slow_clk_src = rtc_clk_slow_src_get();
|
||||
soc_clk_calibration_clk_src_t cali_clk_sel = (soc_clk_calibration_clk_src_t)cal_clk;
|
||||
if (cal_clk == RTC_CAL_RTC_MUX) {
|
||||
if (cal_clk_sel == CLK_CAL_RTC_SLOW) {
|
||||
is_cal_clk_rtc_slow = true;
|
||||
switch (slow_clk_src) {
|
||||
case SOC_RTC_SLOW_CLK_SRC_RC_SLOW_D4:
|
||||
cali_clk_sel = CLK_CAL_RC_SLOW;
|
||||
cal_clk_sel = CLK_CAL_RC_SLOW;
|
||||
break;
|
||||
case SOC_RTC_SLOW_CLK_SRC_XTAL32K:
|
||||
cali_clk_sel = CLK_CAL_32K_XTAL;
|
||||
cal_clk_sel = CLK_CAL_32K_XTAL;
|
||||
break;
|
||||
case SOC_RTC_SLOW_CLK_SRC_OSC_SLOW:
|
||||
cali_clk_sel = CLK_CAL_32K_OSC_SLOW;
|
||||
cal_clk_sel = CLK_CAL_32K_OSC_SLOW;
|
||||
break;
|
||||
default:
|
||||
ESP_EARLY_LOGE(TAG, "clock not supported to be calibrated");
|
||||
@@ -49,18 +61,23 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
|
||||
}
|
||||
}
|
||||
|
||||
if (cal_clk_sel != CLK_CAL_RC_SLOW && cal_clk_sel != CLK_CAL_32K_XTAL && cal_clk_sel != CLK_CAL_32K_OSC_SLOW && cal_clk_sel != CLK_CAL_RC_FAST) {
|
||||
ESP_EARLY_LOGE(TAG, "calibration not yet supported for this clock");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Enable requested clock (rc_slow clock is always on) */
|
||||
// All clocks on/off takes time to be stable, so we shouldn't frequently enable/disable the clock
|
||||
// Only enable if originally was disabled, and set back to the disable state after calibration is done
|
||||
// If the clock is already on, then do nothing
|
||||
bool dig_32k_xtal_enabled = clk_ll_xtal32k_digi_is_enabled();
|
||||
if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
if (cal_clk_sel == CLK_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
clk_ll_xtal32k_digi_enable();
|
||||
}
|
||||
|
||||
bool rc_fast_enabled = clk_ll_rc_fast_is_enabled();
|
||||
bool dig_rc_fast_enabled = clk_ll_rc_fast_digi_is_enabled();
|
||||
if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
if (cal_clk_sel == CLK_CAL_RC_FAST) {
|
||||
if (!rc_fast_enabled) {
|
||||
rtc_clk_8m_enable(true);
|
||||
}
|
||||
@@ -83,19 +100,19 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
|
||||
}
|
||||
|
||||
/* Prepare calibration */
|
||||
clk_ll_calibration_set_target(cali_clk_sel);
|
||||
uint32_t clk_cal_divider = CLK_CAL_DIV_VAL(cal_clk);
|
||||
clk_ll_calibration_set_divider(clk_cal_divider);
|
||||
clk_ll_freq_calulation_set_target(cal_clk_sel);
|
||||
uint32_t clk_cal_divider = CLK_CAL_DIV_VAL(cal_clk_sel);
|
||||
clk_ll_freq_calculation_set_divider(clk_cal_divider);
|
||||
CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING);
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_MAX, slowclk_cycles);
|
||||
/* Figure out how long to wait for calibration to finish */
|
||||
|
||||
/* Set timeout reg and expect time delay*/
|
||||
uint32_t expected_freq;
|
||||
if (cali_clk_sel == CLK_CAL_32K_XTAL || cali_clk_sel == CLK_CAL_32K_OSC_SLOW) {
|
||||
if (cal_clk_sel == CLK_CAL_32K_XTAL || cal_clk_sel == CLK_CAL_32K_OSC_SLOW) {
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_SLOW_CLK_32K_CAL_TIMEOUT_THRES(slowclk_cycles));
|
||||
expected_freq = SOC_CLK_XTAL32K_FREQ_APPROX;
|
||||
} else if (cali_clk_sel == CLK_CAL_RC_FAST) {
|
||||
} else if (cal_clk_sel == CLK_CAL_RC_FAST) {
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_FAST_CLK_20M_CAL_TIMEOUT_THRES(slowclk_cycles));
|
||||
expected_freq = SOC_CLK_RC_FAST_FREQ_APPROX;
|
||||
} else {
|
||||
@@ -123,14 +140,14 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
|
||||
}
|
||||
}
|
||||
CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START);
|
||||
clk_ll_calibration_set_divider(1);
|
||||
clk_ll_freq_calculation_set_divider(1);
|
||||
|
||||
/* if dig_32k_xtal was originally off and enabled due to calibration, then set back to off state */
|
||||
if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
if (cal_clk_sel == CLK_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
clk_ll_xtal32k_digi_disable();
|
||||
}
|
||||
|
||||
if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
if (cal_clk_sel == CLK_CAL_RC_FAST) {
|
||||
if (!dig_rc_fast_enabled) {
|
||||
rtc_dig_clk8m_disable();
|
||||
}
|
||||
@@ -139,7 +156,7 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
|
||||
}
|
||||
}
|
||||
|
||||
if (cal_clk == RTC_CAL_RTC_MUX && slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC_SLOW_D4) {
|
||||
if (is_cal_clk_rtc_slow && slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC_SLOW_D4) {
|
||||
// calibration was done on RC_SLOW clock, but rtc_slow_clk src is RC_SLOW_D4, so we need to multiply the cal_val by 4
|
||||
cal_val *= 4;
|
||||
}
|
||||
@@ -154,14 +171,14 @@ static bool rtc_clk_cal_32k_valid(soc_xtal_freq_t xtal_freq, uint32_t slowclk_cy
|
||||
return (actual_xtal_cycles >= (expected_xtal_cycles - delta)) && (actual_xtal_cycles <= (expected_xtal_cycles + delta));
|
||||
}
|
||||
|
||||
uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
uint32_t rtc_clk_cal(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slowclk_cycles)
|
||||
{
|
||||
slowclk_cycles /= (cal_clk == RTC_CAL_RTC_MUX) ? 1 : CLK_CAL_DIV_VAL(cal_clk);
|
||||
slowclk_cycles /= (cal_clk_sel == CLK_CAL_RTC_SLOW) ? 1 : CLK_CAL_DIV_VAL(cal_clk_sel);
|
||||
assert(slowclk_cycles);
|
||||
soc_xtal_freq_t xtal_freq = rtc_clk_xtal_freq_get();
|
||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk, slowclk_cycles);
|
||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk_sel, slowclk_cycles);
|
||||
|
||||
if (cal_clk == RTC_CAL_32K_XTAL && !rtc_clk_cal_32k_valid((uint32_t)xtal_freq, slowclk_cycles, xtal_cycles)) {
|
||||
if (cal_clk_sel == CLK_CAL_32K_XTAL && !rtc_clk_cal_32k_valid((uint32_t)xtal_freq, slowclk_cycles, xtal_cycles)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -149,27 +149,19 @@ typedef struct rtc_cpu_freq_config_s {
|
||||
#define RTC_VDDSDIO_TIEH_1_8V 0 //!< TIEH field value for 1.8V VDDSDIO
|
||||
#define RTC_VDDSDIO_TIEH_3_3V 1 //!< TIEH field value for 3.3V VDDSDIO
|
||||
|
||||
/**
|
||||
* @brief Clock source to be calibrated using rtc_clk_cal function
|
||||
*
|
||||
* @note On ESP32P4, the enum values somehow reflects the register field values of HP_SYS_CLKRST_REG_TIMERGRP0_TGRT_CLK_SRC_SEL.
|
||||
*/
|
||||
typedef enum {
|
||||
RTC_CAL_RTC_MUX = -1, //!< Currently selected RTC_SLOW_CLK
|
||||
RTC_CAL_MPLL = 0, //!< 500MHz MSPI_PLL_CLK
|
||||
RTC_CAL_SPLL = 1, //!< 480MHz SYS_PLL_CLK
|
||||
RTC_CAL_CPLL = 2, //!< 400MHz CPU_PLL_CLK
|
||||
RTC_CAL_APLL = 3, //!< AUDIO_PLL_CLK
|
||||
RTC_CAL_SDIO_PLL0 = 4, //!< SDIO_PLL0_CLK
|
||||
RTC_CAL_SDIO_PLL1 = 5, //!< SDIO_PLL1_CLK
|
||||
RTC_CAL_SDIO_PLL2 = 6, //!< SDIO_PLL2_CLK
|
||||
RTC_CAL_RC_FAST = 7, //!< Internal 20MHz RC oscillator
|
||||
RTC_CAL_RC_SLOW = 8, //!< Internal 150kHz RC oscillator
|
||||
RTC_CAL_RC32K = 9, //!< Internal 32kHz RC oscillator, as one type of 32k clock
|
||||
RTC_CAL_32K_XTAL = 10, //!< External 32kHz XTAL, as one type of 32k clock
|
||||
RTC_CAL_LP_PLL = 11, //!< 8MHz LP_PLL_CLK
|
||||
RTC_CAL_INVALID_CLK, //!< Clock not available to calibrate
|
||||
} rtc_cal_sel_t;
|
||||
#define RTC_CAL_RTC_MUX _Pragma ("GCC warning \"'RTC_CAL_RTC_MUX' macro is deprecated\"") CLK_CAL_RTC_SLOW
|
||||
#define RTC_CAL_MPLL _Pragma ("GCC warning \"'RTC_CAL_MPLL' macro is deprecated\"") CLK_CAL_MPLL
|
||||
#define RTC_CAL_SPLL _Pragma ("GCC warning \"'RTC_CAL_SPLL' macro is deprecated\"") CLK_CAL_SPLL
|
||||
#define RTC_CAL_CPLL _Pragma ("GCC warning \"'RTC_CAL_CPLL' macro is deprecated\"") CLK_CAL_CPLL
|
||||
#define RTC_CAL_APLL _Pragma ("GCC warning \"'RTC_CAL_APLL' macro is deprecated\"") CLK_CAL_APLL
|
||||
#define RTC_CAL_SDIO_PLL0 _Pragma ("GCC warning \"'RTC_CAL_SDIO_PLL0' macro is deprecated\"") CLK_CAL_SDIO_PLL0
|
||||
#define RTC_CAL_SDIO_PLL1 _Pragma ("GCC warning \"'RTC_CAL_SDIO_PLL1' macro is deprecated\"") CLK_CAL_SDIO_PLL1
|
||||
#define RTC_CAL_SDIO_PLL2 _Pragma ("GCC warning \"'RTC_CAL_SDIO_PLL2' macro is deprecated\"") CLK_CAL_SDIO_PLL2
|
||||
#define RTC_CAL_RC_FAST _Pragma ("GCC warning \"'RTC_CAL_RC_FAST' macro is deprecated\"") CLK_CAL_RC_FAST
|
||||
#define RTC_CAL_RC_SLOW _Pragma ("GCC warning \"'RTC_CAL_RC_SLOW' macro is deprecated\"") CLK_CAL_RC_SLOW
|
||||
#define RTC_CAL_RC32K _Pragma ("GCC warning \"'RTC_CAL_RC32K' macro is deprecated\"") CLK_CAL_RC32K
|
||||
#define RTC_CAL_32K_XTAL _Pragma ("GCC warning \"'RTC_CAL_32K_XTAL' macro is deprecated\"") CLK_CAL_32K_XTAL
|
||||
#define RTC_CAL_LP_PLL _Pragma ("GCC warning \"'RTC_CAL_LP_PLL' macro is deprecated\"") CLK_CAL_LP_PLL
|
||||
|
||||
/**
|
||||
* Initialization parameters for rtc_clk_init
|
||||
@@ -391,26 +383,6 @@ void rtc_clk_cpu_freq_set_xtal(void);
|
||||
*/
|
||||
uint32_t rtc_clk_apb_freq_get(void);
|
||||
|
||||
/**
|
||||
* @brief Clock calibration function used by rtc_clk_cal
|
||||
*
|
||||
* Calibration of RTC_SLOW_CLK is performed using a special feature of TIMG0.
|
||||
* This feature counts the number of XTAL clock cycles within a given number of
|
||||
* RTC_SLOW_CLK cycles.
|
||||
*
|
||||
* Slow clock calibration feature has two modes of operation: one-off and cycling.
|
||||
* In cycling mode (which is enabled by default on SoC reset), counting of XTAL
|
||||
* cycles within RTC_SLOW_CLK cycle is done continuously. Cycling mode is enabled
|
||||
* using TIMG_RTC_CALI_START_CYCLING bit. In one-off mode counting is performed
|
||||
* once, and TIMG_RTC_CALI_RDY bit is set when counting is done. One-off mode is
|
||||
* enabled using TIMG_RTC_CALI_START bit.
|
||||
*
|
||||
* @param cal_clk which clock to calibrate
|
||||
* @param slowclk_cycles number of slow clock cycles to count
|
||||
* @return number of XTAL clock cycles within the given number of slow clock cycles
|
||||
*/
|
||||
uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles);
|
||||
|
||||
/**
|
||||
* @brief Measure RTC slow clock's period, based on main XTAL frequency
|
||||
*
|
||||
@@ -424,12 +396,12 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles);
|
||||
* the check fails, then consider this an invalid 32k clock and return 0. This
|
||||
* check can filter some jamming signal.
|
||||
*
|
||||
* @param cal_clk clock to be measured
|
||||
* @param cal_clk_sel clock to be measured
|
||||
* @param slow_clk_cycles number of slow clock cycles to average
|
||||
* @return average slow clock period in microseconds, Q13.19 fixed point format,
|
||||
* or 0 if calibration has timed out
|
||||
*/
|
||||
uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slow_clk_cycles);
|
||||
uint32_t rtc_clk_cal(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slow_clk_cycles);
|
||||
|
||||
/**
|
||||
* @brief Convert time interval from microseconds to RTC_SLOW_CLK cycles
|
||||
|
||||
@@ -18,67 +18,69 @@
|
||||
|
||||
__attribute__((unused)) static const char *TAG = "rtc_time";
|
||||
|
||||
/* Calibration of clock frequency is performed using a special feature of TIMG0.
|
||||
* This feature counts the number of XTAL clock cycles within a given number of
|
||||
* clock cycles.
|
||||
*/
|
||||
#define CLK_CAL_TIMEOUT_THRES(cal_clk_sel, cycles) ((cal_clk_sel == CLK_CAL_RC32K || cal_clk_sel == CLK_CAL_32K_XTAL) ? (cycles << 12) : (cycles << 10))
|
||||
|
||||
#define CLK_CAL_TIMEOUT_THRES(cal_clk, cycles) ((cal_clk == RTC_CAL_RC32K || cal_clk == RTC_CAL_32K_XTAL) ? (cycles << 12) : (cycles << 10))
|
||||
|
||||
// Calibration can only be performed on relatively slow speed clock signal. Therefore, for high-speed clocks,
|
||||
// calibration is performed on their DIV_CLKs. The divider is configurable. We set:
|
||||
#define CLK_CAL_DIV_VAL(cal_clk) \
|
||||
((cal_clk == RTC_CAL_RC_SLOW || cal_clk == RTC_CAL_RC32K || cal_clk == RTC_CAL_32K_XTAL) ? 1 : \
|
||||
(cal_clk == RTC_CAL_LP_PLL) ? 25 : \
|
||||
(cal_clk == RTC_CAL_RC_FAST) ? 50 : \
|
||||
(cal_clk == RTC_CAL_APLL) ? 200 : \
|
||||
// Calculation can only be performed on relatively slow speed clock signal. Therefore, for high-speed clocks,
|
||||
// calculation is performed on their DIV_CLKs. The divider is configurable. We set:
|
||||
#define CLK_CAL_DIV_VAL(cal_clk_sel) \
|
||||
((cal_clk_sel == CLK_CAL_RC_SLOW || cal_clk_sel == CLK_CAL_RC32K || cal_clk_sel == CLK_CAL_32K_XTAL) ? 1 : \
|
||||
(cal_clk_sel == CLK_CAL_LP_PLL) ? 25 : \
|
||||
(cal_clk_sel == CLK_CAL_RC_FAST) ? 50 : \
|
||||
(cal_clk_sel == CLK_CAL_APLL) ? 200 : \
|
||||
4000)
|
||||
|
||||
// CLK_CAL_FREQ_APPROX = CLK_FREQ_APPROX / CLK_CAL_DIV_VAL
|
||||
#define CLK_CAL_FREQ_APPROX(cal_clk) \
|
||||
((cal_clk == RTC_CAL_MPLL) ? (CLK_LL_PLL_500M_FREQ_MHZ * MHZ / 4000) : \
|
||||
(cal_clk == RTC_CAL_SPLL) ? (CLK_LL_PLL_480M_FREQ_MHZ * MHZ / 4000) : \
|
||||
(cal_clk == RTC_CAL_CPLL) ? (CLK_LL_PLL_400M_FREQ_MHZ * MHZ / 4000) : \
|
||||
(cal_clk == RTC_CAL_APLL) ? (105 * MHZ / 200) : \
|
||||
(cal_clk == RTC_CAL_SDIO_PLL0 || cal_clk == RTC_CAL_SDIO_PLL1 || cal_clk == RTC_CAL_SDIO_PLL2) ? (200 * MHZ / 4000) : \
|
||||
(cal_clk == RTC_CAL_RC_FAST) ? (SOC_CLK_RC_FAST_FREQ_APPROX / 50) : \
|
||||
(cal_clk == RTC_CAL_RC_SLOW) ? (SOC_CLK_RC_SLOW_FREQ_APPROX) : \
|
||||
(cal_clk == RTC_CAL_RC32K) ? (SOC_CLK_RC32K_FREQ_APPROX) : \
|
||||
(cal_clk == RTC_CAL_32K_XTAL) ? (SOC_CLK_XTAL32K_FREQ_APPROX) : \
|
||||
(cal_clk == RTC_CAL_LP_PLL) ? (CLK_LL_PLL_8M_FREQ_MHZ * MHZ / 25) : \
|
||||
#define CLK_CAL_FREQ_APPROX(cal_clk_sel) \
|
||||
((cal_clk_sel == CLK_CAL_MPLL) ? (CLK_LL_PLL_500M_FREQ_MHZ * MHZ / 4000) : \
|
||||
(cal_clk_sel == CLK_CAL_SPLL) ? (CLK_LL_PLL_480M_FREQ_MHZ * MHZ / 4000) : \
|
||||
(cal_clk_sel == CLK_CAL_CPLL) ? (CLK_LL_PLL_400M_FREQ_MHZ * MHZ / 4000) : \
|
||||
(cal_clk_sel == CLK_CAL_APLL) ? (105 * MHZ / 200) : \
|
||||
(cal_clk_sel == CLK_CAL_SDIO_PLL0 || cal_clk_sel == CLK_CAL_SDIO_PLL1 || cal_clk_sel == CLK_CAL_SDIO_PLL2) ? (200 * MHZ / 4000) : \
|
||||
(cal_clk_sel == CLK_CAL_RC_FAST) ? (SOC_CLK_RC_FAST_FREQ_APPROX / 50) : \
|
||||
(cal_clk_sel == CLK_CAL_RC_SLOW) ? (SOC_CLK_RC_SLOW_FREQ_APPROX) : \
|
||||
(cal_clk_sel == CLK_CAL_RC32K) ? (SOC_CLK_RC32K_FREQ_APPROX) : \
|
||||
(cal_clk_sel == CLK_CAL_32K_XTAL) ? (SOC_CLK_XTAL32K_FREQ_APPROX) : \
|
||||
(cal_clk_sel == CLK_CAL_LP_PLL) ? (CLK_LL_PLL_8M_FREQ_MHZ * MHZ / 25) : \
|
||||
0)
|
||||
|
||||
uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
/**
|
||||
* @brief Clock frequency calculation function used by rtc_clk_cal
|
||||
*
|
||||
* Calculation of clock frequency is performed using a special feature of TIMG0.
|
||||
* This feature counts the number of XTAL clock cycles within a given number of
|
||||
* clock cycles.
|
||||
*
|
||||
* @param cal_clk_sel which clock to calculate frequency
|
||||
* @param slowclk_cycles number of slow clock cycles to count
|
||||
* @return number of XTAL clock cycles within the given number of slow clock cycles
|
||||
*/
|
||||
static uint32_t rtc_clk_cal_internal(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slowclk_cycles)
|
||||
{
|
||||
assert(slowclk_cycles < TIMG_RTC_CALI_MAX_V);
|
||||
|
||||
if (cal_clk == RTC_CAL_RTC_MUX) {
|
||||
if (cal_clk_sel == CLK_CAL_RTC_SLOW) {
|
||||
soc_rtc_slow_clk_src_t slow_clk_src = rtc_clk_slow_src_get();
|
||||
if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC_SLOW) {
|
||||
cal_clk = RTC_CAL_RC_SLOW;
|
||||
cal_clk_sel = CLK_CAL_RC_SLOW;
|
||||
} else if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) {
|
||||
cal_clk = RTC_CAL_32K_XTAL;
|
||||
cal_clk_sel = CLK_CAL_32K_XTAL;
|
||||
} else if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC32K) {
|
||||
cal_clk = RTC_CAL_RC32K;
|
||||
cal_clk_sel = CLK_CAL_RC32K;
|
||||
}
|
||||
}
|
||||
if (cal_clk < 0 || cal_clk >= RTC_CAL_INVALID_CLK) {
|
||||
ESP_EARLY_LOGE(TAG, "clock not supported to be calibrated");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Enable requested clock (some clocks are always on) */
|
||||
// All clocks on/off takes time to be stable, so we shouldn't frequently enable/disable the clock
|
||||
// Only enable if originally was disabled, and set back to the disable state after calibration is done
|
||||
// If the clock is already on, then do nothing
|
||||
bool dig_32k_xtal_enabled = clk_ll_xtal32k_digi_is_enabled();
|
||||
if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
clk_ll_xtal32k_digi_enable();
|
||||
if (cal_clk_sel == CLK_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
clk_ll_xtal32k_digi_enable();
|
||||
}
|
||||
|
||||
bool rc_fast_enabled = clk_ll_rc_fast_is_enabled();
|
||||
bool dig_rc_fast_enabled = clk_ll_rc_fast_digi_is_enabled();
|
||||
if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
if (cal_clk_sel == CLK_CAL_RC_FAST) {
|
||||
if (!rc_fast_enabled) {
|
||||
rtc_clk_8m_enable(true);
|
||||
}
|
||||
@@ -89,7 +91,7 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
|
||||
bool rc32k_enabled = clk_ll_rc32k_is_enabled();
|
||||
bool dig_rc32k_enabled = clk_ll_rc32k_digi_is_enabled();
|
||||
if (cal_clk == RTC_CAL_RC32K) {
|
||||
if (cal_clk_sel == CLK_CAL_RC32K) {
|
||||
if (!rc32k_enabled) {
|
||||
rtc_clk_rc32k_enable(true);
|
||||
}
|
||||
@@ -112,16 +114,16 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
}
|
||||
|
||||
/* Prepare calibration */
|
||||
REG_SET_FIELD(HP_SYS_CLKRST_PERI_CLK_CTRL21_REG, HP_SYS_CLKRST_REG_TIMERGRP0_TGRT_CLK_SRC_SEL, cal_clk);
|
||||
uint32_t clk_cal_divider = CLK_CAL_DIV_VAL(cal_clk);
|
||||
REG_SET_FIELD(HP_SYS_CLKRST_PERI_CLK_CTRL21_REG, HP_SYS_CLKRST_REG_TIMERGRP0_TGRT_CLK_DIV_NUM, clk_cal_divider - 1);
|
||||
clk_ll_freq_calulation_set_target(cal_clk_sel);
|
||||
uint32_t clk_cal_divider = CLK_CAL_DIV_VAL(cal_clk_sel);
|
||||
clk_ll_freq_calculation_set_divider(clk_cal_divider);
|
||||
CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING);
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_MAX, slowclk_cycles);
|
||||
/* Figure out how long to wait for calibration to finish */
|
||||
|
||||
/* Set timeout reg and expect time delay*/
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, CLK_CAL_TIMEOUT_THRES(cal_clk, slowclk_cycles));
|
||||
uint32_t expected_freq = CLK_CAL_FREQ_APPROX(cal_clk);
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, CLK_CAL_TIMEOUT_THRES(cal_clk_sel, slowclk_cycles));
|
||||
uint32_t expected_freq = CLK_CAL_FREQ_APPROX(cal_clk_sel);
|
||||
assert(expected_freq);
|
||||
uint32_t us_time_estimate = (uint32_t) (((uint64_t) slowclk_cycles) * MHZ / expected_freq);
|
||||
/* Start calibration */
|
||||
@@ -143,14 +145,14 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
}
|
||||
}
|
||||
CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START);
|
||||
CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_PERI_CLK_CTRL21_REG, HP_SYS_CLKRST_REG_TIMERGRP0_TGRT_CLK_DIV_NUM_M);
|
||||
clk_ll_freq_calculation_set_divider(1);
|
||||
|
||||
/* if dig_32k_xtal was originally off and enabled due to calibration, then set back to off state */
|
||||
if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
if (cal_clk_sel == CLK_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
clk_ll_xtal32k_digi_disable();
|
||||
}
|
||||
|
||||
if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
if (cal_clk_sel == CLK_CAL_RC_FAST) {
|
||||
if (!dig_rc_fast_enabled) {
|
||||
rtc_dig_clk8m_disable();
|
||||
}
|
||||
@@ -159,7 +161,7 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
}
|
||||
}
|
||||
|
||||
if (cal_clk == RTC_CAL_RC32K) {
|
||||
if (cal_clk_sel == CLK_CAL_RC32K) {
|
||||
if (!dig_rc32k_enabled) {
|
||||
clk_ll_rc32k_digi_disable();
|
||||
}
|
||||
@@ -178,14 +180,14 @@ static bool rtc_clk_cal_32k_valid(uint32_t xtal_freq, uint32_t slowclk_cycles, u
|
||||
return (actual_xtal_cycles >= (expected_xtal_cycles - delta)) && (actual_xtal_cycles <= (expected_xtal_cycles + delta));
|
||||
}
|
||||
|
||||
uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
uint32_t rtc_clk_cal(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slowclk_cycles)
|
||||
{
|
||||
slowclk_cycles /= (cal_clk == RTC_CAL_RTC_MUX) ? 1 : CLK_CAL_DIV_VAL(cal_clk);
|
||||
slowclk_cycles /= (cal_clk_sel == CLK_CAL_RTC_SLOW) ? 1 : CLK_CAL_DIV_VAL(cal_clk_sel);
|
||||
assert(slowclk_cycles);
|
||||
soc_xtal_freq_t xtal_freq = rtc_clk_xtal_freq_get();
|
||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk, slowclk_cycles);
|
||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk_sel, slowclk_cycles);
|
||||
|
||||
if (cal_clk == RTC_CAL_32K_XTAL && !rtc_clk_cal_32k_valid((uint32_t)xtal_freq, slowclk_cycles, xtal_cycles)) {
|
||||
if (cal_clk_sel == CLK_CAL_32K_XTAL && !rtc_clk_cal_32k_valid((uint32_t)xtal_freq, slowclk_cycles, xtal_cycles)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -159,15 +159,10 @@ typedef struct rtc_cpu_freq_config_s {
|
||||
#define RTC_VDDSDIO_TIEH_1_8V 0 //!< TIEH field value for 1.8V VDDSDIO
|
||||
#define RTC_VDDSDIO_TIEH_3_3V 1 //!< TIEH field value for 3.3V VDDSDIO
|
||||
|
||||
/**
|
||||
* @brief Clock source to be calibrated using rtc_clk_cal function
|
||||
*/
|
||||
typedef enum {
|
||||
RTC_CAL_RTC_MUX = 0, //!< Currently selected RTC SLOW_CLK
|
||||
RTC_CAL_8MD256 = 1, //!< Internal 8 MHz RC oscillator, divided by 256
|
||||
RTC_CAL_32K_XTAL = 2, //!< External 32 kHz XTAL
|
||||
RTC_CAL_INTERNAL_OSC = 3 //!< Internal 150 kHz oscillator
|
||||
} rtc_cal_sel_t;
|
||||
#define RTC_CAL_RTC_MUX _Pragma ("GCC warning \"'RTC_CAL_RTC_MUX' macro is deprecated\"") CLK_CAL_RTC_SLOW
|
||||
#define RTC_CAL_8MD256 _Pragma ("GCC warning \"'RTC_CAL_8MD256' macro is deprecated\"") CLK_CAL_RC_FAST_D256
|
||||
#define RTC_CAL_32K_XTAL _Pragma ("GCC warning \"'RTC_CAL_32K_XTAL' macro is deprecated\"") CLK_CAL_32K_XTAL
|
||||
#define RTC_CAL_INTERNAL_OSC _Pragma ("GCC warning \"'RTC_CAL_INTERNAL_OSC' macro is deprecated\"") CLK_CAL_RC_SLOW
|
||||
|
||||
/**
|
||||
* Initialization parameters for rtc_clk_init
|
||||
@@ -470,8 +465,6 @@ void rtc_clk_apb_freq_update(uint32_t apb_freq);
|
||||
*/
|
||||
uint32_t rtc_clk_apb_freq_get(void);
|
||||
|
||||
uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles, uint32_t cal_mode);
|
||||
|
||||
/**
|
||||
* @brief Measure RTC slow clock's period, based on main XTAL frequency
|
||||
*
|
||||
@@ -485,21 +478,21 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles, ui
|
||||
* the check fails, then consider this an invalid 32k clock and return 0. This
|
||||
* check can filter some jamming signal.
|
||||
*
|
||||
* @param cal_clk clock to be measured
|
||||
* @param cal_clk_sel clock to be measured
|
||||
* @param slow_clk_cycles number of slow clock cycles to average
|
||||
* @return average slow clock period in microseconds, Q13.19 fixed point format,
|
||||
* or 0 if calibration has timed out
|
||||
*/
|
||||
uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slow_clk_cycles);
|
||||
uint32_t rtc_clk_cal(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slow_clk_cycles);
|
||||
|
||||
/**
|
||||
* @brief Measure ratio between XTAL frequency and RTC slow clock frequency
|
||||
* @param cal_clk slow clock to be measured
|
||||
* @param cal_clk_sel slow clock to be measured
|
||||
* @param slow_clk_cycles number of slow clock cycles to average
|
||||
* @return average ratio between XTAL frequency and slow clock frequency,
|
||||
* Q13.19 fixed point format, or 0 if calibration has timed out.
|
||||
*/
|
||||
uint32_t rtc_clk_cal_ratio(rtc_cal_sel_t cal_clk, uint32_t slow_clk_cycles);
|
||||
uint32_t rtc_clk_cal_ratio(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slow_clk_cycles);
|
||||
|
||||
/**
|
||||
* @brief Convert time interval from microseconds to RTC_SLOW_CLK cycles
|
||||
@@ -848,10 +841,10 @@ void rtc_vddsdio_set_config(rtc_vddsdio_config_t config);
|
||||
/**
|
||||
* Using valid hardware calibration value to calibrate slowclk
|
||||
* If there is no hardware calibration in process, start hardware calibration and wait for calibration finished
|
||||
* @param cal_clk clock to be measured
|
||||
* @param cal_clk_sel clock to be measured
|
||||
* @param slowclk_cycles if no hardware calibration in process, use this amount of slow cycles to calibrate slowclk.
|
||||
*/
|
||||
uint32_t rtc_clk_cal_cycling(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles);
|
||||
uint32_t rtc_clk_cal_cycling(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slowclk_cycles);
|
||||
|
||||
|
||||
// -------------------------- CLOCK TREE DEFS ALIAS ----------------------------
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -255,16 +255,9 @@ static void calibrate_ocode(void)
|
||||
4. wait o-code calibration done flag(odone_flag & bg_odone_flag) or timeout;
|
||||
5. set cpu to old-config.
|
||||
*/
|
||||
soc_rtc_slow_clk_src_t slow_clk_src = rtc_clk_slow_src_get();
|
||||
rtc_cal_sel_t cal_clk = RTC_CAL_RTC_MUX;
|
||||
if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) {
|
||||
cal_clk = RTC_CAL_32K_XTAL;
|
||||
} else if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256) {
|
||||
cal_clk = RTC_CAL_8MD256;
|
||||
}
|
||||
|
||||
uint64_t max_delay_time_us = 10000;
|
||||
uint32_t slow_clk_period = rtc_clk_cal(cal_clk, 100);
|
||||
uint32_t slow_clk_period = rtc_clk_cal(CLK_CAL_RTC_SLOW, 100);
|
||||
uint64_t max_delay_cycle = rtc_time_us_to_slowclk(max_delay_time_us, slow_clk_period);
|
||||
uint64_t cycle0 = rtc_time_get();
|
||||
uint64_t timeout_cycle = cycle0 + max_delay_cycle;
|
||||
|
||||
@@ -14,11 +14,11 @@
|
||||
#include "soc/timer_group_reg.h"
|
||||
#include "esp_private/periph_ctrl.h"
|
||||
|
||||
/* Calibration of RTC_SLOW_CLK is performed using a special feature of TIMG0.
|
||||
/* Calculation of RTC_SLOW_CLK is performed using a special feature of TIMG0.
|
||||
* This feature counts the number of XTAL clock cycles within a given number of
|
||||
* RTC_SLOW_CLK cycles.
|
||||
*
|
||||
* Slow clock calibration feature has two modes of operation: one-off and cycling.
|
||||
* Slow clock frequency calculation feature has two modes of operation: one-off and cycling.
|
||||
* In cycling mode (which is enabled by default on SoC reset), counting of XTAL
|
||||
* cycles within RTC_SLOW_CLK cycle is done continuously. Cycling mode is enabled
|
||||
* using TIMG_RTC_CALI_START_CYCLING bit. In one-off mode counting is performed
|
||||
@@ -28,11 +28,11 @@
|
||||
|
||||
/**
|
||||
* @brief One-off clock calibration function used by rtc_clk_cal_internal
|
||||
* @param cal_clk which clock to calibrate
|
||||
* @param cal_clk_sel which clock to calculate frequency
|
||||
* @param slowclk_cycles number of slow clock cycles to count
|
||||
* @return number of XTAL clock cycles within the given number of slow clock cycles
|
||||
*/
|
||||
static uint32_t rtc_clk_cal_internal_oneoff(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
static uint32_t rtc_clk_cal_internal_oneoff(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slowclk_cycles)
|
||||
{
|
||||
/* There may be another calibration process already running during we call this function,
|
||||
* so we should wait the last process is done.
|
||||
@@ -48,17 +48,17 @@ static uint32_t rtc_clk_cal_internal_oneoff(rtc_cal_sel_t cal_clk, uint32_t slow
|
||||
}
|
||||
|
||||
/* Prepare calibration */
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_CLK_SEL, cal_clk);
|
||||
clk_ll_freq_calulation_set_target(cal_clk_sel);
|
||||
CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING);
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_MAX, slowclk_cycles);
|
||||
/* Figure out how long to wait for calibration to finish */
|
||||
|
||||
/* Set timeout reg and expect time delay*/
|
||||
uint32_t expected_freq;
|
||||
if (cal_clk == RTC_CAL_32K_XTAL) {
|
||||
if (cal_clk_sel == CLK_CAL_32K_XTAL) {
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_SLOW_CLK_X32K_CAL_TIMEOUT_THRES(slowclk_cycles));
|
||||
expected_freq = SOC_CLK_XTAL32K_FREQ_APPROX;
|
||||
} else if (cal_clk == RTC_CAL_8MD256) {
|
||||
} else if (cal_clk_sel == CLK_CAL_RC_FAST_D256) {
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_SLOW_CLK_8MD256_CAL_TIMEOUT_THRES(slowclk_cycles));
|
||||
expected_freq = SOC_CLK_RC_FAST_D256_FREQ_APPROX;
|
||||
} else {
|
||||
@@ -89,20 +89,19 @@ static uint32_t rtc_clk_cal_internal_oneoff(rtc_cal_sel_t cal_clk, uint32_t slow
|
||||
|
||||
/**
|
||||
* @brief Cycling clock calibration function used by rtc_clk_cal_internal
|
||||
* @param cal_clk which clock to calibrate
|
||||
* @param cal_clk_sel which clock to calculate frequency
|
||||
* @param slowclk_cycles number of slow clock cycles to count
|
||||
* @return number of XTAL clock cycles within the given number of slow clock cycles
|
||||
*/
|
||||
static uint32_t rtc_clk_cal_internal_cycling(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
static uint32_t rtc_clk_cal_internal_cycling(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slowclk_cycles)
|
||||
{
|
||||
/* Get which slowclk is in calibration and max cali cycles */
|
||||
rtc_cal_sel_t in_calibration_clk;
|
||||
in_calibration_clk = REG_GET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_CLK_SEL);
|
||||
soc_clk_freq_calculation_src_t in_calibration_clk = REG_GET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_CLK_SEL);
|
||||
uint32_t cali_slowclk_cycles = REG_GET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_MAX);
|
||||
/* If no calibration in process or calibration period equal to 0, use slowclk_cycles cycles to calibrate slowclk */
|
||||
if (cali_slowclk_cycles == 0 || !GET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING) || in_calibration_clk != cal_clk) {
|
||||
if (cali_slowclk_cycles == 0 || !GET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING) || in_calibration_clk != cal_clk_sel) {
|
||||
CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING);
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_CLK_SEL, cal_clk);
|
||||
clk_ll_freq_calulation_set_target(cal_clk_sel);
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_MAX, slowclk_cycles);
|
||||
SET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING);
|
||||
cali_slowclk_cycles = slowclk_cycles;
|
||||
@@ -133,56 +132,51 @@ static uint32_t rtc_clk_xtal_to_slowclk(uint64_t xtal_cycles, uint32_t slowclk_c
|
||||
|
||||
/**
|
||||
* @brief Clock calibration function used by rtc_clk_cal and rtc_clk_cal_ratio
|
||||
* @param cal_clk which clock to calibrate
|
||||
* @param cal_clk_sel which clock to calculate frequency
|
||||
* @param slowclk_cycles number of slow clock cycles to count
|
||||
* @return number of XTAL clock cycles within the given number of slow clock cycles
|
||||
*/
|
||||
uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles, uint32_t cal_mode)
|
||||
static uint32_t rtc_clk_cal_internal(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slowclk_cycles, uint32_t cal_mode)
|
||||
{
|
||||
/* On ESP32S2, choosing RTC_CAL_RTC_MUX results in calibration of
|
||||
* the 90k RTC clock regardless of the currently selected SLOW_CLK.
|
||||
* On the ESP32, it used the currently selected SLOW_CLK.
|
||||
* The following code emulates ESP32 behavior:
|
||||
*/
|
||||
if (cal_clk == RTC_CAL_RTC_MUX) {
|
||||
if (cal_clk_sel == CLK_CAL_RTC_SLOW) {
|
||||
soc_rtc_slow_clk_src_t slow_clk_src = rtc_clk_slow_src_get();
|
||||
if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) {
|
||||
cal_clk = RTC_CAL_32K_XTAL;
|
||||
if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC_SLOW) {
|
||||
cal_clk_sel = CLK_CAL_RC_SLOW;
|
||||
} else if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) {
|
||||
cal_clk_sel = CLK_CAL_32K_XTAL;
|
||||
} else if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256) {
|
||||
cal_clk = RTC_CAL_8MD256;
|
||||
cal_clk_sel = CLK_CAL_RC_FAST_D256;
|
||||
}
|
||||
} else if (cal_clk == RTC_CAL_INTERNAL_OSC) {
|
||||
cal_clk = RTC_CAL_RTC_MUX;
|
||||
}
|
||||
|
||||
/* Enable requested clock (90k clock is always on) */
|
||||
bool dig_32k_xtal_enabled = clk_ll_xtal32k_digi_is_enabled();
|
||||
if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
if (cal_clk_sel == CLK_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
clk_ll_xtal32k_digi_enable();
|
||||
}
|
||||
|
||||
bool rc_fast_enabled = clk_ll_rc_fast_is_enabled();
|
||||
bool rc_fast_d256_enabled = clk_ll_rc_fast_d256_is_enabled();
|
||||
if (cal_clk == RTC_CAL_8MD256) {
|
||||
if (cal_clk_sel == CLK_CAL_RC_FAST_D256) {
|
||||
rtc_clk_8m_enable(true, true);
|
||||
clk_ll_rc_fast_d256_digi_enable();
|
||||
}
|
||||
|
||||
uint32_t cal_val;
|
||||
if (cal_mode == RTC_TIME_CAL_ONEOFF_MODE) {
|
||||
cal_val = rtc_clk_cal_internal_oneoff(cal_clk, slowclk_cycles);
|
||||
cal_val = rtc_clk_cal_internal_oneoff(cal_clk_sel, slowclk_cycles);
|
||||
} else {
|
||||
cal_val = rtc_clk_cal_internal_cycling(cal_clk, slowclk_cycles);
|
||||
cal_val = rtc_clk_cal_internal_cycling(cal_clk_sel, slowclk_cycles);
|
||||
}
|
||||
|
||||
CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START);
|
||||
|
||||
/* if dig_32k_xtal was originally off and enabled due to calibration, then set back to off state */
|
||||
if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
if (cal_clk_sel == CLK_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
clk_ll_xtal32k_digi_disable();
|
||||
}
|
||||
|
||||
if (cal_clk == RTC_CAL_8MD256) {
|
||||
if (cal_clk_sel == CLK_CAL_RC_FAST_D256) {
|
||||
clk_ll_rc_fast_d256_digi_disable();
|
||||
rtc_clk_8m_enable(rc_fast_enabled, rc_fast_d256_enabled);
|
||||
}
|
||||
@@ -190,10 +184,10 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles, ui
|
||||
return cal_val;
|
||||
}
|
||||
|
||||
uint32_t rtc_clk_cal_ratio(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
uint32_t rtc_clk_cal_ratio(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slowclk_cycles)
|
||||
{
|
||||
assert(slowclk_cycles);
|
||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk, slowclk_cycles, RTC_TIME_CAL_ONEOFF_MODE);
|
||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk_sel, slowclk_cycles, RTC_TIME_CAL_ONEOFF_MODE);
|
||||
uint64_t ratio_64 = ((xtal_cycles << RTC_CLK_CAL_FRACT)) / slowclk_cycles;
|
||||
uint32_t ratio = (uint32_t)(ratio_64 & UINT32_MAX);
|
||||
return ratio;
|
||||
@@ -206,20 +200,20 @@ static inline bool rtc_clk_cal_32k_valid(uint32_t xtal_freq, uint32_t slowclk_cy
|
||||
return (actual_xtal_cycles >= (expected_xtal_cycles - delta)) && (actual_xtal_cycles <= (expected_xtal_cycles + delta));
|
||||
}
|
||||
|
||||
uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
uint32_t rtc_clk_cal(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slowclk_cycles)
|
||||
{
|
||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk, slowclk_cycles, RTC_TIME_CAL_ONEOFF_MODE);
|
||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk_sel, slowclk_cycles, RTC_TIME_CAL_ONEOFF_MODE);
|
||||
|
||||
if ((cal_clk == RTC_CAL_32K_XTAL) && !rtc_clk_cal_32k_valid((uint32_t)rtc_clk_xtal_freq_get(), slowclk_cycles, xtal_cycles)) {
|
||||
if ((cal_clk_sel == CLK_CAL_32K_XTAL) && !rtc_clk_cal_32k_valid((uint32_t)rtc_clk_xtal_freq_get(), slowclk_cycles, xtal_cycles)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return rtc_clk_xtal_to_slowclk(xtal_cycles, slowclk_cycles);
|
||||
}
|
||||
|
||||
uint32_t rtc_clk_cal_cycling(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
uint32_t rtc_clk_cal_cycling(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slowclk_cycles)
|
||||
{
|
||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk, slowclk_cycles, RTC_TIME_CAL_CYCLING_MODE);
|
||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk_sel, slowclk_cycles, RTC_TIME_CAL_CYCLING_MODE);
|
||||
uint32_t period = rtc_clk_xtal_to_slowclk(xtal_cycles, slowclk_cycles);
|
||||
return period;
|
||||
}
|
||||
|
||||
@@ -161,15 +161,10 @@ typedef struct rtc_cpu_freq_config_s {
|
||||
#define RTC_VDDSDIO_TIEH_1_8V 0 //!< TIEH field value for 1.8V VDDSDIO
|
||||
#define RTC_VDDSDIO_TIEH_3_3V 1 //!< TIEH field value for 3.3V VDDSDIO
|
||||
|
||||
/**
|
||||
* @brief Clock source to be calibrated using rtc_clk_cal function
|
||||
*/
|
||||
typedef enum {
|
||||
RTC_CAL_RTC_MUX = 0, //!< Currently selected RTC SLOW_CLK
|
||||
RTC_CAL_8MD256 = 1, //!< Internal 8 MHz RC oscillator, divided by 256
|
||||
RTC_CAL_32K_XTAL = 2, //!< External 32 kHz XTAL
|
||||
RTC_CAL_INTERNAL_OSC = 3 //!< Internal 150 kHz oscillator
|
||||
} rtc_cal_sel_t;
|
||||
#define RTC_CAL_RTC_MUX _Pragma ("GCC warning \"'RTC_CAL_RTC_MUX' macro is deprecated\"") CLK_CAL_RTC_SLOW
|
||||
#define RTC_CAL_8MD256 _Pragma ("GCC warning \"'RTC_CAL_8MD256' macro is deprecated\"") CLK_CAL_RC_FAST_D256
|
||||
#define RTC_CAL_32K_XTAL _Pragma ("GCC warning \"'RTC_CAL_32K_XTAL' macro is deprecated\"") CLK_CAL_32K_XTAL
|
||||
#define RTC_CAL_INTERNAL_OSC _Pragma ("GCC warning \"'RTC_CAL_INTERNAL_OSC' macro is deprecated\"") CLK_CAL_RC_SLOW
|
||||
|
||||
/**
|
||||
* Initialization parameters for rtc_clk_init
|
||||
@@ -448,8 +443,6 @@ void rtc_clk_apb_freq_update(uint32_t apb_freq);
|
||||
*/
|
||||
uint32_t rtc_clk_apb_freq_get(void);
|
||||
|
||||
uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles);
|
||||
|
||||
/**
|
||||
* @brief Measure RTC slow clock's period, based on main XTAL frequency
|
||||
*
|
||||
@@ -463,21 +456,21 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles);
|
||||
* the check fails, then consider this an invalid 32k clock and return 0. This
|
||||
* check can filter some jamming signal.
|
||||
*
|
||||
* @param cal_clk clock to be measured
|
||||
* @param cal_clk_sel clock to be measured
|
||||
* @param slow_clk_cycles number of slow clock cycles to average
|
||||
* @return average slow clock period in microseconds, Q13.19 fixed point format,
|
||||
* or 0 if calibration has timed out
|
||||
*/
|
||||
uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slow_clk_cycles);
|
||||
uint32_t rtc_clk_cal(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slow_clk_cycles);
|
||||
|
||||
/**
|
||||
* @brief Measure ratio between XTAL frequency and RTC slow clock frequency
|
||||
* @param cal_clk slow clock to be measured
|
||||
* @param cal_clk_sel slow clock to be measured
|
||||
* @param slow_clk_cycles number of slow clock cycles to average
|
||||
* @return average ratio between XTAL frequency and slow clock frequency,
|
||||
* Q13.19 fixed point format, or 0 if calibration has timed out.
|
||||
*/
|
||||
uint32_t rtc_clk_cal_ratio(rtc_cal_sel_t cal_clk, uint32_t slow_clk_cycles);
|
||||
uint32_t rtc_clk_cal_ratio(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slow_clk_cycles);
|
||||
|
||||
/**
|
||||
* @brief Convert time interval from microseconds to RTC_SLOW_CLK cycles
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -283,16 +283,9 @@ static void calibrate_ocode(void)
|
||||
4. wait o-code calibration done flag(odone_flag & bg_odone_flag) or timeout;
|
||||
5. set cpu to old-config.
|
||||
*/
|
||||
soc_rtc_slow_clk_src_t slow_clk_src = rtc_clk_slow_src_get();
|
||||
rtc_cal_sel_t cal_clk = RTC_CAL_RTC_MUX;
|
||||
if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) {
|
||||
cal_clk = RTC_CAL_32K_XTAL;
|
||||
} else if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256) {
|
||||
cal_clk = RTC_CAL_8MD256;
|
||||
}
|
||||
|
||||
uint64_t max_delay_time_us = 10000;
|
||||
uint32_t slow_clk_period = rtc_clk_cal(cal_clk, 100);
|
||||
uint32_t slow_clk_period = rtc_clk_cal(CLK_CAL_RTC_SLOW, 100);
|
||||
uint64_t max_delay_cycle = rtc_time_us_to_slowclk(max_delay_time_us, slow_clk_period);
|
||||
uint64_t cycle0 = rtc_time_get();
|
||||
uint64_t timeout_cycle = cycle0 + max_delay_cycle;
|
||||
|
||||
@@ -14,11 +14,11 @@
|
||||
#include "soc/timer_group_reg.h"
|
||||
#include "esp_private/periph_ctrl.h"
|
||||
|
||||
/* Calibration of RTC_SLOW_CLK is performed using a special feature of TIMG0.
|
||||
/* Calculation of RTC_SLOW_CLK is performed using a special feature of TIMG0.
|
||||
* This feature counts the number of XTAL clock cycles within a given number of
|
||||
* RTC_SLOW_CLK cycles.
|
||||
*
|
||||
* Slow clock calibration feature has two modes of operation: one-off and cycling.
|
||||
* Slow clock frequency calculation feature has two modes of operation: one-off and cycling.
|
||||
* In cycling mode (which is enabled by default on SoC reset), counting of XTAL
|
||||
* cycles within RTC_SLOW_CLK cycle is done continuously. Cycling mode is enabled
|
||||
* using TIMG_RTC_CALI_START_CYCLING bit. In one-off mode counting is performed
|
||||
@@ -27,38 +27,33 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Clock calibration function used by rtc_clk_cal and rtc_clk_cal_ratio
|
||||
* @param cal_clk which clock to calibrate
|
||||
* @brief Clock frequency calculation function used by rtc_clk_cal and rtc_clk_cal_ratio
|
||||
* @param cal_clk_sel which clock to calculate frequency
|
||||
* @param slowclk_cycles number of slow clock cycles to count
|
||||
* @return number of XTAL clock cycles within the given number of slow clock cycles
|
||||
*/
|
||||
uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
static uint32_t rtc_clk_cal_internal(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slowclk_cycles)
|
||||
{
|
||||
/* On ESP32S3, choosing RTC_CAL_RTC_MUX results in calibration of
|
||||
* the 150k RTC clock regardless of the currently selected SLOW_CLK.
|
||||
* On the ESP32, it used the currently selected SLOW_CLK.
|
||||
* The following code emulates ESP32 behavior:
|
||||
*/
|
||||
if (cal_clk == RTC_CAL_RTC_MUX) {
|
||||
if (cal_clk_sel == CLK_CAL_RTC_SLOW) {
|
||||
soc_rtc_slow_clk_src_t slow_clk_src = rtc_clk_slow_src_get();
|
||||
if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) {
|
||||
cal_clk = RTC_CAL_32K_XTAL;
|
||||
if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC_SLOW) {
|
||||
cal_clk_sel = CLK_CAL_RC_SLOW;
|
||||
} else if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) {
|
||||
cal_clk_sel = CLK_CAL_32K_XTAL;
|
||||
} else if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256) {
|
||||
cal_clk = RTC_CAL_8MD256;
|
||||
cal_clk_sel = CLK_CAL_RC_FAST_D256;
|
||||
}
|
||||
} else if (cal_clk == RTC_CAL_INTERNAL_OSC) {
|
||||
cal_clk = RTC_CAL_RTC_MUX;
|
||||
}
|
||||
|
||||
/* Enable requested clock (150k clock is always on) */
|
||||
bool dig_32k_xtal_enabled = clk_ll_xtal32k_digi_is_enabled();
|
||||
if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
if (cal_clk_sel == CLK_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
clk_ll_xtal32k_digi_enable();
|
||||
}
|
||||
|
||||
bool rc_fast_enabled = clk_ll_rc_fast_is_enabled();
|
||||
bool rc_fast_d256_enabled = clk_ll_rc_fast_d256_is_enabled();
|
||||
if (cal_clk == RTC_CAL_8MD256) {
|
||||
if (cal_clk_sel == CLK_CAL_RC_FAST_D256) {
|
||||
rtc_clk_8m_enable(true, true);
|
||||
clk_ll_rc_fast_d256_digi_enable();
|
||||
}
|
||||
@@ -76,17 +71,17 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
}
|
||||
|
||||
/* Prepare calibration */
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_CLK_SEL, cal_clk);
|
||||
clk_ll_freq_calulation_set_target(cal_clk_sel);
|
||||
CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING);
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_MAX, slowclk_cycles);
|
||||
/* Figure out how long to wait for calibration to finish */
|
||||
|
||||
/* Set timeout reg and expect time delay*/
|
||||
uint32_t expected_freq;
|
||||
if (cal_clk == RTC_CAL_32K_XTAL) {
|
||||
if (cal_clk_sel == CLK_CAL_32K_XTAL) {
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_SLOW_CLK_X32K_CAL_TIMEOUT_THRES(slowclk_cycles));
|
||||
expected_freq = SOC_CLK_XTAL32K_FREQ_APPROX;
|
||||
} else if (cal_clk == RTC_CAL_8MD256) {
|
||||
} else if (cal_clk_sel == CLK_CAL_RC_FAST_D256) {
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_SLOW_CLK_8MD256_CAL_TIMEOUT_THRES(slowclk_cycles));
|
||||
expected_freq = SOC_CLK_RC_FAST_D256_FREQ_APPROX;
|
||||
} else {
|
||||
@@ -114,11 +109,11 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START);
|
||||
|
||||
/* if dig_32k_xtal was originally off and enabled due to calibration, then set back to off state */
|
||||
if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
if (cal_clk_sel == CLK_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
clk_ll_xtal32k_digi_disable();
|
||||
}
|
||||
|
||||
if (cal_clk == RTC_CAL_8MD256) {
|
||||
if (cal_clk_sel == CLK_CAL_RC_FAST_D256) {
|
||||
clk_ll_rc_fast_d256_digi_disable();
|
||||
rtc_clk_8m_enable(rc_fast_enabled, rc_fast_d256_enabled);
|
||||
}
|
||||
@@ -126,10 +121,10 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
return cal_val;
|
||||
}
|
||||
|
||||
uint32_t rtc_clk_cal_ratio(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
uint32_t rtc_clk_cal_ratio(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slowclk_cycles)
|
||||
{
|
||||
assert(slowclk_cycles);
|
||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk, slowclk_cycles);
|
||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk_sel, slowclk_cycles);
|
||||
uint64_t ratio_64 = ((xtal_cycles << RTC_CLK_CAL_FRACT)) / slowclk_cycles;
|
||||
uint32_t ratio = (uint32_t)(ratio_64 & UINT32_MAX);
|
||||
return ratio;
|
||||
@@ -142,13 +137,13 @@ static inline bool rtc_clk_cal_32k_valid(uint32_t xtal_freq, uint32_t slowclk_cy
|
||||
return (actual_xtal_cycles >= (expected_xtal_cycles - delta)) && (actual_xtal_cycles <= (expected_xtal_cycles + delta));
|
||||
}
|
||||
|
||||
uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
uint32_t rtc_clk_cal(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slowclk_cycles)
|
||||
{
|
||||
assert(slowclk_cycles);
|
||||
soc_xtal_freq_t xtal_freq = rtc_clk_xtal_freq_get();
|
||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk, slowclk_cycles);
|
||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk_sel, slowclk_cycles);
|
||||
|
||||
if ((cal_clk == RTC_CAL_32K_XTAL) && !rtc_clk_cal_32k_valid((uint32_t)xtal_freq, slowclk_cycles, xtal_cycles)) {
|
||||
if ((cal_clk_sel == CLK_CAL_32K_XTAL) && !rtc_clk_cal_32k_valid((uint32_t)xtal_freq, slowclk_cycles, xtal_cycles)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -59,7 +59,7 @@ 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);
|
||||
cal_val = rtc_clk_cal(CLK_CAL_RTC_SLOW, 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();
|
||||
@@ -82,11 +82,11 @@ uint32_t esp_clk_tree_rc_fast_d256_get_freq_hz(esp_clk_tree_src_freq_precision_t
|
||||
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));
|
||||
s_calibrated_freq.rc_fast_d256 = rtc_clk_freq_cal(rtc_clk_cal(CLK_CAL_RC_FAST_D256, 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));
|
||||
s_calibrated_freq.rc_fast_d256 = rtc_clk_freq_cal(rtc_clk_cal(CLK_CAL_RC_FAST_D256, DEFAULT_32K_CLK_CAL_CYCLES));
|
||||
return s_calibrated_freq.rc_fast_d256;
|
||||
default:
|
||||
return 0;
|
||||
@@ -102,11 +102,11 @@ uint32_t esp_clk_tree_xtal32k_get_freq_hz(esp_clk_tree_src_freq_precision_t prec
|
||||
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));
|
||||
s_calibrated_freq.xtal32k = rtc_clk_freq_cal(rtc_clk_cal(CLK_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));
|
||||
s_calibrated_freq.xtal32k = rtc_clk_freq_cal(rtc_clk_cal(CLK_CAL_32K_XTAL, DEFAULT_32K_CLK_CAL_CYCLES));
|
||||
return s_calibrated_freq.xtal32k;
|
||||
default:
|
||||
return 0;
|
||||
@@ -122,11 +122,11 @@ uint32_t esp_clk_tree_osc_slow_get_freq_hz(esp_clk_tree_src_freq_precision_t pre
|
||||
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));
|
||||
s_calibrated_freq.osc_slow = rtc_clk_freq_cal(rtc_clk_cal(CLK_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));
|
||||
s_calibrated_freq.osc_slow = rtc_clk_freq_cal(rtc_clk_cal(CLK_CAL_32K_OSC_SLOW, DEFAULT_32K_CLK_CAL_CYCLES));
|
||||
return s_calibrated_freq.osc_slow;
|
||||
default:
|
||||
return 0;
|
||||
@@ -161,7 +161,7 @@ uint32_t esp_clk_tree_rc_fast_get_freq_hz(esp_clk_tree_src_freq_precision_t prec
|
||||
#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));
|
||||
s_calibrated_freq.rc_fast = rtc_clk_freq_cal(rtc_clk_cal(CLK_CAL_RC_FAST, DEFAULT_RC_FAST_CAL_CYCLES));
|
||||
}
|
||||
return s_calibrated_freq.rc_fast;
|
||||
#endif //SOC_CLK_RC_FAST_D256_SUPPORTED
|
||||
|
||||
@@ -828,18 +828,18 @@ static SLEEP_FN_ATTR void sleep_low_power_clock_calibration(bool is_dslp)
|
||||
} else {
|
||||
// If the external 32 kHz XTAL does not exist, use the internal 150 kHz RC oscillator
|
||||
// as the RTC slow clock source.
|
||||
s_config.rtc_clk_cal_period = rtc_clk_cal(RTC_CAL_RTC_MUX, RTC_CLK_SRC_CAL_CYCLES);
|
||||
s_config.rtc_clk_cal_period = rtc_clk_cal(CLK_CAL_RTC_SLOW, RTC_CLK_SRC_CAL_CYCLES);
|
||||
esp_clk_slowclk_cal_set(s_config.rtc_clk_cal_period);
|
||||
}
|
||||
#elif CONFIG_RTC_CLK_SRC_INT_RC && CONFIG_IDF_TARGET_ESP32S2
|
||||
s_config.rtc_clk_cal_period = rtc_clk_cal_cycling(RTC_CAL_RTC_MUX, RTC_CLK_SRC_CAL_CYCLES);
|
||||
s_config.rtc_clk_cal_period = rtc_clk_cal_cycling(CLK_CAL_RTC_SLOW, RTC_CLK_SRC_CAL_CYCLES);
|
||||
esp_clk_slowclk_cal_set(s_config.rtc_clk_cal_period);
|
||||
#else
|
||||
#if CONFIG_PM_ENABLE
|
||||
if ((s_lightsleep_cnt % CONFIG_PM_LIGHTSLEEP_RTC_OSC_CAL_INTERVAL == 0) || is_dslp)
|
||||
#endif
|
||||
{
|
||||
s_config.rtc_clk_cal_period = rtc_clk_cal(RTC_CAL_RTC_MUX, RTC_CLK_SRC_CAL_CYCLES);
|
||||
s_config.rtc_clk_cal_period = rtc_clk_cal(CLK_CAL_RTC_SLOW, RTC_CLK_SRC_CAL_CYCLES);
|
||||
esp_clk_slowclk_cal_set(s_config.rtc_clk_cal_period);
|
||||
}
|
||||
#endif
|
||||
@@ -850,7 +850,7 @@ static SLEEP_FN_ATTR void sleep_low_power_clock_calibration(bool is_dslp)
|
||||
if ((s_lightsleep_cnt % CONFIG_PM_LIGHTSLEEP_RTC_OSC_CAL_INTERVAL == 0) || is_dslp)
|
||||
#endif
|
||||
{
|
||||
s_config.fast_clk_cal_period = rtc_clk_cal(RTC_CAL_RC_FAST, FAST_CLK_SRC_CAL_CYCLES);
|
||||
s_config.fast_clk_cal_period = rtc_clk_cal(CLK_CAL_RC_FAST, FAST_CLK_SRC_CAL_CYCLES);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
#define CALIBRATE_ONE(cali_clk) calibrate_one(cali_clk, #cali_clk)
|
||||
|
||||
static uint32_t calibrate_one(rtc_cal_sel_t cal_clk, const char* name)
|
||||
static uint32_t calibrate_one(soc_clk_freq_calculation_src_t cal_clk, const char* name)
|
||||
{
|
||||
const uint32_t cal_count = 1000;
|
||||
const float factor = (1 << 19) * 1000.0f;
|
||||
@@ -54,13 +54,13 @@ TEST_CASE("RTC_SLOW_CLK sources calibration", "[rtc_clk]")
|
||||
|
||||
// By default Kconfig, RTC_SLOW_CLK source is RC_SLOW
|
||||
soc_rtc_slow_clk_src_t default_rtc_slow_clk_src = rtc_clk_slow_src_get();
|
||||
CALIBRATE_ONE(RTC_CAL_RTC_MUX);
|
||||
CALIBRATE_ONE(CLK_CAL_RTC_SLOW);
|
||||
#if SOC_CLK_RC_FAST_D256_SUPPORTED
|
||||
CALIBRATE_ONE(RTC_CAL_8MD256);
|
||||
CALIBRATE_ONE(CLK_CAL_RC_FAST_D256);
|
||||
#endif
|
||||
|
||||
#if SOC_CLK_XTAL32K_SUPPORTED
|
||||
uint32_t cal_32k = CALIBRATE_ONE(RTC_CAL_32K_XTAL);
|
||||
uint32_t cal_32k = CALIBRATE_ONE(CLK_CAL_32K_XTAL);
|
||||
if (cal_32k == 0) {
|
||||
printf("32K XTAL OSC has not started up\n");
|
||||
} else {
|
||||
@@ -68,11 +68,11 @@ TEST_CASE("RTC_SLOW_CLK sources calibration", "[rtc_clk]")
|
||||
rtc_clk_slow_src_set(SOC_RTC_SLOW_CLK_SRC_XTAL32K);
|
||||
printf("done\n");
|
||||
|
||||
CALIBRATE_ONE(RTC_CAL_RTC_MUX);
|
||||
CALIBRATE_ONE(CLK_CAL_RTC_SLOW);
|
||||
#if SOC_CLK_RC_FAST_D256_SUPPORTED
|
||||
CALIBRATE_ONE(RTC_CAL_8MD256);
|
||||
CALIBRATE_ONE(CLK_CAL_RC_FAST_D256);
|
||||
#endif
|
||||
CALIBRATE_ONE(RTC_CAL_32K_XTAL);
|
||||
CALIBRATE_ONE(CLK_CAL_32K_XTAL);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -81,16 +81,16 @@ TEST_CASE("RTC_SLOW_CLK sources calibration", "[rtc_clk]")
|
||||
rtc_clk_slow_src_set(SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256);
|
||||
printf("done\n");
|
||||
|
||||
CALIBRATE_ONE(RTC_CAL_RTC_MUX);
|
||||
CALIBRATE_ONE(RTC_CAL_8MD256);
|
||||
CALIBRATE_ONE(CLK_CAL_RTC_SLOW);
|
||||
CALIBRATE_ONE(CLK_CAL_RC_FAST_D256);
|
||||
#if SOC_CLK_XTAL32K_SUPPORTED
|
||||
CALIBRATE_ONE(RTC_CAL_32K_XTAL);
|
||||
CALIBRATE_ONE(CLK_CAL_32K_XTAL);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if SOC_CLK_OSC_SLOW_SUPPORTED
|
||||
rtc_clk_32k_enable_external();
|
||||
uint32_t cal_ext_slow_clk = CALIBRATE_ONE(RTC_CAL_32K_OSC_SLOW);
|
||||
uint32_t cal_ext_slow_clk = CALIBRATE_ONE(CLK_CAL_32K_OSC_SLOW);
|
||||
if (cal_ext_slow_clk == 0) {
|
||||
printf("EXT CLOCK by PIN has not started up\n");
|
||||
} else {
|
||||
@@ -98,11 +98,11 @@ TEST_CASE("RTC_SLOW_CLK sources calibration", "[rtc_clk]")
|
||||
rtc_clk_slow_src_set(SOC_RTC_SLOW_CLK_SRC_OSC_SLOW);
|
||||
printf("done\n");
|
||||
|
||||
CALIBRATE_ONE(RTC_CAL_RTC_MUX);
|
||||
CALIBRATE_ONE(CLK_CAL_RTC_SLOW);
|
||||
#if SOC_CLK_RC_FAST_D256_SUPPORTED
|
||||
CALIBRATE_ONE(RTC_CAL_8MD256);
|
||||
CALIBRATE_ONE(CLK_CAL_RC_FAST_D256);
|
||||
#endif
|
||||
CALIBRATE_ONE(RTC_CAL_32K_OSC_SLOW);
|
||||
CALIBRATE_ONE(CLK_CAL_32K_OSC_SLOW);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user