feat(PowerManagement/lightsleep): Support ESP_SLEEP_EVENT_CALLBACKS

This commit is contained in:
Lou Tianhao 2023-07-06 15:52:21 +08:00
parent a28a09855d
commit 450e685cb7
10 changed files with 257 additions and 3 deletions

View File

@ -28,6 +28,7 @@ if(NOT BOOTLOADER_BUILD)
"rtc_module.c" "rtc_module.c"
"sleep_modes.c" "sleep_modes.c"
"sleep_gpio.c" "sleep_gpio.c"
"sleep_event.c"
"sleep_modem.c" "sleep_modem.c"
"regi2c_ctrl.c" "regi2c_ctrl.c"
"esp_gpio_reserve.c" "esp_gpio_reserve.c"

View File

@ -176,6 +176,20 @@ menu "Hardware Settings"
help help
When using rtc gpio wakeup source during deepsleep without external pull-up/downs, you may want to When using rtc gpio wakeup source during deepsleep without external pull-up/downs, you may want to
make use of the internal ones. make use of the internal ones.
config ESP_SLEEP_EVENT_CALLBACKS
bool "Enable registration of sleep event callbacks"
depends on FREERTOS_USE_TICKLESS_IDLE
default n
help
If enabled, it allows user to register sleep event callbacks. It is primarily designed for internal
developers and customers can use PM_LIGHT_SLEEP_CALLBACKS as an alternative.
NOTE: These callbacks are executed from the IDLE task context hence you cannot have any blocking calls
in your callbacks.
NOTE: Enabling these callbacks may change sleep duration calculations based on time spent in
callback and hence it is highly recommended to keep them as short as possible.
endmenu endmenu
menu "ESP_SLEEP_WORKAROUND" menu "ESP_SLEEP_WORKAROUND"

View File

