]> granicus.if.org Git - esp-idf/commitdiff
newlib: use RTC_STORE registers to keep boot time instead of RTC_SLOW_MEM
authorIvan Grokhotkov <igrokhotkov@gmail.com>
Wed, 11 Jan 2017 09:28:09 +0000 (17:28 +0800)
committerIvan Grokhotkov <igrokhotkov@gmail.com>
Thu, 12 Jan 2017 06:43:34 +0000 (14:43 +0800)
This allows RTC_SLOW_MEM to be powered down in deep sleep if no other variables are placed into RTC_SLOW_MEM.

components/esp32/Kconfig
components/esp32/include/rom/rtc.h
components/newlib/time.c

index bc35ca0e8f64b1d039f4d3fa4744afdd49021062..f0f74e989540c00be00a4ec5cba4ae13568d88de 100644 (file)
@@ -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"
index 1ff7f033b961b89d73a455e12b7ff4a6bb4ff169..e3c031775d71a730453f53e7d44050c473d04ffd 100644 (file)
@@ -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 {
index 363e17b3eb810731d606d74c3370e35e98574d6e..c9fa72eeee82b80a44f552218b6264b9b4615b53 100644 (file)
@@ -21,6 +21,7 @@
 #include <sys/time.h>
 #include <sys/times.h>
 #include <sys/lock.h>
+#include <rom/rtc.h>
 #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