diff --git a/components/esp_hw_support/include/esp_sleep.h b/components/esp_hw_support/include/esp_sleep.h index ec282ab59f..a24e6596aa 100644 --- a/components/esp_hw_support/include/esp_sleep.h +++ b/components/esp_hw_support/include/esp_sleep.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -173,9 +173,13 @@ esp_err_t esp_sleep_enable_ulp_wakeup(void); /** * @brief Enable wakeup by timer * @param time_in_us time before wakeup, in microseconds + * @note The valid `time_in_us` value depends on the bit width of the lp_timer/rtc_timer counter and the + * current slow clock source selection (Refer RTC clock source configuration in menuconfig). + * Valid values should be positive values less than RTC slow clock period * (2 ^ RTC timer bitwidth). + * * @return * - ESP_OK on success - * - ESP_ERR_INVALID_ARG if value is out of range (TBD) + * - ESP_ERR_INVALID_ARG if value is out of range. */ esp_err_t esp_sleep_enable_timer_wakeup(uint64_t time_in_us); diff --git a/components/esp_hw_support/port/esp32/rtc_time.c b/components/esp_hw_support/port/esp32/rtc_time.c index a967ade043..447c109ec8 100644 --- a/components/esp_hw_support/port/esp32/rtc_time.c +++ b/components/esp_hw_support/port/esp32/rtc_time.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -145,9 +145,9 @@ uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles) uint64_t rtc_time_us_to_slowclk(uint64_t time_in_us, uint32_t period) { assert(period); - /* Overflow will happen in this function if time_in_us >= 2^45, which is about 400 days. - * TODO: fix overflow. - */ + if (time_in_us > (UINT64_MAX >> RTC_CLK_CAL_FRACT)) { + return ((time_in_us / period) << RTC_CLK_CAL_FRACT) + ((time_in_us % period) << RTC_CLK_CAL_FRACT) / period; + } return (time_in_us << RTC_CLK_CAL_FRACT) / period; } diff --git a/components/esp_hw_support/port/esp32c2/rtc_time.c b/components/esp_hw_support/port/esp32c2/rtc_time.c index 9adf6f9706..5c7470dad4 100644 --- a/components/esp_hw_support/port/esp32c2/rtc_time.c +++ b/components/esp_hw_support/port/esp32c2/rtc_time.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -159,9 +159,9 @@ uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles) uint64_t rtc_time_us_to_slowclk(uint64_t time_in_us, uint32_t period) { assert(period); - /* Overflow will happen in this function if time_in_us >= 2^45, which is about 400 days. - * TODO: fix overflow. - */ + if (time_in_us > (UINT64_MAX >> RTC_CLK_CAL_FRACT)) { + return ((time_in_us / period) << RTC_CLK_CAL_FRACT) + ((time_in_us % period) << RTC_CLK_CAL_FRACT) / period; + } return (time_in_us << RTC_CLK_CAL_FRACT) / period; } diff --git a/components/esp_hw_support/port/esp32c3/rtc_time.c b/components/esp_hw_support/port/esp32c3/rtc_time.c index 0dd9cecfd9..bf1aa97259 100644 --- a/components/esp_hw_support/port/esp32c3/rtc_time.c +++ b/components/esp_hw_support/port/esp32c3/rtc_time.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -162,9 +162,9 @@ uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles) uint64_t rtc_time_us_to_slowclk(uint64_t time_in_us, uint32_t period) { assert(period); - /* Overflow will happen in this function if time_in_us >= 2^45, which is about 400 days. - * TODO: fix overflow. - */ + if (time_in_us > (UINT64_MAX >> RTC_CLK_CAL_FRACT)) { + return ((time_in_us / period) << RTC_CLK_CAL_FRACT) + ((time_in_us % period) << RTC_CLK_CAL_FRACT) / period; + } return (time_in_us << RTC_CLK_CAL_FRACT) / period; } diff --git a/components/esp_hw_support/port/esp32c5/rtc_time.c b/components/esp_hw_support/port/esp32c5/rtc_time.c index 2e085fcc9d..4e260b2389 100644 --- a/components/esp_hw_support/port/esp32c5/rtc_time.c +++ b/components/esp_hw_support/port/esp32c5/rtc_time.c @@ -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 */ @@ -233,9 +233,10 @@ uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles) uint64_t rtc_time_us_to_slowclk(uint64_t time_in_us, uint32_t period) { - /* Overflow will happen in this function if time_in_us >= 2^45, which is about 400 days. - * TODO: fix overflow. - */ + assert(period); + if (time_in_us > (UINT64_MAX >> RTC_CLK_CAL_FRACT)) { + return ((time_in_us / period) << RTC_CLK_CAL_FRACT) + ((time_in_us % period) << RTC_CLK_CAL_FRACT) / period; + } return (time_in_us << RTC_CLK_CAL_FRACT) / period; } diff --git a/components/esp_hw_support/port/esp32c6/rtc_time.c b/components/esp_hw_support/port/esp32c6/rtc_time.c index 98896e786c..a2393ec04a 100644 --- a/components/esp_hw_support/port/esp32c6/rtc_time.c +++ b/components/esp_hw_support/port/esp32c6/rtc_time.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -241,9 +241,9 @@ uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles) uint64_t rtc_time_us_to_slowclk(uint64_t time_in_us, uint32_t period) { assert(period); - /* Overflow will happen in this function if time_in_us >= 2^45, which is about 400 days. - * TODO: fix overflow. - */ + if (time_in_us > (UINT64_MAX >> RTC_CLK_CAL_FRACT)) { + return ((time_in_us / period) << RTC_CLK_CAL_FRACT) + ((time_in_us % period) << RTC_CLK_CAL_FRACT) / period; + } return (time_in_us << RTC_CLK_CAL_FRACT) / period; } diff --git a/components/esp_hw_support/port/esp32c61/rtc_time.c b/components/esp_hw_support/port/esp32c61/rtc_time.c index 182d32ee3f..688b777334 100644 --- a/components/esp_hw_support/port/esp32c61/rtc_time.c +++ b/components/esp_hw_support/port/esp32c61/rtc_time.c @@ -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 */ @@ -236,9 +236,9 @@ uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles) uint64_t rtc_time_us_to_slowclk(uint64_t time_in_us, uint32_t period) { assert(period); - /* Overflow will happen in this function if time_in_us >= 2^45, which is about 400 days. - * TODO: fix overflow. - */ + if (time_in_us > (UINT64_MAX >> RTC_CLK_CAL_FRACT)) { + return ((time_in_us / period) << RTC_CLK_CAL_FRACT) + ((time_in_us % period) << RTC_CLK_CAL_FRACT) / period; + } return (time_in_us << RTC_CLK_CAL_FRACT) / period; } diff --git a/components/esp_hw_support/port/esp32h2/rtc_time.c b/components/esp_hw_support/port/esp32h2/rtc_time.c index 708fedcb20..ccd3dc491f 100644 --- a/components/esp_hw_support/port/esp32h2/rtc_time.c +++ b/components/esp_hw_support/port/esp32h2/rtc_time.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -241,9 +241,9 @@ uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles) uint64_t rtc_time_us_to_slowclk(uint64_t time_in_us, uint32_t period) { assert(period); - /* Overflow will happen in this function if time_in_us >= 2^45, which is about 400 days. - * TODO: fix overflow. - */ + if (time_in_us > (UINT64_MAX >> RTC_CLK_CAL_FRACT)) { + return ((time_in_us / period) << RTC_CLK_CAL_FRACT) + ((time_in_us % period) << RTC_CLK_CAL_FRACT) / period; + } return (time_in_us << RTC_CLK_CAL_FRACT) / period; } diff --git a/components/esp_hw_support/port/esp32p4/rtc_time.c b/components/esp_hw_support/port/esp32p4/rtc_time.c index b1a5ae6674..d7a9cf5bab 100644 --- a/components/esp_hw_support/port/esp32p4/rtc_time.c +++ b/components/esp_hw_support/port/esp32p4/rtc_time.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -198,9 +198,9 @@ uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles) uint64_t rtc_time_us_to_slowclk(uint64_t time_in_us, uint32_t period) { assert(period); - /* Overflow will happen in this function if time_in_us >= 2^45, which is about 400 days. - * TODO: fix overflow. - */ + if (time_in_us > (UINT64_MAX >> RTC_CLK_CAL_FRACT)) { + return ((time_in_us / period) << RTC_CLK_CAL_FRACT) + ((time_in_us % period) << RTC_CLK_CAL_FRACT) / period; + } return (time_in_us << RTC_CLK_CAL_FRACT) / period; } diff --git a/components/esp_hw_support/port/esp32s2/rtc_time.c b/components/esp_hw_support/port/esp32s2/rtc_time.c index 5d6df04504..76df279092 100644 --- a/components/esp_hw_support/port/esp32s2/rtc_time.c +++ b/components/esp_hw_support/port/esp32s2/rtc_time.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -227,9 +227,9 @@ uint32_t rtc_clk_cal_cycling(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles) uint64_t rtc_time_us_to_slowclk(uint64_t time_in_us, uint32_t period) { assert(period); - /* Overflow will happen in this function if time_in_us >= 2^45, which is about 400 days. - * TODO: fix overflow. - */ + if (time_in_us > (UINT64_MAX >> RTC_CLK_CAL_FRACT)) { + return ((time_in_us / period) << RTC_CLK_CAL_FRACT) + ((time_in_us % period) << RTC_CLK_CAL_FRACT) / period; + } return (time_in_us << RTC_CLK_CAL_FRACT) / period; } diff --git a/components/esp_hw_support/port/esp32s3/rtc_time.c b/components/esp_hw_support/port/esp32s3/rtc_time.c index 6a7d036ee4..834676a880 100644 --- a/components/esp_hw_support/port/esp32s3/rtc_time.c +++ b/components/esp_hw_support/port/esp32s3/rtc_time.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -161,9 +161,9 @@ uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles) uint64_t rtc_time_us_to_slowclk(uint64_t time_in_us, uint32_t period) { assert(period); - /* Overflow will happen in this function if time_in_us >= 2^45, which is about 400 days. - * TODO: fix overflow. - */ + if (time_in_us > (UINT64_MAX >> RTC_CLK_CAL_FRACT)) { + return ((time_in_us / period) << RTC_CLK_CAL_FRACT) + ((time_in_us % period) << RTC_CLK_CAL_FRACT) / period; + } return (time_in_us << RTC_CLK_CAL_FRACT) / period; } diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index 986ca80311..3dae58b49b 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -13,6 +13,7 @@ #include "esp_rom_caps.h" #include "esp_memory_utils.h" #include "esp_sleep.h" +#include "esp_private/esp_clk_tree_common.h" #include "esp_private/esp_sleep_internal.h" #include "esp_private/esp_timer_private.h" #include "esp_private/rtc_clk.h" @@ -1620,6 +1621,10 @@ esp_err_t esp_sleep_enable_ulp_wakeup(void) esp_err_t esp_sleep_enable_timer_wakeup(uint64_t time_in_us) { + if (time_in_us > ((BIT64(SOC_LP_TIMER_BIT_WIDTH_LO + SOC_LP_TIMER_BIT_WIDTH_HI) - 1) / esp_clk_tree_lp_slow_get_freq_hz(ESP_CLK_TREE_SRC_FREQ_PRECISION_APPROX)) * MHZ ) { + return ESP_ERR_INVALID_ARG; + } + s_config.wakeup_triggers |= RTC_TIMER_TRIG_EN; s_config.sleep_duration = time_in_us; return ESP_OK; diff --git a/components/esp_system/test_apps/esp_system_unity_tests/main/test_sleep.c b/components/esp_system/test_apps/esp_system_unity_tests/main/test_sleep.c index 10ac4c2f2c..c41c983db7 100644 --- a/components/esp_system/test_apps/esp_system_unity_tests/main/test_sleep.c +++ b/components/esp_system/test_apps/esp_system_unity_tests/main/test_sleep.c @@ -23,10 +23,12 @@ #include "esp_newlib.h" #include "test_utils.h" #include "sdkconfig.h" +#include "esp_clk_tree.h" #include "esp_rom_uart.h" #include "esp_rom_sys.h" #include "esp_timer.h" #include "esp_private/esp_clk.h" +#include "esp_private/esp_clk_tree_common.h" #include "esp_private/uart_share_hw_ctrl.h" #include "esp_random.h" #include "nvs_flash.h" @@ -54,6 +56,10 @@ __attribute__((unused)) static struct timeval tv_start, tv_stop; #if SOC_LIGHT_SLEEP_SUPPORTED TEST_CASE("wake up from light sleep using timer", "[lightsleep]") { + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_sleep_enable_timer_wakeup(UINT64_MAX)); + uint64_t lp_timer_max_allowed_time_in_us = ((BIT64(SOC_LP_TIMER_BIT_WIDTH_LO + SOC_LP_TIMER_BIT_WIDTH_HI) - 1) / esp_clk_tree_lp_slow_get_freq_hz(ESP_CLK_TREE_SRC_FREQ_PRECISION_APPROX)) * MHZ; + TEST_ASSERT_EQUAL(ESP_OK, esp_sleep_enable_timer_wakeup(lp_timer_max_allowed_time_in_us)); + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_sleep_enable_timer_wakeup(lp_timer_max_allowed_time_in_us + 1)); esp_sleep_enable_timer_wakeup(2000000); gettimeofday(&tv_start, NULL); esp_light_sleep_start(); diff --git a/components/soc/esp32/include/soc/Kconfig.soc_caps.in b/components/soc/esp32/include/soc/Kconfig.soc_caps.in index bed61353ce..ab9ec405a0 100644 --- a/components/soc/esp32/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32/include/soc/Kconfig.soc_caps.in @@ -707,6 +707,14 @@ config SOC_TIMER_GROUP_SUPPORT_APB bool default y +config SOC_LP_TIMER_BIT_WIDTH_LO + int + default 32 + +config SOC_LP_TIMER_BIT_WIDTH_HI + int + default 16 + config SOC_TOUCH_SENSOR_VERSION int default 1 diff --git a/components/soc/esp32/include/soc/soc_caps.h b/components/soc/esp32/include/soc/soc_caps.h index b06e0669f1..10e2a35ce2 100644 --- a/components/soc/esp32/include/soc/soc_caps.h +++ b/components/soc/esp32/include/soc/soc_caps.h @@ -327,6 +327,10 @@ #define SOC_TIMER_GROUP_TOTAL_TIMERS (4) #define SOC_TIMER_GROUP_SUPPORT_APB (1) +/*-------------------------- LP_TIMER CAPS ----------------------------------*/ +#define SOC_LP_TIMER_BIT_WIDTH_LO 32 // Bit width of lp_timer low part +#define SOC_LP_TIMER_BIT_WIDTH_HI 16 // Bit width of lp_timer high part + /*-------------------------- TOUCH SENSOR CAPS -------------------------------*/ #define SOC_TOUCH_SENSOR_VERSION (1U) /*!