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();
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();

View File

@ -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

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);
}
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")));

View File

@ -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")));

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/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