From 30e7af2ffb9544de3c7107c5cef787aaf42ab29e Mon Sep 17 00:00:00 2001 From: jingli Date: Tue, 14 Jun 2022 14:49:26 +0800 Subject: [PATCH] system/sleep: simplify code for time compensation when wakeup from light sleep --- components/esp_hw_support/sleep_modes.c | 27 +++++----------- .../include/esp_private/esp_timer_private.h | 31 +++++++++---------- components/esp_timer/src/esp_timer_impl_lac.c | 14 ++++++--- .../esp_timer/src/esp_timer_impl_systimer.c | 16 ++++++++-- tools/ci/check_copyright_ignore.txt | 1 - 5 files changed, 45 insertions(+), 44 deletions(-) diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index 0afac30632..1160906181 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -650,7 +650,7 @@ esp_err_t esp_light_sleep_start(void) s_config.ccount_ticks_record = cpu_ll_get_cycle_count(); static portMUX_TYPE light_sleep_lock = portMUX_INITIALIZER_UNLOCKED; portENTER_CRITICAL(&light_sleep_lock); - /* We will be calling esp_timer_private_advance inside DPORT access critical + /* We will be calling esp_timer_private_set inside DPORT access critical * section. Make sure the code on the other CPU is not holding esp_timer * lock, otherwise there will be deadlock. */ @@ -758,29 +758,16 @@ esp_err_t esp_light_sleep_start(void) s_light_sleep_wakeup = true; - // System timer has been clock gated for the duration of the sleep, correct for that. -#ifdef CONFIG_IDF_TARGET_ESP32C3 - /** - * On esp32c3, rtc_time_get() is non-blocking, esp_timer_get_time() is - * blocking, and the measurement data shows that this order is better. - */ - uint64_t high_res_time_at_end = esp_timer_get_time(); + // System timer has been stopped for the duration of the sleep, correct for that. uint64_t rtc_ticks_at_end = rtc_time_get(); -#else - uint64_t rtc_ticks_at_end = rtc_time_get(); - uint64_t high_res_time_at_end = esp_timer_get_time(); -#endif - uint64_t rtc_time_diff = rtc_time_slowclk_to_us(rtc_ticks_at_end - s_config.rtc_ticks_at_sleep_start, s_config.rtc_clk_cal_period); - uint64_t high_res_time_diff = high_res_time_at_end - high_res_time_at_start; - int64_t time_diff = rtc_time_diff - high_res_time_diff; - /* Small negative values (up to 1 RTC_SLOW clock period) are possible, - * for very small values of sleep_duration. Ignore those to keep esp_timer - * monotonic. + /** + * If sleep duration is too small(less than 1 rtc_slow_clk cycle), rtc_time_diff will be zero. + * In this case, just ignore the time compensation and keep esp_timer monotonic. */ - if (time_diff > 0) { - esp_timer_private_advance(time_diff); + if (rtc_time_diff > 0) { + esp_timer_private_set(high_res_time_at_start + rtc_time_diff); } esp_set_time_from_rtc(); diff --git a/components/esp_timer/include/esp_private/esp_timer_private.h b/components/esp_timer/include/esp_private/esp_timer_private.h index ecd4264111..4744b20a39 100644 --- a/components/esp_timer/include/esp_private/esp_timer_private.h +++ b/components/esp_timer/include/esp_private/esp_timer_private.h @@ -1,16 +1,8 @@ -// Copyright 2017 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2017-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -43,13 +35,20 @@ extern "C" { void esp_timer_private_update_apb_freq(uint32_t apb_ticks_per_us); /** - * @brief Adjust current esp_timer time by a certain value + * @brief Set esp_timer time to a certain value * * Called from light sleep code to synchronize esp_timer time with RTC time. * - * @param time_us adjustment to apply to esp_timer time, in microseconds + * @param new_us the value to be set to esp_timer time, in microseconds */ -void esp_timer_private_advance(int64_t time_us); +void esp_timer_private_set(uint64_t new_us); + +/** + * @brief Adjust current esp_timer time by a certain value + * + * @param time_diff_us adjustment to apply to esp_timer time, in microseconds + */ +void esp_timer_private_advance(int64_t time_diff_us); /** * @brief obtain internal critical section used esp_timer implementation diff --git a/components/esp_timer/src/esp_timer_impl_lac.c b/components/esp_timer/src/esp_timer_impl_lac.c index 47f4b89501..dc3ab65023 100644 --- a/components/esp_timer/src/esp_timer_impl_lac.c +++ b/components/esp_timer/src/esp_timer_impl_lac.c @@ -195,17 +195,22 @@ void IRAM_ATTR esp_timer_impl_update_apb_freq(uint32_t apb_ticks_per_us) portEXIT_CRITICAL(&s_time_update_lock); } -void esp_timer_impl_advance(int64_t time_diff_us) +void esp_timer_impl_set(uint64_t new_us) { portENTER_CRITICAL(&s_time_update_lock); - uint64_t now = esp_timer_impl_get_time(); - timer_64b_reg_t dst = { .val = (now + time_diff_us) * TICKS_PER_US }; + timer_64b_reg_t dst = { .val = new_us * TICKS_PER_US }; REG_WRITE(LOAD_LO_REG, dst.lo); REG_WRITE(LOAD_HI_REG, dst.hi); REG_WRITE(LOAD_REG, 1); portEXIT_CRITICAL(&s_time_update_lock); } +void esp_timer_impl_advance(int64_t time_diff_us) +{ + uint64_t now = esp_timer_impl_get_time(); + esp_timer_impl_set(now + time_diff_us); +} + esp_err_t esp_timer_impl_early_init(void) { periph_module_enable(PERIPH_LACT); @@ -286,6 +291,7 @@ uint64_t esp_timer_impl_get_alarm_reg(void) } void esp_timer_private_update_apb_freq(uint32_t apb_ticks_per_us) __attribute__((alias("esp_timer_impl_update_apb_freq"))); -void esp_timer_private_advance(int64_t time_us) __attribute__((alias("esp_timer_impl_advance"))); +void esp_timer_private_set(uint64_t new_us) __attribute__((alias("esp_timer_impl_set"))); +void esp_timer_private_advance(int64_t time_diff_us) __attribute__((alias("esp_timer_impl_advance"))); void esp_timer_private_lock(void) __attribute__((alias("esp_timer_impl_lock"))); void esp_timer_private_unlock(void) __attribute__((alias("esp_timer_impl_unlock"))); diff --git a/components/esp_timer/src/esp_timer_impl_systimer.c b/components/esp_timer/src/esp_timer_impl_systimer.c index 75e9a16b1d..e7141830b1 100644 --- a/components/esp_timer/src/esp_timer_impl_systimer.c +++ b/components/esp_timer/src/esp_timer_impl_systimer.c @@ -101,10 +101,19 @@ void IRAM_ATTR esp_timer_impl_update_apb_freq(uint32_t apb_ticks_per_us) #endif } -void esp_timer_impl_advance(int64_t time_us) +void esp_timer_impl_set(uint64_t new_us) { portENTER_CRITICAL_SAFE(&s_time_update_lock); - systimer_hal_counter_value_advance(&systimer_hal, SYSTIMER_LL_COUNTER_CLOCK, time_us); + systimer_counter_value_t new_count = { .val = new_us * SYSTIMER_LL_TICKS_PER_US }; + systimer_ll_set_counter_value(systimer_hal.dev, SYSTIMER_LL_COUNTER_CLOCK, new_count.val); + systimer_ll_apply_counter_value(systimer_hal.dev, SYSTIMER_LL_COUNTER_CLOCK); + portEXIT_CRITICAL_SAFE(&s_time_update_lock); +} + +void esp_timer_impl_advance(int64_t time_diff_us) +{ + portENTER_CRITICAL_SAFE(&s_time_update_lock); + systimer_hal_counter_value_advance(&systimer_hal, SYSTIMER_LL_COUNTER_CLOCK, time_diff_us); portEXIT_CRITICAL_SAFE(&s_time_update_lock); } @@ -192,6 +201,7 @@ uint64_t esp_timer_impl_get_alarm_reg(void) } void esp_timer_private_update_apb_freq(uint32_t apb_ticks_per_us) __attribute__((alias("esp_timer_impl_update_apb_freq"))); -void esp_timer_private_advance(int64_t time_us) __attribute__((alias("esp_timer_impl_advance"))); +void esp_timer_private_set(uint64_t new_us) __attribute__((alias("esp_timer_impl_set"))); +void esp_timer_private_advance(int64_t time_diff_us) __attribute__((alias("esp_timer_impl_advance"))); void esp_timer_private_lock(void) __attribute__((alias("esp_timer_impl_lock"))); void esp_timer_private_unlock(void) __attribute__((alias("esp_timer_impl_unlock"))); diff --git a/tools/ci/check_copyright_ignore.txt b/tools/ci/check_copyright_ignore.txt index 5ce37ea15d..b6f0c8ad8a 100644 --- a/tools/ci/check_copyright_ignore.txt +++ b/tools/ci/check_copyright_ignore.txt @@ -694,7 +694,6 @@ components/esp_system/test_eh_frame_parser/eh_frame_parser_impl.h components/esp_system/test_eh_frame_parser/esp_private/panic_internal.h components/esp_system/test_eh_frame_parser/linker.ld components/esp_system/ubsan.c -components/esp_timer/include/esp_private/esp_timer_private.h components/esp_timer/test/test_esp_timer.c components/esp_timer/test/test_esp_timer_light_sleep.c components/esp_timer/test/test_ets_timer.c