From c50e5d45a381702308cc5bea0b1e3c62f02873d2 Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Mon, 13 Mar 2023 19:10:02 +0800 Subject: [PATCH] feature: add deep sleep prepare callback hook --- components/esp_hw_support/include/esp_sleep.h | 26 +++++++++ components/esp_hw_support/sleep_modes.c | 54 +++++++++++++++---- 2 files changed, 71 insertions(+), 9 deletions(-) diff --git a/components/esp_hw_support/include/esp_sleep.h b/components/esp_hw_support/include/esp_sleep.h index 4210a5169a..a632af4b37 100644 --- a/components/esp_hw_support/include/esp_sleep.h +++ b/components/esp_hw_support/include/esp_sleep.h @@ -18,6 +18,11 @@ extern "C" { #endif +/* + Definitions for the deepsleep prepare callbacks +*/ +typedef void (*esp_deep_sleep_cb_t)(void); + /** * @brief Logic function used for EXT1 wakeup mode. */ @@ -453,6 +458,27 @@ esp_err_t esp_light_sleep_start(void); void esp_deep_sleep(uint64_t time_in_us) __attribute__((noreturn)); +/** + * @brief Register a callback to be called from the deep sleep prepare + * + * @warning deepsleep callbacks should without parameters, and MUST NOT, + * UNDER ANY CIRCUMSTANCES, CALL A FUNCTION THAT MIGHT BLOCK. + * + * @param new_dslp_cb Callback to be called + * + * @return + * - ESP_OK: Callback registered to the deepsleep misc_modules_sleep_prepare + * - ESP_ERR_NO_MEM: No more hook space for register the callback + */ +esp_err_t esp_deep_sleep_register_hook(esp_deep_sleep_cb_t new_dslp_cb); + +/** + * @brief Unregister an deepsleep callback + * + * @param old_dslp_cb Callback to be unregistered + */ +void esp_deep_sleep_deregister_hook(esp_deep_sleep_cb_t old_dslp_cb); + /** * @brief Get the wakeup source which caused wakeup from sleep * diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index 41aaa3d8e3..8eac356940 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -150,6 +150,10 @@ #define CHECK_SOURCE(source, value, mask) ((s_config.wakeup_triggers & mask) && \ (source == value)) +#define MAX_DSLP_HOOKS 3 + +static esp_deep_sleep_cb_t s_dslp_cb[MAX_DSLP_HOOKS]={0}; + /** * Internal structure which holds all requested deep sleep parameters */ @@ -343,6 +347,32 @@ void esp_deep_sleep(uint64_t time_in_us) esp_deep_sleep_start(); } +esp_err_t esp_deep_sleep_register_hook(esp_deep_sleep_cb_t new_dslp_cb) +{ + portENTER_CRITICAL(&spinlock_rtc_deep_sleep); + for(int n = 0; n < MAX_DSLP_HOOKS; n++){ + if (s_dslp_cb[n]==NULL || s_dslp_cb[n]==new_dslp_cb) { + s_dslp_cb[n]=new_dslp_cb; + portEXIT_CRITICAL(&spinlock_rtc_deep_sleep); + return ESP_OK; + } + } + portEXIT_CRITICAL(&spinlock_rtc_deep_sleep); + ESP_LOGE(TAG, "Registered deepsleep callbacks exceeds MAX_DSLP_HOOKS"); + return ESP_ERR_NO_MEM; +} + +void esp_deep_sleep_deregister_hook(esp_deep_sleep_cb_t old_dslp_cb) +{ + portENTER_CRITICAL(&spinlock_rtc_deep_sleep); + for(int n = 0; n < MAX_DSLP_HOOKS; n++){ + if(s_dslp_cb[n] == old_dslp_cb) { + s_dslp_cb[n] = NULL; + } + } + portEXIT_CRITICAL(&spinlock_rtc_deep_sleep); +} + // [refactor-todo] provide target logic for body of uart functions below static void IRAM_ATTR flush_uarts(void) { @@ -392,21 +422,29 @@ static void IRAM_ATTR resume_uarts(void) /** * These save-restore workaround should be moved to lower layer */ -inline static void IRAM_ATTR misc_modules_sleep_prepare(void) +inline static void IRAM_ATTR misc_modules_sleep_prepare(bool deep_sleep) { + if (deep_sleep){ + for (int n = 0; n < MAX_DSLP_HOOKS; n++) { + if (s_dslp_cb[n] != NULL) { + s_dslp_cb[n](); + } + } + } else { #if CONFIG_MAC_BB_PD - mac_bb_power_down_cb_execute(); + mac_bb_power_down_cb_execute(); #endif #if CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL - gpio_sleep_mode_config_apply(); + gpio_sleep_mode_config_apply(); #endif #if SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_RTCCNTL - sleep_enable_cpu_retention(); + sleep_enable_cpu_retention(); #endif #if REGI2C_ANA_CALI_PD_WORKAROUND - regi2c_analog_cali_reg_read(); + regi2c_analog_cali_reg_read(); #endif - sar_periph_ctrl_power_disable(); + sar_periph_ctrl_power_disable(); + } } /** @@ -511,9 +549,7 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t mo #endif #endif //!CONFIG_IDF_TARGET_ESP32C6 - if (!deep_sleep) { - misc_modules_sleep_prepare(); - } + misc_modules_sleep_prepare(deep_sleep); #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 if (deep_sleep) {