Merge branch 'refactor/systimer_reset_alternative' into 'master'

Systimer reset alternative on S2 (and others)

See merge request espressif/esp-idf!12694
This commit is contained in:
Angus Gratton 2021-03-29 09:27:41 +00:00
commit a2740be080
12 changed files with 139 additions and 29 deletions

View File

@ -327,7 +327,7 @@ TEST_CASE("Test rtc clk calibration compensation", "[rtc_clk]")
// so that t2 > t1 remains true
int64_t t2 = esp_rtc_get_time_us();
TEST_ASSERT(t2 > t1);
TEST_ASSERT_GREATER_THAN(t1, t2);
// Restore calibration value
esp_clk_slowclk_cal_set(esp_clk_slowclk_cal_get() * 2);
@ -337,7 +337,7 @@ TEST_CASE("Test rtc clk calibration compensation", "[rtc_clk]")
t2 = esp_rtc_get_time_us();
TEST_ASSERT(t2 > t1);
TEST_ASSERT_GREATER_THAN(t1, t2);
}
static void trigger_deepsleep(void)
@ -364,7 +364,7 @@ static void check_time_deepsleep_1(void)
RESET_REASON reason = rtc_get_reset_reason(0);
TEST_ASSERT(reason == DEEPSLEEP_RESET);
int64_t end = esp_rtc_get_time_us();
TEST_ASSERT(end > start);
TEST_ASSERT_GREATER_THAN(start, end);
esp_clk_slowclk_cal_set(esp_clk_slowclk_cal_get() * 2);
@ -384,7 +384,7 @@ static void check_time_deepsleep_2(void)
RESET_REASON reason = rtc_get_reset_reason(0);
TEST_ASSERT(reason == DEEPSLEEP_RESET);
int64_t end = esp_rtc_get_time_us();
TEST_ASSERT(end > start);
TEST_ASSERT_GREATER_THAN(start, end);
}
TEST_CASE_MULTIPLE_STAGES("Test rtc clk calibration compensation across deep sleep", "[rtc_clk][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET]", trigger_deepsleep, check_time_deepsleep_1, check_time_deepsleep_2);

View File

@ -0,0 +1,29 @@
## System Notes
### Timekeeping
The following are the timekeeping mechanisms available and their differences:
1. System time (`esp_system_get_time`)
Time with the origin at `g_startup_time`. The implementation is not handled by `esp_system`,
but it does provide a default implementation using RTC timer. Currently, `esp_timer`
provides system time, since the hardware timers are under the control of that
component. However, no matter the underlying timer, the system time provider
should maintain the definition of having the origin point at `g_startup_time`.
2. `esp_timer` time (`esp_timer_get_time`)
This is the time read from an underlying hardware timer, controlled through config. Origin
is at the point where the underlying timer starts counting.
3. `newlib` time (`gettimeofday`)
Timekeeping function in standard library. Can be set (`settimeofday`) or moved forward/backward (`adjtime`);
with the possibility of the changes being made persistent through config.
Currently implemented in terms of system time, as the point of origin is fixed.
If persistence is enabled, RTC time is also used in conjuction with system time.
4. RTC time (`esp_rtc_get_time_us`)
Time read from RTC timer.

View File

@ -61,11 +61,11 @@ void esp_reset_reason_set_hint(esp_reset_reason_t hint);
*/
esp_reset_reason_t esp_reset_reason_get_hint(void);
/**
* @brief Get the time in microseconds since startup
*
* @returns time since startup in microseconds
* @returns time since g_startup_time; definition should be fixed by system time provider
* no matter the underlying timer used.
*/
int64_t esp_system_get_time(void);

View File

@ -316,7 +316,6 @@ __attribute__((weak)) void esp_perip_clk_init(void)
DPORT_CLEAR_PERI_REG_MASK(DPORT_BT_LPCK_DIV_FRAC_REG, DPORT_LPCLK_SEL_8M);
DPORT_SET_PERI_REG_MASK(DPORT_BT_LPCK_DIV_FRAC_REG, DPORT_LPCLK_SEL_RTC_SLOW);
periph_ll_reset(PERIPH_SYSTIMER_MODULE);
/* Enable RNG clock. */
periph_module_enable(PERIPH_RNG_MODULE);

View File

