From b5da8a52c6872a24cc2316ee44cdcb9f15683b30 Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Thu, 22 May 2025 14:21:56 +0800 Subject: [PATCH] feat(esp_hw_support): compensate the error introduced to LACT during APB frequency switching --- .../esp_hw_support/port/esp32/rtc_clk.c | 34 +++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) 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 */