From 3eed53a0719cf48449846ff8b49ba9cafb401d96 Mon Sep 17 00:00:00 2001 From: Daniel Ansorregui Date: Sun, 17 Mar 2024 13:51:56 +0000 Subject: [PATCH] Allow to configure sleep RTC calibration * The default behaviour is to run some calibration cycles to ensure RTC slow clock is vlaid during the sleep time. * However, depending on the application this might be redundant or detrimental * Added an option to configure it if required # Conflicts: # components/esp_hw_support/sleep_modes.c --- .../esp_hw_support/port/esp32/Kconfig.rtc | 18 ++++++++++++ components/esp_hw_support/sleep_modes.c | 29 ++++++++++++------- 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/components/esp_hw_support/port/esp32/Kconfig.rtc b/components/esp_hw_support/port/esp32/Kconfig.rtc index 117edae8ae..884d51b19f 100644 --- a/components/esp_hw_support/port/esp32/Kconfig.rtc +++ b/components/esp_hw_support/port/esp32/Kconfig.rtc @@ -85,6 +85,24 @@ config RTC_CLK_CAL_CYCLES In case more value will help improve the definition of the launch of the crystal. If the crystal could not start, it will be switched to internal RC. +config RTC_CLK_SLEEP_CAL_CYCLES + int "Number of cycles to calibrate RTC_SLOW_CLK before sleep" + default 10 + range 0 1000 + help + Just before entering light/deep sleep, a small calibration is done + on the RTC_SLOW_CLK. Having a calibrated RTC_SLOW_CLK is required + in order to proper measure time while in sleep modes and allow proper + wake up from timers. + This option defaults to 10 cycles (around 300us) but can be lowered + down to 0 to avoid calibration, and take the previous one as valid. + It can be particularly useful when the RTC_SLOW_CLK calibration is + done by the APP code using various external sources like NTP + and comparing the long term drift of the clock, or when using a very + stable external oscillator. + It can also be interesting for reducing power usage in APPs that are + constantly entering light sleep. + config RTC_XTAL_CAL_RETRY int "Number of attempts to repeat 32k XTAL calibration" default 1 diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index 38a9f34633..0dc327612e 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -125,7 +125,11 @@ #define ESP_SLEEP_WAIT_FLASH_READY_DEFAULT_DELAY_US 700 // Cycles for RTC Timer clock source (internal oscillator) calibrate +#ifndef CONFIG_RTC_CLK_SLEEP_CAL_CYCLES #define RTC_CLK_SRC_CAL_CYCLES (10) +#else +#define RTC_CLK_SRC_CAL_CYCLES CONFIG_RTC_CLK_SLEEP_CAL_CYCLES +#endif #define FAST_CLK_SRC_CAL_CYCLES (2048) /* ~ 127.4 us */ #ifdef CONFIG_IDF_TARGET_ESP32 @@ -617,7 +621,22 @@ FORCE_INLINE_ATTR void misc_modules_wake_prepare(void) static IRAM_ATTR void sleep_low_power_clock_calibration(bool is_dslp) { + + // Calibrate rtc fast clock, only PMU supported chips sleep process is needed. +#if SOC_PMU_SUPPORTED +#if CONFIG_PM_ENABLE + 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); + } +#endif + // Calibrate rtc slow clock + if (RTC_CLK_SRC_CAL_CYCLES <= 0) + s_config.rtc_clk_cal_period = esp_clk_slowclk_cal_get(); + return; + } #ifdef CONFIG_ESP_SYSTEM_RTC_EXT_XTAL if (rtc_clk_slow_src_get() == SOC_RTC_SLOW_CLK_SRC_XTAL32K) { uint64_t time_per_us = 1000000ULL; @@ -640,16 +659,6 @@ static IRAM_ATTR void sleep_low_power_clock_calibration(bool is_dslp) esp_clk_slowclk_cal_set(s_config.rtc_clk_cal_period); } #endif - - // Calibrate rtc fast clock, only PMU supported chips sleep process is needed. -#if SOC_PMU_SUPPORTED -#if CONFIG_PM_ENABLE - 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); - } -#endif }