From 355dd102571c3753312fa216e15ba02661bbd81f Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Fri, 4 Dec 2020 10:19:39 +0800 Subject: [PATCH 1/9] light sleep: dfs support for esp32c3 --- components/esp_pm/CMakeLists.txt | 8 --- .../esp32c3/pm.h} | 29 ++++++++- components/esp_pm/include/esp_pm.h | 2 + components/esp_pm/pm_impl.c | 60 ++++++++++++++----- components/esp_pm/pm_trace.c | 9 +++ components/freertos/port/riscv/port.c | 9 +++ components/hal/esp32/include/hal/cpu_ll.h | 5 ++ components/hal/esp32c3/include/hal/cpu_ll.h | 5 ++ components/hal/esp32s2/include/hal/cpu_ll.h | 5 ++ components/hal/esp32s3/include/hal/cpu_ll.h | 5 ++ components/hal/include/hal/cpu_hal.h | 5 ++ components/riscv/vectors.S | 18 ++++++ .../wifi/power_save/main/Kconfig.projbuild | 9 ++- examples/wifi/power_save/main/power_save.c | 2 + 14 files changed, 141 insertions(+), 30 deletions(-) rename components/esp_pm/{pm_impl_riscv_temp.c => include/esp32c3/pm.h} (51%) diff --git a/components/esp_pm/CMakeLists.txt b/components/esp_pm/CMakeLists.txt index f57c21df69..b802986ec1 100644 --- a/components/esp_pm/CMakeLists.txt +++ b/components/esp_pm/CMakeLists.txt @@ -1,11 +1,3 @@ -idf_build_get_property(target IDF_TARGET) -if(${target} STREQUAL "esp32c3") - # TODO ESP32-C3 IDF-2107 - include the headers to avoid compile errors, no functions available to link... - idf_component_register(SRCS "pm_impl_riscv_temp.c" INCLUDE_DIRS include) - return() -endif() - - idf_component_register(SRCS "pm_locks.c" "pm_trace.c" "pm_impl.c" INCLUDE_DIRS include LDFRAGMENTS linker.lf) diff --git a/components/esp_pm/pm_impl_riscv_temp.c b/components/esp_pm/include/esp32c3/pm.h similarity index 51% rename from components/esp_pm/pm_impl_riscv_temp.c rename to components/esp_pm/include/esp32c3/pm.h index 59c94b50d8..7ceecd12c1 100644 --- a/components/esp_pm/pm_impl_riscv_temp.c +++ b/components/esp_pm/include/esp32c3/pm.h @@ -12,8 +12,31 @@ // See the License for the specific language governing permissions and // limitations under the License. -/* TODO ESP32-C3 Placeholder until IDF-2107 when this file can be dropped */ -void esp_pm_impl_waiti(void) -{ +#pragma once +#include +#include +#include "esp_err.h" + +#include "soc/rtc.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @brief Power management config for ESP32C3 + * + * Pass a pointer to this structure as an argument to esp_pm_configure function. + */ +typedef struct { + int max_freq_mhz; /*!< Maximum CPU frequency, in MHz */ + int min_freq_mhz; /*!< Minimum CPU frequency to use when no locks are taken, in MHz */ + bool light_sleep_enable; /*!< Enter light sleep when no locks are taken */ +} esp_pm_config_esp32c3_t; + + +#ifdef __cplusplus } +#endif diff --git a/components/esp_pm/include/esp_pm.h b/components/esp_pm/include/esp_pm.h index d15a904bee..4d5146316b 100644 --- a/components/esp_pm/include/esp_pm.h +++ b/components/esp_pm/include/esp_pm.h @@ -23,6 +23,8 @@ #include "esp32s2/pm.h" #elif CONFIG_IDF_TARGET_ESP32S3 #include "esp32s3/pm.h" +#elif CONFIG_IDF_TARGET_ESP32C3 +#include "esp32c3/pm.h" #endif #ifdef __cplusplus diff --git a/components/esp_pm/pm_impl.c b/components/esp_pm/pm_impl.c index 81caf32c0c..b2b8a2effc 100644 --- a/components/esp_pm/pm_impl.c +++ b/components/esp_pm/pm_impl.c @@ -31,8 +31,10 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" +#if __XTENSA__ #include "freertos/xtensa_timer.h" #include "xtensa/core-macros.h" +#endif #include "esp_private/pm_impl.h" #include "esp_private/pm_trace.h" @@ -54,10 +56,15 @@ #elif CONFIG_IDF_TARGET_ESP32S3 #include "esp32s3/clk.h" #include "esp32s3/pm.h" +#elif CONFIG_IDF_TARGET_ESP32C3 +#include "esp32c3/clk.h" +#include "esp32c3/pm.h" +#include "driver/gpio.h" #endif #define MHZ (1000000) +#if __XTENSA__ /* CCOMPARE update timeout, in CPU cycles. Any value above ~600 cycles will work * for the purpose of detecting a deadlock. */ @@ -67,6 +74,7 @@ * than this. This is to prevent setting CCOMPARE below CCOUNT. */ #define CCOMPARE_MIN_CYCLES_IN_FUTURE 1000 +#endif /* When light sleep is used, wake this number of microseconds earlier than * the next tick. @@ -85,6 +93,9 @@ /* Minimal divider at which REF_CLK_FREQ can be obtained */ #define REF_CLK_DIV_MIN 2 #define DEFAULT_CPU_FREQ CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ +#elif CONFIG_IDF_TARGET_ESP32C3 +#define REF_CLK_DIV_MIN 2 +#define DEFAULT_CPU_FREQ CONFIG_ESP32C3_DEFAULT_CPU_FREQ_MHZ #endif #ifdef CONFIG_PM_PROFILING @@ -104,12 +115,6 @@ static size_t s_mode_lock_counts[PM_MODE_COUNT]; /* Bit mask of locked modes. BIT(i) is set iff s_mode_lock_counts[i] > 0. */ static uint32_t s_mode_mask; -/* Divider and multiplier used to adjust (ccompare - ccount) duration. - * Only set to non-zero values when switch is in progress. - */ -static uint32_t s_ccount_div; -static uint32_t s_ccount_mul; - #if CONFIG_FREERTOS_USE_TICKLESS_IDLE #define PERIPH_SKIP_LIGHT_SLEEP_NO 1 @@ -133,11 +138,6 @@ static bool s_skip_light_sleep[portNUM_PROCESSORS]; #endif // portNUM_PROCESSORS == 2 #endif // CONFIG_FREERTOS_USE_TICKLESS_IDLE -/* Indicates to the ISR hook that CCOMPARE needs to be updated on the given CPU. - * Used in conjunction with cross-core interrupt to update CCOMPARE on the other CPU. - */ -static volatile bool s_need_update_ccompare[portNUM_PROCESSORS]; - /* A flag indicating that Idle hook has run on a given CPU; * Next interrupt on the same CPU will take s_rtos_lock_handle. */ @@ -177,9 +177,23 @@ static const char* s_mode_names[] = { }; #endif // WITH_PROFILING -static const char* TAG = "pm_" CONFIG_IDF_TARGET; +#if __XTENSA__ +/* Indicates to the ISR hook that CCOMPARE needs to be updated on the given CPU. + * Used in conjunction with cross-core interrupt to update CCOMPARE on the other CPU. + */ +static volatile bool s_need_update_ccompare[portNUM_PROCESSORS]; + +/* Divider and multiplier used to adjust (ccompare - ccount) duration. + * Only set to non-zero values when switch is in progress. + */ +static uint32_t s_ccount_div; +static uint32_t s_ccount_mul; static void update_ccompare(void); +#endif // __XTENSA__ + +static const char* TAG = "pm"; + static void do_switch(pm_mode_t new_mode); static void leave_idle(void); static void on_freq_update(uint32_t old_ticks_per_us, uint32_t ticks_per_us); @@ -211,6 +225,8 @@ esp_err_t esp_pm_configure(const void* vconfig) const esp_pm_config_esp32s2_t* config = (const esp_pm_config_esp32s2_t*) vconfig; #elif CONFIG_IDF_TARGET_ESP32S3 const esp_pm_config_esp32s3_t* config = (const esp_pm_config_esp32s3_t*) vconfig; +#elif CONFIG_IDF_TARGET_ESP32C3 + const esp_pm_config_esp32c3_t* config = (const esp_pm_config_esp32c3_t*) vconfig; #endif #ifndef CONFIG_FREERTOS_USE_TICKLESS_IDLE @@ -256,7 +272,7 @@ esp_err_t esp_pm_configure(const void* vconfig) */ apb_max_freq = 80; } -#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 +#else int apb_max_freq = MIN(max_freq_mhz, 80); /* CPU frequency in APB_MAX mode */ #endif @@ -357,8 +373,11 @@ static void IRAM_ATTR on_freq_update(uint32_t old_ticks_per_us, uint32_t ticks_p esp_timer_private_update_apb_freq(apb_ticks_per_us); } +#if __XTENSA__ +#if XT_RTOS_TIMER_INT /* Calculate new tick divisor */ _xt_tick_divisor = ticks_per_us * MHZ / XT_TICK_PER_SEC; +#endif int core_id = xPortGetCoreID(); if (s_rtos_lock_handle[core_id] != NULL) { @@ -391,6 +410,7 @@ static void IRAM_ATTR on_freq_update(uint32_t old_ticks_per_us, uint32_t ticks_p s_ccount_div = 0; ESP_PM_TRACE_EXIT(CCOMPARE_UPDATE, core_id); } +#endif // __XTENSA__ } /** @@ -412,9 +432,11 @@ static void IRAM_ATTR do_switch(pm_mode_t new_mode) portEXIT_CRITICAL_ISR(&s_switch_lock); return; } +#if __XTENSA__ if (s_need_update_ccompare[core_id]) { s_need_update_ccompare[core_id] = false; } +#endif portEXIT_CRITICAL_ISR(&s_switch_lock); } while (true); s_new_mode = new_mode; @@ -455,6 +477,7 @@ static void IRAM_ATTR do_switch(pm_mode_t new_mode) portEXIT_CRITICAL_ISR(&s_switch_lock); } +#if __XTENSA__ /** * @brief Calculate new CCOMPARE value based on s_ccount_{mul,div} * @@ -475,6 +498,7 @@ static void IRAM_ATTR update_ccompare(void) } } } +#endif // __XTENSA__ static void IRAM_ATTR leave_idle(void) { @@ -578,6 +602,7 @@ void IRAM_ATTR vApplicationSleep( TickType_t xExpectedIdleTime ) /* Adjust RTOS tick count based on the amount of time spent in sleep */ vTaskStepTick(slept_ticks); +#if __XTENSA__ /* Trigger tick interrupt, since sleep time was longer * than portTICK_PERIOD_MS. Note that setting INTSET does not * work for timer interrupt, and changing CCOMPARE would clear @@ -587,6 +612,7 @@ void IRAM_ATTR vApplicationSleep( TickType_t xExpectedIdleTime ) while (!(XTHAL_GET_INTERRUPT() & BIT(XT_TIMER_INTNUM))) { ; } +#endif } other_core_should_skip_light_sleep(core_id); } @@ -676,6 +702,8 @@ void esp_pm_impl_init(void) esp_pm_config_esp32s2_t cfg = { #elif CONFIG_IDF_TARGET_ESP32S3 esp_pm_config_esp32s3_t cfg = { +#elif CONFIG_IDF_TARGET_ESP32C3 + esp_pm_config_esp32c3_t cfg = { #endif .max_freq_mhz = DEFAULT_CPU_FREQ, .min_freq_mhz = xtal_freq, @@ -709,7 +737,7 @@ void IRAM_ATTR esp_pm_impl_isr_hook(void) * from happening in this section, since they will also call into esp_pm_impl_isr_hook. */ uint32_t state = portENTER_CRITICAL_NESTED(); -#if portNUM_PROCESSORS == 2 +#if __XTENSA__ && (portNUM_PROCESSORS == 2) if (s_need_update_ccompare[core_id]) { update_ccompare(); s_need_update_ccompare[core_id] = false; @@ -728,7 +756,7 @@ void esp_pm_impl_waiti(void) #if CONFIG_FREERTOS_USE_TICKLESS_IDLE int core_id = xPortGetCoreID(); if (s_skipped_light_sleep[core_id]) { - asm("waiti 0"); + cpu_hal_waiti(); /* Interrupt took the CPU out of waiti and s_rtos_lock_handle[core_id] * is now taken. However since we are back to idle task, we can release * the lock so that vApplicationSleep can attempt to enter light sleep. @@ -737,7 +765,7 @@ void esp_pm_impl_waiti(void) s_skipped_light_sleep[core_id] = false; } #else - asm("waiti 0"); + cpu_hal_waiti(); #endif // CONFIG_FREERTOS_USE_TICKLESS_IDLE } diff --git a/components/esp_pm/pm_trace.c b/components/esp_pm/pm_trace.c index 5cdb666d67..291897aa11 100644 --- a/components/esp_pm/pm_trace.c +++ b/components/esp_pm/pm_trace.c @@ -21,12 +21,21 @@ * Feel free to change when debugging. */ static const int DRAM_ATTR s_trace_io[] = { +#ifndef CONFIG_IDF_TARGET_ESP32C3 BIT(4), BIT(5), // ESP_PM_TRACE_IDLE BIT(16), BIT(17), // ESP_PM_TRACE_TICK BIT(18), BIT(18), // ESP_PM_TRACE_FREQ_SWITCH BIT(19), BIT(19), // ESP_PM_TRACE_CCOMPARE_UPDATE BIT(25), BIT(26), // ESP_PM_TRACE_ISR_HOOK BIT(27), BIT(27), // ESP_PM_TRACE_SLEEP +#else + BIT(2), BIT(3), // ESP_PM_TRACE_IDLE + BIT(4), BIT(5), // ESP_PM_TRACE_TICK + BIT(6), BIT(6), // ESP_PM_TRACE_FREQ_SWITCH + BIT(7), BIT(7), // ESP_PM_TRACE_CCOMPARE_UPDATE + BIT(8), BIT(9), // ESP_PM_TRACE_ISR_HOOK + BIT(18), BIT(18), // ESP_PM_TRACE_SLEEP +#endif }; void esp_pm_trace_init(void) diff --git a/components/freertos/port/riscv/port.c b/components/freertos/port/riscv/port.c index 95d5ace0a4..6c6ce2b583 100644 --- a/components/freertos/port/riscv/port.c +++ b/components/freertos/port/riscv/port.c @@ -96,6 +96,7 @@ #include "esp_attr.h" #include "esp_debug_helpers.h" #include "esp_log.h" +#include "esp_private/pm_trace.h" /** * @brief A variable is used to keep track of the critical section nesting. @@ -215,6 +216,10 @@ IRAM_ATTR void vPortSysTickHandler(void *arg) systimer_ll_clear_alarm_int(SYSTIMER_ALARM_0); +#ifdef CONFIG_PM_TRACE + ESP_PM_TRACE_ENTER(TICK, xPortGetCoreID()); +#endif + if (!uxSchedulerRunning) { return; } @@ -222,6 +227,10 @@ IRAM_ATTR void vPortSysTickHandler(void *arg) if (xTaskIncrementTick() != pdFALSE) { vPortYieldFromISR(); } + +#ifdef CONFIG_PM_TRACE + ESP_PM_TRACE_EXIT(TICK, xPortGetCoreID()); +#endif } BaseType_t xPortStartScheduler(void) diff --git a/components/hal/esp32/include/hal/cpu_ll.h b/components/hal/esp32/include/hal/cpu_ll.h index f93a5e9355..7a83ddbc43 100644 --- a/components/hal/esp32/include/hal/cpu_ll.h +++ b/components/hal/esp32/include/hal/cpu_ll.h @@ -178,6 +178,11 @@ static inline void cpu_ll_set_vecbase(const void* vecbase) asm volatile ("wsr %0, vecbase" :: "r" (vecbase)); } +static inline void cpu_ll_waiti(void) +{ + asm volatile ("waiti 0\n"); +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32c3/include/hal/cpu_ll.h b/components/hal/esp32c3/include/hal/cpu_ll.h index fb8d9b32bc..1ac07fdab0 100644 --- a/components/hal/esp32c3/include/hal/cpu_ll.h +++ b/components/hal/esp32c3/include/hal/cpu_ll.h @@ -151,6 +151,11 @@ static inline void cpu_ll_set_vecbase(const void* vecbase) RV_WRITE_CSR(mtvec, vecbase_int); } +static inline void cpu_ll_waiti(void) +{ + asm volatile ("wfi\n"); +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32s2/include/hal/cpu_ll.h b/components/hal/esp32s2/include/hal/cpu_ll.h index d52d4489ad..c70955eba2 100644 --- a/components/hal/esp32s2/include/hal/cpu_ll.h +++ b/components/hal/esp32s2/include/hal/cpu_ll.h @@ -197,6 +197,11 @@ static inline void cpu_ll_write_dedic_gpio_mask(uint32_t mask, uint32_t value) asm volatile("wr_mask_gpio_out %0, %1" : : "r"(value), "r"(mask):); } +static inline void cpu_ll_waiti(void) +{ + asm volatile ("waiti 0\n"); +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32s3/include/hal/cpu_ll.h b/components/hal/esp32s3/include/hal/cpu_ll.h index 6753f60954..ea50870f93 100644 --- a/components/hal/esp32s3/include/hal/cpu_ll.h +++ b/components/hal/esp32s3/include/hal/cpu_ll.h @@ -177,6 +177,11 @@ static inline void cpu_ll_set_vecbase(const void *vecbase) asm volatile ("wsr %0, vecbase" :: "r" (vecbase)); } +static inline void cpu_ll_waiti(void) +{ + asm volatile ("waiti 0\n"); +} + static inline uint32_t cpu_ll_read_dedic_gpio_in(void) { uint32_t value = 0; diff --git a/components/hal/include/hal/cpu_hal.h b/components/hal/include/hal/cpu_hal.h index a930771187..e6b7c62d2f 100644 --- a/components/hal/include/hal/cpu_hal.h +++ b/components/hal/include/hal/cpu_hal.h @@ -73,6 +73,11 @@ extern "C" { */ #define cpu_hal_break() cpu_ll_break() +/** + * Wait for interrupt. + */ +#define cpu_hal_waiti() cpu_ll_waiti() + #if SOC_CPU_BREAKPOINTS_NUM > 0 /** diff --git a/components/riscv/vectors.S b/components/riscv/vectors.S index 6580517fa8..a0ba847a15 100644 --- a/components/riscv/vectors.S +++ b/components/riscv/vectors.S @@ -14,6 +14,8 @@ #include "soc/soc.h" #include "soc/interrupt_reg.h" #include "riscv/rvruntime-frames.h" +#include "soc/soc_caps.h" +#include "sdkconfig.h" .equ SAVE_REGS, 32 @@ -243,6 +245,22 @@ _interrupt_handler: li t0, 0x8 csrrs t0, mstatus, t0 + #ifdef CONFIG_PM_TRACE + li a0, 0 /* = ESP_PM_TRACE_IDLE */ + #if SOC_CPU_CORES_NUM == 1 + li a1, 0 /* No need to check core ID on single core hardware */ + #else + csrr a1, mhartid + #endif + la t0, esp_pm_trace_exit + jalr t0 /* absolute jump, avoid the 1 MiB range constraint */ + #endif + + #ifdef CONFIG_PM_ENABLE + la t0, esp_pm_impl_isr_hook + jalr t0 /* absolute jump, avoid the 1 MiB range constraint */ + #endif + /* call the C dispatcher */ mv a0, sp /* argument 1, stack pointer */ csrr a1, mcause /* argument 2, interrupt number */ diff --git a/examples/wifi/power_save/main/Kconfig.projbuild b/examples/wifi/power_save/main/Kconfig.projbuild index 0d733fbadf..dce8517002 100644 --- a/examples/wifi/power_save/main/Kconfig.projbuild +++ b/examples/wifi/power_save/main/Kconfig.projbuild @@ -43,6 +43,7 @@ menu "Example Configuration" choice EXAMPLE_MAX_CPU_FREQ prompt "Maximum CPU frequency" default EXAMPLE_MAX_CPU_FREQ_80 + depends on PM_ENABLE help Maximum CPU frequency to use for dynamic frequency scaling. @@ -52,6 +53,7 @@ menu "Example Configuration" bool "160 MHz" config EXAMPLE_MAX_CPU_FREQ_240 bool "240 MHz" + depends on IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 endchoice config EXAMPLE_MAX_CPU_FREQ_MHZ @@ -64,19 +66,20 @@ menu "Example Configuration" choice EXAMPLE_MIN_CPU_FREQ prompt "Minimum CPU frequency" default EXAMPLE_MIN_CPU_FREQ_10M + depends on PM_ENABLE help Minimum CPU frequency to use for dynamic frequency scaling. Should be set to XTAL frequency or XTAL frequency divided by integer. config EXAMPLE_MIN_CPU_FREQ_40M bool "40 MHz (use with 40MHz XTAL)" - depends on IDF_TARGET_ESP32S2 || ESP32_XTAL_FREQ_40 || ESP32_XTAL_FREQ_AUTO + depends on IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32C3 || ESP32_XTAL_FREQ_40 || ESP32_XTAL_FREQ_AUTO config EXAMPLE_MIN_CPU_FREQ_20M bool "20 MHz (use with 40MHz XTAL)" - depends on IDF_TARGET_ESP32S2 || ESP32_XTAL_FREQ_40 || ESP32_XTAL_FREQ_AUTO + depends on IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32C3 || ESP32_XTAL_FREQ_40 || ESP32_XTAL_FREQ_AUTO config EXAMPLE_MIN_CPU_FREQ_10M bool "10 MHz (use with 40MHz XTAL)" - depends on IDF_TARGET_ESP32S2 || ESP32_XTAL_FREQ_40 || ESP32_XTAL_FREQ_AUTO + depends on IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32C3 || ESP32_XTAL_FREQ_40 || ESP32_XTAL_FREQ_AUTO config EXAMPLE_MIN_CPU_FREQ_26M bool "26 MHz (use with 26MHz XTAL)" depends on ESP32_XTAL_FREQ_26 || ESP32_XTAL_FREQ_AUTO diff --git a/examples/wifi/power_save/main/power_save.c b/examples/wifi/power_save/main/power_save.c index 6e6203b9d6..ccb7889f19 100644 --- a/examples/wifi/power_save/main/power_save.c +++ b/examples/wifi/power_save/main/power_save.c @@ -99,6 +99,8 @@ void app_main(void) esp_pm_config_esp32_t pm_config = { #elif CONFIG_IDF_TARGET_ESP32S2 esp_pm_config_esp32s2_t pm_config = { +#elif CONFIG_IDF_TARGET_ESP32C3 + esp_pm_config_esp32c3_t pm_config = { #endif .max_freq_mhz = CONFIG_EXAMPLE_MAX_CPU_FREQ_MHZ, .min_freq_mhz = CONFIG_EXAMPLE_MIN_CPU_FREQ_MHZ, From aa7fd175b9447e1fad3503085443cc6398faea56 Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Tue, 12 Jan 2021 19:10:21 +0800 Subject: [PATCH 2/9] light sleep: light sleep support for esp32c3 --- components/esp_system/CMakeLists.txt | 9 +-- components/esp_system/sleep_modes.c | 64 ++++++++++++------- components/soc/esp32/include/soc/soc_caps.h | 3 + components/soc/esp32c3/include/soc/rtc.h | 2 +- components/soc/esp32c3/include/soc/soc_caps.h | 5 ++ components/soc/esp32s2/include/soc/soc_caps.h | 4 ++ components/soc/esp32s3/include/soc/rtc.h | 2 +- components/soc/esp32s3/include/soc/soc_caps.h | 7 ++ 8 files changed, 64 insertions(+), 32 deletions(-) diff --git a/components/esp_system/CMakeLists.txt b/components/esp_system/CMakeLists.txt index fd0b518f07..df6fe27a5f 100644 --- a/components/esp_system/CMakeLists.txt +++ b/components/esp_system/CMakeLists.txt @@ -1,17 +1,10 @@ - -idf_build_get_property(target IDF_TARGET) -# Remove when sleep is brought up on master for C3 TODO ESP32-C3 IDF-2571 -if(NOT (${target} STREQUAL "esp32c3") ) - list(APPEND sleep_src "sleep_modes.c") -endif() - idf_component_register(SRCS "intr_alloc.c" "esp_async_memcpy.c" "panic.c" "system_api.c" "startup.c" "system_time.c" - "${sleep_src}" + "sleep_modes.c" INCLUDE_DIRS include PRIV_REQUIRES spi_flash # [refactor-todo] requirements due to init code, diff --git a/components/esp_system/sleep_modes.c b/components/esp_system/sleep_modes.c index b5b030a8c4..d68d3c880b 100644 --- a/components/esp_system/sleep_modes.c +++ b/components/esp_system/sleep_modes.c @@ -171,8 +171,10 @@ static portMUX_TYPE spinlock_rtc_deep_sleep = portMUX_INITIALIZER_UNLOCKED; static const char* TAG = "sleep"; static uint32_t get_power_down_flags(void); +#if SOC_PM_SUPPORT_EXT_WAKEUP static void ext0_wakeup_prepare(void); static void ext1_wakeup_prepare(void); +#endif static void timer_wakeup_prepare(void); #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 static void touch_wakeup_prepare(void); @@ -326,8 +328,7 @@ void esp_sleep_gpio_status_switch_configure(bool enable) } } } - -#endif +#endif // SOC_GPIO_SUPPORT_SLP_SWITCH static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags) { @@ -356,6 +357,7 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags) rtc_clk_cpu_freq_get_config(&cpu_freq_config); rtc_clk_cpu_freq_set_xtal(); +#if SOC_PM_SUPPORT_EXT_WAKEUP // Configure pins for external wakeup if (s_config.wakeup_triggers & RTC_EXT0_TRIG_EN) { ext0_wakeup_prepare(); @@ -363,6 +365,7 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags) if (s_config.wakeup_triggers & RTC_EXT1_TRIG_EN) { ext1_wakeup_prepare(); } +#endif #ifdef CONFIG_IDF_TARGET_ESP32 // Enable ULP wakeup @@ -407,6 +410,7 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags) // Enter sleep rtc_sleep_config_t config = RTC_SLEEP_CONFIG_DEFAULT(pd_flags); rtc_sleep_init(config); + rtc_sleep_low_init(s_config.rtc_clk_cal_period); // Set state machine time for light sleep if(!deep_sleep) { @@ -665,6 +669,7 @@ esp_err_t esp_sleep_disable_wakeup_source(esp_sleep_source_t source) } else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_TIMER, RTC_TIMER_TRIG_EN)) { s_config.wakeup_triggers &= ~RTC_TIMER_TRIG_EN; s_config.sleep_duration = 0; +#if SOC_PM_SUPPORT_EXT_WAKEUP } else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_EXT0, RTC_EXT0_TRIG_EN)) { s_config.ext0_rtc_gpio_num = 0; s_config.ext0_trigger_level = 0; @@ -673,8 +678,11 @@ esp_err_t esp_sleep_disable_wakeup_source(esp_sleep_source_t source) s_config.ext1_rtc_gpio_mask = 0; s_config.ext1_trigger_mode = 0; s_config.wakeup_triggers &= ~RTC_EXT1_TRIG_EN; +#endif +#if SOC_TOUCH_PAD_WAKE_SUPPORTED } else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_TOUCHPAD, RTC_TOUCH_TRIG_EN)) { s_config.wakeup_triggers &= ~RTC_TOUCH_TRIG_EN; +#endif } else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_GPIO, RTC_GPIO_TRIG_EN)) { s_config.wakeup_triggers &= ~RTC_GPIO_TRIG_EN; } else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_UART, (RTC_UART0_TRIG_EN | RTC_UART1_TRIG_EN))) { @@ -712,6 +720,8 @@ esp_err_t esp_sleep_enable_ulp_wakeup(void) #elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 s_config.wakeup_triggers |= (RTC_ULP_TRIG_EN | RTC_COCPU_TRIG_EN | RTC_COCPU_TRAP_TRIG_EN); return ESP_OK; +#else + return ESP_ERR_NOT_SUPPORTED; #endif } @@ -733,7 +743,6 @@ static void timer_wakeup_prepare(void) rtc_hal_set_wakeup_timer(s_config.rtc_ticks_at_sleep_start + ticks); } - #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 /* In deep sleep mode, only the sleep channel is supported, and other touch channels should be turned off. */ static void touch_wakeup_prepare(void) @@ -749,6 +758,7 @@ static void touch_wakeup_prepare(void) } #endif +#if SOC_TOUCH_SENSOR_NUM > 0 esp_err_t esp_sleep_enable_touchpad_wakeup(void) { #if ((defined CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT) || (defined CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT_V2)) @@ -773,6 +783,7 @@ touch_pad_t esp_sleep_get_touchpad_wakeup_status(void) assert(ret == ESP_OK && "wakeup reason is RTC_TOUCH_TRIG_EN but SENS_TOUCH_MEAS_EN is zero"); return pad_num; } +#endif // SOC_TOUCH_SENSOR_NUM > 0 bool esp_sleep_is_valid_wakeup_gpio(gpio_num_t gpio_num) { @@ -783,6 +794,7 @@ bool esp_sleep_is_valid_wakeup_gpio(gpio_num_t gpio_num) #endif } +#if SOC_PM_SUPPORT_EXT_WAKEUP esp_err_t esp_sleep_enable_ext0_wakeup(gpio_num_t gpio_num, int level) { if (level < 0 || level > 1) { @@ -889,6 +901,7 @@ uint64_t esp_sleep_get_ext1_wakeup_status(void) } return gpio_mask; } +#endif // SOC_PM_SUPPORT_EXT_WAKEUP esp_err_t esp_sleep_enable_gpio_wakeup(void) { @@ -917,14 +930,11 @@ esp_err_t esp_sleep_enable_uart_wakeup(int uart_num) esp_err_t esp_sleep_enable_wifi_wakeup(void) { -#if CONFIG_IDF_TARGET_ESP32 - return ESP_ERR_NOT_SUPPORTED; -#elif CONFIG_IDF_TARGET_ESP32S2 +#if SOC_PM_SUPPORT_WIFI_WAKEUP s_config.wakeup_triggers |= RTC_WIFI_TRIG_EN; return ESP_OK; -#elif CONFIG_IDF_TARGET_ESP32S3 - s_config.wakeup_triggers |= RTC_MAC_TRIG_EN; - return ESP_OK; +#else + return ESP_ERR_NOT_SUPPORTED; #endif } @@ -937,29 +947,39 @@ esp_sleep_wakeup_cause_t esp_sleep_get_wakeup_cause(void) #ifdef CONFIG_IDF_TARGET_ESP32 uint32_t wakeup_cause = REG_GET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, RTC_CNTL_WAKEUP_CAUSE); -#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 +#else uint32_t wakeup_cause = REG_GET_FIELD(RTC_CNTL_SLP_WAKEUP_CAUSE_REG, RTC_CNTL_WAKEUP_CAUSE); #endif - if (wakeup_cause & RTC_EXT0_TRIG_EN) { - return ESP_SLEEP_WAKEUP_EXT0; - } else if (wakeup_cause & RTC_EXT1_TRIG_EN) { - return ESP_SLEEP_WAKEUP_EXT1; - } else if (wakeup_cause & RTC_TIMER_TRIG_EN) { + if (wakeup_cause & RTC_TIMER_TRIG_EN) { return ESP_SLEEP_WAKEUP_TIMER; - } else if (wakeup_cause & RTC_TOUCH_TRIG_EN) { - return ESP_SLEEP_WAKEUP_TOUCHPAD; -#if SOC_ULP_SUPPORTED - } else if (wakeup_cause & RTC_ULP_TRIG_EN) { - return ESP_SLEEP_WAKEUP_ULP; -#endif } else if (wakeup_cause & RTC_GPIO_TRIG_EN) { return ESP_SLEEP_WAKEUP_GPIO; } else if (wakeup_cause & (RTC_UART0_TRIG_EN | RTC_UART1_TRIG_EN)) { return ESP_SLEEP_WAKEUP_UART; -#if CONFIG_IDF_TARGET_ESP32S2 +#if SOC_PM_SUPPORT_EXT_WAKEUP + } else if (wakeup_cause & RTC_EXT0_TRIG_EN) { + return ESP_SLEEP_WAKEUP_EXT0; + } else if (wakeup_cause & RTC_EXT1_TRIG_EN) { + return ESP_SLEEP_WAKEUP_EXT1; +#endif +#if SOC_TOUCH_PAD_WAKE_SUPPORTED + } else if (wakeup_cause & RTC_TOUCH_TRIG_EN) { + return ESP_SLEEP_WAKEUP_TOUCHPAD; +#endif +#if SOC_ULP_SUPPORTED + } else if (wakeup_cause & RTC_ULP_TRIG_EN) { + return ESP_SLEEP_WAKEUP_ULP; +#endif +#if SOC_PM_SUPPORT_WIFI_WAKEUP } else if (wakeup_cause & RTC_WIFI_TRIG_EN) { return ESP_SLEEP_WAKEUP_WIFI; +#endif +#if SOC_PM_SUPPORT_BT_WAKEUP + } else if (wakeup_cause & RTC_BT_TRIG_EN) { + return ESP_SLEEP_WAKEUP_BT; +#endif +#if CONFIG_IDF_TARGET_ESP32S2 } else if (wakeup_cause & RTC_COCPU_TRIG_EN) { return ESP_SLEEP_WAKEUP_ULP; } else if (wakeup_cause & RTC_COCPU_TRAP_TRIG_EN) { diff --git a/components/soc/esp32/include/soc/soc_caps.h b/components/soc/esp32/include/soc/soc_caps.h index 3e83316209..2585c27053 100644 --- a/components/soc/esp32/include/soc/soc_caps.h +++ b/components/soc/esp32/include/soc/soc_caps.h @@ -268,6 +268,9 @@ #define SOC_AES_SUPPORT_AES_192 (1) #define SOC_AES_SUPPORT_AES_256 (1) +/*-------------------------- Power Management CAPS ---------------------------*/ +#define SOC_PM_SUPPORT_EXT_WAKEUP (1) + /* ---------------------------- Compatibility ------------------------------- */ #define SOC_CAN_SUPPORTED SOC_TWAI_SUPPORTED #define CAN_BRP_MIN SOC_TWAI_BRP_MIN diff --git a/components/soc/esp32c3/include/soc/rtc.h b/components/soc/esp32c3/include/soc/rtc.h index 199d1a8753..aadf5da145 100644 --- a/components/soc/esp32c3/include/soc/rtc.h +++ b/components/soc/esp32c3/include/soc/rtc.h @@ -722,7 +722,7 @@ void rtc_sleep_set_wakeup_time(uint64_t t); #define RTC_GPIO_TRIG_EN BIT(2) //!< GPIO wakeup #define RTC_TIMER_TRIG_EN BIT(3) //!< Timer wakeup -#define RTC_MAC_TRIG_EN BIT(5) //!< MAC wakeup (light sleep only) +#define RTC_WIFI_TRIG_EN BIT(5) //!< WIFI wakeup (light sleep only) #define RTC_UART0_TRIG_EN BIT(6) //!< UART0 wakeup (light sleep only) #define RTC_UART1_TRIG_EN BIT(7) //!< UART1 wakeup (light sleep only) #define RTC_BT_TRIG_EN BIT(10) //!< BT wakeup (light sleep only) diff --git a/components/soc/esp32c3/include/soc/soc_caps.h b/components/soc/esp32c3/include/soc/soc_caps.h index 8d3295bf46..0c063980b6 100644 --- a/components/soc/esp32c3/include/soc/soc_caps.h +++ b/components/soc/esp32c3/include/soc/soc_caps.h @@ -121,3 +121,8 @@ /*-------------------------- COEXISTENCE HARDWARE PTI CAPS -------------------------------*/ #define SOC_COEX_HW_PTI (1) + +/*-------------------------- Power Management CAPS ----------------------------*/ +#define SOC_PM_SUPPORT_WIFI_WAKEUP (1) + +#define SOC_PM_SUPPORT_BT_WAKEUP (1) diff --git a/components/soc/esp32s2/include/soc/soc_caps.h b/components/soc/esp32s2/include/soc/soc_caps.h index 54552da3b1..fd33bffdd9 100644 --- a/components/soc/esp32s2/include/soc/soc_caps.h +++ b/components/soc/esp32s2/include/soc/soc_caps.h @@ -295,6 +295,10 @@ /*-------------------------- WI-FI HARDWARE TSF CAPS -------------------------------*/ #define SOC_WIFI_HW_TSF (1) +/*-------------------------- Power Management CAPS ---------------------------*/ +#define SOC_PM_SUPPORT_EXT_WAKEUP (1) + +#define SOC_PM_SUPPORT_WIFI_WAKEUP (1) /* ---------------------------- Compatibility ------------------------------- */ // No contents diff --git a/components/soc/esp32s3/include/soc/rtc.h b/components/soc/esp32s3/include/soc/rtc.h index 85df37c975..9a1fb0616f 100644 --- a/components/soc/esp32s3/include/soc/rtc.h +++ b/components/soc/esp32s3/include/soc/rtc.h @@ -718,7 +718,7 @@ void rtc_sleep_set_wakeup_time(uint64_t t); #define RTC_GPIO_TRIG_EN BIT(2) //!< GPIO wakeup (light sleep only) #define RTC_TIMER_TRIG_EN BIT(3) //!< Timer wakeup #define RTC_SDIO_TRIG_EN BIT(4) //!< SDIO wakeup (light sleep only) -#define RTC_MAC_TRIG_EN BIT(5) //!< MAC wakeup (light sleep only) +#define RTC_WIFI_TRIG_EN BIT(5) //!< WIFI wakeup (light sleep only) #define RTC_UART0_TRIG_EN BIT(6) //!< UART0 wakeup (light sleep only) #define RTC_UART1_TRIG_EN BIT(7) //!< UART1 wakeup (light sleep only) #define RTC_TOUCH_TRIG_EN BIT(8) //!< Touch wakeup diff --git a/components/soc/esp32s3/include/soc/soc_caps.h b/components/soc/esp32s3/include/soc/soc_caps.h index 51c01861a8..b295ed6e4d 100644 --- a/components/soc/esp32s3/include/soc/soc_caps.h +++ b/components/soc/esp32s3/include/soc/soc_caps.h @@ -143,6 +143,13 @@ /*-------------------------- AES CAPS -----------------------------------------*/ #define SOC_AES_SUPPORT_DMA (1) +/*-------------------------- Power Management CAPS ---------------------------*/ +#define SOC_PM_SUPPORT_EXT_WAKEUP (1) + +#define SOC_PM_SUPPORT_WIFI_WAKEUP (1) + +#define SOC_PM_SUPPORT_BT_WAKEUP (1) + /* Has a centralized DMA, which is shared with all peripherals */ #define SOC_AES_GENERAL_DMA (1) From ac7d1bec767b482f4f68c38dc770f1f607a34f56 Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Fri, 4 Dec 2020 11:09:21 +0800 Subject: [PATCH 3/9] light sleep: overhead time accuracy optimization for esp32c3 --- components/esp_pm/pm_impl.c | 2 + components/esp_system/sleep_modes.c | 62 +++++++++---------- .../hal/esp32c3/include/hal/rtc_cntl_ll.h | 6 +- components/soc/esp32c3/include/soc/rtc.h | 5 +- 4 files changed, 41 insertions(+), 34 deletions(-) diff --git a/components/esp_pm/pm_impl.c b/components/esp_pm/pm_impl.c index b2b8a2effc..6ad8703544 100644 --- a/components/esp_pm/pm_impl.c +++ b/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); diff --git a/components/esp_system/sleep_modes.c b/components/esp_system/sleep_modes.c index d68d3c880b..b21a43d077 100644 --- a/components/esp_system/sleep_modes.c +++ b/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; diff --git a/components/hal/esp32c3/include/hal/rtc_cntl_ll.h b/components/hal/esp32c3/include/hal/rtc_cntl_ll.h index 45a4e1f552..0e472eb80b 100644 --- a/components/hal/esp32c3/include/hal/rtc_cntl_ll.h +++ b/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) diff --git a/components/soc/esp32c3/include/soc/rtc.h b/components/soc/esp32c3/include/soc/rtc.h index aadf5da145..b03359c2a6 100644 --- a/components/soc/esp32c3/include/soc/rtc.h +++ b/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) From 6d12fdd6e705b8d4531849c77643e120327c0b2b Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Fri, 4 Dec 2020 11:33:15 +0800 Subject: [PATCH 4/9] light sleep: add gpio configure workaround at slept status for esp32c3 --- components/driver/include/driver/gpio.h | 9 +- components/hal/esp32c3/include/hal/gpio_ll.h | 111 ++++++++++++++++++ .../soc/esp32c3/include/soc/gpio_caps.h | 3 + 3 files changed, 116 insertions(+), 7 deletions(-) diff --git a/components/driver/include/driver/gpio.h b/components/driver/include/driver/gpio.h index d9fe4289f0..cac61ac99d 100644 --- a/components/driver/include/driver/gpio.h +++ b/components/driver/include/driver/gpio.h @@ -462,7 +462,6 @@ esp_err_t gpio_sleep_sel_en(gpio_num_t gpio_num); * * @return * - ESP_OK Success - * */ esp_err_t gpio_sleep_sel_dis(gpio_num_t gpio_num); @@ -477,7 +476,6 @@ esp_err_t gpio_sleep_sel_dis(gpio_num_t gpio_num); * @return * - ESP_OK Success * - ESP_ERR_INVALID_ARG GPIO error - * */ esp_err_t gpio_sleep_set_direction(gpio_num_t gpio_num, gpio_mode_t mode); @@ -492,7 +490,6 @@ esp_err_t gpio_sleep_set_direction(gpio_num_t gpio_num, gpio_mode_t mode); * @return * - ESP_OK Success * - ESP_ERR_INVALID_ARG : Parameter error - * */ esp_err_t gpio_sleep_set_pull_mode(gpio_num_t gpio_num, gpio_pull_mode_t pull); @@ -504,8 +501,7 @@ esp_err_t gpio_sleep_set_pull_mode(gpio_num_t gpio_num, gpio_pull_mode_t pull); * * @return * - ESP_OK Success - * - * */ + */ esp_err_t gpio_sleep_pupd_config_apply(gpio_num_t gpio_num); /** @@ -515,8 +511,7 @@ esp_err_t gpio_sleep_pupd_config_apply(gpio_num_t gpio_num); * * @return * - ESP_OK Success - * - * */ + */ esp_err_t gpio_sleep_pupd_config_unapply(gpio_num_t gpio_num); #endif #endif diff --git a/components/hal/esp32c3/include/hal/gpio_ll.h b/components/hal/esp32c3/include/hal/gpio_ll.h index 4fd25d7c27..7f37281358 100644 --- a/components/hal/esp32c3/include/hal/gpio_ll.h +++ b/components/hal/esp32c3/include/hal/gpio_ll.h @@ -399,6 +399,117 @@ static inline void gpio_ll_force_unhold_all(gpio_dev_t *hw) SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_CLR_DG_PAD_AUTOHOLD); } +/** + * @brief Enable GPIO pin used for wakeup from sleep. + * + * @param hw Peripheral GPIO hardware instance address. + * @param gpio_num GPIO number + */ +static inline void gpio_ll_sleep_sel_en(gpio_dev_t *hw, gpio_num_t gpio_num) +{ + PIN_SLP_SEL_ENABLE(GPIO_PIN_MUX_REG[gpio_num]); +} + +/** + * @brief Disable GPIO pin used for wakeup from sleep. + * + * @param hw Peripheral GPIO hardware instance address. + * @param gpio_num GPIO number + */ +static inline void gpio_ll_sleep_sel_dis(gpio_dev_t *hw, gpio_num_t gpio_num) +{ + PIN_SLP_SEL_DISABLE(GPIO_PIN_MUX_REG[gpio_num]); +} + +/** + * @brief Disable GPIO pull-up in sleep mode. + * + * @param hw Peripheral GPIO hardware instance address. + * @param gpio_num GPIO number + */ +static inline void gpio_ll_sleep_pullup_dis(gpio_dev_t *hw, gpio_num_t gpio_num) +{ + PIN_SLP_PULLUP_DISABLE(GPIO_PIN_MUX_REG[gpio_num]); +} + +/** + * @brief Enable GPIO pull-up in sleep mode. + * + * @param hw Peripheral GPIO hardware instance address. + * @param gpio_num GPIO number + */ +static inline void gpio_ll_sleep_pullup_en(gpio_dev_t *hw, gpio_num_t gpio_num) +{ + PIN_SLP_PULLUP_ENABLE(GPIO_PIN_MUX_REG[gpio_num]); +} + +/** + * @brief Enable GPIO pull-down in sleep mode. + * + * @param hw Peripheral GPIO hardware instance address. + * @param gpio_num GPIO number + */ +static inline void gpio_ll_sleep_pulldown_en(gpio_dev_t *hw, gpio_num_t gpio_num) +{ + PIN_SLP_PULLDOWN_ENABLE(GPIO_PIN_MUX_REG[gpio_num]); +} + +/** + * @brief Disable GPIO pull-down in sleep mode. + * + * @param hw Peripheral GPIO hardware instance address. + * @param gpio_num GPIO number + */ +static inline void gpio_ll_sleep_pulldown_dis(gpio_dev_t *hw, gpio_num_t gpio_num) +{ + PIN_SLP_PULLDOWN_DISABLE(GPIO_PIN_MUX_REG[gpio_num]); +} + +/** + * @brief Disable GPIO input in sleep mode. + * + * @param hw Peripheral GPIO hardware instance address. + * @param gpio_num GPIO number + */ +static inline void gpio_ll_sleep_input_disable(gpio_dev_t *hw, gpio_num_t gpio_num) +{ + PIN_SLP_INPUT_DISABLE(GPIO_PIN_MUX_REG[gpio_num]); +} + +/** + * @brief Enable GPIO input in sleep mode. + * + * @param hw Peripheral GPIO hardware instance address. + * @param gpio_num GPIO number + */ +static inline void gpio_ll_sleep_input_enable(gpio_dev_t *hw, gpio_num_t gpio_num) +{ + PIN_SLP_INPUT_ENABLE(GPIO_PIN_MUX_REG[gpio_num]); +} + +/** + * @brief Disable GPIO output in sleep mode. + * + * @param hw Peripheral GPIO hardware instance address. + * @param gpio_num GPIO number + */ +static inline void gpio_ll_sleep_output_disable(gpio_dev_t *hw, gpio_num_t gpio_num) +{ + PIN_SLP_OUTPUT_DISABLE(GPIO_PIN_MUX_REG[gpio_num]); +} + +/** + * @brief Enable GPIO output in sleep mode. + * + * @param hw Peripheral GPIO hardware instance address. + * @param gpio_num GPIO number + */ +static inline void gpio_ll_sleep_output_enable(gpio_dev_t *hw, gpio_num_t gpio_num) +{ + PIN_SLP_OUTPUT_ENABLE(GPIO_PIN_MUX_REG[gpio_num]); +} + + #ifdef __cplusplus } #endif diff --git a/components/soc/esp32c3/include/soc/gpio_caps.h b/components/soc/esp32c3/include/soc/gpio_caps.h index ebbc15d885..9b6924ed64 100644 --- a/components/soc/esp32c3/include/soc/gpio_caps.h +++ b/components/soc/esp32c3/include/soc/gpio_caps.h @@ -36,6 +36,9 @@ extern "C" { #define SOC_GPIO_VALID_GPIO_MASK ((1U< Date: Fri, 4 Dec 2020 11:20:07 +0800 Subject: [PATCH 5/9] fix set `UART_FORCE_XOFF` can't stop new Tx request issue --- components/esp_system/sleep_modes.c | 38 +++++++---------- components/hal/esp32/include/hal/uart_ll.h | 39 ++++++++++++++++++ components/hal/esp32c3/include/hal/uart_ll.h | 41 +++++++++++++++++++ components/hal/esp32s2/include/hal/uart_ll.h | 39 ++++++++++++++++++ components/hal/esp32s3/include/hal/uart_ll.h | 39 ++++++++++++++++++ .../soc/esp32c3/include/soc/uart_caps.h | 5 +++ 6 files changed, 177 insertions(+), 24 deletions(-) diff --git a/components/esp_system/sleep_modes.c b/components/esp_system/sleep_modes.c index b21a43d077..4ecf1da2d7 100644 --- a/components/esp_system/sleep_modes.c +++ b/components/esp_system/sleep_modes.c @@ -232,20 +232,17 @@ static void IRAM_ATTR flush_uarts(void) static void IRAM_ATTR suspend_uarts(void) { for (int i = 0; i < SOC_UART_NUM; ++i) { -#ifdef CONFIG_IDF_TARGET_ESP32 - /* Note: Set `UART_FORCE_XOFF` can't stop new Tx request. */ - REG_SET_BIT(UART_FLOW_CONF_REG(i), UART_FORCE_XOFF); - while (REG_GET_FIELD(UART_STATUS_REG(i), UART_ST_UTX_OUT) != 0) { - ; - } -#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 - if (periph_ll_periph_enabled(PERIPH_UART0_MODULE + i)) { - REG_CLR_BIT(UART_FLOW_CONF_REG(i), UART_FORCE_XON); - REG_SET_BIT(UART_FLOW_CONF_REG(i), UART_SW_FLOW_CON_EN | UART_FORCE_XOFF); - while (REG_GET_FIELD(UART_FSM_STATUS_REG(i), UART_ST_UTX_OUT) != 0) { - ; - } - } +#ifndef CONFIG_IDF_TARGET_ESP32 + if (!periph_ll_periph_enabled(PERIPH_UART0_MODULE + i)) continue; +#endif + uart_ll_force_xoff(i); +#if SOC_UART_SUPPORT_FSM_TX_WAIT_SEND + uint32_t uart_fsm = 0; + do { + uart_fsm = uart_ll_get_fsm_status(i); + } while (!(uart_fsm == UART_FSM_IDLE || uart_fsm == UART_FSM_TX_WAIT_SEND)); +#else + while (uart_ll_get_fsm_status(i) != 0) {} #endif } } @@ -253,17 +250,10 @@ static void IRAM_ATTR suspend_uarts(void) static void IRAM_ATTR resume_uarts(void) { for (int i = 0; i < SOC_UART_NUM; ++i) { -#ifdef CONFIG_IDF_TARGET_ESP32 - REG_CLR_BIT(UART_FLOW_CONF_REG(i), UART_FORCE_XOFF); - REG_SET_BIT(UART_FLOW_CONF_REG(i), UART_FORCE_XON); - REG_CLR_BIT(UART_FLOW_CONF_REG(i), UART_FORCE_XON); -#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 - if (periph_ll_periph_enabled(PERIPH_UART0_MODULE + i)) { - REG_CLR_BIT(UART_FLOW_CONF_REG(i), UART_FORCE_XOFF); - REG_SET_BIT(UART_FLOW_CONF_REG(i), UART_FORCE_XON); - REG_CLR_BIT(UART_FLOW_CONF_REG(i), UART_SW_FLOW_CON_EN | UART_FORCE_XON); - } +#ifndef CONFIG_IDF_TARGET_ESP32 + if (!periph_ll_periph_enabled(PERIPH_UART0_MODULE + i)) continue; #endif + uart_ll_force_xon(i); } } diff --git a/components/hal/esp32/include/hal/uart_ll.h b/components/hal/esp32/include/hal/uart_ll.h index e749014a72..66f4c028d1 100644 --- a/components/hal/esp32/include/hal/uart_ll.h +++ b/components/hal/esp32/include/hal/uart_ll.h @@ -894,6 +894,45 @@ static inline uint16_t uart_ll_max_tout_thrd(uart_dev_t *hw) return tout_thrd; } +/** + * @brief Force UART xoff. + * + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * + * @return None. + */ +static inline void uart_ll_force_xoff(uart_port_t uart_num) +{ + /* Note: Set `UART_FORCE_XOFF` can't stop new Tx request. */ + REG_SET_BIT(UART_FLOW_CONF_REG(uart_num), UART_FORCE_XOFF); +} + +/** + * @brief Force UART xon. + * + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * + * @return None. + */ +static inline void uart_ll_force_xon(uart_port_t uart_num) +{ + REG_CLR_BIT(UART_FLOW_CONF_REG(uart_num), UART_FORCE_XOFF); + REG_SET_BIT(UART_FLOW_CONF_REG(uart_num), UART_FORCE_XON); + REG_CLR_BIT(UART_FLOW_CONF_REG(uart_num), UART_FORCE_XON); +} + +/** + * @brief Get UART final state machine status. + * + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * + * @return UART module FSM status. + */ +static inline uint32_t uart_ll_get_fsm_status(uart_port_t uart_num) +{ + return REG_GET_FIELD(UART_STATUS_REG(uart_num), UART_ST_UTX_OUT); +} + #undef UART_LL_TOUT_REF_FACTOR_DEFAULT #ifdef __cplusplus diff --git a/components/hal/esp32c3/include/hal/uart_ll.h b/components/hal/esp32c3/include/hal/uart_ll.h index cd39b40afe..a06cc72d70 100644 --- a/components/hal/esp32c3/include/hal/uart_ll.h +++ b/components/hal/esp32c3/include/hal/uart_ll.h @@ -884,6 +884,47 @@ static inline uint16_t uart_ll_max_tout_thrd(uart_dev_t *hw) return UART_RX_TOUT_THRHD_V; } +/** + * @brief Force UART xoff. + * + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * + * @return None. + */ +static inline void uart_ll_force_xoff(uart_port_t uart_num) +{ + REG_CLR_BIT(UART_FLOW_CONF_REG(uart_num), UART_FORCE_XON); + REG_SET_BIT(UART_FLOW_CONF_REG(uart_num), UART_SW_FLOW_CON_EN | UART_FORCE_XOFF); + REG_SET_BIT(UART_ID_REG(uart_num), UART_UPDATE); +} + +/** + * @brief Force UART xon. + * + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * + * @return None. + */ +static inline void uart_ll_force_xon(uart_port_t uart_num) +{ + REG_CLR_BIT(UART_FLOW_CONF_REG(uart_num), UART_FORCE_XOFF); + REG_SET_BIT(UART_FLOW_CONF_REG(uart_num), UART_FORCE_XON); + REG_CLR_BIT(UART_FLOW_CONF_REG(uart_num), UART_SW_FLOW_CON_EN | UART_FORCE_XON); + REG_SET_BIT(UART_ID_REG(uart_num), UART_UPDATE); +} + +/** + * @brief Get UART final state machine status. + * + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * + * @return UART module FSM status. + */ +static inline uint32_t uart_ll_get_fsm_status(uart_port_t uart_num) +{ + return REG_GET_FIELD(UART_FSM_STATUS_REG(uart_num), UART_ST_UTX_OUT); +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32s2/include/hal/uart_ll.h b/components/hal/esp32s2/include/hal/uart_ll.h index 012396a0ee..e0685fd713 100644 --- a/components/hal/esp32s2/include/hal/uart_ll.h +++ b/components/hal/esp32s2/include/hal/uart_ll.h @@ -826,6 +826,45 @@ static inline uint16_t uart_ll_max_tout_thrd(uart_dev_t *hw) return UART_RX_TOUT_THRHD_V; } +/** + * @brief Force UART xoff. + * + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * + * @return None. + */ +static inline void uart_ll_force_xoff(uart_port_t uart_num) +{ + REG_CLR_BIT(UART_FLOW_CONF_REG(uart_num), UART_FORCE_XON); + REG_SET_BIT(UART_FLOW_CONF_REG(uart_num), UART_SW_FLOW_CON_EN | UART_FORCE_XOFF); +} + +/** + * @brief Force UART xon. + * + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * + * @return None. + */ +static inline void uart_ll_force_xon(uart_port_t uart_num) +{ + REG_CLR_BIT(UART_FLOW_CONF_REG(uart_num), UART_FORCE_XOFF); + REG_SET_BIT(UART_FLOW_CONF_REG(uart_num), UART_FORCE_XON); + REG_CLR_BIT(UART_FLOW_CONF_REG(uart_num), UART_SW_FLOW_CON_EN | UART_FORCE_XON); +} + +/** + * @brief Get UART final state machine status. + * + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * + * @return UART module FSM status. + */ +static inline uint32_t uart_ll_get_fsm_status(uart_port_t uart_num) +{ + return REG_GET_FIELD(UART_FSM_STATUS_REG(uart_num), UART_ST_UTX_OUT); +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32s3/include/hal/uart_ll.h b/components/hal/esp32s3/include/hal/uart_ll.h index 14d6be3593..c5a167b298 100644 --- a/components/hal/esp32s3/include/hal/uart_ll.h +++ b/components/hal/esp32s3/include/hal/uart_ll.h @@ -852,6 +852,45 @@ static inline uint16_t uart_ll_max_tout_thrd(uart_dev_t *hw) return UART_RX_TOUT_THRHD_V; } +/** + * @brief Force UART xoff. + * + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * + * @return None. + */ +static inline void uart_ll_force_xoff(uart_port_t uart_num) +{ + REG_CLR_BIT(UART_FLOW_CONF_REG(uart_num), UART_FORCE_XON); + REG_SET_BIT(UART_FLOW_CONF_REG(uart_num), UART_SW_FLOW_CON_EN | UART_FORCE_XOFF); +} + +/** + * @brief Force UART xon. + * + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * + * @return None. + */ +static inline void uart_ll_force_xon(uart_port_t uart_num) +{ + REG_CLR_BIT(UART_FLOW_CONF_REG(uart_num), UART_FORCE_XOFF); + REG_SET_BIT(UART_FLOW_CONF_REG(uart_num), UART_FORCE_XON); + REG_CLR_BIT(UART_FLOW_CONF_REG(uart_num), UART_SW_FLOW_CON_EN | UART_FORCE_XON); +} + +/** + * @brief Get UART final state machine status. + * + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * + * @return UART module FSM status. + */ +static inline uint32_t uart_ll_get_fsm_status(uart_port_t uart_num) +{ + return REG_GET_FIELD(UART_FSM_STATUS_REG(uart_num), UART_ST_UTX_OUT); +} + #ifdef __cplusplus } #endif diff --git a/components/soc/esp32c3/include/soc/uart_caps.h b/components/soc/esp32c3/include/soc/uart_caps.h index 28a3c43b30..bcbca36a3b 100644 --- a/components/soc/esp32c3/include/soc/uart_caps.h +++ b/components/soc/esp32c3/include/soc/uart_caps.h @@ -27,6 +27,11 @@ extern "C" { // ESP32-C3 have 2 UART #define SOC_UART_NUM (2) +// UART has an extra TX_WAIT_SEND state when the FIFO is not empty and XOFF is enabled +#define SOC_UART_SUPPORT_FSM_TX_WAIT_SEND (1) +#define UART_FSM_IDLE (0x0) +#define UART_FSM_TX_WAIT_SEND (0xf) + #ifdef __cplusplus } #endif From 63c4e5481f15b63a9376836bf3ec40c4642b1f68 Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Tue, 15 Dec 2020 11:38:41 +0800 Subject: [PATCH 6/9] fix no RTOS SysTick interrupt for a period of time after the OS Scheduler is started --- components/freertos/port/riscv/port.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/freertos/port/riscv/port.c b/components/freertos/port/riscv/port.c index 6c6ce2b583..82e1d40fa3 100644 --- a/components/freertos/port/riscv/port.c +++ b/components/freertos/port/riscv/port.c @@ -152,11 +152,11 @@ void vPortSetupTimer(void) /* configure the timer */ systimer_hal_init(); + systimer_hal_connect_alarm_counter(SYSTIMER_ALARM_0, SYSTIMER_COUNTER_1); systimer_hal_enable_counter(SYSTIMER_COUNTER_1); systimer_hal_set_alarm_period(SYSTIMER_ALARM_0, 1000000UL / CONFIG_FREERTOS_HZ); systimer_hal_select_alarm_mode(SYSTIMER_ALARM_0, SYSTIMER_ALARM_MODE_PERIOD); systimer_hal_enable_alarm_int(SYSTIMER_ALARM_0); - systimer_hal_connect_alarm_counter(SYSTIMER_ALARM_0, SYSTIMER_COUNTER_1); } void prvTaskExitError(void) From f168ac3b3985348e893d94ac64cab66e79264cb9 Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Thu, 24 Dec 2020 21:02:32 +0800 Subject: [PATCH 7/9] light sleep: add cpu power down support for esp32c3 --- components/esp_pm/linker.lf | 2 + components/esp_pm/pm_impl.c | 8 +++ components/esp_system/Kconfig | 8 +++ .../include/esp_private/sleep_modes.h | 40 ++++++++++++ components/esp_system/include/esp_sleep.h | 1 + components/esp_system/sleep_modes.c | 54 +++++++++++++++- components/hal/CMakeLists.txt | 3 +- .../hal/esp32c3/include/hal/rtc_cntl_ll.h | 16 +++++ components/hal/esp32c3/rtc_cntl_hal.c | 61 +++++++++++++++++++ components/hal/include/hal/rtc_hal.h | 8 +++ components/soc/esp32c3/include/soc/rtc_caps.h | 22 +++++++ components/soc/esp32c3/include/soc/soc_caps.h | 3 + 12 files changed, 224 insertions(+), 2 deletions(-) create mode 100644 components/esp_system/include/esp_private/sleep_modes.h create mode 100644 components/hal/esp32c3/rtc_cntl_hal.c create mode 100644 components/soc/esp32c3/include/soc/rtc_caps.h diff --git a/components/esp_pm/linker.lf b/components/esp_pm/linker.lf index 67c8051b96..f332580978 100644 --- a/components/esp_pm/linker.lf +++ b/components/esp_pm/linker.lf @@ -72,3 +72,5 @@ entries: gpio_hal_workaround:gpio_hal_sleep_pupd_config_unapply (noflash) gpio_hal_workaround:gpio_hal_sleep_mode_setup_wrapper (noflash) gpio_hal_workaround:gpio_hal_fun_pupd_restore (noflash) + if PM_SLP_IRAM_OPT = y && ESP_SYSTEM_PM_POWER_DOWN_CPU = y: + rtc_cntl_hal:rtc_cntl_hal_enable_cpu_retention (noflash) diff --git a/components/esp_pm/pm_impl.c b/components/esp_pm/pm_impl.c index 6ad8703544..3b02cc64b0 100644 --- a/components/esp_pm/pm_impl.c +++ b/components/esp_pm/pm_impl.c @@ -60,6 +60,7 @@ #include "esp32c3/clk.h" #include "esp32c3/pm.h" #include "driver/gpio.h" +#include "esp_private/sleep_modes.h" #endif #define MHZ (1000000) @@ -303,6 +304,13 @@ esp_err_t esp_pm_configure(const void* vconfig) esp_sleep_gpio_status_switch_configure(config->light_sleep_enable); #endif +#if CONFIG_ESP_SYSTEM_PM_POWER_DOWN_CPU && SOC_PM_SUPPORT_CPU_PD + esp_err_t ret = esp_sleep_cpu_pd_low_init(config->light_sleep_enable); + if (config->light_sleep_enable && ret != ESP_OK) { + ESP_LOGW(TAG, "Failed to enable CPU power down during light sleep."); + } +#endif + return ESP_OK; } diff --git a/components/esp_system/Kconfig b/components/esp_system/Kconfig index 342b2c24ca..c31ab7c313 100644 --- a/components/esp_system/Kconfig +++ b/components/esp_system/Kconfig @@ -87,4 +87,12 @@ menu "ESP System Settings" If enabled, chip will try to power down flash at light sleep, which costs more time when chip wakes up. Only can be enabled if there is no SPIRAM configured. + config ESP_SYSTEM_PM_POWER_DOWN_CPU + bool "Power down CPU in light sleep" + depends on IDF_TARGET_ESP32C3 + default y + help + If enabled, the CPU will be powered down in light sleep. Enabling this option will consume + 1.68 KB of internal RAM and will reduce sleep current consumption by about 100 uA. + endmenu # ESP System Settings diff --git a/components/esp_system/include/esp_private/sleep_modes.h b/components/esp_system/include/esp_private/sleep_modes.h new file mode 100644 index 0000000000..e1584a8b57 --- /dev/null +++ b/components/esp_system/include/esp_private/sleep_modes.h @@ -0,0 +1,40 @@ +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include +#include +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef CONFIG_ESP_SYSTEM_PM_POWER_DOWN_CPU +/** + * @brief CPU Power down low-level initialize + * + * @param enable enable or disable CPU power down during light sleep + * @return + * - ESP_OK on success + * - ESP_ERR_NO_MEM not enough retention memory + */ +esp_err_t esp_sleep_cpu_pd_low_init(bool enable); +#endif + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_system/include/esp_sleep.h b/components/esp_system/include/esp_sleep.h index 423bee51a1..6bc65b980a 100644 --- a/components/esp_system/include/esp_sleep.h +++ b/components/esp_system/include/esp_sleep.h @@ -42,6 +42,7 @@ typedef enum { ESP_PD_DOMAIN_RTC_SLOW_MEM, //!< RTC slow memory ESP_PD_DOMAIN_RTC_FAST_MEM, //!< RTC fast memory ESP_PD_DOMAIN_XTAL, //!< XTAL oscillator + ESP_PD_DOMAIN_CPU, //!< CPU core ESP_PD_DOMAIN_MAX //!< Number of domains } esp_sleep_pd_domain_t; diff --git a/components/esp_system/sleep_modes.c b/components/esp_system/sleep_modes.c index 4ecf1da2d7..1c846df1f3 100644 --- a/components/esp_system/sleep_modes.c +++ b/components/esp_system/sleep_modes.c @@ -70,6 +70,9 @@ #include "esp32s3/rom/cache.h" #include "esp32c3/rom/rtc.h" #include "soc/extmem_reg.h" +#include "esp_heap_caps.h" +#include "hal/rtc_hal.h" +#include "soc/rtc_caps.h" #endif // If light sleep time is less than that, don't power down flash @@ -141,10 +144,13 @@ typedef struct { uint32_t sleep_time_overhead_out; uint32_t rtc_clk_cal_period; uint64_t rtc_ticks_at_sleep_start; +#if SOC_PM_SUPPORT_CPU_PD + void *cpu_pd_mem; +#endif } sleep_config_t; static sleep_config_t s_config = { - .pd_options = { ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO }, + .pd_options = { ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO }, .ccount_ticks_record = 0, .sleep_time_overhead_out = DEFAULT_SLEEP_OUT_OVERHEAD_US, .wakeup_triggers = 0 @@ -259,6 +265,32 @@ static void IRAM_ATTR resume_uarts(void) inline static uint32_t IRAM_ATTR call_rtc_sleep_start(uint32_t reject_triggers); +#if SOC_PM_SUPPORT_CPU_PD +esp_err_t esp_sleep_cpu_pd_low_init(bool enable) +{ + if (enable) { + if (s_config.cpu_pd_mem == NULL) { + void *buf = heap_caps_aligned_alloc(RTC_CNTL_CPU_PD_DMA_ADDR_ALIGN, + RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE + RTC_HAL_DMA_LINK_NODE_SIZE, + MALLOC_CAP_RETENTION|MALLOC_CAP_DEFAULT); + if (buf) { + memset(buf, 0, RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE + RTC_HAL_DMA_LINK_NODE_SIZE); + s_config.cpu_pd_mem = rtc_cntl_hal_dma_link_init(buf, + buf+RTC_HAL_DMA_LINK_NODE_SIZE, RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE, NULL); + } else { + return ESP_ERR_NO_MEM; + } + } + } else { + if (s_config.cpu_pd_mem) { + heap_caps_free(s_config.cpu_pd_mem); + s_config.cpu_pd_mem = NULL; + } + } + return ESP_OK; +} +#endif // SOC_PM_SUPPORT_CPU_PD + #if SOC_GPIO_SUPPORT_SLP_SWITCH #if CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL static inline void gpio_sleep_mode_config_apply(void) @@ -434,6 +466,10 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags) s_config.ccount_ticks_record = cpu_ll_get_cycle_count(); } +#if SOC_PM_SUPPORT_CPU_PD + rtc_cntl_hal_disable_cpu_retention(); +#endif + #if CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL gpio_sleep_mode_config_unapply(); #endif @@ -591,6 +627,10 @@ esp_err_t esp_light_sleep_start(void) periph_inform_out_light_sleep_overhead(s_config.sleep_time_adjustment - sleep_time_overhead_in); +#if SOC_PM_SUPPORT_CPU_PD + rtc_cntl_hal_enable_cpu_retention(s_config.cpu_pd_mem); +#endif + rtc_vddsdio_config_t vddsdio_config = rtc_vddsdio_get_config(); // Safety net: enable WDT in case exit from light sleep fails @@ -1046,6 +1086,12 @@ static uint32_t get_power_down_flags(void) #endif // SOC_TOUCH_PAD_WAKE_SUPPORTED } +#if !SOC_PM_SUPPORT_CPU_PD + if (s_config.pd_options[ESP_PD_DOMAIN_CPU] == ESP_PD_OPTION_AUTO) { + s_config.pd_options[ESP_PD_DOMAIN_CPU] = ESP_PD_OPTION_ON; + } +#endif + if (s_config.pd_options[ESP_PD_DOMAIN_XTAL] == ESP_PD_OPTION_AUTO) { s_config.pd_options[ESP_PD_DOMAIN_XTAL] = ESP_PD_OPTION_OFF; } @@ -1071,6 +1117,12 @@ static uint32_t get_power_down_flags(void) pd_flags |= RTC_SLEEP_PD_RTC_PERIPH; } +#if SOC_PM_SUPPORT_CPU_PD + if (s_config.pd_options[ESP_PD_DOMAIN_CPU] != ESP_PD_OPTION_ON) { + pd_flags |= RTC_SLEEP_PD_CPU; + } +#endif + #ifdef CONFIG_IDF_TARGET_ESP32 pd_flags |= RTC_SLEEP_PD_XTAL; #endif diff --git a/components/hal/CMakeLists.txt b/components/hal/CMakeLists.txt index 28e0bc3213..68e3cbfac6 100644 --- a/components/hal/CMakeLists.txt +++ b/components/hal/CMakeLists.txt @@ -92,7 +92,8 @@ if(NOT BOOTLOADER_BUILD) "esp32c3/systimer_hal.c" "esp32c3/hmac_hal.c" "spi_flash_hal_gpspi.c" - "spi_slave_hd_hal.c") + "spi_slave_hd_hal.c" + "esp32c3/rtc_cntl_hal.c") endif() endif() diff --git a/components/hal/esp32c3/include/hal/rtc_cntl_ll.h b/components/hal/esp32c3/include/hal/rtc_cntl_ll.h index 0e472eb80b..bcc8d0fcdb 100644 --- a/components/hal/esp32c3/include/hal/rtc_cntl_ll.h +++ b/components/hal/esp32c3/include/hal/rtc_cntl_ll.h @@ -17,6 +17,7 @@ #include "soc/soc.h" #include "soc/rtc.h" #include "soc/rtc_cntl_reg.h" +#include "soc/apb_ctrl_reg.h" #ifdef __cplusplus extern "C" { @@ -47,6 +48,21 @@ static inline void rtc_cntl_ll_ext1_clear_wakeup_pins(void) REG_SET_BIT(RTC_CNTL_GPIO_WAKEUP_REG, RTC_CNTL_GPIO_WAKEUP_STATUS_CLR); } +static inline void rtc_cntl_ll_enable_cpu_retention(uint32_t addr) +{ + /* write memory address to register */ + REG_SET_FIELD(APB_CTRL_RETENTION_CTRL_REG, APB_CTRL_RETENTION_LINK_ADDR, (uint32_t)addr); + /* Enable clock */ + REG_SET_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN); + /* Enable retention when cpu sleep enable */ + REG_SET_BIT(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_EN); +} + +static inline void rtc_cntl_ll_disable_cpu_retention(void) +{ + REG_CLR_BIT(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_EN); +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32c3/rtc_cntl_hal.c b/components/hal/esp32c3/rtc_cntl_hal.c new file mode 100644 index 0000000000..0c8e1eb9a3 --- /dev/null +++ b/components/hal/esp32c3/rtc_cntl_hal.c @@ -0,0 +1,61 @@ +// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// The HAL layer for RTC CNTL (common part) + +#include "hal/rtc_hal.h" +#include "soc/soc_caps.h" +#include "esp32c3/rom/lldesc.h" +#include "esp_attr.h" + +#define RTC_CNTL_HAL_LINK_BUF_SIZE_MIN (RTC_CNTL_CPU_PD_DMA_BLOCK_SIZE) /* The minimum size of dma link buffer */ + +typedef struct rtc_cntl_link_buf_conf { + uint32_t cfg[4]; /* 4 word for dma link buffer configuration */ +} rtc_cntl_link_buf_conf_t; + +void * rtc_cntl_hal_dma_link_init(void *elem, void *buff, int size, void *next) +{ + assert(elem != NULL); + assert(buff != NULL); + assert(size >= RTC_CNTL_HAL_LINK_BUF_SIZE_MIN); + + lldesc_t *plink = (lldesc_t *)elem; + + plink->eof = next ? 0 : 1; + plink->owner = 1; + plink->size = size >> 4; /* in unit of 16 bytes */ + plink->length = size >> 4; + plink->buf = buff; + plink->offset = 0; + plink->sosf = 0; + STAILQ_NEXT(plink, qe) = next; + return (void *)plink; +} + +void rtc_cntl_hal_enable_cpu_retention(void *addr) +{ + if (addr) { + lldesc_t *plink = (lldesc_t *)addr; + + /* dma link buffer configure */ + rtc_cntl_link_buf_conf_t *pbuf = (rtc_cntl_link_buf_conf_t *)plink->buf; + pbuf->cfg[0] = 0; + pbuf->cfg[1] = 0; + pbuf->cfg[2] = 0; + pbuf->cfg[3] = (uint32_t)-1; + + rtc_cntl_ll_enable_cpu_retention((uint32_t)addr); + } +} diff --git a/components/hal/include/hal/rtc_hal.h b/components/hal/include/hal/rtc_hal.h index 94c016c568..e4874ad168 100644 --- a/components/hal/include/hal/rtc_hal.h +++ b/components/hal/include/hal/rtc_hal.h @@ -18,6 +18,8 @@ #include "hal/rtc_io_ll.h" #include "hal/rtc_cntl_ll.h" +#define RTC_HAL_DMA_LINK_NODE_SIZE (16) + #define rtc_hal_ext1_get_wakeup_pins() rtc_cntl_ll_ext1_get_wakeup_pins() #define rtc_hal_ext1_set_wakeup_pins(mask, mode) rtc_cntl_ll_ext1_set_wakeup_pins(mask, mode) @@ -26,6 +28,12 @@ #define rtc_hal_set_wakeup_timer(ticks) rtc_cntl_ll_set_wakeup_timer(ticks) +void * rtc_cntl_hal_dma_link_init(void *elem, void *buff, int size, void *next); + +void rtc_cntl_hal_enable_cpu_retention(void *addr); + +#define rtc_cntl_hal_disable_cpu_retention() rtc_cntl_ll_disable_cpu_retention() + /* * Enable wakeup from ULP coprocessor. */ diff --git a/components/soc/esp32c3/include/soc/rtc_caps.h b/components/soc/esp32c3/include/soc/rtc_caps.h new file mode 100644 index 0000000000..aa71a3ec2b --- /dev/null +++ b/components/soc/esp32c3/include/soc/rtc_caps.h @@ -0,0 +1,22 @@ +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#define RTC_CNTL_CPU_PD_DMA_BUS_WIDTH (128) +#define RTC_CNTL_CPU_PD_REG_FILE_NUM (108) +#define RTC_CNTL_CPU_PD_DMA_ADDR_ALIGN (RTC_CNTL_CPU_PD_DMA_BUS_WIDTH >> 3) +#define RTC_CNTL_CPU_PD_DMA_BLOCK_SIZE (RTC_CNTL_CPU_PD_DMA_BUS_WIDTH >> 3) + +#define RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE (RTC_CNTL_CPU_PD_REG_FILE_NUM * (RTC_CNTL_CPU_PD_DMA_BUS_WIDTH >> 3)) diff --git a/components/soc/esp32c3/include/soc/soc_caps.h b/components/soc/esp32c3/include/soc/soc_caps.h index 0c063980b6..021f9b1438 100644 --- a/components/soc/esp32c3/include/soc/soc_caps.h +++ b/components/soc/esp32c3/include/soc/soc_caps.h @@ -44,6 +44,7 @@ #include "rmt_caps.h" #include "spi_caps.h" #include "uart_caps.h" +#include "rtc_caps.h" /*-------------------------- TOUCH SENSOR CAPS -------------------------------*/ #define SOC_TOUCH_SENSOR_NUM (0) /*! No touch sensors on ESP32-C3 */ @@ -126,3 +127,5 @@ #define SOC_PM_SUPPORT_WIFI_WAKEUP (1) #define SOC_PM_SUPPORT_BT_WAKEUP (1) + +#define SOC_PM_SUPPORT_CPU_PD (1) From 27ddbf5fccb6122238c84e333fa5f50d25b6dd89 Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Tue, 19 Jan 2021 14:57:52 +0800 Subject: [PATCH 8/9] light sleep: libphy optimization for esp32c3 --- components/esp_rom/esp32c3/ld/esp32c3.rom.ld | 24 ++++++++++---------- components/esp_wifi/include/phy.h | 7 ++++++ components/esp_wifi/lib | 2 +- components/esp_wifi/src/phy_init.c | 4 ++++ 4 files changed, 24 insertions(+), 13 deletions(-) diff --git a/components/esp_rom/esp32c3/ld/esp32c3.rom.ld b/components/esp_rom/esp32c3/ld/esp32c3.rom.ld index 91e1cf5fb9..d2bb9fdd88 100644 --- a/components/esp_rom/esp32c3/ld/esp32c3.rom.ld +++ b/components/esp_rom/esp32c3/ld/esp32c3.rom.ld @@ -1838,7 +1838,7 @@ rom_pbus_workmode = 0x400019a0; rom_pbus_xpd_rx_off = 0x400019a4; rom_pbus_xpd_rx_on = 0x400019a8; rom_pbus_xpd_tx_off = 0x400019ac; -rom_pbus_xpd_tx_on = 0x400019b0; +/* rom_pbus_xpd_tx_on = 0x400019b0; */ rom_phy_byte_to_word = 0x400019b4; rom_phy_disable_cca = 0x400019b8; rom_phy_enable_cca = 0x400019bc; @@ -1855,7 +1855,7 @@ rom_set_loopback_gain = 0x400019e4; rom_set_noise_floor = 0x400019e8; rom_set_rxclk_en = 0x400019ec; rom_set_tx_dig_gain = 0x400019f0; -rom_set_txcap_reg = 0x400019f4; +/* rom_set_txcap_reg = 0x400019f4; */ rom_set_txclk_en = 0x400019f8; rom_spur_cal = 0x400019fc; rom_spur_reg_write_one_tone = 0x40001a00; @@ -1879,21 +1879,21 @@ rom_tx_paon_set = 0x40001a44; rom_i2cmst_reg_init = 0x40001a48; rom_iq_corr_enable = 0x40001a4c; rom_fe_reg_init = 0x40001a50; -rom_agc_reg_init = 0x40001a54; -rom_bb_reg_init = 0x40001a58; +/* rom_agc_reg_init = 0x40001a54; */ +/* rom_bb_reg_init = 0x40001a58; */ rom_mac_enable_bb = 0x40001a5c; rom_bb_wdg_cfg = 0x40001a60; rom_force_txon = 0x40001a64; rom_fe_txrx_reset = 0x40001a68; rom_set_rx_comp = 0x40001a6c; -rom_set_pbus_reg = 0x40001a70; +/* rom_set_pbus_reg = 0x40001a70; */ rom_write_chan_freq = 0x40001a74; -rom_phy_xpd_rf = 0x40001a78; +/* rom_phy_xpd_rf = 0x40001a78; */ rom_set_xpd_sar = 0x40001a7c; rom_write_dac_gain2 = 0x40001a80; rom_rtc_sar2_init = 0x40001a84; rom_get_target_power_offset = 0x40001a88; -rom_write_txrate_power_offset = 0x40001a8c; +/* rom_write_txrate_power_offset = 0x40001a8c; */ rom_get_rate_fcc_index = 0x40001a90; rom_get_rate_target_power = 0x40001a94; rom_write_wifi_dig_gain = 0x40001a98; @@ -1903,7 +1903,7 @@ rom_read_sar2_code = 0x40001aa4; rom_get_sar2_vol = 0x40001aa8; rom_get_pll_vol = 0x40001aac; rom_get_phy_target_power = 0x40001ab0; -rom_temp_to_power = 0x40001ab4; +/* rom_temp_to_power = 0x40001ab4; */ rom_phy_track_pll_cap = 0x40001ab8; rom_phy_pwdet_always_en = 0x40001abc; rom_phy_pwdet_onetime_en = 0x40001ac0; @@ -1920,13 +1920,13 @@ rom_i2c_paral_write_num = 0x40001ae8; rom_i2c_paral_write_mask = 0x40001aec; rom_bb_bss_cbw40_ana = 0x40001af0; rom_chan_to_freq = 0x40001af4; -rom_open_i2c_xpd = 0x40001af8; +/* rom_open_i2c_xpd = 0x40001af8; */ rom_dac_rate_set = 0x40001afc; -rom_tsens_read_init = 0x40001b00; -rom_tsens_code_read = 0x40001b04; +/* rom_tsens_read_init = 0x40001b00; */ +/* rom_tsens_code_read = 0x40001b04; */ rom_tsens_index_to_dac = 0x40001b08; rom_tsens_index_to_offset = 0x40001b0c; -rom_tsens_dac_cal = 0x40001b10; +/* rom_tsens_dac_cal = 0x40001b10; */ rom_code_to_temp = 0x40001b14; rom_write_pll_cap_mem = 0x40001b18; rom_pll_correct_dcap = 0x40001b1c; diff --git a/components/esp_wifi/include/phy.h b/components/esp_wifi/include/phy.h index 352ce97595..69e7e66507 100644 --- a/components/esp_wifi/include/phy.h +++ b/components/esp_wifi/include/phy.h @@ -73,6 +73,13 @@ void phy_wakeup_init(void); */ void phy_close_rf(void); +#if CONFIG_IDF_TARGET_ESP32C3 +/** + * @brief Disable PHY temperature sensor. + */ +void phy_xpd_tsens(void); +#endif + #if CONFIG_MAC_BB_PD /** * @brief Store and load baseband registers. diff --git a/components/esp_wifi/lib b/components/esp_wifi/lib index 7a3e28bf73..c5cf57a2d0 160000 --- a/components/esp_wifi/lib +++ b/components/esp_wifi/lib @@ -1 +1 @@ -Subproject commit 7a3e28bf73aa80977575980e1c47af087b6eb23b +Subproject commit c5cf57a2d0d61fa18dc847a4d13cd678c43bc7f5 diff --git a/components/esp_wifi/src/phy_init.c b/components/esp_wifi/src/phy_init.c index e7afc74986..5851f8a99e 100644 --- a/components/esp_wifi/src/phy_init.c +++ b/components/esp_wifi/src/phy_init.c @@ -239,6 +239,10 @@ IRAM_ATTR void esp_phy_disable(void) if (s_phy_access_ref == 0) { // Disable PHY and RF. phy_close_rf(); +#if CONFIG_IDF_TARGET_ESP32C3 + // Disable PHY temperature sensor + phy_xpd_tsens(); +#endif #if CONFIG_IDF_TARGET_ESP32 // Update WiFi MAC time before disalbe WiFi/BT common peripheral clock phy_update_wifi_mac_time(true, esp_timer_get_time()); From 3170ecf2683c2a862eba355c4058f803b8c87610 Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Thu, 14 Jan 2021 14:32:31 +0800 Subject: [PATCH 9/9] deep sleep: add empty interface rtc_deep_sleep_start for esp32c3 --- .../esp_hw_support/port/esp32c3/rtc_sleep.c | 6 +++++ components/soc/esp32c3/include/soc/rtc.h | 23 +++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/components/esp_hw_support/port/esp32c3/rtc_sleep.c b/components/esp_hw_support/port/esp32c3/rtc_sleep.c index 5d3c6eed1f..57dea490ea 100644 --- a/components/esp_hw_support/port/esp32c3/rtc_sleep.c +++ b/components/esp_hw_support/port/esp32c3/rtc_sleep.c @@ -13,6 +13,7 @@ // limitations under the License. #include +#include #include "soc/soc.h" #include "soc/rtc.h" #include "soc/rtc_cntl_reg.h" @@ -163,3 +164,8 @@ uint32_t rtc_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp } return reject; } + +uint32_t rtc_deep_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt) +{ + abort(); // ESP32-C3 TODO IDF-2560 +} diff --git a/components/soc/esp32c3/include/soc/rtc.h b/components/soc/esp32c3/include/soc/rtc.h index b03359c2a6..8ad29c0d78 100644 --- a/components/soc/esp32c3/include/soc/rtc.h +++ b/components/soc/esp32c3/include/soc/rtc.h @@ -758,6 +758,29 @@ void rtc_sleep_set_wakeup_time(uint64_t t); */ uint32_t rtc_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu); +/** + * @brief Enter deep sleep mode + * + * Similar to rtc_sleep_start(), but additionally uses hardware to calculate the CRC value + * of RTC FAST memory. On wake, this CRC is used to determine if a deep sleep wake + * stub is valid to execute (if a wake address is set). + * + * No RAM is accessed while calculating the CRC and going into deep sleep, which makes + * this function safe to use even if the caller's stack is in RTC FAST memory. + * + * @note If no deep sleep wake stub address is set then calling rtc_sleep_start() will + * have the same effect and takes less time as CRC calculation is skipped. + * + * @note This function should only be called after rtc_sleep_init() has been called to + * configure the system for deep sleep. + * + * @param wakeup_opt - same as for rtc_sleep_start + * @param reject_opt - same as for rtc_sleep_start + * + * @return non-zero if sleep was rejected by hardware + */ +uint32_t rtc_deep_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt); + /** * RTC power and clock control initialization settings */