Răsfoiți Sursa

Merge branch 'refactor/simplify_code_for_time_compensation_when_sleep' into 'master'

system/sleep: simplify code for time compensation when wakeup from light sleep

See merge request espressif/esp-idf!18491
Jing Li 3 ani în urmă
părinte
comite
074c708cf0

+ 7 - 20
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();
-    uint64_t rtc_ticks_at_end = rtc_time_get();
-#else
+    // System timer has been stopped for the duration of the sleep, correct for that.
     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();
 

+ 15 - 16
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_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_us);
+void esp_timer_private_advance(int64_t time_diff_us);
 
 /**
  * @brief obtain internal critical section used esp_timer implementation

+ 10 - 4
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")));

+ 13 - 3
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")));

+ 0 - 1
tools/ci/check_copyright_ignore.txt

@@ -693,7 +693,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