From 12d2347e240d023cf6c0d341fd1570ac44e8a681 Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Thu, 12 Jun 2025 11:29:33 +0800 Subject: [PATCH] change(esp_timer): make esp_timer timming drift always be negative --- .../esp_hw_support/port/esp32/rtc_clk.c | 22 +++++------ .../test_apps/main/test_esp_timer_dfs.c | 37 ++++++++++++------- 2 files changed, 34 insertions(+), 25 deletions(-) diff --git a/components/esp_hw_support/port/esp32/rtc_clk.c b/components/esp_hw_support/port/esp32/rtc_clk.c index df155ba849..f13a8a870f 100644 --- a/components/esp_hw_support/port/esp32/rtc_clk.c +++ b/components/esp_hw_support/port/esp32/rtc_clk.c @@ -403,16 +403,16 @@ static void rtc_clk_cpu_freq_to_8m(void) } #ifndef BOOTLOADER_BUILD -static const DRAM_ATTR int16_t dfs_lact_conpensate_table[3][3] = { \ +static const DRAM_ATTR int16_t dfs_lact_compensate_table[3][3] = { \ /* From / To 80 160 240*/ \ -/* 10 */ {138, 220, 18}, \ -/* 20 */ {128, 205, -3579}, \ -/* 40 */ {34, 100, 0}, \ +/* 10 */ {78, 172, -1}, \ +/* 20 */ {2, 105, -90}, \ +/* 40 */ {-190, -18, -372}, \ }; __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]; + return dfs_lact_compensate_table[(cur_freq == 10) ? 0 : (cur_freq == 20) ? 1 : 2][(tar_freq == 80) ? 0 : (tar_freq == 160) ? 1 : 2]; } #endif @@ -437,6 +437,12 @@ NOINLINE_ATTR static void rtc_clk_cpu_freq_to_pll_mhz(int cpu_freq_mhz) } #endif clk_ll_cpu_set_freq_mhz_from_pll(cpu_freq_mhz); + /* adjust ref_tick */ + clk_ll_ref_tick_set_divider(SOC_CPU_CLK_SRC_PLL, cpu_freq_mhz); + /* switch clock source */ + clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_PLL); + rtc_clk_apb_freq_update(80 * MHZ); + esp_rom_set_cpu_ticks_per_us(cpu_freq_mhz); #ifndef BOOTLOADER_BUILD if (cur_freq <= 40 && delay_cycle < 0) { for (int i = 0; i > delay_cycle; --i) { @@ -445,12 +451,6 @@ NOINLINE_ATTR static void rtc_clk_cpu_freq_to_pll_mhz(int cpu_freq_mhz) 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 */ - clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_PLL); - rtc_clk_apb_freq_update(80 * MHZ); - esp_rom_set_cpu_ticks_per_us(cpu_freq_mhz); rtc_clk_wait_for_slow_cycle(); esp_rom_delay_us(30); } diff --git a/components/esp_timer/test_apps/main/test_esp_timer_dfs.c b/components/esp_timer/test_apps/main/test_esp_timer_dfs.c index 2fe568880e..072a2e2810 100644 --- a/components/esp_timer/test_apps/main/test_esp_timer_dfs.c +++ b/components/esp_timer/test_apps/main/test_esp_timer_dfs.c @@ -63,15 +63,19 @@ static IRAM_ATTR void periodic_timer_callback(void* arg) static int64_t measuring_periodic_timer_accuracy(uint64_t alarm_records[]) { int64_t sum_jitter_us = 0; - int64_t max_jitter_us = 0; + int64_t max_jitter_us = -(ALARM_PERIOD_MS * 1000); + int64_t min_jitter_us = ALARM_PERIOD_MS * 1000; int64_t jitter_array[ALARM_TIMES] = {0}; for (int i = 1; i <= ALARM_TIMES; ++i) { int64_t jitter_us = (int64_t)alarm_records[i] - (int64_t)alarm_records[i - 1] - ALARM_PERIOD_MS * 1000; jitter_array[i - 1] = jitter_us; - if (llabs(jitter_us) > llabs(max_jitter_us)) { + if (jitter_us > max_jitter_us) { max_jitter_us = jitter_us; } + if (jitter_us < min_jitter_us) { + min_jitter_us = jitter_us; + } sum_jitter_us += jitter_us; } int64_t avg_jitter_us = sum_jitter_us / ALARM_TIMES; @@ -86,14 +90,19 @@ static int64_t measuring_periodic_timer_accuracy(uint64_t alarm_records[]) double stddev = sqrt(variance); printf("Average jitter us: %"PRIi64"\n", avg_jitter_us); - printf("Max jitter us: %"PRIi64"\n", max_jitter_us); + if (max_jitter_us > 0) { + printf("\e[1;31mMax jitter us: %"PRIi64"\n\e[0m", max_jitter_us); + } else { + printf("Max jitter us: %"PRIi64"\n", max_jitter_us); + } + printf("Min jitter us: %"PRIi64"\n", min_jitter_us); printf("Standard Deviation: %.3f\n", stddev); printf("Drift Percentage: %.3f%%\n", (double)avg_jitter_us / (ALARM_PERIOD_MS * 10)); // Reset measurement s_current_alarm = 0; bzero(s_alarm_records, sizeof(s_alarm_records)); - return avg_jitter_us; + return max_jitter_us; } static int64_t test_periodic_timer_accuracy_on_dfs(esp_timer_handle_t timer) @@ -109,9 +118,9 @@ static int64_t test_periodic_timer_accuracy_on_dfs(esp_timer_handle_t timer) // Each FreeRTOS tick will perform a min_freq_mhz->max_freq_mhz -> min_freq_mhz frequency switch xSemaphoreTake(s_alarm_finished, portMAX_DELAY); ESP_ERROR_CHECK(esp_timer_stop(timer)); - int64_t avg_jitter_us = measuring_periodic_timer_accuracy(s_alarm_records); + int64_t max_jitter_us = measuring_periodic_timer_accuracy(s_alarm_records); vSemaphoreDelete(s_alarm_finished); - return avg_jitter_us; + return max_jitter_us; } // The results of this test are meaningful only if `CONFIG_ESP_SYSTEM_RTC_EXT_XTAL` is enabled @@ -183,7 +192,7 @@ TEST_CASE("Test DFS lact conpensate magic table ", "[esp_timer][manual][ignore]" esp_pm_configure(&pm_config); int32_t max_delay = 300; - int32_t min_delay = (pm_config.max_freq_mhz == 240) ? -4000 : 0; + int32_t min_delay = (pm_config.max_freq_mhz == 240) ? -4000 : -300; int32_t test_delay = (max_delay + min_delay) / 2; int32_t last_delay = 0; int32_t best_delay = 0; @@ -192,19 +201,19 @@ TEST_CASE("Test DFS lact conpensate magic table ", "[esp_timer][manual][ignore]" do { printf("Test delay %ld\n", test_delay); test_lact_compensation_delay = test_delay; - int64_t avg = test_periodic_timer_accuracy_on_dfs(periodic_timer); + int64_t max_jitter_us = test_periodic_timer_accuracy_on_dfs(periodic_timer); last_delay = test_delay; - if (avg < 0) { - test_delay = (test_delay + max_delay) / 2; - min_delay = last_delay; - } else { + if (max_jitter_us > 0) { test_delay = (test_delay + min_delay) / 2; max_delay = last_delay; + } else { + test_delay = (test_delay + max_delay) / 2; + min_delay = last_delay; } - if (llabs(avg) < llabs(min_avg)) { + if (llabs(max_jitter_us) < llabs(min_avg)) { best_delay = last_delay; - min_avg = avg; + min_avg = max_jitter_us; } } while (test_delay != last_delay);