Просмотр исходного кода

Merge branch 'bugfix/check_a_time_after_deepsleep' into 'master'

Fix esp32s2 timekeeping on deep sleep issue

See merge request espressif/esp-idf!12623
Angus Gratton 4 лет назад
Родитель
Сommit
7ebefe2e2b
2 измененных файлов с 102 добавлено и 3 удалено
  1. 100 2
      components/esp_hw_support/test/test_rtc_clk.c
  2. 2 1
      components/newlib/port/esp_time_impl.c

+ 100 - 2
components/esp_hw_support/test/test_rtc_clk.c

@@ -1,6 +1,7 @@
 #include <stdio.h>
 #include "unity.h"
 
+#include "esp_attr.h"
 #include "soc/soc_caps.h"
 #include "soc/rtc.h"
 #include "soc/rtc_periph.h"
@@ -18,12 +19,31 @@
 #include "esp_rom_sys.h"
 #include "esp_rom_uart.h"
 
+#include "esp_sleep.h"
+#include "esp_system.h"
+
+#if CONFIG_IDF_TARGET_ESP32
+#include "esp32/rtc.h"
+#include "esp32/clk.h"
+#include "esp32/rom/rtc.h"
+#elif CONFIG_IDF_TARGET_ESP32S2
+#include "esp32s2/rtc.h"
+#include "esp32s2/clk.h"
+#include "esp32s2/rom/rtc.h"
+#elif CONFIG_IDF_TARGET_ESP32S3
+#include "esp32s3/rtc.h"
+#include "esp32s3/clk.h"
+#include "esp32s3/rom/rtc.h"
+#elif CONFIG_IDF_TARGET_ESP32C3
+#include "esp32c3/rtc.h"
+#include "esp32c3/clk.h"
+#include "esp32c3/rom/rtc.h"
+#endif
+
 extern void rtc_clk_select_rtc_slow_clk(void);
 
 #if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32S3, ESP32C3)
 
-#include "esp32/clk.h"
-
 #define CALIBRATE_ONE(cali_clk) calibrate_one(cali_clk, #cali_clk)
 
 static uint32_t calibrate_one(rtc_cal_sel_t cal_clk, const char* name)
@@ -290,3 +310,81 @@ TEST_CASE("Test starting 'External 32kHz XTAL' on the board without it.", "[rtc_
 }
 
 #endif
+
+static RTC_NOINIT_ATTR int64_t start = 0;
+
+TEST_CASE("Test rtc clk calibration compensation", "[rtc_clk]")
+{
+    int64_t t1 = esp_rtc_get_time_us();
+
+    // Modify calibration value
+    esp_clk_slowclk_cal_set(esp_clk_slowclk_cal_get() / 2);
+
+    // Delay for error accumulation.
+    vTaskDelay(pdMS_TO_TICKS(1000));
+
+    // Internally, the origin point of rtc clk has been adjusted
+    // so that t2 > t1 remains true
+    int64_t t2 = esp_rtc_get_time_us();
+
+    TEST_ASSERT(t2 > t1);
+
+    // Restore calibration value
+    esp_clk_slowclk_cal_set(esp_clk_slowclk_cal_get() * 2);
+
+    // Delay for error accumulation.
+    vTaskDelay(pdMS_TO_TICKS(1000));
+
+    t2 = esp_rtc_get_time_us();
+
+    TEST_ASSERT(t2 > t1);
+}
+
+static void trigger_deepsleep(void)
+{
+    printf("Trigger deep sleep. Waiting for 10 sec ...\n");
+
+    // Simulate the dispersion of the calibration coefficients at start-up.
+    // Corrupt the calibration factor.
+    esp_clk_slowclk_cal_set(esp_clk_slowclk_cal_get() / 2);
+
+    // Delay for error accumulation.
+    vTaskDelay(pdMS_TO_TICKS(1000));
+
+    // Save start time. Deep sleep.
+    start = esp_rtc_get_time_us();
+    esp_sleep_enable_timer_wakeup(1000);
+    // In function esp_deep_sleep_start() uses function esp_sync_counters_rtc_and_frc()
+    // to prevent a negative time after wake up.
+    esp_deep_sleep_start();
+}
+
+static void check_time_deepsleep_1(void)
+{
+    RESET_REASON reason = rtc_get_reset_reason(0);
+    TEST_ASSERT(reason == DEEPSLEEP_RESET);
+    int64_t end = esp_rtc_get_time_us();
+    TEST_ASSERT(end > start);
+
+    esp_clk_slowclk_cal_set(esp_clk_slowclk_cal_get() * 2);
+
+    // Delay for error accumulation.
+    vTaskDelay(pdMS_TO_TICKS(1000));
+
+    start = esp_rtc_get_time_us();
+
+    esp_sleep_enable_timer_wakeup(1000);
+    // In function esp_deep_sleep_start() uses function esp_sync_counters_rtc_and_frc()
+    // to prevent a negative time after wake up.
+    esp_deep_sleep_start();
+}
+
+static void check_time_deepsleep_2(void)
+{
+    RESET_REASON reason = rtc_get_reset_reason(0);
+    TEST_ASSERT(reason == DEEPSLEEP_RESET);
+    int64_t end = esp_rtc_get_time_us();
+    TEST_ASSERT(end > start);
+}
+
+TEST_CASE_MULTIPLE_STAGES("Test rtc clk calibration compensation across deep sleep", "[rtc_clk][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET]", trigger_deepsleep, check_time_deepsleep_1, check_time_deepsleep_2);

+ 2 - 1
components/newlib/port/esp_time_impl.c

@@ -16,6 +16,7 @@
 #include <sys/time.h>
 #include <sys/lock.h>
 
+#include "esp_attr.h"
 #include "esp_system.h"
 
 #include "soc/rtc.h"
@@ -60,7 +61,7 @@ static uint64_t s_boot_time; // when RTC is used to persist time, two RTC_STORE
 static _lock_t s_boot_time_lock;
 
 static _lock_t s_esp_rtc_time_lock;
-static uint64_t s_esp_rtc_time_us, s_rtc_last_ticks;
+static RTC_DATA_ATTR uint64_t s_esp_rtc_time_us = 0, s_rtc_last_ticks = 0;
 
 #if defined( CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER ) || defined( CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER )
 uint64_t esp_time_impl_get_time_since_boot(void)