@ -0,0 +1,122 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stddef.h>
#include <stdbool.h>
#include "esp_err.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
/**
* Using SLEEP_EVENT to determine the execution of specific
* code at a particular point in the sleep flow.
*/
SLEEP_EVENT_HW_EXIT_SLEEP, // CPU wake up and start to work
SLEEP_EVENT_SW_CLK_READY, // CPU frequency restore
SLEEP_EVENT_SW_EXIT_SLEEP, // End of esp_light_sleep_start
SLEEP_EVENT_SW_GOTO_SLEEP, // Beginning of esp_light_sleep_start
SLEEP_EVENT_HW_TIME_START, // Start timing the sleep time
SLEEP_EVENT_HW_GOTO_SLEEP, // Hardware is about to power off
SLEEP_EVENT_SW_CPU_TO_MEM_START, // CPU registers are starting to be saved
SLEEP_EVENT_SW_CPU_TO_MEM_END, // CPU registers have finished saving
#if CONFIG_IDF_TARGET_ESP32H2
SLEEP_EVENT_HW_FLASH_BBPLL_EN_START, // Beginning of rtc_clk_bbpll_enable when using FLASH_PLL
SLEEP_EVENT_HW_FLASH_BBPLL_EN_STOP, // End of rtc_clk_bbpll_enable when using FLASH_PLL
#endif
SLEEP_EVENT_HW_BBPLL_EN_START, // Beginning of rtc_clk_bbpll_enable
SLEEP_EVENT_HW_BBPLL_EN_STOP, // End of rtc_clk_bbpll_enable
SLEEP_EVENT_CB_INDEX_NUM,
} esp_sleep_event_cb_index_t;
/**
* @brief Function prototype for light sleep event callback functions (if CONFIG_FREERTOS_USE_TICKLESS_IDLE).
* @param user_arg is the user provided argument while registering callbacks.
* @param ext_arg is an externally provided parameter that is used when the callback is executed.
* @return None
*/
typedef void (*esp_sleep_event_cb_t)(void *user_arg, void *ext_arg);
/**
* @brief Function entry parameter types for light sleep event callback functions (if CONFIG_FREERTOS_USE_TICKLESS_IDLE)
*/
struct _esp_sleep_event_cb_config_t {
/**
* Callback function defined by internal developers.
*/
esp_sleep_event_cb_t cb;
/**
* Input parameters of callback function defined by internal developers.
*/
void *user_arg;
/**
* Execution priority of callback function defined by internal developers.
* The smaller the priority, the earlier it executes when call esp_sleep_execute_event_callbacks.
* If functions have the same priority, the function registered first will be executed first.
*/
uint32_t prior;
/**
* Next callback configuration defined by internal developer.
*/
struct _esp_sleep_event_cb_config_t *next;
};
typedef struct _esp_sleep_event_cb_config_t esp_sleep_event_cb_config_t;
struct _esp_sleep_event_cbs_config_t {
/**
* Callback configurations defined by internal developers.
*/
esp_sleep_event_cb_config_t *sleep_event_cb_config[SLEEP_EVENT_CB_INDEX_NUM];
};
typedef struct _esp_sleep_event_cbs_config_t esp_sleep_event_cbs_config_t;
/**
* @brief Register event callbacks for light sleep internal events (if CONFIG_FREERTOS_USE_TICKLESS_IDLE)
* @param event_id Designed to register the corresponding event_cb in g_sleep_event_cbs_config
* @param event_cb_conf Config struct containing event callback function and corresponding argument
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG if the input parameter event_cb_conf is NULL or event_id is out of range
* - ESP_ERR_NO_MEM if the remaining memory is insufficient to support malloc
* - ESP_FAIL if register the same function repeatedly
*
* @note Some of these callback functions are called from IDLE task context hence they cannot call any blocking functions
* @note Passing NULL value will not deregister the callbacks, it will silently ignore and return ESP_OK
*/
esp_err_t esp_sleep_register_event_callback(esp_sleep_event_cb_index_t event_id, const esp_sleep_event_cb_config_t *event_cb_conf);
/**
* @brief Unregister event callbacks for light sleep internal events (if CONFIG_FREERTOS_USE_TICKLESS_IDLE)
* @param event_id Designed to unregister the corresponding event_cb in g_sleep_event_cbs_config
* @param event_cb_conf Config struct containing event callback function and corresponding argument
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG if the input parameter cb is NULL or event_id is out of range
*/
esp_err_t esp_sleep_unregister_event_callback(esp_sleep_event_cb_index_t event_id, esp_sleep_event_cb_t cb);
/**
* @brief Designed to execute functions in the esp_sleep_event_cb_config_t linked list
*
* @param event_id Designed to annotate the corresponding event_cb in g_sleep_event_cbs_config
* @param ext_arg Designed to pass external parameters
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG if event_id is out of range
*/
esp_err_t esp_sleep_execute_event_callbacks(esp_sleep_event_cb_index_t event_id, void *ext_arg);
#ifdef __cplusplus
}
#endif

View File

