diff --git a/components/esp32/Kconfig b/components/esp32/Kconfig index bc35ca0e8..f0f74e989 100644 --- a/components/esp32/Kconfig +++ b/components/esp32/Kconfig @@ -381,6 +381,8 @@ choice ESP32_TIME_SYSCALL longer to run. - If no timers are used, gettimeofday and time functions return -1 and set errno to ENOSYS. + - When RTC is used for timekeeping, two RTC_STORE registers are + used to keep time in deep sleep mode. config ESP32_TIME_SYSCALL_USE_RTC bool "RTC" diff --git a/components/esp32/include/rom/rtc.h b/components/esp32/include/rom/rtc.h index 1ff7f033b..e3c031775 100644 --- a/components/esp32/include/rom/rtc.h +++ b/components/esp32/include/rom/rtc.h @@ -53,16 +53,18 @@ extern "C" { * Rtc store registers usage * RTC_CNTL_STORE0_REG * RTC_CNTL_STORE1_REG - * RTC_CNTL_STORE2_REG - * RTC_CNTL_STORE3_REG - * RTC_CNTL_STORE4_REG Reserved - * RTC_CNTL_STORE5_REG External Xtal Frequency + * RTC_CNTL_STORE2_REG Boot time, low word + * RTC_CNTL_STORE3_REG Boot time, high word + * RTC_CNTL_STORE4_REG External XTAL frequency + * RTC_CNTL_STORE5_REG APB bus frequency * RTC_CNTL_STORE6_REG FAST_RTC_MEMORY_ENTRY * RTC_CNTL_STORE7_REG FAST_RTC_MEMORY_CRC ************************************************************************************* */ -#define RTC_ENTRY_ADDR_REG RTC_CNTL_STORE6_REG -#define RTC_MEMORY_CRC_REG RTC_CNTL_STORE7_REG +#define RTC_BOOT_TIME_LOW_REG RTC_CNTL_STORE2_REG +#define RTC_BOOT_TIME_HIGH_REG RTC_CNTL_STORE3_REG +#define RTC_ENTRY_ADDR_REG RTC_CNTL_STORE6_REG +#define RTC_MEMORY_CRC_REG RTC_CNTL_STORE7_REG typedef enum { diff --git a/components/newlib/time.c b/components/newlib/time.c index 363e17b3e..c9fa72eee 100644 --- a/components/newlib/time.c +++ b/components/newlib/time.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "esp_attr.h" #include "esp_intr_alloc.h" #include "soc/soc.h" @@ -58,9 +59,9 @@ static uint64_t get_rtc_time_us() // s_boot_time: time from Epoch to the first boot time #ifdef WITH_RTC -static RTC_DATA_ATTR struct timeval s_boot_time; +// when RTC is used to persist time, two RTC_STORE registers are used to store boot time #elif defined(WITH_FRC1) -static struct timeval s_boot_time; +static uint64_t s_boot_time; #endif #if defined(WITH_RTC) || defined(WITH_FRC1) @@ -88,6 +89,31 @@ static void IRAM_ATTR frc_timer_isr() #endif // WITH_FRC1 +static void set_boot_time(uint64_t time_us) +{ + _lock_acquire(&s_boot_time_lock); +#ifdef WITH_RTC + REG_WRITE(RTC_BOOT_TIME_LOW_REG, (uint32_t) (time_us & 0xffffffff)); + REG_WRITE(RTC_BOOT_TIME_HIGH_REG, (uint32_t) (time_us >> 32)); +#else + s_boot_time = time_us; +#endif + _lock_release(&s_boot_time_lock); +} + +static uint64_t get_boot_time() +{ + uint64_t result; + _lock_acquire(&s_boot_time_lock); +#ifdef WITH_RTC + result = ((uint64_t) REG_READ(RTC_BOOT_TIME_LOW_REG)) + (((uint64_t) REG_READ(RTC_BOOT_TIME_HIGH_REG)) << 32); +#else + result = s_boot_time; +#endif + _lock_release(&s_boot_time_lock); + return result; +} + void esp_setup_time_syscalls() { #if defined( WITH_FRC1 ) @@ -148,13 +174,10 @@ int IRAM_ATTR _gettimeofday_r(struct _reent *r, struct timeval *tv, void *tz) { (void) tz; #if defined( WITH_FRC1 ) || defined( WITH_RTC ) - uint64_t microseconds = get_time_since_boot(); if (tv) { - _lock_acquire(&s_boot_time_lock); - microseconds += s_boot_time.tv_usec; - tv->tv_sec = s_boot_time.tv_sec + microseconds / 1000000; + uint64_t microseconds = get_boot_time() + get_time_since_boot(); + tv->tv_sec = microseconds / 1000000; tv->tv_usec = microseconds % 1000000; - _lock_release(&s_boot_time_lock); } return 0; #else @@ -168,14 +191,9 @@ int settimeofday(const struct timeval *tv, const struct timezone *tz) (void) tz; #if defined( WITH_FRC1 ) || defined( WITH_RTC ) if (tv) { - _lock_acquire(&s_boot_time_lock); uint64_t now = ((uint64_t) tv->tv_sec) * 1000000LL + tv->tv_usec; uint64_t since_boot = get_time_since_boot(); - uint64_t boot_time = now - since_boot; - - s_boot_time.tv_sec = boot_time / 1000000; - s_boot_time.tv_usec = boot_time % 1000000; - _lock_release(&s_boot_time_lock); + set_boot_time(now - since_boot); } return 0; #else