diff --git a/components/esp_hw_support/linker.lf b/components/esp_hw_support/linker.lf index afb2231606..f6d5847180 100644 --- a/components/esp_hw_support/linker.lf +++ b/components/esp_hw_support/linker.lf @@ -12,22 +12,31 @@ entries: cpu: esp_cpu_clear_watchpoint (noflash) cpu: esp_cpu_compare_and_set (noflash) esp_memory_utils (noflash) - rtc_clk (noflash) clk_utils (noflash) + if PM_SLP_IRAM_OPT = y: + rtc_clk (noflash) + rtc_time (noflash_text) if SOC_CONFIGURABLE_VDDSDIO_SUPPORTED = y: rtc_init:rtc_vddsdio_get_config (noflash) rtc_init:rtc_vddsdio_set_config (noflash) if IDF_TARGET_ESP32 = y || IDF_TARGET_ESP32S2 = y || IDF_TARGET_ESP32S3 = y || IDF_TARGET_ESP32C2 = y || IDF_TARGET_ESP32C3 = y: - rtc_sleep (noflash_text) - rtc_time (noflash_text) + rtc_sleep:rtc_sleep_start (noflash) + if PM_SLP_IRAM_OPT = y: + rtc_sleep:rtc_sleep_get_default_config (noflash) + rtc_sleep:rtc_sleep_init (noflash) + rtc_sleep:rtc_sleep_low_init (noflash) + if IDF_TARGET_ESP32 = y || IDF_TARGET_ESP32S2 = y: + rtc_sleep:rtc_sleep_pd (noflash) + if IDF_TARGET_ESP32S3 = y || IDF_TARGET_ESP32C2 = y || IDF_TARGET_ESP32C3 = y: + rtc_sleep:rtc_sleep_pu (noflash) if SOC_PMU_SUPPORTED = y && SOC_LIGHT_SLEEP_SUPPORTED = y: pmu_sleep (noflash) if SPIRAM_FLASH_LOAD_TO_PSRAM = y: pmu_init (noflash) pmu_param (noflash) - if SOC_USB_SERIAL_JTAG_SUPPORTED = y: + if PM_SLP_IRAM_OPT = y && SOC_USB_SERIAL_JTAG_SUPPORTED = y: sleep_console (noflash) - if SOC_USB_OTG_SUPPORTED && SOC_PM_SUPPORT_CNNT_PD = y: + if PM_SLP_IRAM_OPT = y && SOC_USB_OTG_SUPPORTED && SOC_PM_SUPPORT_CNNT_PD = y: sleep_usb (noflash) if IDF_TARGET_ESP32 = y || IDF_TARGET_ESP32S2 = y: rtc_wdt (noflash_text) @@ -41,7 +50,7 @@ entries: if SOC_ADC_SHARED_POWER = y: if ADC_ONESHOT_CTRL_FUNC_IN_IRAM = y: sar_periph_ctrl (noflash) - else: + elif PM_SLP_IRAM_OPT = y: sar_periph_ctrl: sar_periph_ctrl_power_enable (noflash) [mapping:soc_pm] diff --git a/components/esp_hw_support/port/esp32/rtc_sleep.c b/components/esp_hw_support/port/esp32/rtc_sleep.c index 7116f3eefa..1e51ac04ac 100644 --- a/components/esp_hw_support/port/esp32/rtc_sleep.c +++ b/components/esp_hw_support/port/esp32/rtc_sleep.c @@ -65,7 +65,7 @@ typedef struct { * Configure whether certain peripherals are powered down in deep sleep * @param cfg power down flags as rtc_sleep_pd_config_t structure */ -static void rtc_sleep_pd(rtc_sleep_pd_config_t cfg) +void rtc_sleep_pd(rtc_sleep_pd_config_t cfg) { REG_SET_FIELD(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_LSLP_MEM_FORCE_PU, ~cfg.dig_pd); REG_SET_FIELD(RTC_CNTL_PWC_REG, RTC_CNTL_SLOWMEM_FORCE_LPU, ~cfg.rtc_pd); @@ -345,7 +345,7 @@ uint32_t rtc_deep_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt) return rtc_sleep_finish(); } -static uint32_t rtc_sleep_finish(void) +static IRAM_ATTR uint32_t rtc_sleep_finish(void) { /* In deep sleep mode, we never get here */ uint32_t reject = REG_GET_FIELD(RTC_CNTL_INT_RAW_REG, RTC_CNTL_SLP_REJECT_INT_RAW); diff --git a/components/esp_hw_support/port/esp32c2/rtc_sleep.c b/components/esp_hw_support/port/esp32c2/rtc_sleep.c index 4fc7e0142a..e59b3840c0 100644 --- a/components/esp_hw_support/port/esp32c2/rtc_sleep.c +++ b/components/esp_hw_support/port/esp32c2/rtc_sleep.c @@ -222,7 +222,7 @@ uint32_t rtc_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp return rtc_sleep_finish(lslp_mem_inf_fpu); } -static uint32_t rtc_sleep_finish(uint32_t lslp_mem_inf_fpu) +static IRAM_ATTR uint32_t rtc_sleep_finish(uint32_t lslp_mem_inf_fpu) { /* In deep sleep mode, we never get here */ uint32_t reject = REG_GET_FIELD(RTC_CNTL_INT_RAW_REG, RTC_CNTL_SLP_REJECT_INT_RAW); diff --git a/components/esp_hw_support/port/esp32c3/rtc_sleep.c b/components/esp_hw_support/port/esp32c3/rtc_sleep.c index 0c02bd0411..564915bab5 100644 --- a/components/esp_hw_support/port/esp32c3/rtc_sleep.c +++ b/components/esp_hw_support/port/esp32c3/rtc_sleep.c @@ -352,7 +352,7 @@ uint32_t rtc_deep_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt) return rtc_sleep_finish(0); } -static uint32_t rtc_sleep_finish(uint32_t lslp_mem_inf_fpu) +static IRAM_ATTR uint32_t rtc_sleep_finish(uint32_t lslp_mem_inf_fpu) { /* In deep sleep mode, we never get here */ uint32_t reject = REG_GET_FIELD(RTC_CNTL_INT_RAW_REG, RTC_CNTL_SLP_REJECT_INT_RAW); diff --git a/components/esp_hw_support/port/esp32s2/rtc_sleep.c b/components/esp_hw_support/port/esp32s2/rtc_sleep.c index 741156e597..a34b3ceb0e 100644 --- a/components/esp_hw_support/port/esp32s2/rtc_sleep.c +++ b/components/esp_hw_support/port/esp32s2/rtc_sleep.c @@ -361,7 +361,7 @@ uint32_t rtc_deep_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt) return rtc_sleep_finish(0); } -static uint32_t rtc_sleep_finish(uint32_t lslp_mem_inf_fpu) +static IRAM_ATTR uint32_t rtc_sleep_finish(uint32_t lslp_mem_inf_fpu) { /* In deep sleep mode, we never get here */ uint32_t reject = REG_GET_FIELD(RTC_CNTL_INT_RAW_REG, RTC_CNTL_SLP_REJECT_INT_RAW); diff --git a/components/esp_hw_support/port/esp32s3/rtc_sleep.c b/components/esp_hw_support/port/esp32s3/rtc_sleep.c index 1203c95d64..da565067ae 100644 --- a/components/esp_hw_support/port/esp32s3/rtc_sleep.c +++ b/components/esp_hw_support/port/esp32s3/rtc_sleep.c @@ -284,7 +284,7 @@ __attribute__((weak)) uint32_t rtc_sleep_start(uint32_t wakeup_opt, uint32_t rej return rtc_sleep_finish(lslp_mem_inf_fpu); } -static uint32_t rtc_sleep_finish(uint32_t lslp_mem_inf_fpu) +static IRAM_ATTR uint32_t rtc_sleep_finish(uint32_t lslp_mem_inf_fpu) { /* In deep sleep mode, we never get here */ uint32_t reject = REG_GET_FIELD(RTC_CNTL_INT_RAW_REG, RTC_CNTL_SLP_REJECT_INT_RAW); diff --git a/components/esp_hw_support/sleep_modem.c b/components/esp_hw_support/sleep_modem.c index c9beb449d1..8f5a6f5140 100644 --- a/components/esp_hw_support/sleep_modem.c +++ b/components/esp_hw_support/sleep_modem.c @@ -77,7 +77,7 @@ esp_err_t esp_unregister_mac_bb_pd_callback(mac_bb_power_down_cb_t cb) return ESP_ERR_INVALID_STATE; } -void IRAM_ATTR mac_bb_power_down_cb_execute(void) +void mac_bb_power_down_cb_execute(void) { for (int i = 0; i < MAC_BB_POWER_DOWN_CB_NO; i++) { if (s_mac_bb_power_down_cb[i]) { @@ -118,7 +118,7 @@ esp_err_t esp_unregister_mac_bb_pu_callback(mac_bb_power_up_cb_t cb) return ESP_ERR_INVALID_STATE; } -void IRAM_ATTR mac_bb_power_up_cb_execute(void) +void mac_bb_power_up_cb_execute(void) { for (int i = 0; i < MAC_BB_POWER_UP_CB_NO; i++) { if (s_mac_bb_power_up_cb[i]) { diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index a0e8f8fd16..5dc5d3ee53 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -216,6 +216,12 @@ #define CHECK_SOURCE(source, value, mask) ((s_config.wakeup_triggers & mask) && \ (source == value)) +#if CONFIG_PM_SLP_IRAM_OPT +# define SLEEP_FN_ATTR IRAM_ATTR +#else +# define SLEEP_FN_ATTR +#endif + #define MAX_DSLP_HOOKS 3 static esp_deep_sleep_cb_t s_dslp_cb[MAX_DSLP_HOOKS] = {0}; @@ -525,7 +531,7 @@ static uint32_t s_stopped_tgwdt_bmap = 0; #endif // Must be called from critical sections. -static void IRAM_ATTR suspend_timers(uint32_t sleep_flags) { +static SLEEP_FN_ATTR void suspend_timers(uint32_t sleep_flags) { if (!(sleep_flags & RTC_SLEEP_PD_XTAL)) { #if SOC_SLEEP_TGWDT_STOP_WORKAROUND /* If timegroup implemented task watchdog or interrupt watchdog is running, we have to stop it. */ @@ -547,7 +553,7 @@ static void IRAM_ATTR suspend_timers(uint32_t sleep_flags) { } // Must be called from critical sections. -static void IRAM_ATTR resume_timers(uint32_t sleep_flags) { +static SLEEP_FN_ATTR void resume_timers(uint32_t sleep_flags) { if (!(sleep_flags & RTC_SLEEP_PD_XTAL)) { #if SOC_SLEEP_SYSTIMER_STALL_WORKAROUND for (uint32_t counter_id = 0; counter_id < SOC_SYSTIMER_COUNTER_NUM; ++counter_id) { @@ -567,7 +573,7 @@ static void IRAM_ATTR resume_timers(uint32_t sleep_flags) { } // [refactor-todo] provide target logic for body of uart functions below -static void IRAM_ATTR flush_uarts(void) +static SLEEP_FN_ATTR void flush_uarts(void) { for (int i = 0; i < SOC_UART_HP_NUM; ++i) { if (uart_ll_is_enabled(i)) { @@ -582,7 +588,7 @@ static uint32_t s_suspended_uarts_bmap = 0; * Suspend enabled uarts and return suspended uarts bit map. * Must be called from critical sections. */ -FORCE_INLINE_ATTR void suspend_uarts(void) +static SLEEP_FN_ATTR void suspend_uarts(void) { s_suspended_uarts_bmap = 0; for (int i = 0; i < SOC_UART_HP_NUM; ++i) { @@ -603,7 +609,7 @@ FORCE_INLINE_ATTR void suspend_uarts(void) } // Must be called from critical sections -FORCE_INLINE_ATTR void resume_uarts(void) +static SLEEP_FN_ATTR void resume_uarts(void) { for (int i = 0; i < SOC_UART_HP_NUM; ++i) { if (s_suspended_uarts_bmap & 0x1) { @@ -629,7 +635,7 @@ FORCE_INLINE_ATTR void resume_uarts(void) completion time has exceeded the wakeup time, we should abandon the flush, skip the sleep and return ESP_ERR_SLEEP_REJECT. */ -FORCE_INLINE_ATTR bool light_sleep_uart_prepare(uint32_t sleep_flags, int64_t sleep_duration) +static SLEEP_FN_ATTR bool light_sleep_uart_prepare(uint32_t sleep_flags, int64_t sleep_duration) { bool should_skip_sleep = false; #if !SOC_PM_SUPPORT_TOP_PD || !CONFIG_ESP_CONSOLE_UART @@ -662,7 +668,7 @@ FORCE_INLINE_ATTR bool light_sleep_uart_prepare(uint32_t sleep_flags, int64_t sl /** * These save-restore workaround should be moved to lower layer */ -FORCE_INLINE_ATTR void misc_modules_sleep_prepare(uint32_t sleep_flags, bool deep_sleep) +static SLEEP_FN_ATTR void misc_modules_sleep_prepare(uint32_t sleep_flags, bool deep_sleep) { if (deep_sleep){ for (int n = 0; n < MAX_DSLP_HOOKS; n++) { @@ -716,7 +722,7 @@ FORCE_INLINE_ATTR void misc_modules_sleep_prepare(uint32_t sleep_flags, bool dee /** * These save-restore workaround should be moved to lower layer */ -FORCE_INLINE_ATTR void misc_modules_wake_prepare(uint32_t sleep_flags) +static SLEEP_FN_ATTR void misc_modules_wake_prepare(uint32_t sleep_flags) { #if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP if (sleep_flags & PMU_SLEEP_PD_TOP) { @@ -760,7 +766,7 @@ FORCE_INLINE_ATTR void misc_modules_wake_prepare(uint32_t sleep_flags) #endif } -static IRAM_ATTR void sleep_low_power_clock_calibration(bool is_dslp) +static SLEEP_FN_ATTR void sleep_low_power_clock_calibration(bool is_dslp) { // Calibrate rtc slow clock #ifdef CONFIG_ESP_SYSTEM_RTC_EXT_XTAL @@ -800,7 +806,7 @@ static IRAM_ATTR void sleep_low_power_clock_calibration(bool is_dslp) inline static uint32_t call_rtc_sleep_start(uint32_t reject_triggers, uint32_t lslp_mem_inf_fpu, bool dslp); -static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t sleep_flags, uint32_t clk_flags, esp_sleep_mode_t mode, bool allow_sleep_rejection) +static esp_err_t SLEEP_FN_ATTR esp_sleep_start(uint32_t sleep_flags, uint32_t clk_flags, esp_sleep_mode_t mode, bool allow_sleep_rejection) { // Stop UART output so that output is not lost due to APB frequency change. // For light sleep, suspend UART output — it will resume after wakeup. @@ -1254,9 +1260,9 @@ esp_err_t IRAM_ATTR esp_deep_sleep_try_to_start(void) * Placed into IRAM as flash may need some time to be powered on. */ static esp_err_t esp_light_sleep_inner(uint32_t sleep_flags, uint32_t clk_flags, - uint32_t flash_enable_time_us) IRAM_ATTR __attribute__((noinline)); + uint32_t flash_enable_time_us) __attribute__((noinline)); -static esp_err_t esp_light_sleep_inner(uint32_t sleep_flags, uint32_t clk_flags, +static SLEEP_FN_ATTR esp_err_t esp_light_sleep_inner(uint32_t sleep_flags, uint32_t clk_flags, uint32_t flash_enable_time_us) { #if SOC_CONFIGURABLE_VDDSDIO_SUPPORTED @@ -1687,7 +1693,7 @@ esp_err_t esp_sleep_enable_vad_wakeup(void) } #endif -static esp_err_t timer_wakeup_prepare(int64_t sleep_duration) +static SLEEP_FN_ATTR esp_err_t timer_wakeup_prepare(int64_t sleep_duration) { if (sleep_duration < 0) { sleep_duration = 0; @@ -2325,7 +2331,7 @@ FORCE_INLINE_ATTR bool top_domain_pd_allowed(void) { } #endif -static uint32_t get_power_down_flags(void) +static SLEEP_FN_ATTR uint32_t get_power_down_flags(void) { // Where needed, convert AUTO options to ON. Later interpret AUTO as OFF. @@ -2502,7 +2508,7 @@ static uint32_t get_power_down_flags(void) return pd_flags; } -static uint32_t get_sleep_flags(uint32_t sleep_flags, bool deepsleep) +static SLEEP_FN_ATTR uint32_t get_sleep_flags(uint32_t sleep_flags, bool deepsleep) { // Override user-configured FOSC power modes. if (s_sleep_sub_mode_ref_cnt[ESP_SLEEP_RTC_USE_RC_FAST_MODE]) { @@ -2554,7 +2560,7 @@ static uint32_t get_sleep_flags(uint32_t sleep_flags, bool deepsleep) return sleep_flags; } -static uint32_t get_sleep_clock_icg_flags(void) +static SLEEP_FN_ATTR uint32_t get_sleep_clock_icg_flags(void) { uint32_t clk_flags = 0; diff --git a/components/esp_pm/linker.lf b/components/esp_pm/linker.lf index a27799567b..f53768a6ba 100644 --- a/components/esp_pm/linker.lf +++ b/components/esp_pm/linker.lf @@ -7,17 +7,33 @@ entries: if PM_SLP_IRAM_OPT = y: pm_impl:esp_pm_impl_get_cpu_freq (noflash) + if FREERTOS_USE_TICKLESS_IDLE = y: + pm_impl:vApplicationSleep (noflash) [mapping:esp_hw_support_pm] archive: libesp_hw_support.a entries: if PM_SLP_IRAM_OPT = y: - sleep_modes:esp_light_sleep_start (noflash) - sleep_modes:esp_sleep_enable_timer_wakeup (noflash) - sleep_modes:timer_wakeup_prepare (noflash) - sleep_modes:get_power_down_flags (noflash) - sleep_modes:get_sleep_flags (noflash) - sleep_modes:get_sleep_clock_icg_flags (noflash) + if SOC_LIGHT_SLEEP_SUPPORTED = y: + sleep_modes:esp_light_sleep_start (noflash) + sleep_modes:esp_sleep_enable_timer_wakeup (noflash) + sleep_modem:modem_domain_pd_allowed (noflash) + sleep_modem:periph_inform_out_light_sleep_overhead (noflash) + sleep_modem:sleep_modem_reject_triggers (noflash) + if ESP_PHY_MAC_BB_PD = y: + sleep_modem:mac_bb_power_down_cb_execute (noflash) + sleep_modem:mac_bb_power_up_cb_execute (noflash) + if GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL = y: + sleep_gpio:gpio_sleep_mode_config_apply (noflash) + if SOC_PM_SUPPORT_TOP_PD = y: + sleep_clock:clock_domain_pd_allowed (noflash) + sleep_system_peripheral:peripheral_domain_pd_allowed (noflash) + if SOC_PM_CPU_RETENTION_BY_RTCCNTL = y && (PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP = y || SOC_PM_SUPPORT_TAGMEM_PD = y): + sleep_cpu:sleep_enable_cpu_retention (noflash) + if PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP = y || (SOC_CPU_IN_TOP_DOMAIN = y && PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP = y): + sleep_cpu:cpu_domain_pd_allowed (noflash) + if SOC_PM_MMU_TABLE_RETENTION_WHEN_TOP_PD = y && PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP = y: + sleep_mmu:mmu_domain_pd_allowed (noflash) esp_clk:esp_clk_slowclk_cal_set (noflash) esp_clk:esp_clk_slowclk_cal_get (noflash) esp_clk:esp_rtc_get_time_us (noflash) @@ -27,19 +43,6 @@ entries: esp_clk:calc_checksum (noflash) if SOC_SYSTIMER_SUPPORTED = y: systimer (noflash) - if GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL = y: - sleep_gpio:gpio_sleep_mode_config_apply (noflash) - if SOC_PM_CPU_RETENTION_BY_RTCCNTL = y && (PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP = y || SOC_PM_SUPPORT_TAGMEM_PD = y): - sleep_cpu:sleep_enable_cpu_retention (noflash) - if PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP = y || (SOC_CPU_IN_TOP_DOMAIN = y && PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP = y): - sleep_cpu:cpu_domain_pd_allowed (noflash) - if SOC_PM_SUPPORT_TOP_PD = y: - sleep_clock:clock_domain_pd_allowed (noflash) - sleep_system_peripheral:peripheral_domain_pd_allowed (noflash) - if SOC_PM_MMU_TABLE_RETENTION_WHEN_TOP_PD = y && PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP = y: - sleep_mmu:mmu_domain_pd_allowed (noflash) - sleep_modem:modem_domain_pd_allowed (noflash) - sleep_modem:periph_inform_out_light_sleep_overhead (noflash) sar_periph_ctrl:sar_periph_ctrl_power_disable (noflash) if SOC_TEMP_SENSOR_SUPPORTED = y: sar_periph_ctrl_common:temperature_sensor_power_acquire (noflash) diff --git a/components/esp_pm/pm_impl.c b/components/esp_pm/pm_impl.c index 4d5031a360..d320bd150b 100644 --- a/components/esp_pm/pm_impl.c +++ b/components/esp_pm/pm_impl.c @@ -803,7 +803,7 @@ static inline void IRAM_ATTR other_core_should_skip_light_sleep(int core_id) #endif } -void IRAM_ATTR vApplicationSleep( TickType_t xExpectedIdleTime ) +void vApplicationSleep( TickType_t xExpectedIdleTime ) { portENTER_CRITICAL(&s_switch_lock); int core_id = xPortGetCoreID();