@ -19,6 +19,7 @@
#include "hal/regi2c_ctrl_ll.h" #include "hal/regi2c_ctrl_ll.h"
#include "soc/io_mux_reg.h" #include "soc/io_mux_reg.h"
#include "soc/lp_aon_reg.h" #include "soc/lp_aon_reg.h"
#include "esp_private/sleep_event.h"
#ifdef BOOTLOADER_BUILD #ifdef BOOTLOADER_BUILD
#include "hal/modem_lpcon_ll.h" #include "hal/modem_lpcon_ll.h"
@ -252,6 +253,10 @@ bool rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz, rtc_cpu_freq_config_t *ou
return true; return true;
} }
__attribute__((weak)) void rtc_clk_set_cpu_switch_to_bbpll(int event_id)
{
}
void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config) void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config)
{ {
soc_cpu_clk_src_t old_cpu_clk_src = clk_ll_cpu_get_src(); soc_cpu_clk_src_t old_cpu_clk_src = clk_ll_cpu_get_src();
@ -263,10 +268,12 @@ void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config)
} }
} else if (config->source == SOC_CPU_CLK_SRC_PLL) { } else if (config->source == SOC_CPU_CLK_SRC_PLL) {
if (old_cpu_clk_src != SOC_CPU_CLK_SRC_PLL) { if (old_cpu_clk_src != SOC_CPU_CLK_SRC_PLL) {
rtc_clk_set_cpu_switch_to_bbpll(SLEEP_EVENT_HW_BBPLL_EN_START);
rtc_clk_bbpll_enable(); rtc_clk_bbpll_enable();
rtc_clk_bbpll_configure(rtc_clk_xtal_freq_get(), config->source_freq_mhz); rtc_clk_bbpll_configure(rtc_clk_xtal_freq_get(), config->source_freq_mhz);
} }
rtc_clk_cpu_freq_to_pll_mhz(config->freq_mhz); rtc_clk_cpu_freq_to_pll_mhz(config->freq_mhz);
rtc_clk_set_cpu_switch_to_bbpll(SLEEP_EVENT_HW_BBPLL_EN_STOP);
} else if (config->source == SOC_CPU_CLK_SRC_RC_FAST) { } else if (config->source == SOC_CPU_CLK_SRC_RC_FAST) {
rtc_clk_cpu_freq_to_8m(); rtc_clk_cpu_freq_to_8m();
if ((old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL) && !s_bbpll_digi_consumers_ref_count) { if ((old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL) && !s_bbpll_digi_consumers_ref_count) {

View File

@ -20,6 +20,7 @@
#include "soc/io_mux_reg.h" #include "soc/io_mux_reg.h"
#include "soc/lp_aon_reg.h" #include "soc/lp_aon_reg.h"
#include "soc/lp_clkrst_reg.h" #include "soc/lp_clkrst_reg.h"
#include "esp_private/sleep_event.h"
#ifdef BOOTLOADER_BUILD #ifdef BOOTLOADER_BUILD
#include "hal/modem_lpcon_ll.h" #include "hal/modem_lpcon_ll.h"
@ -297,6 +298,10 @@ bool rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz, rtc_cpu_freq_config_t *ou
return true; return true;
} }
__attribute__((weak)) void rtc_clk_set_cpu_switch_to_bbpll(int event_id)
{
}
void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config) void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config)
{ {
soc_cpu_clk_src_t old_cpu_clk_src = clk_ll_cpu_get_src(); soc_cpu_clk_src_t old_cpu_clk_src = clk_ll_cpu_get_src();
@ -308,10 +313,12 @@ void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config)
} }
} else if (config->source == SOC_CPU_CLK_SRC_PLL) { } else if (config->source == SOC_CPU_CLK_SRC_PLL) {
if (old_cpu_clk_src != SOC_CPU_CLK_SRC_PLL && old_cpu_clk_src != SOC_CPU_CLK_SRC_FLASH_PLL) { if (old_cpu_clk_src != SOC_CPU_CLK_SRC_PLL && old_cpu_clk_src != SOC_CPU_CLK_SRC_FLASH_PLL) {
rtc_clk_set_cpu_switch_to_bbpll(SLEEP_EVENT_HW_BBPLL_EN_START);
rtc_clk_bbpll_enable(); rtc_clk_bbpll_enable();
rtc_clk_bbpll_configure(rtc_clk_xtal_freq_get(), config->source_freq_mhz); rtc_clk_bbpll_configure(rtc_clk_xtal_freq_get(), config->source_freq_mhz);
} }
rtc_clk_cpu_freq_to_pll_mhz(config->freq_mhz); rtc_clk_cpu_freq_to_pll_mhz(config->freq_mhz);
rtc_clk_set_cpu_switch_to_bbpll(SLEEP_EVENT_HW_BBPLL_EN_STOP);
} else if (config->source == SOC_CPU_CLK_SRC_RC_FAST) { } else if (config->source == SOC_CPU_CLK_SRC_RC_FAST) {
rtc_clk_cpu_freq_to_8m(); rtc_clk_cpu_freq_to_8m();
if ((old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL || old_cpu_clk_src == SOC_CPU_CLK_SRC_FLASH_PLL) && if ((old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL || old_cpu_clk_src == SOC_CPU_CLK_SRC_FLASH_PLL) &&
@ -322,10 +329,12 @@ void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config)
if (old_cpu_clk_src != SOC_CPU_CLK_SRC_PLL && old_cpu_clk_src != SOC_CPU_CLK_SRC_FLASH_PLL) { if (old_cpu_clk_src != SOC_CPU_CLK_SRC_PLL && old_cpu_clk_src != SOC_CPU_CLK_SRC_FLASH_PLL) {
// On ESP32H2, FLASH_PLL (64MHz) is directly derived from the BBPLL (96MHz) // On ESP32H2, FLASH_PLL (64MHz) is directly derived from the BBPLL (96MHz)
// Therefore, enabling and configuration are applied to BBPLL. // Therefore, enabling and configuration are applied to BBPLL.
rtc_clk_set_cpu_switch_to_bbpll(SLEEP_EVENT_HW_FLASH_BBPLL_EN_START);
rtc_clk_bbpll_enable(); rtc_clk_bbpll_enable();
rtc_clk_bbpll_configure(rtc_clk_xtal_freq_get(), CLK_LL_PLL_96M_FREQ_MHZ); rtc_clk_bbpll_configure(rtc_clk_xtal_freq_get(), CLK_LL_PLL_96M_FREQ_MHZ);
} }
rtc_clk_cpu_freq_to_flash_pll(config->freq_mhz, config->div); rtc_clk_cpu_freq_to_flash_pll(config->freq_mhz, config->div);
rtc_clk_set_cpu_switch_to_bbpll(SLEEP_EVENT_HW_FLASH_BBPLL_EN_STOP);
} }
} }

