Explorar el Código

light sleep: overhead time accuracy optimization for esp32c3

Li Shuai hace 5 años
padre
commit
ac7d1bec76

+ 2 - 0
components/esp_pm/pm_impl.c

@@ -612,6 +612,8 @@ void IRAM_ATTR vApplicationSleep( TickType_t xExpectedIdleTime )
                 while (!(XTHAL_GET_INTERRUPT() & BIT(XT_TIMER_INTNUM))) {
                     ;
                 }
+#elif __riscv
+                portYIELD_WITHIN_API();
 #endif
             }
             other_core_should_skip_light_sleep(core_id);

+ 31 - 31
components/esp_system/sleep_modes.c

@@ -82,42 +82,32 @@
 #define RTC_CLK_SRC_CAL_CYCLES      (10)
 
 #ifdef CONFIG_IDF_TARGET_ESP32
-#define DEFAULT_CPU_FREQ_MHZ           CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ
-#define DEFAULT_SLEEP_OUT_OVERHEAD_US  (212)
-#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (60)
+#define DEFAULT_CPU_FREQ_MHZ                CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ
+#define DEFAULT_SLEEP_OUT_OVERHEAD_US       (212)
+#define DEFAULT_HARDWARE_OUT_OVERHEAD_US    (60)
 #elif CONFIG_IDF_TARGET_ESP32S2
-#define DEFAULT_CPU_FREQ_MHZ           CONFIG_ESP32S2_DEFAULT_CPU_FREQ_MHZ
-#define DEFAULT_SLEEP_OUT_OVERHEAD_US  (147)
-#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (28)
+#define DEFAULT_CPU_FREQ_MHZ                CONFIG_ESP32S2_DEFAULT_CPU_FREQ_MHZ
+#define DEFAULT_SLEEP_OUT_OVERHEAD_US       (147)
+#define DEFAULT_HARDWARE_OUT_OVERHEAD_US    (28)
 #elif CONFIG_IDF_TARGET_ESP32S3
-#define DEFAULT_CPU_FREQ_MHZ           CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ
-#define DEFAULT_SLEEP_OUT_OVERHEAD_US  (0)
-#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (0)
+#define DEFAULT_CPU_FREQ_MHZ                CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ
+#define DEFAULT_SLEEP_OUT_OVERHEAD_US       (0)
+#define DEFAULT_HARDWARE_OUT_OVERHEAD_US    (0)
 #elif CONFIG_IDF_TARGET_ESP32C3
-#define DEFAULT_CPU_FREQ_MHZ        CONFIG_ESP32C3_DEFAULT_CPU_FREQ_MHZ
+#define DEFAULT_CPU_FREQ_MHZ                CONFIG_ESP32C3_DEFAULT_CPU_FREQ_MHZ
+#define DEFAULT_SLEEP_OUT_OVERHEAD_US       (105)
+#define DEFAULT_HARDWARE_OUT_OVERHEAD_US    (37)
 #endif
 
-#if defined(CONFIG_IDF_TARGET_ESP32) || defined(CONFIG_IDF_TARGET_ESP32S2)
-#define LIGHT_SLEEP_TIME_OVERHEAD_US DEFAULT_HARDWARE_OUT_OVERHEAD_US
-#if defined(CONFIG_ESP32_RTC_CLK_SRC_EXT_CRYS) || defined (CONFIG_ESP32S2_RTC_CLK_SRC_EXT_CRYS)
-#define DEEP_SLEEP_TIME_OVERHEAD_US    (650 + 100 * 240 / DEFAULT_CPU_FREQ_MHZ)
+#define LIGHT_SLEEP_TIME_OVERHEAD_US        DEFAULT_HARDWARE_OUT_OVERHEAD_US
+#if defined(CONFIG_ESP32_RTC_CLK_SRC_EXT_CRYS)   || \
+    defined(CONFIG_ESP32S2_RTC_CLK_SRC_EXT_CRYS) || \
+    defined(CONFIG_ESP32C3_RTC_CLK_SRC_EXT_CRYS) || \
+    defined(CONFIG_ESP32S3_RTC_CLK_SRC_EXT_CRYS)
+#define DEEP_SLEEP_TIME_OVERHEAD_US         (650 + 100 * 240 / DEFAULT_CPU_FREQ_MHZ)
 #else
