From 8140b10a1602290f05b24e793fd22b929eb92b04 Mon Sep 17 00:00:00 2001 From: Konstantin Kondrashov Date: Thu, 28 Oct 2021 17:33:46 +0000 Subject: [PATCH] esp_system: Adds sync of FRC & RTC counters in esp_restart (v4.3) --- components/esp32c3/system_api_esp32c3.c | 2 +- components/esp_system/system_api.c | 2 +- components/esp_timer/src/system_time.c | 11 +++ components/newlib/test/test_time.c | 105 ++++++++++++++++++++++++ 4 files changed, 118 insertions(+), 2 deletions(-) diff --git a/components/esp32c3/system_api_esp32c3.c b/components/esp32c3/system_api_esp32c3.c index eb7f170974..dbf43ddfe7 100644 --- a/components/esp32c3/system_api_esp32c3.c +++ b/components/esp32c3/system_api_esp32c3.c @@ -106,7 +106,7 @@ void IRAM_ATTR esp_restart_noos(void) // Reset timer/spi/uart SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN0_REG, - SYSTEM_TIMERS_RST | SYSTEM_SPI01_RST | SYSTEM_UART_RST); + SYSTEM_TIMERS_RST | SYSTEM_SPI01_RST | SYSTEM_UART_RST | SYSTEM_SYSTIMER_RST); REG_WRITE(SYSTEM_PERIP_RST_EN0_REG, 0); // Reset dma SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_DMA_RST); diff --git a/components/esp_system/system_api.c b/components/esp_system/system_api.c index d20cb00102..5a7b1e3083 100644 --- a/components/esp_system/system_api.c +++ b/components/esp_system/system_api.c @@ -16,8 +16,8 @@ #include "esp32c3/memprot.h" #endif +#define SHUTDOWN_HANDLERS_NO 5 -#define SHUTDOWN_HANDLERS_NO 4 static shutdown_handler_t shutdown_handlers[SHUTDOWN_HANDLERS_NO]; esp_err_t esp_register_shutdown_handler(shutdown_handler_t handler) diff --git a/components/esp_timer/src/system_time.c b/components/esp_timer/src/system_time.c index 08f0e7d292..ff4e03844a 100644 --- a/components/esp_timer/src/system_time.c +++ b/components/esp_timer/src/system_time.c @@ -19,6 +19,9 @@ #if CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER #include "esp_timer.h" #include "esp_timer_impl.h" +#include "esp_system.h" +#include "esp_newlib.h" +#include "esp_log.h" #include "esp_private/startup_internal.h" @@ -32,6 +35,8 @@ #include "esp32c3/rtc.h" #endif +__attribute__((unused)) static const char* TAG = "system_time"; + // Correction for underlying timer to keep definition // of system time consistent. static int64_t s_correction_us = 0; @@ -39,6 +44,12 @@ 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(); +#if defined(CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER) && defined(CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER) + esp_err_t err = esp_register_shutdown_handler(esp_sync_counters_rtc_and_frc); + if (err != ESP_OK) { + ESP_LOGW(TAG, "Register shutdown handler failed, err = 0x%x", err); + } +#endif } int64_t IRAM_ATTR esp_system_get_time(void) diff --git a/components/newlib/test/test_time.c b/components/newlib/test/test_time.c index 64ca582fca..752fa091ab 100644 --- a/components/newlib/test/test_time.c +++ b/components/newlib/test/test_time.c @@ -16,20 +16,27 @@ #include "esp_rom_sys.h" #include "esp_system.h" #include "esp_timer.h" +#include "esp_private/system_internal.h" +#include "esp_private/esp_timer_private.h" +#include "../priv_include/esp_time_impl.h" #include "esp_private/system_internal.h" #if CONFIG_IDF_TARGET_ESP32 #include "esp32/clk.h" +#include "esp32/rtc.h" #define TARGET_DEFAULT_CPU_FREQ_MHZ CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ #elif CONFIG_IDF_TARGET_ESP32S2 #include "esp32s2/clk.h" +#include "esp32s2/rtc.h" #define TARGET_DEFAULT_CPU_FREQ_MHZ CONFIG_ESP32S2_DEFAULT_CPU_FREQ_MHZ #elif CONFIG_IDF_TARGET_ESP32S3 #include "esp32s3/clk.h" +#include "esp32s3/rtc.h" #define TARGET_DEFAULT_CPU_FREQ_MHZ CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ #elif CONFIG_IDF_TARGET_ESP32C3 #include "esp32c3/clk.h" +#include "esp32c3/rtc.h" #define TARGET_DEFAULT_CPU_FREQ_MHZ CONFIG_ESP32C3_DEFAULT_CPU_FREQ_MHZ #endif @@ -528,3 +535,101 @@ TEST_CASE("test time functions wide 64 bits", "[newlib]") } #endif // CONFIG_SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS + +#if defined( CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER ) && defined( CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER ) + +extern int64_t s_microseconds_offset; +static const uint64_t s_start_timestamp = 1606838354; +static RTC_NOINIT_ATTR uint64_t s_saved_time; +static RTC_NOINIT_ATTR uint64_t s_time_in_reboot; + +typedef enum { + TYPE_REBOOT_ABORT = 0, + TYPE_REBOOT_RESTART, +} type_reboot_t; + +static void print_counters(void) +{ + int64_t frc = esp_system_get_time(); + int64_t rtc = esp_rtc_get_time_us(); + uint64_t boot_time = esp_time_impl_get_boot_time(); + printf("\tFRC %lld (us)\n", frc); + printf("\tRTC %lld (us)\n", rtc); + printf("\tBOOT %lld (us)\n", boot_time); + printf("\ts_microseconds_offset %lld (us)\n", s_microseconds_offset); + printf("delta RTC - FRC counters %lld (us)\n", rtc - frc); +} + +static void set_initial_condition(type_reboot_t type_reboot, int error_time) +{ + print_counters(); + + struct timeval tv = { .tv_sec = s_start_timestamp, .tv_usec = 0, }; + settimeofday(&tv, NULL); + printf("set timestamp %lld (s)\n", s_start_timestamp); + + print_counters(); + + int delay_s = abs(error_time) * 2; + printf("Waiting for %d (s) ...\n", delay_s); + vTaskDelay(delay_s * 1000 / portTICK_RATE_MS); + + print_counters(); + + printf("FRC counter increased to %d (s)\n", error_time); + esp_timer_private_advance(error_time * 1000000ULL); + + print_counters(); + + gettimeofday(&tv, NULL); + s_saved_time = tv.tv_sec; + printf("s_saved_time %lld (s)\n", s_saved_time); + int dt = s_saved_time - s_start_timestamp; + printf("delta timestamp = %d (s)\n", dt); + TEST_ASSERT_GREATER_OR_EQUAL(error_time, dt); + s_time_in_reboot = esp_rtc_get_time_us(); + + if (type_reboot == TYPE_REBOOT_ABORT) { + printf("Update boot time based on diff\n"); + esp_sync_counters_rtc_and_frc(); + print_counters(); + printf("reboot as abort\n"); + abort(); + } else if (type_reboot == TYPE_REBOOT_RESTART) { + printf("reboot as restart\n"); + esp_restart(); + } +} + +static void set_timestamp1(void) +{ + set_initial_condition(TYPE_REBOOT_ABORT, 5); +} + +static void set_timestamp2(void) +{ + set_initial_condition(TYPE_REBOOT_RESTART, 5); +} + +static void set_timestamp3(void) +{ + set_initial_condition(TYPE_REBOOT_RESTART, -5); +} + +static void check_time(void) +{ + print_counters(); + int latency_before_run_ut = 1 + (esp_rtc_get_time_us() - s_time_in_reboot) / 1000000; + struct timeval tv; + gettimeofday(&tv, NULL); + printf("timestamp %ld (s)\n", tv.tv_sec); + int dt = tv.tv_sec - s_saved_time; + printf("delta timestamp = %d (s)\n", dt); + TEST_ASSERT_GREATER_OR_EQUAL(0, dt); + TEST_ASSERT_LESS_OR_EQUAL(latency_before_run_ut, dt); +} + +TEST_CASE_MULTIPLE_STAGES("Timestamp after abort is correct in case RTC & FRC have + big error", "[newlib][reset=abort,SW_CPU_RESET]", set_timestamp1, check_time); +TEST_CASE_MULTIPLE_STAGES("Timestamp after restart is correct in case RTC & FRC have + big error", "[newlib][reset=SW_CPU_RESET]", set_timestamp2, check_time); +TEST_CASE_MULTIPLE_STAGES("Timestamp after restart is correct in case RTC & FRC have - big error", "[newlib][reset=SW_CPU_RESET]", set_timestamp3, check_time); +#endif // CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER && CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER