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

This commit is contained in:
jingli 2022-06-14 14:49:26 +08:00
parent 317f6292c7
commit 30e7af2ffb
5 changed files with 45 additions and 44 deletions

View File

@ -650,7 +650,7 @@ esp_err_t esp_light_sleep_start(void)
s_config.ccount_ticks_record = cpu_ll_get_cycle_count(); s_config.ccount_ticks_record = cpu_ll_get_cycle_count();
static portMUX_TYPE light_sleep_lock = portMUX_INITIALIZER_UNLOCKED; static portMUX_TYPE light_sleep_lock = portMUX_INITIALIZER_UNLOCKED;
portENTER_CRITICAL(&light_sleep_lock); 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 * section. Make sure the code on the other CPU is not holding esp_timer
* lock, otherwise there will be deadlock. * lock, otherwise there will be deadlock.
*/ */
@ -758,29 +758,16 @@ esp_err_t esp_light_sleep_start(void)
s_light_sleep_wakeup = true; s_light_sleep_wakeup = true;
// System timer has been clock gated for the duration of the sleep, correct for that. // System timer has been stopped 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(); 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 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, * If sleep duration is too small(less than 1 rtc_slow_clk cycle), rtc_time_diff will be zero.
* for very small values of sleep_duration. Ignore those to keep esp_timer * In this case, just ignore the time compensation and keep esp_timer monotonic.
* monotonic.
*/ */
if (time_diff > 0) { if (rtc_time_diff > 0) {
esp_timer_private_advance(time_diff); esp_timer_private_set(high_res_time_at_start + rtc_time_diff);
} }
esp_set_time_from_rtc(); esp_set_time_from_rtc();

View File

@ -1,16 +1,8 @@
// Copyright 2017 Espressif Systems (Shanghai) PTE LTD /*
// * SPDX-FileCopyrightText: 2017-2022 Espressif Systems (Shanghai) CO LTD
// Licensed under the Apache License, Version 2.0 (the "License"); *
// you may not use this file except in compliance with the License. * SPDX-License-Identifier: Apache-2.0
// 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.
#pragma once #pragma once
@ -43,13 +35,20 @@ extern "C" {
void esp_timer_private_update_apb_freq(uint32_t apb_ticks_per_us); 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. * 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 * @brief obtain internal critical section used esp_timer implementation

View File

@ -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); 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); portENTER_CRITICAL(&s_time_update_lock);
uint64_t now = esp_timer_impl_get_time(); timer_64b_reg_t dst = { .val = new_us * TICKS_PER_US };
timer_64b_reg_t dst = { .val = (now + time_diff_us) * TICKS_PER_US };
REG_WRITE(LOAD_LO_REG, dst.lo); REG_WRITE(LOAD_LO_REG, dst.lo);
REG_WRITE(LOAD_HI_REG, dst.hi); REG_WRITE(LOAD_HI_REG, dst.hi);
REG_WRITE(LOAD_REG, 1); REG_WRITE(LOAD_REG, 1);
portEXIT_CRITICAL(&s_time_update_lock); 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) esp_err_t esp_timer_impl_early_init(void)
{ {
periph_module_enable(PERIPH_LACT); 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_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_lock(void) __attribute__((alias("esp_timer_impl_lock")));
void esp_timer_private_unlock(void) __attribute__((alias("esp_timer_impl_unlock"))); void esp_timer_private_unlock(void) __attribute__((alias("esp_timer_impl_unlock")));

View File

@ -101,10 +101,19 @@ void IRAM_ATTR esp_timer_impl_update_apb_freq(uint32_t apb_ticks_per_us)
#endif #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); 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); 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_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_lock(void) __attribute__((alias("esp_timer_impl_lock")));
void esp_timer_private_unlock(void) __attribute__((alias("esp_timer_impl_unlock"))); void esp_timer_private_unlock(void) __attribute__((alias("esp_timer_impl_unlock")));

View File

@ -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/esp_private/panic_internal.h
components/esp_system/test_eh_frame_parser/linker.ld components/esp_system/test_eh_frame_parser/linker.ld
components/esp_system/ubsan.c 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.c
components/esp_timer/test/test_esp_timer_light_sleep.c components/esp_timer/test/test_esp_timer_light_sleep.c
components/esp_timer/test/test_ets_timer.c components/esp_timer/test/test_ets_timer.c