@ -0,0 +1,36 @@
#include <stdio.h>
#include "unity.h"
#include "esp_private/system_internal.h"
#if CONFIG_IDF_TARGET_ESP32
#include "esp32/clk.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/clk.h"
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/clk.h"
#elif CONFIG_IDF_TARGET_ESP32C3
#include "esp32c3/clk.h"
#endif
TEST_CASE("Test effect of rtc clk calibration compensation on system time", "[esp_system]")
{
uint32_t prev_cal = esp_clk_slowclk_cal_get();
int64_t t1 = esp_system_get_time();
// Modify calibration value
esp_clk_slowclk_cal_set(prev_cal/2);
// Internally, the origin point of rtc clk has been adjusted
// so that t2 > t1 remains true
int64_t t2 = esp_system_get_time();
TEST_ASSERT_GREATER_THAN(t1, t2);
// Restore calibration value
esp_clk_slowclk_cal_set(prev_cal);
t2 = esp_system_get_time();
TEST_ASSERT_GREATER_THAN(t1, t2);
}

View File

@ -1,7 +1,8 @@
idf_build_get_property(target IDF_TARGET)
set(srcs "src/esp_timer.c"
"src/ets_timer_legacy.c")
"src/ets_timer_legacy.c"
"src/system_time.c")
if(CONFIG_ESP_TIMER_IMPL_FRC2)
list(APPEND srcs "src/esp_timer_impl_frc_legacy.c")

View File

@ -184,8 +184,7 @@ esp_err_t esp_timer_delete(esp_timer_handle_t timer);
/**
* @brief Get time in microseconds since boot
* @return number of microseconds since esp_timer_init was called (this normally
* happens early during application startup).
* @return number of microseconds since underlying timer has been started
*/
int64_t esp_timer_get_time(void);

View File

@ -132,3 +132,10 @@ uint64_t esp_timer_impl_get_counter_reg(void);
* @return the value of the alarm register
*/
uint64_t esp_timer_impl_get_alarm_reg(void);
#if CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER
/**
* @brief Initialize esp_timer as system time provider.
*/
void esp_timer_impl_init_system_time(void);
#endif

View File

@ -446,9 +446,7 @@ esp_err_t esp_timer_init(void)
}
#if CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER
// [refactor-todo] this logic, "esp_rtc_get_time_us() - g_startup_time", is also
// the weak definition of esp_system_get_time; find a way to remove this duplication.
esp_timer_private_advance(esp_rtc_get_time_us() - g_startup_time);
esp_timer_impl_init_system_time();
#endif
return ESP_OK;
@ -600,17 +598,3 @@ int64_t IRAM_ATTR esp_timer_get_next_alarm(void)
}
return next_alarm;
}
// Provides strong definition for system time functions relied upon
// by core components.
#if CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER
int64_t IRAM_ATTR esp_system_get_time(void)
{
return esp_timer_get_time();
}
uint32_t IRAM_ATTR esp_system_get_time_resolution(void)
{
return 1000;
}
#endif

View File

@ -0,0 +1,53 @@
// 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.
// Provides strong definition for system time functions relied upon
// by core components.
#include "sdkconfig.h"
#if CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER
#include "esp_timer.h"
#include "esp_timer_impl.h"
#include "esp_private/startup_internal.h"
#if CONFIG_IDF_TARGET_ESP32
#include "esp32/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32C3
#include "esp32c3/rtc.h"
#endif
// Correction for underlying timer to keep definition
// of system time consistent.
static int64_t s_correction_us = 0;
void esp_timer_impl_init_system_time(void)
{
s_correction_us = esp_rtc_get_time_us() - g_startup_time - esp_timer_impl_get_time();
}
int64_t IRAM_ATTR esp_system_get_time(void)
{
return esp_timer_get_time() + s_correction_us;
}
uint32_t IRAM_ATTR esp_system_get_time_resolution(void)
{
return 1000;
}
#endif

View File

@ -51,7 +51,7 @@
// Offset between FRC timer and the RTC.
// Initialized after reset or light sleep.
#if defined(CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER) && defined(CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER)
uint64_t s_microseconds_offset = 0;
int64_t s_microseconds_offset = 0;
#endif
#ifndef CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER

View File

@ -17,6 +17,8 @@
#include "esp_system.h"
#include "esp_timer.h"
#include "esp_private/system_internal.h"
#if CONFIG_IDF_TARGET_ESP32
#include "esp32/clk.h"
#define TARGET_DEFAULT_CPU_FREQ_MHZ CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ
@ -403,7 +405,7 @@ void test_posix_timers_clock (void)
TEST_ASSERT_EQUAL_INT(1000, ts.tv_nsec);
TEST_ASSERT(clock_gettime(CLOCK_MONOTONIC, &ts) == 0);
delta_monotonic_us = esp_timer_get_time() - (ts.tv_sec * 1000000L + ts.tv_nsec / 1000L);
delta_monotonic_us = esp_system_get_time() - (ts.tv_sec * 1000000L + ts.tv_nsec / 1000L);
TEST_ASSERT(delta_monotonic_us > 0 || delta_monotonic_us == 0);
TEST_ASSERT_INT_WITHIN(5000L, 0, delta_monotonic_us);