-#define DEEP_SLEEP_TIME_OVERHEAD_US    (250 + 100 * 240 / DEFAULT_CPU_FREQ_MHZ)
-#endif // defined(CONFIG_ESP32_RTC_CLK_SRC_EXT_CRYS) || defined (CONFIG_ESP32S2_RTC_CLK_SRC_EXT_CRYS)
-
-#elif defined(CONFIG_IDF_TARGET_ESP32C3)
-#ifdef CONFIG_ESP32C3_RTC_CLK_SRC_EXT_CRYS
-#define LIGHT_SLEEP_TIME_OVERHEAD_US (650 + 30 * 240 / CONFIG_ESP32C3_DEFAULT_CPU_FREQ_MHZ)
-#define DEEP_SLEEP_TIME_OVERHEAD_US (650 + 100 * 240 / CONFIG_ESP32C3_DEFAULT_CPU_FREQ_MHZ)
-#else
-#define LIGHT_SLEEP_TIME_OVERHEAD_US (250 + 30 * 240 / CONFIG_ESP32C3_DEFAULT_CPU_FREQ_MHZ)
-#define DEEP_SLEEP_TIME_OVERHEAD_US (250 + 100 * 240 / CONFIG_ESP32C3_DEFAULT_CPU_FREQ_MHZ)
-#endif // CONFIG_ESP32C3_RTC_CLK_SRC_EXT_CRYS
-
-#else   //  other target
-#define LIGHT_SLEEP_TIME_OVERHEAD_US 0
-#define DEEP_SLEEP_TIME_OVERHEAD_US 0
-#endif  //  CONFIG_IDF_TARGET_*
+#define DEEP_SLEEP_TIME_OVERHEAD_US         (250 + 100 * 240 / DEFAULT_CPU_FREQ_MHZ)
+#endif
 
 #if defined(CONFIG_IDF_TARGET_ESP32) && defined(CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY)
 #define DEEP_SLEEP_WAKEUP_DELAY     CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY
@@ -457,6 +447,7 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags)
 #if CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL
     gpio_sleep_mode_config_unapply();
 #endif
+
     // re-enable UART output
     resume_uarts();
 
@@ -553,7 +544,7 @@ esp_err_t esp_light_sleep_start(void)
     uint32_t pd_flags = get_power_down_flags();
 
     // Re-calibrate the RTC Timer clock
-#if defined(CONFIG_ESP32_RTC_CLK_SRC_EXT_CRYS) || defined(CONFIG_ESP32S2_RTC_CLK_SRC_EXT_CRYS)
+#if defined(CONFIG_ESP32_RTC_CLK_SRC_EXT_CRYS) || defined(CONFIG_ESP32S2_RTC_CLK_SRC_EXT_CRYS) || defined(CONFIG_ESP32C3_RTC_CLK_SRC_EXT_CRYS)
     uint64_t time_per_us = 1000000ULL;
     s_config.rtc_clk_cal_period = (time_per_us << RTC_CLK_CAL_FRACT) / rtc_clk_slow_freq_get_hz();
 #elif defined(CONFIG_ESP32S2_RTC_CLK_SRC_INT_RC)
@@ -631,8 +622,17 @@ esp_err_t esp_light_sleep_start(void)
     s_light_sleep_wakeup = true;
 
     // FRC1 has been clock gated for the duration of the sleep, correct for that.
+#ifdef CONFIG_IDF_TARGET_ESP32C3
+    /**
+     * On esp32c3, rtc_time_get() is non-blocking, esp_system_get_time() is
+     * blocking, and the measurement data shows that this order is better.
+     */
+    uint64_t frc_time_at_end = esp_system_get_time();
+    uint64_t rtc_ticks_at_end = rtc_time_get();
+#else
     uint64_t rtc_ticks_at_end = rtc_time_get();
     uint64_t frc_time_at_end = esp_system_get_time();
+#endif
 
     uint64_t rtc_time_diff = rtc_time_slowclk_to_us(rtc_ticks_at_end - s_config.rtc_ticks_at_sleep_start, s_config.rtc_clk_cal_period);
     uint64_t frc_time_diff = frc_time_at_end - frc_time_at_start;

+ 5 - 1
components/hal/esp32c3/include/hal/rtc_cntl_ll.h

@@ -24,7 +24,11 @@ extern "C" {
 
 static inline void rtc_cntl_ll_set_wakeup_timer(uint64_t t)
 {
-    abort(); // ESP32-C3 TODO IDF-2106
+    WRITE_PERI_REG(RTC_CNTL_SLP_TIMER0_REG, t & UINT32_MAX);
+    WRITE_PERI_REG(RTC_CNTL_SLP_TIMER1_REG, t >> 32);
+
+    SET_PERI_REG_MASK(RTC_CNTL_INT_CLR_REG, RTC_CNTL_MAIN_TIMER_INT_CLR_M);
+    SET_PERI_REG_MASK(RTC_CNTL_SLP_TIMER1_REG, RTC_CNTL_MAIN_TIMER_ALARM_EN_M);
 }
 
 static inline uint32_t rtc_cntl_ll_ext1_get_wakeup_pins(void)

+ 3 - 2
components/soc/esp32c3/include/soc/rtc.h

@@ -103,9 +103,10 @@ extern "C" {
 #define RTC_CNTL_SCK_DCAP_DEFAULT   255
 
 /* Various delays to be programmed into power control state machines */
-#define RTC_CNTL_XTL_BUF_WAIT_SLP_US            (1000)
-#define RTC_CNTL_PLL_BUF_WAIT_SLP_CYCLES        (2)
+#define RTC_CNTL_XTL_BUF_WAIT_SLP_US            (250)
+#define RTC_CNTL_PLL_BUF_WAIT_SLP_CYCLES        (1)
 #define RTC_CNTL_CK8M_WAIT_SLP_CYCLES           (4)
+#define RTC_CNTL_WAKEUP_DELAY_CYCLES            (5)
 #define RTC_CNTL_OTHER_BLOCKS_POWERUP_CYCLES    (1)
 #define RTC_CNTL_OTHER_BLOCKS_WAIT_CYCLES       (1)