kopia lustrzana https://github.com/espressif/esp-idf
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 directlypull/5778/head
rodzic
5785e4dfb6
commit
346cf4430d
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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")
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
|
|
Ładowanie…
Reference in New Issue