esp_system: introduce system time functions

- Introduce system time function and concept of system time provider.
esp_timer is system time provider when present.
- Set the reference point for system time, g_startup_time.
- Use the system time functions in newlib instead of calling esp_timer
functions directly
pull/5778/head
Renz Bagaporo 2020-06-23 16:46:06 +08:00
rodzic 5785e4dfb6
commit 346cf4430d
14 zmienionych plików z 172 dodań i 31 usunięć

Wyświetl plik

@ -61,6 +61,16 @@ void esp_reset_reason_set_hint(esp_reset_reason_t hint);
*/
esp_reset_reason_t esp_reset_reason_get_hint(void);
/**
* @brief Set function which provides `esp_system_get_time`.
*
* @param time_fn function which provides system time
* @param resolution resolution in microseconds of the time provider function specified
*/
void esp_system_set_time_provider(esp_system_time_fn_t time_fn, uint32_t resolution);
#ifdef __cplusplus
}
#endif

Wyświetl plik

@ -1,4 +1,4 @@
idf_component_register(SRCS "panic.c" "system_api.c" "startup.c"
idf_component_register(SRCS "panic.c" "system_api.c" "startup.c" "system_time.c"
INCLUDE_DIRS include
PRIV_REQUIRES spi_flash app_update
# requirements due to startup code
@ -21,4 +21,4 @@ endif()
set_source_files_properties(
startup.c
PROPERTIES COMPILE_FLAGS
-fno-stack-protector)
-fno-stack-protector)

Wyświetl plik

@ -64,6 +64,10 @@ static __attribute__((used)) esp_system_init_fn_t _SECTION_ATTR_IMPL(".esp_syste
static __attribute__((used)) __VA_ARGS__ void __esp_system_init_fn_##f(void) // [refactor-todo] this can be made public API if we allow components to declare init functions,
// instead of calling them explicitly
extern uint64_t g_startup_time; // Startup time that serves as the point of origin for system time. Should be set by the entry
// function in the port layer. May be 0 as well if this is not backed by a persistent counter, in which case
// startup time = system time = 0 at the point the entry function sets this variable.
#ifdef __cplusplus
}
#endif

Wyświetl plik

@ -28,6 +28,8 @@
extern "C" {
#endif
typedef int64_t (*esp_system_time_fn_t)(void);
typedef enum {
ESP_MAC_WIFI_STA,
ESP_MAC_WIFI_SOFTAP,
@ -286,6 +288,20 @@ typedef struct {
*/
void esp_chip_info(esp_chip_info_t* out_info);
/**
* @brief Get the time in microseconds since startup
*
* @returns time since startup in microseconds
*/
int64_t esp_system_get_time(void);
/**
* @brief Get the resolution of the time returned by `esp_system_get_time`.
*
* @returns the resolution in microseconds
*/
uint32_t esp_system_get_time_resolution(void);
#if CONFIG_ESP32_ECO3_CACHE_LOCK_FIX
/**
* @brief Cache lock bug exists or not

Wyświetl plik

@ -55,6 +55,8 @@
#include "soc/dport_reg.h"
#include "soc/efuse_reg.h"
#include "soc/cpu.h"
#include "soc/rtc.h"
#include "soc/spinlock.h"
#include "trax.h"
@ -67,6 +69,7 @@
#endif
#include "esp_private/startup_internal.h"
#include "esp_private/system_internal.h"
extern int _bss_start;
extern int _bss_end;
@ -95,16 +98,27 @@ static volatile bool s_cpu_inited[SOC_CPU_CORES_NUM] = { false };
static volatile bool s_resume_cores;
#endif
uint64_t g_startup_time = 0;
// If CONFIG_SPIRAM_IGNORE_NOTFOUND is set and external RAM is not found or errors out on testing, this is set to false.
bool g_spiram_ok = true;
static int64_t default_system_time_fn(void)
{
int64_t t = 0;
static spinlock_t s_time_lock = SPINLOCK_INITIALIZER;
spinlock_acquire(&s_time_lock, SPINLOCK_WAIT_FOREVER);
t = (esp_rtc_get_time_us() - g_startup_time);
spinlock_release(&s_time_lock);
return t;
}
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
void startup_resume_other_cores(void)
{
s_resume_cores = true;
}
void IRAM_ATTR call_start_cpu1(void)
{
cpu_hal_set_vecbase(&_init_start);
@ -352,6 +366,12 @@ void IRAM_ATTR call_start_cpu0(void)
esp_clk_init();
esp_perip_clk_init();
// Now that the clocks have been set-up, set the startup time from RTC
// and default RTC-backed system time provider.
g_startup_time = esp_rtc_get_time_us();
esp_system_set_time_provider(default_system_time_fn, 1000000L / rtc_clk_slow_freq_get_hz());
intr_matrix_clear();
#ifdef CONFIG_ESP_CONSOLE_UART

Wyświetl plik

@ -183,6 +183,7 @@ static void IRAM_ATTR do_core_init(void)
fail initializing it properly. */
heap_caps_init();
esp_setup_syscall_table();
esp_newlib_time_init();
if (g_spiram_ok) {
#if CONFIG_SPIRAM_BOOT_INIT && (CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC)
@ -244,9 +245,6 @@ static void IRAM_ATTR do_core_init(void)
esp_efuse_disable_basic_rom_console();
#endif
esp_timer_init();
esp_set_time_from_rtc();
// [refactor-todo] move this to secondary init
#if CONFIG_APPTRACE_ENABLE
err = esp_apptrace_init();
@ -301,6 +299,7 @@ static void IRAM_ATTR do_secondary_init(void)
void IRAM_ATTR start_cpu0_default(void)
{
ESP_EARLY_LOGI(TAG, "Pro cpu start user code");
// Display information about the current running image.
@ -353,6 +352,8 @@ void IRAM_ATTR start_cpu0_default(void)
IRAM_ATTR ESP_SYSTEM_INIT_FN(init_components0, BIT(0))
{
esp_timer_init();
#if defined(CONFIG_PM_ENABLE) && defined(CONFIG_ESP_CONSOLE_UART)
/* When DFS is enabled, use REFTICK as UART clock source */
uart_ll_set_baudrate(UART_LL_GET_HW(CONFIG_ESP_CONSOLE_UART_NUM), UART_SCLK_REF_TICK, CONFIG_ESP_CONSOLE_UART_BAUDRATE);

Wyświetl plik

@ -0,0 +1,41 @@
// Copyright 2020 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.
#include "esp_system.h"
#include "esp_attr.h"
typedef struct {
esp_system_time_fn_t fn; // time provider function
uint32_t resolution; // resolution in microseconds of the time provider
} system_time_provider_t;
// This is expected to be modified only on startup, so
// it should be safe to not put locks on it.
static system_time_provider_t s_system_time_provider;
int64_t IRAM_ATTR esp_system_get_time(void)
{
return (*s_system_time_provider.fn)();
}
uint32_t IRAM_ATTR esp_system_get_time_resolution(void)
{
return s_system_time_provider.resolution;
}
void esp_system_set_time_provider(esp_system_time_fn_t time_fn, uint32_t resolution)
{
s_system_time_provider.fn = time_fn;
s_system_time_provider.resolution = resolution;
}

Wyświetl plik

@ -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/timekeeping.c")
if(CONFIG_ESP_TIMER_IMPL_FRC2)
list(APPEND srcs "src/esp_timer_impl_frc_legacy.c")

Wyświetl plik

@ -117,3 +117,8 @@ 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);
/**
* @brief Initialize and provide system timekeeping functions.
*/
esp_err_t esp_timer_timekeeping_impl_init(void);

Wyświetl plik

@ -97,7 +97,6 @@ static StaticQueue_t s_timer_semaphore_memory;
static portMUX_TYPE s_timer_lock = portMUX_INITIALIZER_UNLOCKED;
esp_err_t esp_timer_create(const esp_timer_create_args_t* args,
esp_timer_handle_t* out_handle)
{
@ -349,7 +348,6 @@ static IRAM_ATTR bool is_initialized(void)
return s_timer_task != NULL;
}
esp_err_t esp_timer_init(void)
{
esp_err_t err;
@ -380,6 +378,11 @@ esp_err_t esp_timer_init(void)
goto out;
}
err = esp_timer_timekeeping_impl_init();
if (err != ESP_OK) {
goto out;
}
return ESP_OK;
out:
@ -505,4 +508,4 @@ int64_t IRAM_ATTR esp_timer_get_next_alarm(void)
}
timer_list_unlock();
return next_alarm;
}
}

Wyświetl plik

@ -0,0 +1,45 @@
// Copyright 2020 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.
#include "esp_timer.h"
#include "esp_private/esp_timer_private.h"
#include "esp_private/system_internal.h"
#include "sdkconfig.h"
#if defined( CONFIG_ESP32_TIME_SYSCALL_USE_FRC1 ) || \
defined( CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1 ) || \
defined( CONFIG_ESP32S2_TIME_SYSCALL_USE_FRC1 ) || \
defined( CONFIG_ESP32S2_TIME_SYSCALL_USE_RTC_FRC1 )
#define WITH_FRC 1
#endif
#if WITH_FRC
void esp_timer_timekeeping_impl_init(void)
{
// esp_system_get_time here calls the previous system time provider.
// This should add the time elapsed from g_startup_time up to esp_timer_init,
// therefore keeping it as the point of reference (g_startup_time, that is).
esp_timer_private_advance(esp_system_get_time());
// esp_timer provides microsecond-resolution timers to the system
esp_system_set_time_provider(esp_timer_get_time, 1);
}
#else
void esp_timer_timekeeping_impl_init(void)
{
// Do not override default system time provider
}
#endif

Wyświetl plik

@ -21,7 +21,7 @@ list(APPEND ldfragments newlib.lf)
idf_component_register(SRCS "${srcs}"
INCLUDE_DIRS "${include_dirs}"
PRIV_INCLUDE_DIRS priv_include
PRIV_REQUIRES soc esp_timer
PRIV_REQUIRES soc
LDFRAGMENTS "${ldfragments}")
# Toolchain libraries require code defined in this component

Wyświetl plik

@ -15,8 +15,6 @@
#include <time.h>
#include <sys/time.h>
#include "esp_timer.h"
#include "esp_system.h"
#include "soc/spinlock.h"
@ -70,24 +68,31 @@ uint64_t esp_time_impl_get_time_since_boot(void)
#ifdef WITH_FRC
#ifdef WITH_RTC
microseconds = s_microseconds_offset + esp_timer_get_time();
microseconds = s_microseconds_offset + esp_system_get_time();
#else
microseconds = esp_timer_get_time();
microseconds = esp_system_get_time();
#endif // WITH_RTC
#elif defined(WITH_RTC)
spinlock_acquire(&s_time_lock, SPINLOCK_WAIT_FOREVER);
microseconds = esp_rtc_get_time_us();
spinlock_release(&s_time_lock);
#endif // WITH_FRC
return microseconds;
}
uint64_t esp_time_impl_get_time(void)
{
uint64_t microseconds = 0;
#if defined( WITH_FRC )
return esp_timer_get_time();
microseconds = esp_system_get_time();
#elif defined( WITH_RTC )
return esp_rtc_get_time_us();
spinlock_acquire(&s_time_lock, SPINLOCK_WAIT_FOREVER);
microseconds = esp_rtc_get_time_us();
spinlock_release(&s_time_lock);
#endif // WITH_FRC
return microseconds;
}
#endif // defined( WITH_FRC ) || defined( WITH_RTC )
@ -175,7 +180,7 @@ void esp_set_time_from_rtc(void)
{
#if defined( WITH_FRC ) && defined( WITH_RTC )
// initialize time from RTC clock
s_microseconds_offset = esp_rtc_get_time_us() - esp_timer_get_time();
s_microseconds_offset = esp_rtc_get_time_us() - esp_system_get_time();
#endif // WITH_FRC && WITH_RTC
}
@ -185,7 +190,7 @@ void esp_sync_counters_rtc_and_frc(void)
struct timeval tv;
gettimeofday(&tv, NULL);
settimeofday(&tv, NULL);
int64_t s_microseconds_offset_cur = esp_rtc_get_time_us() - esp_timer_get_time();
int64_t s_microseconds_offset_cur = esp_rtc_get_time_us() - esp_system_get_time();
esp_time_impl_set_boot_time(esp_time_impl_get_boot_time() + ((int64_t)s_microseconds_offset - s_microseconds_offset_cur));
#endif
}
@ -193,15 +198,4 @@ void esp_sync_counters_rtc_and_frc(void)
void esp_time_impl_init(void)
{
esp_set_time_from_rtc();
}
uint32_t esp_time_impl_get_time_resolution(void)
{
#if defined( WITH_FRC )
return 1L;
#elif defined( WITH_RTC )
uint32_t rtc_freq = rtc_clk_slow_freq_get_hz();
assert(rtc_freq != 0);
return 1000000L / rtc_freq;
#endif // WITH_FRC
}

Wyświetl plik

@ -22,6 +22,7 @@
#include <sys/time.h>
#include <sys/times.h>
#include "esp_system.h"
#include "esp_attr.h"
#include "freertos/FreeRTOS.h"
@ -285,7 +286,7 @@ int clock_getres (clockid_t clock_id, struct timespec *res)
}
res->tv_sec = 0;
res->tv_nsec = esp_time_impl_get_time_resolution() * 1000;
res->tv_nsec = esp_system_get_time_resolution() * 1000;
return 0;
#else