From 11f32b88ac69ca618b5779a4e524cf568bc1e045 Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Wed, 21 May 2025 10:08:03 +0800 Subject: [PATCH] feat(esp_hw_support): compensate the error introduced to LACT during APB frequency switching --- components/esp_hw_support/linker.lf | 3 ++ .../esp_hw_support/port/esp32/rtc_clk.c | 34 +++++++++++++++++-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/components/esp_hw_support/linker.lf b/components/esp_hw_support/linker.lf index 430cdb8ae1..9218409e71 100644 --- a/components/esp_hw_support/linker.lf +++ b/components/esp_hw_support/linker.lf @@ -16,6 +16,9 @@ entries: if PM_SLP_IRAM_OPT = y: rtc_clk (noflash) rtc_time (noflash_text) + if IDF_TARGET_ESP32 = y: + rtc_clk:rtc_clk_cpu_freq_to_pll_mhz (noflash) + rtc_clk:rtc_clk_cpu_freq_to_xtal (noflash) if SOC_CONFIGURABLE_VDDSDIO_SUPPORTED = y: rtc_init:rtc_vddsdio_get_config (noflash) rtc_init:rtc_vddsdio_set_config (noflash) diff --git a/components/esp_hw_support/port/esp32/rtc_clk.c b/components/esp_hw_support/port/esp32/rtc_clk.c index f863246518..df155ba849 100644 --- a/components/esp_hw_support/port/esp32/rtc_clk.c +++ b/components/esp_hw_support/port/esp32/rtc_clk.c @@ -402,19 +402,49 @@ static void rtc_clk_cpu_freq_to_8m(void) rtc_clk_apb_freq_update(SOC_CLK_RC_FAST_FREQ_APPROX); } +#ifndef BOOTLOADER_BUILD +static const DRAM_ATTR int16_t dfs_lact_conpensate_table[3][3] = { \ +/* From / To 80 160 240*/ \ +/* 10 */ {138, 220, 18}, \ +/* 20 */ {128, 205, -3579}, \ +/* 40 */ {34, 100, 0}, \ +}; + +__attribute__((weak)) IRAM_ATTR int16_t rtc_clk_get_lact_compensation_delay(uint32_t cur_freq, uint32_t tar_freq) +{ + return dfs_lact_conpensate_table[(cur_freq == 10) ? 0 : (cur_freq == 20) ? 1 : 2][(tar_freq == 80) ? 0 : (tar_freq == 160) ? 1 : 2]; +} +#endif + /** * Switch to one of PLL-based frequencies. Current frequency can be XTAL or PLL. * PLL must already be enabled. * @param cpu_freq new CPU frequency */ -static void rtc_clk_cpu_freq_to_pll_mhz(int cpu_freq_mhz) +__attribute__((optimize("-O2"))) +NOINLINE_ATTR static void rtc_clk_cpu_freq_to_pll_mhz(int cpu_freq_mhz) { int dbias = (cpu_freq_mhz == 240) ? DIG_DBIAS_240M : DIG_DBIAS_80M_160M; REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, dbias); #ifndef BOOTLOADER_BUILD - timer_ll_set_lact_clock_prescale(TIMER_LL_GET_HW(LACT_MODULE), 80 / LACT_TICKS_PER_US); + uint32_t cur_freq = esp_rom_get_cpu_ticks_per_us(); + int16_t delay_cycle = rtc_clk_get_lact_compensation_delay(cur_freq, cpu_freq_mhz); + if (cur_freq <= 40 && delay_cycle >= 0) { + timer_ll_set_lact_clock_prescale(TIMER_LL_GET_HW(LACT_MODULE), 80 / LACT_TICKS_PER_US); + for (int i = 0; i < delay_cycle; ++i) { + __asm__ __volatile__("nop"); + } + } #endif clk_ll_cpu_set_freq_mhz_from_pll(cpu_freq_mhz); +#ifndef BOOTLOADER_BUILD + if (cur_freq <= 40 && delay_cycle < 0) { + for (int i = 0; i > delay_cycle; --i) { + __asm__ __volatile__("nop"); + } + timer_ll_set_lact_clock_prescale(TIMER_LL_GET_HW(LACT_MODULE), 80 / LACT_TICKS_PER_US); + } +#endif /* adjust ref_tick */ clk_ll_ref_tick_set_divider(SOC_CPU_CLK_SRC_PLL, cpu_freq_mhz); /* switch clock source */