View File

@ -20,6 +20,7 @@
#include "esp_heap_caps.h" #include "esp_heap_caps.h"
#include "soc/soc_caps.h" #include "soc/soc_caps.h"
#include "esp_private/sleep_cpu.h" #include "esp_private/sleep_cpu.h"
#include "esp_private/sleep_event.h"
#include "sdkconfig.h" #include "sdkconfig.h"
#if SOC_PMU_SUPPORTED #if SOC_PMU_SUPPORTED
@ -685,6 +686,7 @@ static IRAM_ATTR esp_err_t do_cpu_retention(sleep_cpu_entry_cb_t goto_sleep,
{ {
RvCoreCriticalSleepFrame * frame = rv_core_critical_regs_save(); RvCoreCriticalSleepFrame * frame = rv_core_critical_regs_save();
if ((frame->pmufunc & 0x3) == 0x1) { if ((frame->pmufunc & 0x3) == 0x1) {
esp_sleep_execute_event_callbacks(SLEEP_EVENT_SW_CPU_TO_MEM_END, (void *)0);
#if CONFIG_PM_CHECK_SLEEP_RETENTION_FRAME #if CONFIG_PM_CHECK_SLEEP_RETENTION_FRAME
/* Minus 2 * sizeof(long) is for bypass `pmufunc` and `frame_crc` field */ /* Minus 2 * sizeof(long) is for bypass `pmufunc` and `frame_crc` field */
update_retention_frame_crc((uint32_t*)frame, RV_SLEEP_CTX_FRMSZ - 2 * sizeof(long), (uint32_t *)(&frame->frame_crc)); update_retention_frame_crc((uint32_t*)frame, RV_SLEEP_CTX_FRMSZ - 2 * sizeof(long), (uint32_t *)(&frame->frame_crc));
@ -704,6 +706,7 @@ static IRAM_ATTR esp_err_t do_cpu_retention(sleep_cpu_entry_cb_t goto_sleep,
esp_err_t IRAM_ATTR esp_sleep_cpu_retention(uint32_t (*goto_sleep)(uint32_t, uint32_t, uint32_t, bool), esp_err_t IRAM_ATTR esp_sleep_cpu_retention(uint32_t (*goto_sleep)(uint32_t, uint32_t, uint32_t, bool),
uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu, bool dslp) uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu, bool dslp)
{ {
esp_sleep_execute_event_callbacks(SLEEP_EVENT_SW_CPU_TO_MEM_START, (void *)0);
uint32_t mstatus = save_mstatus_and_disable_global_int(); uint32_t mstatus = save_mstatus_and_disable_global_int();
cpu_domain_dev_regs_save(s_cpu_retention.retent.plic_frame); cpu_domain_dev_regs_save(s_cpu_retention.retent.plic_frame);
@ -728,7 +731,6 @@ esp_err_t IRAM_ATTR esp_sleep_cpu_retention(uint32_t (*goto_sleep)(uint32_t, uin
cpu_domain_dev_regs_restore(s_cpu_retention.retent.intpri_frame); cpu_domain_dev_regs_restore(s_cpu_retention.retent.intpri_frame);
cpu_domain_dev_regs_restore(s_cpu_retention.retent.clint_frame); cpu_domain_dev_regs_restore(s_cpu_retention.retent.clint_frame);
cpu_domain_dev_regs_restore(s_cpu_retention.retent.plic_frame); cpu_domain_dev_regs_restore(s_cpu_retention.retent.plic_frame);
restore_mstatus(mstatus); restore_mstatus(mstatus);
return err; return err;
} }

View File

@ -0,0 +1,91 @@
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stddef.h>
#include <string.h>
#include "sdkconfig.h"
#include "soc/soc_caps.h"
#include "esp_private/sleep_event.h"
#include "esp_sleep.h"
#include "esp_log.h"
#include "esp_check.h"
#include "freertos/FreeRTOS.h"
#if CONFIG_ESP_SLEEP_EVENT_CALLBACKS
esp_sleep_event_cbs_config_t g_sleep_event_cbs_config;
static portMUX_TYPE s_sleep_event_mutex = portMUX_INITIALIZER_UNLOCKED;
esp_err_t esp_sleep_register_event_callback(esp_sleep_event_cb_index_t event_id, const esp_sleep_event_cb_config_t *event_cb_conf) {
if (event_cb_conf == NULL || event_id >= SLEEP_EVENT_CB_INDEX_NUM) {
return ESP_ERR_INVALID_ARG;
}
esp_sleep_event_cb_config_t *new_config = (esp_sleep_event_cb_config_t *)heap_caps_malloc(sizeof(esp_sleep_event_cb_config_t), MALLOC_CAP_INTERNAL);
if (new_config == NULL) {
return ESP_ERR_NO_MEM; /* Memory allocation failed */
}
portENTER_CRITICAL(&s_sleep_event_mutex);
esp_sleep_event_cb_config_t **current_ptr = &(g_sleep_event_cbs_config.sleep_event_cb_config[event_id]);
while (*current_ptr != NULL) {
if (((*current_ptr)->cb) == (event_cb_conf->cb)) {
free(new_config);
portEXIT_CRITICAL(&s_sleep_event_mutex);
return ESP_FAIL;
}
current_ptr = &((*current_ptr)->next);
}
*new_config = *event_cb_conf;
while (*current_ptr != NULL && (*current_ptr)->prior <= new_config->prior) {
current_ptr = &((*current_ptr)->next);
}
new_config->next = *current_ptr;
*current_ptr = new_config;
portEXIT_CRITICAL(&s_sleep_event_mutex);
return ESP_OK;
}
esp_err_t esp_sleep_unregister_event_callback(esp_sleep_event_cb_index_t event_id, esp_sleep_event_cb_t cb) {
if (cb == NULL || event_id >= SLEEP_EVENT_CB_INDEX_NUM) {
return ESP_ERR_INVALID_ARG;
}
portENTER_CRITICAL(&s_sleep_event_mutex);
esp_sleep_event_cb_config_t **current_ptr = &(g_sleep_event_cbs_config.sleep_event_cb_config[event_id]);
while (*current_ptr != NULL) {
if (((*current_ptr)->cb) == cb) {
esp_sleep_event_cb_config_t *temp = *current_ptr;
*current_ptr = (*current_ptr)->next;
free(temp);
break;
}
current_ptr = &((*current_ptr)->next);
}
portEXIT_CRITICAL(&s_sleep_event_mutex);
return ESP_OK;
}
#endif
#if CONFIG_ESP_SLEEP_EVENT_CALLBACKS
esp_err_t IRAM_ATTR esp_sleep_execute_event_callbacks(esp_sleep_event_cb_index_t event_id, void *ext_arg)
{
if (event_id >= SLEEP_EVENT_CB_INDEX_NUM) {
return ESP_ERR_INVALID_ARG;
}
esp_sleep_event_cb_config_t *current = g_sleep_event_cbs_config.sleep_event_cb_config[event_id];
while (current != NULL) {
(current->cb)(current->user_arg, ext_arg);
current = current->next;
}
return ESP_OK;
}
#else
esp_err_t IRAM_ATTR esp_sleep_execute_event_callbacks(esp_sleep_event_cb_index_t event_id, void *ext_arg)
{
return ESP_OK;
}
#endif

View File

@ -14,6 +14,7 @@
#include "esp_sleep.h" #include "esp_sleep.h"
#include "esp_private/esp_sleep_internal.h" #include "esp_private/esp_sleep_internal.h"
#include "esp_private/esp_timer_private.h" #include "esp_private/esp_timer_private.h"
#include "esp_private/sleep_event.h"
#include "esp_private/system_internal.h" #include "esp_private/system_internal.h"
#include "esp_log.h" #include "esp_log.h"
#include "esp_newlib.h" #include "esp_newlib.h"
@ -757,12 +758,14 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m
#if SOC_PMU_SUPPORTED #if SOC_PMU_SUPPORTED
#if SOC_PM_CPU_RETENTION_BY_SW #if SOC_PM_CPU_RETENTION_BY_SW
esp_sleep_execute_event_callbacks(SLEEP_EVENT_HW_GOTO_SLEEP, (void *)0);
if (pd_flags & PMU_SLEEP_PD_CPU) { if (pd_flags & PMU_SLEEP_PD_CPU) {
result = esp_sleep_cpu_retention(pmu_sleep_start, s_config.wakeup_triggers, reject_triggers, config.power.hp_sys.dig_power.mem_dslp, deep_sleep); result = esp_sleep_cpu_retention(pmu_sleep_start, s_config.wakeup_triggers, reject_triggers, config.power.hp_sys.dig_power.mem_dslp, deep_sleep);
} else { } else {
#endif #endif
result = call_rtc_sleep_start(reject_triggers, config.power.hp_sys.dig_power.mem_dslp, deep_sleep); result = call_rtc_sleep_start(reject_triggers, config.power.hp_sys.dig_power.mem_dslp, deep_sleep);
} }
esp_sleep_execute_event_callbacks(SLEEP_EVENT_HW_EXIT_SLEEP, (void *)0);
#else #else
result = call_rtc_sleep_start(reject_triggers, config.lslp_mem_inf_fpu, deep_sleep); result = call_rtc_sleep_start(reject_triggers, config.lslp_mem_inf_fpu, deep_sleep);
#endif #endif
@ -804,6 +807,8 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m
rtc_clk_cpu_freq_set_config(&cpu_freq_config); rtc_clk_cpu_freq_set_config(&cpu_freq_config);
} }
esp_sleep_execute_event_callbacks(SLEEP_EVENT_SW_CLK_READY, (void *)0);
if (cpu_freq_config.source == SOC_CPU_CLK_SRC_PLL) { if (cpu_freq_config.source == SOC_CPU_CLK_SRC_PLL) {
// Turn up MSPI speed if switch to PLL // Turn up MSPI speed if switch to PLL
mspi_timing_change_speed_mode_cache_safe(false); mspi_timing_change_speed_mode_cache_safe(false);
@ -970,6 +975,7 @@ FORCE_INLINE_ATTR bool can_power_down_vddsdio(uint32_t pd_flags, const uint32_t
esp_err_t esp_light_sleep_start(void) esp_err_t esp_light_sleep_start(void)
{ {
s_config.ccount_ticks_record = esp_cpu_get_cycle_count(); s_config.ccount_ticks_record = esp_cpu_get_cycle_count();
esp_sleep_execute_event_callbacks(SLEEP_EVENT_SW_GOTO_SLEEP, (void *)0);
#if CONFIG_ESP_TASK_WDT_USE_ESP_TIMER #if CONFIG_ESP_TASK_WDT_USE_ESP_TIMER
esp_err_t timerret = ESP_OK; esp_err_t timerret = ESP_OK;
@ -1007,9 +1013,9 @@ esp_err_t esp_light_sleep_start(void)
s_config.rtc_ticks_at_sleep_start = rtc_time_get(); s_config.rtc_ticks_at_sleep_start = rtc_time_get();
#endif #endif
uint32_t ccount_at_sleep_start = esp_cpu_get_cycle_count(); uint32_t ccount_at_sleep_start = esp_cpu_get_cycle_count();
esp_sleep_execute_event_callbacks(SLEEP_EVENT_HW_TIME_START, (void *)0);
uint64_t high_res_time_at_start = esp_timer_get_time(); uint64_t high_res_time_at_start = esp_timer_get_time();
uint32_t sleep_time_overhead_in = (ccount_at_sleep_start - s_config.ccount_ticks_record) / (esp_clk_cpu_freq() / 1000000ULL); uint32_t sleep_time_overhead_in = (ccount_at_sleep_start - s_config.ccount_ticks_record) / (esp_clk_cpu_freq() / 1000000ULL);
esp_ipc_isr_stall_other_cpu(); esp_ipc_isr_stall_other_cpu();
#if CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION && CONFIG_PM_SLP_IRAM_OPT #if CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION && CONFIG_PM_SLP_IRAM_OPT
@ -1191,6 +1197,7 @@ esp_err_t esp_light_sleep_start(void)
} }
#endif // CONFIG_ESP_TASK_WDT_USE_ESP_TIMER #endif // CONFIG_ESP_TASK_WDT_USE_ESP_TIMER
esp_sleep_execute_event_callbacks(SLEEP_EVENT_SW_EXIT_SLEEP, (void *)0);
s_config.sleep_time_overhead_out = (esp_cpu_get_cycle_count() - s_config.ccount_ticks_record) / (esp_clk_cpu_freq() / 1000000ULL); s_config.sleep_time_overhead_out = (esp_cpu_get_cycle_count() - s_config.ccount_ticks_record) / (esp_clk_cpu_freq() / 1000000ULL);
return err; return err;
} }

View File

@ -153,7 +153,7 @@ menu "Power Management"
default y if PM_ENABLE && BTDM_CTRL_HLI default y if PM_ENABLE && BTDM_CTRL_HLI
config PM_LIGHT_SLEEP_CALLBACKS config PM_LIGHT_SLEEP_CALLBACKS
bool "Enable registration of auto light sleep callbacks" bool "Enable registration of pm light sleep callbacks"
depends on FREERTOS_USE_TICKLESS_IDLE depends on FREERTOS_USE_TICKLESS_IDLE
default n default n
help help

View File

@ -192,6 +192,7 @@ esp_err_t esp_pm_lock_delete(esp_pm_lock_handle_t handle);
*/ */
esp_err_t esp_pm_dump_locks(FILE* stream); esp_err_t esp_pm_dump_locks(FILE* stream);
#if CONFIG_PM_LIGHT_SLEEP_CALLBACKS
/** /**
* @brief Function prototype for light sleep callback functions (if CONFIG_FREERTOS_USE_TICKLESS_IDLE) * @brief Function prototype for light sleep callback functions (if CONFIG_FREERTOS_USE_TICKLESS_IDLE)
* *