esp_time_impl.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. /*
  2. * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include <stdint.h>
  7. #include <time.h>
  8. #include <sys/time.h>
  9. #include <sys/lock.h>
  10. #include "esp_attr.h"
  11. #include "esp_system.h"
  12. #include "soc/rtc.h"
  13. #include "esp_rom_sys.h"
  14. #include "esp_private/system_internal.h"
  15. #include "esp_private/esp_clk.h"
  16. #include "esp_time_impl.h"
  17. #include "sdkconfig.h"
  18. #if CONFIG_IDF_TARGET_ESP32
  19. #include "esp32/rom/rtc.h"
  20. #include "esp32/rtc.h"
  21. #elif CONFIG_IDF_TARGET_ESP32S2
  22. #include "esp32s2/rom/rtc.h"
  23. #include "esp32s2/rtc.h"
  24. #elif CONFIG_IDF_TARGET_ESP32S3
  25. #include "esp32s3/rom/rtc.h"
  26. #include "esp32s3/rtc.h"
  27. #elif CONFIG_IDF_TARGET_ESP32C3
  28. #include "esp32c3/rom/rtc.h"
  29. #include "esp32c3/rtc.h"
  30. #elif CONFIG_IDF_TARGET_ESP32C2
  31. #include "esp32c2/rom/rtc.h"
  32. #include "esp32c2/rtc.h"
  33. #elif CONFIG_IDF_TARGET_ESP32C6
  34. #include "esp32c6/rom/rtc.h"
  35. #include "esp32c6/rtc.h"
  36. #elif CONFIG_IDF_TARGET_ESP32H2
  37. #include "esp32h2/rom/rtc.h"
  38. #include "esp32h2/rtc.h"
  39. #elif CONFIG_IDF_TARGET_ESP32P4
  40. #include "esp32p4/rom/rtc.h"
  41. #include "esp32p4/rtc.h"
  42. #endif
  43. // Offset between High resolution timer and the RTC.
  44. // Initialized after reset or light sleep.
  45. #if defined(CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER) && defined(CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER)
  46. int64_t s_microseconds_offset = 0;
  47. #endif
  48. #ifndef CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER
  49. static uint64_t s_boot_time; // when RTC is used to persist time, two RTC_STORE registers are used to store boot time instead
  50. #endif
  51. static _lock_t s_boot_time_lock;
  52. #if defined( CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER ) || defined( CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER )
  53. uint64_t esp_time_impl_get_time_since_boot(void)
  54. {
  55. uint64_t microseconds = 0;
  56. #ifdef CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER
  57. #ifdef CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER
  58. microseconds = s_microseconds_offset + esp_system_get_time();
  59. #else
  60. microseconds = esp_system_get_time();
  61. #endif // CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER
  62. #elif defined(CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER)
  63. microseconds = esp_rtc_get_time_us();
  64. #endif // CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER
  65. return microseconds;
  66. }
  67. uint64_t esp_time_impl_get_time(void)
  68. {
  69. uint64_t microseconds = 0;
  70. #if defined( CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER )
  71. microseconds = esp_system_get_time();
  72. #elif defined( CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER )
  73. microseconds = esp_rtc_get_time_us();
  74. #endif // CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER
  75. return microseconds;
  76. }
  77. #endif // defined( CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER ) || defined( CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER )
  78. void esp_time_impl_set_boot_time(uint64_t time_us)
  79. {
  80. _lock_acquire(&s_boot_time_lock);
  81. #ifdef CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER
  82. REG_WRITE(RTC_BOOT_TIME_LOW_REG, (uint32_t) (time_us & 0xffffffff));
  83. REG_WRITE(RTC_BOOT_TIME_HIGH_REG, (uint32_t) (time_us >> 32));
  84. #else
  85. s_boot_time = time_us;
  86. #endif
  87. _lock_release(&s_boot_time_lock);
  88. }
  89. uint64_t esp_time_impl_get_boot_time(void)
  90. {
  91. uint64_t result;
  92. _lock_acquire(&s_boot_time_lock);
  93. #ifdef CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER
  94. result = ((uint64_t) REG_READ(RTC_BOOT_TIME_LOW_REG)) + (((uint64_t) REG_READ(RTC_BOOT_TIME_HIGH_REG)) << 32);
  95. #else
  96. result = s_boot_time;
  97. #endif
  98. _lock_release(&s_boot_time_lock);
  99. return result;
  100. }
  101. void esp_set_time_from_rtc(void)
  102. {
  103. #if defined( CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER ) && defined( CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER )
  104. // initialize time from RTC clock
  105. s_microseconds_offset = esp_rtc_get_time_us() - esp_system_get_time();
  106. #endif // CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER && CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER
  107. }
  108. void esp_sync_timekeeping_timers(void)
  109. {
  110. #if defined( CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER ) && defined( CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER )
  111. struct timeval tv;
  112. gettimeofday(&tv, NULL);
  113. settimeofday(&tv, NULL);
  114. int64_t s_microseconds_offset_cur = esp_rtc_get_time_us() - esp_system_get_time();
  115. esp_time_impl_set_boot_time(esp_time_impl_get_boot_time() + ((int64_t)s_microseconds_offset - s_microseconds_offset_cur));
  116. #endif
  117. }
  118. void esp_time_impl_init(void)
  119. {
  120. esp_set_time_from_rtc();
  121. }