Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'bringup/support_callback_mechanism_in_lightsleep_flow_v…
…5.1' into 'release/v5.1' feat(pm): support callback mechanism in lightsleep flow(backport v5.1) See merge request espressif/esp-idf!26365
- Loading branch information
Showing
12 changed files
with
493 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
120 changes: 120 additions & 0 deletions
120
components/esp_hw_support/include/esp_private/sleep_event.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
/* | ||
* 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 esp_err_t (*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 None | ||
*/ | ||
void esp_sleep_execute_event_callbacks(esp_sleep_event_cb_index_t event_id, void *ext_arg); | ||
|
||
#ifdef __cplusplus | ||
} | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
/* | ||
* 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" | ||
|
||
static __attribute__((unused)) const char *TAG = "sleep_event"; | ||
|
||
#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 | ||
|
||
void IRAM_ATTR esp_sleep_execute_event_callbacks(esp_sleep_event_cb_index_t event_id, void *ext_arg) | ||
{ | ||
#if CONFIG_ESP_SLEEP_EVENT_CALLBACKS | ||
if (event_id >= SLEEP_EVENT_CB_INDEX_NUM) { | ||
ESP_EARLY_LOGW(TAG, "event_id out of range"); | ||
return; | ||
} | ||
esp_sleep_event_cb_config_t *current = g_sleep_event_cbs_config.sleep_event_cb_config[event_id]; | ||
while (current != NULL) { | ||
if (current->cb != NULL) { | ||
if (ESP_OK != (*current->cb)(current->user_arg, ext_arg)) { | ||
ESP_EARLY_LOGW(TAG, "esp_sleep_execute_event_callbacks has an err, current->cb = %p", current->cb); | ||
} | ||
} | ||
current = current->next; | ||
} | ||
#endif | ||
} |
Oops, something went wrong.