Merge branch 'feat/optimize_for_esp32h4_light_sleep_ph2' into 'master'

Feat/optimize for esp32h4 light sleep ph2

See merge request espressif/esp-idf!50993
This commit is contained in:
Island
2026-09-17 20:49:00 +08:00
57 changed files with 1001 additions and 298 deletions
@@ -1 +1,5 @@
source "$IDF_PATH/components/bt/porting_btdm/Kconfig.in"
config BT_CTRL_SUPPORT_ETM_WAKEUP
bool
default y
@@ -86,6 +86,10 @@ entries:
[mapping:bt]
archive: libbt.a
entries:
if BT_CTRL_SLEEP_RELATED_CODE_IN_IRAM = y:
btdm_lp:btdm_lp_sleep_cb (noflash)
btdm_lp:btdm_lp_wake_up_cb (noflash)
if ESP_ALLOW_BSS_SEG_EXTERNAL_MEMORY = y:
* (bt_extram_bss);
bt_bss -> extern_ram ALIGN(4) ALIGN(4, post) SURROUND(bt_bss),
+11 -1
View File
@@ -113,7 +113,7 @@
#include "../../common/btdm_le.h"
#endif /* SOC_BLE_SUPPORTED */
#define BTDM_CONFIG_VERSION 0x20260911
#define BTDM_CONFIG_VERSION 0x20260916
#define BTDM_CONFIG_MAGIC_VALUE 0x5a5aa5a5
/* Types definition
@@ -133,6 +133,7 @@
uint8_t sleep_en; /*!< Enable sleep functionality */
uint8_t version_num; /*!< Hardware version number of this chip */
uint8_t bluetooth_mode; /*!< Controller mode: BR/EDR, BLE or Dual Mode */
uint8_t etm_triggered_rf; /*!< Enable enabling RF using ETM */
uint32_t magic; /*!< Magic number for configuration validation */
} esp_bt_ctrl_btdm_config_t;
@@ -157,6 +158,13 @@
#define BTDM_CONTROLLER_MODE_EFF ESP_BT_MODE_BTDM
#endif // defined(CONFIG_BTDM_CTRL_MODE_BLE_ONLY)
#if CONFIG_BT_CTRL_SLEEP_ETM_TRIGGERED_RF
#define MODEM_ETM_CHAN_EN (0x600C8800)
#define MODEM_ETM_CHAN_SET (0x600C8804)
#define MODEM_ETM_CHAN_CLR (0x600C8808)
#define MODEM_ETM_CHAN_MASK (BIT(11))
#endif // CONFIG_BT_CTRL_SLEEP_ETM_TRIGGERED_RF
#if SOC_BT_CLASSIC_SUPPORTED
#define BT_CONTROLLER_INIT_CONFIG_DEFAULT() \
{ \
@@ -173,6 +181,7 @@
.sleep_en = UC_BT_CTRL_SLEEP_ENABLE, \
.version_num = 0, \
.bluetooth_mode = BTDM_CONTROLLER_MODE_EFF, \
.etm_triggered_rf = UC_BT_CTRL_SLEEP_ETM_TRIGGERED_RF, \
.magic = BTDM_CONFIG_MAGIC_VALUE, \
}, \
}
@@ -191,6 +200,7 @@
.sleep_en = UC_BT_CTRL_SLEEP_ENABLE, \
.version_num = 0, \
.bluetooth_mode = BTDM_CONTROLLER_MODE_EFF, \
.etm_triggered_rf = UC_BT_CTRL_SLEEP_ETM_TRIGGERED_RF, \
.magic = BTDM_CONFIG_MAGIC_VALUE, \
}, \
}
@@ -112,7 +112,7 @@ typedef struct {
#include "../../common/btdm_le.h"
#endif /* SOC_BLE_SUPPORTED */
#define BTDM_CONFIG_VERSION 0x20260911
#define BTDM_CONFIG_VERSION 0x20260916
#define BTDM_CONFIG_MAGIC_VALUE 0x5a5aa5a5
/* Types definition
+10
View File
@@ -62,6 +62,16 @@ choice BT_CTRL_LP_CLK_SRC
endchoice
config BT_CTRL_SLEEP_ETM_TRIGGERED_RF
bool "Use ETM to trigger RF enable/disable to optimize power consumption"
default n
select ESP_PHY_HW_SWITCH_RF
depends on SOC_PM_SUPPORT_REGDMA_TRIGGERED_PHY && BT_CTRL_SLEEP_ENABLE && BT_CTRL_SUPPORT_ETM_WAKEUP
help
Trigger RF enable/disable via ETM to accelerate the wakeup process.
Use with caution: undefined behavior may arise when ADC or temperature
sensor are enabled.
config BT_CTRL_SLEEP_RELATED_CODE_IN_IRAM
bool "Put sleep related code into IRAM to optimize power consumption"
default n
@@ -19,7 +19,7 @@ void ble_stack_disable(void);
void ble_stack_reset(void);
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
esp_err_t sleep_modem_ble_mac_modem_state_init(void);
esp_err_t sleep_modem_ble_mac_retention_create(void);
#endif // CONFIG_FREERTOS_USE_TICKLESS_IDLE
void ble_osal_elem_calc(esp_bt_controller_config_t *cfg, btdm_osal_elem_num_t *elem);
@@ -494,7 +494,7 @@ extern const sleep_retention_entries_config_t *r_esp_ble_mac_retention_link_get(
uint8_t extra);
esp_err_t
sleep_modem_ble_mac_modem_state_init(void)
sleep_modem_ble_mac_retention_create(void)
{
uint8_t size;
const sleep_retention_entries_config_t *ble_mac_modem_config =
@@ -22,7 +22,7 @@ int bredr_hci_cmd_rx_handler(uint16_t opcode, const uint8_t *cmdbuf, uint8_t len
uint8_t *rsplen);
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
esp_err_t sleep_modem_bredr_mac_modem_state_init(void);
esp_err_t sleep_modem_bredr_mac_retention_create(void);
#endif // CONFIG_FREERTOS_USE_TICKLESS_IDLE
void bredr_osal_elem_calc(esp_bt_controller_config_t *cfg, btdm_osal_elem_num_t *elem);
@@ -966,7 +966,7 @@ int bredr_stack_reset(void)
}
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
esp_err_t sleep_modem_bredr_mac_modem_state_init(void)
esp_err_t sleep_modem_bredr_mac_retention_create(void)
{
uint8_t size;
const sleep_retention_entries_config_t *bredr_mac_modem_config = r_bredr_mac_retention_link_get(&size);
@@ -139,6 +139,12 @@ extern "C" {
#define UC_BT_CTRL_ALLOW_MALLOC_FROM_SPIRAM (0)
#endif
#if defined (CONFIG_BT_CTRL_SLEEP_ETM_TRIGGERED_RF)
#define UC_BT_CTRL_SLEEP_ETM_TRIGGERED_RF CONFIG_BT_CTRL_SLEEP_ETM_TRIGGERED_RF
#else
#define UC_BT_CTRL_SLEEP_ETM_TRIGGERED_RF 0
#endif // CONFIG_BT_CTRL_SLEEP_ETM_TRIGGERED_RF
#ifdef __cplusplus
}
@@ -10,6 +10,7 @@
#include "esp_bt.h"
#include "btdm_osal.h"
/* From Modem and Phy */
#include "esp_phy_init.h"
#include "esp_private/esp_modem_clock.h"
@@ -30,6 +31,13 @@
// TODO: remove this include after use of HP_SYS_CLKRST_MODEM_CONF_REG is removed
#include "soc/hp_sys_clkrst_reg.h"
#endif
#if CONFIG_BT_CTRL_SLEEP_ETM_TRIGGERED_RF
#include "esp_etm.h"
#include "soc/soc_etm_source.h"
#include "esp_private/etm_interface.h"
#include "esp_private/esp_pau.h"
#endif // CONFIG_BT_CTRL_SLEEP_ETM_TRIGGERED_RF
/*
***************************************************************************************************
* Local Defined Macros
@@ -37,8 +45,16 @@
*/
#define BTDM_LOG_TAG "BTDM_SLEEP"
#define BTDM_RTC_DELAY_US_LIGHT_SLEEP (1800)
#define BTDM_RTC_DELAY_US_MODEM_SLEEP (1500)
#define BTDM_RTC_DELAY_US_LIGHT_SLEEP (1500)
#define BTDM_RTC_DELAY_US_MODEM_SLEEP (400)
#if CONFIG_BT_CTRL_SLEEP_ETM_TRIGGERED_RF
static esp_etm_event_handle_t s_btdm_lp_etm_event = NULL;
static esp_etm_task_handle_t s_btdm_lp_etm_task = NULL;
static esp_etm_channel_handle_t s_btdm_lp_etm_channel = NULL;
static uint8_t s_btdm_lp_phy_clk_en = false;
#endif // CONFIG_BT_CTRL_SLEEP_ETM_TRIGGERED_RF
typedef union {
struct {
@@ -61,10 +77,10 @@ extern bool r_btdm_sleep_should_skip_light_sleep_check(void);
extern const sleep_retention_entries_config_t *r_btdm_mac_retention_link_get(uint8_t *size);
extern void r_btdm_sleep_wake_up_overhead_set(uint32_t overhead);
#if UC_BT_CTRL_BR_EDR_IS_ENABLE
extern esp_err_t sleep_modem_bredr_mac_modem_state_init(void);
extern esp_err_t sleep_modem_bredr_mac_retention_create(void);
#endif // UC_BT_CTRL_BR_EDR_IS_ENABLE
#if UC_BT_CTRL_BLE_IS_ENABLE
extern esp_err_t sleep_modem_ble_mac_modem_state_init(void);
extern esp_err_t sleep_modem_ble_mac_retention_create(void);
#endif // UC_BT_CTRL_BLE_IS_ENABLEs
#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */
extern int r_btdm_hal_rtc_freq_set(uint64_t rtc_freq);
@@ -86,7 +102,9 @@ static uint32_t s_bt_xtal_lpclk_freq = 100000;
static uint32_t s_bt_lpclk_freq = 0;
static uint8_t s_btdm_lp_modem_clk_en = 0;
static uint8_t s_btdm_lp_modem_apb_clk_en = 0;
#if CONFIG_BT_CTRL_SLEEP_ETM_TRIGGERED_RF
static void btdm_lp_soc_etm_set_enable(bool enable);
#endif // CONFIG_BT_CTRL_SLEEP_ETM_TRIGGERED_RF
/*
***************************************************************************************************
* Static Function Definitions
@@ -238,6 +256,14 @@ btdm_lp_sleep_cb(uint32_t enable_tick, void *arg)
return;
}
esp_phy_disable(PHY_MODEM_BT);
#if CONFIG_BT_CTRL_SLEEP_ETM_TRIGGERED_RF
btdm_lp_soc_etm_set_enable(true);
pau_regdma_clear_etm_task_triggered(0);
if (s_btdm_lp_phy_clk_en) {
modem_clock_module_disable(PERIPH_PHY_MODULE);
s_btdm_lp_phy_clk_en = 0;
}
#endif // CONFIG_BT_CTRL_SLEEP_ETM_TRIGGERED_RF
#ifdef CONFIG_PM_ENABLE
esp_pm_lock_release(s_pm_lock);
#endif // CONFIG_PM_ENABLE
@@ -260,6 +286,7 @@ btdm_lp_wake_up_cb(void *arg)
params->bt_wakeup = 0;
}
esp_phy_enable(PHY_MODEM_BT);
#if UC_BT_CTRL_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE
if (params) {
params->bt_wakeup = btdm_lp_check_wakeup_by_bt();
@@ -288,12 +315,20 @@ btdm_lp_modem_retention_create(void)
#if UC_BT_CTRL_BR_EDR_IS_ENABLE
// TODO: check the return value. Shouldn't invoke the upper layer function directly.
sleep_modem_bredr_mac_modem_state_init();
err = sleep_modem_bredr_mac_retention_create();
if (err != ESP_OK) {
ESP_LOGE(BTDM_LOG_TAG, "BT bredr modem state init error");
return err;
}
#endif // UC_BT_CTRL_BR_EDR_IS_ENABLE
#if UC_BT_CTRL_BLE_IS_ENABLE
// TODO: check the return value. Shouldn't invoke the upper layer function directly.
sleep_modem_ble_mac_modem_state_init();
err = sleep_modem_ble_mac_retention_create();
if (err != ESP_OK) {
ESP_LOGE(BTDM_LOG_TAG, "BT ble modem state init error");
return err;
}
#endif // UC_BT_CTRL_BLE_IS_ENABLE
return err;
}
@@ -332,23 +367,161 @@ btdm_lp_modem_state_deinit(void)
esp_err_t err = sleep_retention_module_detach(SLEEP_RETENTION_MODULE_BLE_MAC);
if (err != ESP_OK) {
ESP_LOGE(BTDM_LOG_TAG, "BT sleep retention detach error");
assert(err == ESP_OK);
}
err = sleep_retention_module_free(SLEEP_RETENTION_MODULE_BLE_MAC);
if (err != ESP_OK) {
ESP_LOGE(BTDM_LOG_TAG, "BT sleep retention free error");
assert(err == ESP_OK);
}
err = sleep_retention_module_deinit(SLEEP_RETENTION_MODULE_BLE_MAC);
if (err != ESP_OK) {
ESP_LOGE(BTDM_LOG_TAG, "BT sleep retention deinit error");
assert(err == ESP_OK);
}
}
#endif // UC_BT_CTRL_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE
#if CONFIG_BT_CTRL_SLEEP_ETM_TRIGGERED_RF
static esp_err_t btdm_lp_del_etm_event(esp_etm_event_t *event)
{
free(event);
return ESP_OK;
}
static esp_err_t btdm_lp_del_etm_task(esp_etm_task_t *task)
{
free(task);
return ESP_OK;
}
static int btdm_lp_new_etm_event(void)
{
s_btdm_lp_etm_event = btdm_osal_malloc(sizeof(esp_etm_event_t), 0);
if (!s_btdm_lp_etm_event) {
goto err;
}
s_btdm_lp_etm_event->event_id = MODEM_EVT_G0;
s_btdm_lp_etm_event->del = btdm_lp_del_etm_event;
s_btdm_lp_etm_event->trig_periph = ETM_TRIG_PERIPH_MODEM;
return 0;
err:
if (s_btdm_lp_etm_event) {
btdm_lp_del_etm_event(s_btdm_lp_etm_event);
}
return -1;
}
static int btdm_lp_new_etm_task(void)
{
s_btdm_lp_etm_task = btdm_osal_malloc(sizeof(esp_etm_task_t), 0);
if (!s_btdm_lp_etm_task) {
goto err;
}
s_btdm_lp_etm_task->task_id = REGDMA_TASK_START0;
s_btdm_lp_etm_task->del = btdm_lp_del_etm_task;
s_btdm_lp_etm_task->trig_periph = ETM_TRIG_PERIPH_MODEM;
return 0;
err:
if (s_btdm_lp_etm_task) {
btdm_lp_del_etm_task(s_btdm_lp_etm_task);
}
return -1;
}
static int btdm_lp_soc_etm_configure_init(void)
{
int rc;
esp_etm_channel_config_t etm_config = {.flags.allow_pd = 1,};
if (s_btdm_lp_etm_channel) {
return 0;
}
rc = 0;
rc = btdm_lp_new_etm_event();
if(rc != 0) {
return rc;
}
rc = btdm_lp_new_etm_task();
if(rc != 0) {
return rc;
}
rc = esp_etm_new_channel(&etm_config, &s_btdm_lp_etm_channel);
if(rc != 0) {
return rc;
}
rc = esp_etm_channel_connect(s_btdm_lp_etm_channel, s_btdm_lp_etm_event, s_btdm_lp_etm_task);
if(rc != 0) {
return rc;
}
rc = esp_etm_channel_enable(s_btdm_lp_etm_channel);
return rc;
}
static void btdm_lp_soc_etm_configure_deinit(void)
{
int rc;
if (s_btdm_lp_etm_task) {
rc = esp_etm_del_task(s_btdm_lp_etm_task);
assert(rc == 0);
s_btdm_lp_etm_task = NULL;
}
if (s_btdm_lp_etm_event) {
rc = esp_etm_del_event(s_btdm_lp_etm_event);
assert(rc == 0);
s_btdm_lp_etm_event = NULL;
}
if (!s_btdm_lp_etm_channel) {
return;
}
esp_etm_channel_disable(s_btdm_lp_etm_channel);
rc = esp_etm_del_channel(s_btdm_lp_etm_channel);
assert(rc == 0);
s_btdm_lp_etm_channel = NULL;
}
static void btdm_lp_soc_etm_set_enable(bool enable)
{
if (!s_btdm_lp_etm_channel) {
return;
}
if (enable) {
esp_etm_channel_enable(s_btdm_lp_etm_channel);
} else {
esp_etm_channel_disable(s_btdm_lp_etm_channel);
}
}
static bool IRAM_ATTR btdm_lp_etm_phy_retention_task_triggered(void)
{
return pau_regdma_check_etm_task_triggered(0);
}
bool IRAM_ATTR btdm_lp_check_phy_etm_task_triggered(void)
{
btdm_lp_soc_etm_set_enable(false);
return btdm_lp_etm_phy_retention_task_triggered();
}
void btdm_lp_disable_etm_phy_retention_task(void)
{
/* Disable the ETM task to prevent the RF enable from being triggered */
btdm_lp_soc_etm_set_enable(false);
}
#endif // CONFIG_BT_CTRL_SLEEP_ETM_TRIGGERED_RF
/*
***************************************************************************************************
* Public Function Definitions
@@ -386,6 +559,8 @@ btdm_lp_disable_clock(void)
int
btdm_lp_init(void)
{
esp_err_t rc = 0;
#if UC_BT_CTRL_SLEEP_ENABLE
ESP_LOGI(BTDM_LOG_TAG, "Bluetooth modem sleep is enabled");
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
@@ -398,8 +573,6 @@ btdm_lp_init(void)
#endif // UC_BT_CTRL_SLEEP_ENABLE
#ifdef CONFIG_PM_ENABLE
esp_err_t rc = 0;
rc = esp_pm_lock_create(ESP_PM_CPU_FREQ_MAX, 0, "bt", &s_pm_lock);
if (rc != ESP_OK) {
return -1;
@@ -413,22 +586,31 @@ btdm_lp_init(void)
rc = esp_pm_register_inform_out_light_sleep_overhead_callback(r_btdm_sleep_wake_up_overhead_set);
if (rc != ESP_OK) {
return -2;
return -3;
}
rc = esp_pm_register_skip_light_sleep_callback(r_btdm_sleep_should_skip_light_sleep_check);
if (rc != ESP_OK) {
return -3;
return -4;
}
#endif /* UC_BT_CTRL_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE */
#endif /* CONFIG_PM_ENABLE */
#if CONFIG_BT_CTRL_SLEEP_ETM_TRIGGERED_RF
rc = btdm_lp_soc_etm_configure_init();
if (rc != ESP_OK) {
return -5;
}
#endif // CONFIG_BT_CTRL_SLEEP_ETM_TRIGGERED_RF
r_btdm_hal_rtc_freq_set(s_bt_lpclk_freq);
return 0;
return rc;
}
void
btdm_lp_deinit(void)
{
#if CONFIG_BT_CTRL_SLEEP_ETM_TRIGGERED_RF
btdm_lp_soc_etm_configure_deinit();
#endif // CONFIG_BT_CTRL_SLEEP_ETM_TRIGGERED_RF
#if UC_BT_CTRL_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE
esp_pm_unregister_skip_light_sleep_callback(r_btdm_sleep_should_skip_light_sleep_check);
esp_pm_unregister_inform_out_light_sleep_overhead_callback(r_btdm_sleep_wake_up_overhead_set);
@@ -511,3 +693,17 @@ e_btdm_lp_modem_clock_set(bool enable)
}
}
}
void IRAM_ATTR e_btdm_sleep_etm_rf_prepare(void)
{
#if CONFIG_BT_CTRL_SLEEP_ETM_TRIGGERED_RF
if (!btdm_lp_etm_phy_retention_task_triggered()) {
pau_regdma_set_etm_modem_link_config();
if (!s_btdm_lp_phy_clk_en) {
/* Set phy clock ref to prevent unwanted phy clock disable during RF enable */
modem_clock_module_enable(PERIPH_PHY_MODULE);
s_btdm_lp_phy_clk_en = 1;
}
}
#endif //CONFIG_BT_CTRL_SLEEP_ETM_TRIGGERED_RF
}
@@ -0,0 +1,51 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdlib.h>
#include <stdbool.h>
#include "soc/soc.h"
#include "soc/soc_etm_struct.h"
#include "soc/soc_etm_reg.h"
#ifdef __cplusplus
extern "C" {
#endif
static inline bool pau_etm_ll_get_regdma_event_done_status(int index)
{
return SOC_ETM.etm_evt_st4.val & (SOC_ETM_REGDMA_EVT_DONE0_ST << index);
}
static inline bool pau_etm_ll_get_regdma_event_err_status(int index)
{
return SOC_ETM.etm_evt_st4.val & (SOC_ETM_REGDMA_EVT_ERR0_ST << index);
}
static inline bool pau_etm_ll_get_regdma_task_start_status(int index)
{
return SOC_ETM.etm_task_st4.val & (SOC_ETM_REGDMA_TASK_START0_ST << index);
}
static inline void pau_etm_ll_clear_regdma_event_done_status(int index)
{
SOC_ETM.etm_evt_st4_clr.val = SOC_ETM_REGDMA_EVT_DONE0_ST << index;
}
static inline void pau_etm_ll_clear_regdma_event_err_status(int index)
{
SOC_ETM.etm_evt_st4_clr.val = SOC_ETM_REGDMA_EVT_ERR0_ST << index;
}
static inline void pau_etm_ll_clear_regdma_task_start_status(int index)
{
SOC_ETM.etm_task_st4_clr.val = SOC_ETM_REGDMA_TASK_START0_ST << index;
}
#ifdef __cplusplus
}
#endif
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -222,6 +222,21 @@ static inline void pau_ll_set_regdma_link_wait_read_interval(int interval)
HAL_FORCE_MODIFY_U32_REG_FIELD(LP_AON.backup_dma_cfg0, aon_read_interval_aon, interval);
}
static inline void pau_ll_select_regdma_etm_entry_link0(pau_dev_t *dev, int link)
{
dev->regdma_etm_ctrl.etm_link_sel_0 &= ~0xF;
dev->regdma_etm_ctrl.etm_link_sel_0 |= (link & 0xF);
}
static inline void pau_ll_set_regdma_etm_entry_link0_backup_direction(pau_dev_t *dev, bool to_mem)
{
if (to_mem) {
dev->regdma_etm_ctrl.etm_link_sel_0 |= BIT(4);
} else {
dev->regdma_etm_ctrl.etm_link_sel_0 &= ~BIT(4);
}
}
#ifdef __cplusplus
}
#endif
+54 -1
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -11,12 +11,42 @@
#include "hal/pau_hal.h"
#include "hal/pau_types.h"
#include "hal/lp_aon_ll.h"
#include "hal/pau_etm_ll.h"
void pau_hal_set_regdma_entry_link_addr(pau_hal_context_t *hal, pau_regdma_link_addr_t *link_addr)
{
pau_ll_set_regdma_link_addr((uint32_t)(*link_addr)[0]);
}
void IRAM_ATTR pau_hal_regdma_wait_done(pau_hal_context_t *hal)
{
while (!(pau_ll_get_regdma_intr_raw_signal(hal->dev) & PAU_DONE_INT_RAW));
}
void IRAM_ATTR pau_hal_start_regdma_modem_link(pau_hal_context_t *hal, bool backup_or_restore, bool blocking)
{
pau_ll_clear_regdma_backup_done_intr_state(hal->dev);
pau_ll_select_regdma_entry_link(hal->dev, SOC_PM_PAU_REGDMA_LINK_IDX_PHY);
pau_ll_set_regdma_entry_link_backup_direction(hal->dev, backup_or_restore);
pau_ll_set_regdma_entry_link_backup_start_enable(hal->dev, true);
if (blocking) {
pau_hal_regdma_wait_done(hal);
}
}
bool IRAM_ATTR pau_hal_get_regdma_done_status(pau_hal_context_t *hal)
{
return (pau_ll_get_regdma_intr_status(hal->dev) & 0x1);
}
void IRAM_ATTR pau_hal_stop_regdma_modem_link(pau_hal_context_t *hal)
{
pau_ll_set_regdma_entry_link_backup_start_enable(hal->dev, false);
pau_ll_select_regdma_entry_link(hal->dev, 0); /* restore link select to default */
pau_ll_clear_regdma_backup_done_intr_state(hal->dev);
}
void IRAM_ATTR pau_hal_start_regdma_extra_link(pau_hal_context_t *hal, bool backup_or_restore)
{
pau_ll_clear_regdma_backup_done_intr_state(hal->dev);
@@ -61,3 +91,26 @@ void pau_hal_set_regdma_wait_timeout(pau_hal_context_t *hal, int count, int inte
pau_ll_set_regdma_link_wait_retry_count(count);
pau_ll_set_regdma_link_wait_read_interval(interval);
}
void IRAM_ATTR pau_hal_set_etm_modem_link_config(pau_hal_context_t *hal)
{
pau_ll_clear_regdma_backup_done_intr_state(hal->dev);
pau_ll_select_regdma_etm_entry_link0(hal->dev, SOC_PM_PAU_REGDMA_LINK_IDX_PHY);
pau_ll_set_regdma_etm_entry_link0_backup_direction(hal->dev, false);
}
void IRAM_ATTR pau_hal_stop_etm_modem_link(pau_hal_context_t *hal)
{
pau_ll_select_regdma_etm_entry_link0(hal->dev, 0); /* restore link select to default */
pau_ll_clear_regdma_backup_done_intr_state(hal->dev);
}
bool IRAM_ATTR pau_hal_check_etm_task_triggered(pau_hal_context_t *hal, uint8_t index)
{
return pau_etm_ll_get_regdma_task_start_status(index);
}
void IRAM_ATTR pau_hal_clear_etm_task_triggered(pau_hal_context_t *hal, uint8_t index)
{
pau_etm_ll_clear_regdma_task_start_status(index);
}
@@ -124,6 +124,21 @@ static inline void pau_ll_clear_regdma_backup_error_intr_state(pau_dev_t *dev)
dev->int_clr.error_int_clr = 1;
}
static inline void pau_ll_select_regdma_etm_entry_link0(pau_dev_t *dev, int link)
{
dev->regdma_etm_ctrl.etm_link_sel_0 &= ~0x7;
dev->regdma_etm_ctrl.etm_link_sel_0 |= (link & 0x7);
}
static inline void pau_ll_set_regdma_etm_entry_link0_backup_direction(pau_dev_t *dev, bool to_mem)
{
if (to_mem) {
dev->regdma_etm_ctrl.etm_link_sel_0 |= BIT(3);
} else {
dev->regdma_etm_ctrl.etm_link_sel_0 &= ~BIT(3);
}
}
#ifdef __cplusplus
}
#endif
+13
View File
@@ -109,3 +109,16 @@ void pau_hal_set_regdma_wait_timeout(pau_hal_context_t *hal, int count, int inte
lp_sys_ll_set_pau_link_wait_tout_thres(count);
lp_sys_ll_set_pau_reg_read_interval(interval);
}
void IRAM_ATTR pau_hal_set_etm_modem_link_config(pau_hal_context_t *hal)
{
pau_ll_clear_regdma_backup_done_intr_state(hal->dev);
pau_ll_select_regdma_etm_entry_link0(hal->dev, SOC_PM_PAU_REGDMA_LINK_IDX_PHY);
pau_ll_set_regdma_etm_entry_link0_backup_direction(hal->dev, false);
}
void IRAM_ATTR pau_hal_stop_etm_modem_link(pau_hal_context_t *hal)
{
pau_ll_select_regdma_etm_entry_link0(hal->dev, 0); /* restore link select to default */
pau_ll_clear_regdma_backup_done_intr_state(hal->dev);
}
@@ -213,6 +213,38 @@ void pau_hal_set_regdma_wait_timeout(pau_hal_context_t *hal, int count, int inte
void pau_hal_lp_sys_initialize(void);
#endif
#if SOC_PM_SUPPORT_REGDMA_TRIGGERED_PHY
/**
* @brief Set the configuration of the REGDMA etm modem link
*
* @param hal regdma hal context
*/
void pau_hal_set_etm_modem_link_config(pau_hal_context_t *hal);
/**
* @brief Stop transmission on REGDMA etm modem link
*
* @param hal regdma hal context
*/
void pau_hal_stop_etm_modem_link(pau_hal_context_t *hal);
/**
* @brief Check if the ETM task is triggered
*
* @param hal regdma hal context
* @param index the index of the ETM task
*/
bool pau_hal_check_etm_task_triggered(pau_hal_context_t *hal, uint8_t index);
/**
* @brief Clear the ETM task triggered status
*
* @param hal regdma hal context
* @param index the index of the ETM task
*/
void pau_hal_clear_etm_task_triggered(pau_hal_context_t *hal, uint8_t index);
#endif // SOC_PM_SUPPORT_REGDMA_TRIGGERED_PHY
#endif
#ifdef __cplusplus
@@ -157,6 +157,36 @@ void pau_regdma_register_modem_link_protect(pau_regdma_modem_link_protect_cb_t c
void pau_regdma_unregister_modem_link_protect(void);
#endif // SOC_PM_REGDMA_MODEM_LINK_PROTECT
#if SOC_PM_SUPPORT_REGDMA_TRIGGERED_PHY
/**
* @brief Wait for REGDMA to complete
*/
void pau_regdma_wait_work_done(void);
/**
* @brief Check if the REGDMA task is triggered
* @param index the index of the task
* @return true if the task is triggered, false otherwise
*/
bool pau_regdma_check_etm_task_triggered(uint8_t index);
/**
* @brief Clear the REGDMA task triggered status
* @param index the index of the task
*/
void pau_regdma_clear_etm_task_triggered(uint8_t index);
/**
* @brief Set the configuration of the REGDMA etm modem link
*/
void pau_regdma_set_etm_modem_link_config(void);
/**
* @brief Stop transmission on REGDMA etm modem link
*/
void pau_regdma_stop_etm_modem_link(void);
#endif // SOC_PM_SUPPORT_REGDMA_TRIGGERED_PHY
#ifdef __cplusplus
}
#endif
@@ -285,6 +285,7 @@ esp_err_t sleep_phy_link_deinit(void *link_context);
* @param flags A bitmap to indicate the PHY link regdma description configuration flag
*/
void sleep_phy_link_config(void *link_context, uint32_t flags);
#endif /* SOC_PM_SUPPORT_REGDMA_TRIGGERED_PHY */
#ifdef __cplusplus
@@ -0,0 +1,164 @@
/*
* SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/soc_caps.h"
#include "modem/i2c_ana_mst_reg.h"
#include "soc/apb_saradc_reg.h"
#include "soc/pmu_reg.h"
#include "soc/pcr_reg.h"
#include "esp_check.h"
#include "modem/modem_syscon_reg.h"
#include "modem/modem_lpcon_reg.h"
#include "esp_private/esp_pau.h"
#include "esp_private/sleep_modem.h"
#include "esp_private/sleep_retention.h"
#include "soc/gpio_reg.h"
#if SOC_PM_SUPPORT_REGDMA_TRIGGERED_PHY
#define FECOEX_SET_FREQ_SET_FREQ_REG (0x600C001c)
#define FECOEX_SET_FREQ_EN_SW (BIT(19))
#define FECOEX_FREQ_CTRL1_REG (0x600C0020)
#define FECOEX_SET_FREQ_RESETN (BIT(18))
#define FECOEX_SET_FREQ_SET_FREQ_ST_REG (0x600c0028)
#define FECOEX_SET_FREQ_DONE (BIT(8))
#define FECOEX_BT_CHAN_FORCE_START (2)
#define FECOEX_BT_CHAN_FORCE_END (3)
#define FECOEX_BT_CHAN_FORCE_MASK (0x3)
#define PCR_SDM_INV_PHASE_CONF_REG (0x60094184)
#define PCR_CLK_SDM_EN (BIT(10))
ESP_LOG_ATTR_TAG(TAG, "sleep_phy");
typedef struct {
#define DESC_IDX_I2C_MST_ENA (0)
#define DESC_IDX_I2C_MST_DIS (1)
#define DESC_MODEM_SYSCON_CLK_EN (2)
#define DESC_MODEM_SYSCON_CLK_DIS (3)
void *regdma_desc[DESC_MODEM_SYSCON_CLK_DIS + 1];
} sleep_phy_link_context_t;
#define SYSCON_FE_CLOCK_MSK (MODEM_SYSCON_CLK_FE_APB_EN|MODEM_SYSCON_CLK_FE_32M_EN|MODEM_SYSCON_CLK_FE_SDM_EN|MODEM_SYSCON_CLK_FE_ADC_EN|MODEM_SYSCON_CLK_FE_16M_EN|MODEM_SYSCON_CLK_FE_TXLOGAIN_EN)
esp_err_t sleep_phy_retention_init(void *args)
{
#define PHY_ENTRY() (BIT(SOC_PM_PAU_REGDMA_LINK_IDX_PHY))
static const sleep_retention_entries_config_t phy_modem_config_template[] = {
/* Open modem clock for PHY */
[0] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x00), MODEM_LPCON_CLK_CONF_REG, MODEM_LPCON_CLK_I2C_MST_EN, MODEM_LPCON_CLK_I2C_MST_EN_M, 1, 0), .owner = PHY_ENTRY() }, /* I2C MST enable */
[1] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x01), MODEM_SYSCON_CLK_CONF1_REG, SYSCON_FE_CLOCK_MSK, SYSCON_FE_CLOCK_MSK, 1, 0), .owner = PHY_ENTRY() }, /* FE clock */
[2] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x02), FECOEX_FREQ_CTRL1_REG, 0, FECOEX_SET_FREQ_RESETN, 1, 0), .owner = PHY_ENTRY() },
[3] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x03), PCR_SDM_INV_PHASE_CONF_REG, PCR_CLK_SDM_EN, PCR_CLK_SDM_EN, 1, 0), .owner = PHY_ENTRY() }, /* PCR */
[4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_PHY_LINK(0x04), I2C_ANA_MST_I2C0_CTRL1_REG, I2C_ANA_MST_I2C0_CTRL1_REG, 3, 0, 0), .owner = PHY_ENTRY() },
/* PMU or software to trigger enable RF PHY */
[5] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x05), I2C_ANA_MST_ANA_CONF0_REG, 0, BIT(6), 1, 0), .owner = PHY_ENTRY() }, /* BBPLL calibration enable */
[6] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x06), PMU_RF_PWC_REG, 0xfc000000, 0xfc000000, 1, 0), .owner = PHY_ENTRY() },
[7] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x07), I2C_ANA_MST_ANA_CONF0_REG, BIT(6), BIT(6), 1, 0), .owner = PHY_ENTRY() }, /* BBPLL calibration enable */
[8] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x08), PCR_TSENS_CLK_CONF_REG, PCR_TSENS_CLK_EN, PCR_TSENS_CLK_EN, 1, 0), .owner = PHY_ENTRY() },
[9] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x09), APB_SARADC_APB_TSENS_CTRL_REG, APB_SARADC_TSENS_PU, APB_SARADC_TSENS_PU, 1, 0), .owner = PHY_ENTRY() },
[10] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x0a), I2C_ANA_MST_I2C_BURST_CONF_REG, 0, 0xffffffff, 1, 0), .owner = PHY_ENTRY() },
[11] = { .config = REGDMA_LINK_WAIT_INIT (REGDMA_PHY_LINK(0x0b), I2C_ANA_MST_I2C_BURST_STATUS_REG, I2C_ANA_MST_I2C_MST_BURST_DONE, I2C_ANA_MST_I2C_MST_BURST_DONE, 1, 0), .owner = PHY_ENTRY() },
[12] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x0c), FECOEX_FREQ_CTRL1_REG, FECOEX_SET_FREQ_RESETN, FECOEX_SET_FREQ_RESETN, 1, 0), .owner = PHY_ENTRY() },
[13] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x0d), FECOEX_SET_FREQ_SET_FREQ_ST_REG, FECOEX_BT_CHAN_FORCE_START,FECOEX_BT_CHAN_FORCE_MASK, 1, 0), .owner = PHY_ENTRY() },
[14] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x0e), FECOEX_SET_FREQ_SET_FREQ_REG, FECOEX_SET_FREQ_EN_SW, FECOEX_SET_FREQ_EN_SW, 1, 0), .owner = PHY_ENTRY() },
[15] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x0f), FECOEX_SET_FREQ_SET_FREQ_REG, 0, FECOEX_SET_FREQ_EN_SW, 1, 0), .owner = PHY_ENTRY() },
[16] = { .config = REGDMA_LINK_WAIT_INIT (REGDMA_PHY_LINK(0x10), FECOEX_SET_FREQ_SET_FREQ_ST_REG, FECOEX_SET_FREQ_DONE, FECOEX_SET_FREQ_DONE, 1, 0), .owner = PHY_ENTRY() },
[17] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x11), FECOEX_SET_FREQ_SET_FREQ_ST_REG, FECOEX_BT_CHAN_FORCE_END, FECOEX_BT_CHAN_FORCE_MASK, 1, 0), .owner = PHY_ENTRY() },
/* PMU or software to trigger disable RF PHY */
[18] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x12), FECOEX_SET_FREQ_SET_FREQ_REG, 0, FECOEX_SET_FREQ_EN_SW, 0, 1), .owner = PHY_ENTRY() },
/* PMU or software to trigger disable RF PHY */
[19] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x13), I2C_ANA_MST_I2C_BURST_CONF_REG, 0, 0xffffffff, 0, 1), .owner = PHY_ENTRY() },
[20] = { .config = REGDMA_LINK_WAIT_INIT (REGDMA_PHY_LINK(0x14), I2C_ANA_MST_I2C_BURST_STATUS_REG, I2C_ANA_MST_I2C_MST_BURST_DONE, I2C_ANA_MST_I2C_MST_BURST_DONE, 0, 1), .owner = PHY_ENTRY() },
[21] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x15), APB_SARADC_APB_TSENS_CTRL_REG, 0, APB_SARADC_TSENS_PU,0, 1), .owner = PHY_ENTRY() },
[22] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x16), PCR_TSENS_CLK_CONF_REG, 0, PCR_TSENS_CLK_EN, 0, 1), .owner = PHY_ENTRY() }, /* PCR */
[23] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x17), PMU_RF_PWC_REG, 0x8c000000, 0xfc000000, 0, 1), .owner = PHY_ENTRY() },
[24] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x18), PCR_SDM_INV_PHASE_CONF_REG, 0, PCR_CLK_SDM_EN, 0, 1), .owner = PHY_ENTRY() }, /* PCR */
[25] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x19), MODEM_SYSCON_CLK_CONF1_REG, 0, MODEM_SYSCON_CLK_FE_TXLOGAIN_EN, 0, 1), .owner = PHY_ENTRY() }, /* FE clock */
[26] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x1a), MODEM_LPCON_CLK_CONF_REG, 0, MODEM_LPCON_CLK_I2C_MST_EN_M, 0, 1), .owner = PHY_ENTRY() }, /* I2C MST disable */
[27] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x1b), PMU_SLP_WAKEUP_CNTL7_REG, 0x200000, 0xffff0000, 1, 0), .owner = PHY_ENTRY() },
[28] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x1c), PMU_SLP_WAKEUP_CNTL7_REG, 0x9730000, 0xffff0000, 0, 1), .owner = PHY_ENTRY() },
};
sleep_retention_entries_config_t *phy_modem_config = malloc(sizeof(phy_modem_config_template));
if (phy_modem_config == NULL) {
return ESP_ERR_NO_MEM;
}
memcpy(phy_modem_config, phy_modem_config_template, sizeof(phy_modem_config_template));
extern uint32_t phy_ana_i2c_master_burst_rf_onoff(bool on);
phy_modem_config[0x0a].config.write_wait.value = phy_ana_i2c_master_burst_rf_onoff(true);
phy_modem_config[0x13].config.write_wait.value = phy_ana_i2c_master_burst_rf_onoff(false);
esp_err_t err = sleep_retention_entries_create(phy_modem_config, ARRAY_SIZE(phy_modem_config_template), 5, SLEEP_RETENTION_MODULE_MODEM_PHY);
free(phy_modem_config);
ESP_RETURN_ON_ERROR(err, TAG, "failed to init modem phy link");
return err;
}
esp_err_t sleep_phy_link_init(void **link_context)
{
esp_err_t err = ESP_OK;
#if SOC_PM_PAU_REGDMA_LINK_IDX_PHY
sleep_retention_module_init_param_t init_param = { .cbs = { .create = { .handle = sleep_phy_retention_init, .arg = NULL } } };
err = sleep_retention_module_init(SLEEP_RETENTION_MODULE_MODEM_PHY, &init_param);
if (err == ESP_OK) {
err = sleep_retention_module_allocate(SLEEP_RETENTION_MODULE_MODEM_PHY);
if (err == ESP_OK) {
const int id_array[] = { REGDMA_PHY_LINK(0x00), REGDMA_PHY_LINK(0x1a), /* I2C MST CLK entries */
REGDMA_PHY_LINK(0x01), REGDMA_PHY_LINK(0x19), /* FE modem clock entries */
};
static DRAM_ATTR sleep_phy_link_context_t phy_link_context;
for (int i = 0; (err == ESP_OK) && (i < ARRAY_SIZE(phy_link_context.regdma_desc)); i++) {
void *desc = sleep_retention_find_link_by_id(id_array[i]);
if (desc) {
phy_link_context.regdma_desc[i] = desc;
} else {
err = ESP_ERR_NOT_FOUND;
ESP_LOGE(TAG, "failed to find modem phy link: %x", id_array[i]);
}
}
if (err == ESP_OK) {
*link_context = (void *)&phy_link_context;
}
} else {
ESP_LOGE(TAG, "failed to allocate modem phy link");
}
}
if (err != ESP_OK) {
sleep_phy_link_deinit(NULL);
}
#endif
return err;
}
void IRAM_ATTR sleep_phy_link_config(void *link_context, uint32_t flags)
{
#if SOC_PM_PAU_REGDMA_LINK_IDX_PHY
sleep_phy_link_context_t *phy_link_context = (sleep_phy_link_context_t *)link_context;
if (flags & SLEEP_MODEM_SKIP_I2C_MST_CLK_RETENTION) {
regdma_link_set_skip_flag(phy_link_context->regdma_desc[DESC_IDX_I2C_MST_ENA], true, true);
regdma_link_set_skip_flag(phy_link_context->regdma_desc[DESC_IDX_I2C_MST_DIS], true, true);
regdma_link_set_skip_flag(phy_link_context->regdma_desc[DESC_MODEM_SYSCON_CLK_EN], true, true);
regdma_link_set_skip_flag(phy_link_context->regdma_desc[DESC_MODEM_SYSCON_CLK_DIS], true, true);
} else {
regdma_link_set_skip_flag(phy_link_context->regdma_desc[DESC_IDX_I2C_MST_ENA], true, false);
regdma_link_set_skip_flag(phy_link_context->regdma_desc[DESC_IDX_I2C_MST_DIS], false, true);
regdma_link_set_skip_flag(phy_link_context->regdma_desc[DESC_MODEM_SYSCON_CLK_EN], true, false);
regdma_link_set_skip_flag(phy_link_context->regdma_desc[DESC_MODEM_SYSCON_CLK_DIS], false, true);
}
#endif // SOC_PM_PAU_REGDMA_LINK_IDX_PHY
}
esp_err_t sleep_phy_link_deinit(void *link_head)
{
#if SOC_PM_PAU_REGDMA_LINK_IDX_PHY
sleep_retention_module_free(SLEEP_RETENTION_MODULE_MODEM_PHY);
sleep_retention_module_deinit(SLEEP_RETENTION_MODULE_MODEM_PHY);
#endif
return ESP_OK;
}
#endif /* SOC_PM_SUPPORT_REGDMA_TRIGGERED_PHY */
@@ -99,7 +99,7 @@ static esp_err_t sleep_phy_retention_init(void *arg)
extern uint32_t phy_ana_i2c_master_burst_rf_onoff(bool on);
phy_modem_config[4].config.write_wait.value = phy_ana_i2c_master_burst_rf_onoff(true);
phy_modem_config[15].config.write_wait.value = phy_ana_i2c_master_burst_rf_onoff(false);
esp_err_t err = sleep_retention_entries_create(phy_modem_config, ARRAY_SIZE(phy_modem_config_template), 7, SLEEP_RETENTION_MODULE_MODEM_PHY);
esp_err_t err = sleep_retention_entries_create(phy_modem_config, ARRAY_SIZE(phy_modem_config_template), 5, SLEEP_RETENTION_MODULE_MODEM_PHY);
free(phy_modem_config);
ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate modem phy link");
return ESP_OK;
@@ -234,3 +234,30 @@ bool IRAM_ATTR pau_regdma_enable_aon_link_entry(bool enable)
return origin_bypass_en;
}
#endif
#if SOC_PM_SUPPORT_REGDMA_TRIGGERED_PHY
void IRAM_ATTR pau_regdma_set_etm_modem_link_config(void)
{
pau_hal_set_etm_modem_link_config(PAU_instance()->hal);
}
void IRAM_ATTR pau_regdma_stop_etm_modem_link(void)
{
pau_hal_stop_etm_modem_link(PAU_instance()->hal);
}
void IRAM_ATTR pau_regdma_wait_work_done(void)
{
pau_hal_regdma_wait_done(PAU_instance()->hal);
}
bool IRAM_ATTR pau_regdma_check_etm_task_triggered(uint8_t index)
{
return pau_hal_check_etm_task_triggered(PAU_instance()->hal, index);
}
void IRAM_ATTR pau_regdma_clear_etm_task_triggered(uint8_t index)
{
pau_hal_clear_etm_task_triggered(PAU_instance()->hal, index);
}
#endif // SOC_PM_SUPPORT_REGDMA_TRIGGERED_PHY
+4 -5
View File
@@ -219,7 +219,6 @@ inline __attribute__((always_inline)) bool sleep_modem_phy_link_done(void)
{
return (s_sleep_modem.phy_link_done == 1);
}
#endif /* SOC_PM_SUPPORT_REGDMA_TRIGGERED_PHY */
bool modem_domain_pd_allowed(void)
@@ -257,21 +256,21 @@ bool modem_domain_pd_allowed(void)
uint32_t sleep_modem_reject_triggers(void)
{
uint32_t reject_triggers = 0;
#if SOC_PM_SUPPORT_PMU_MODEM_STATE
#if SOC_PM_SUPPORT_PMU_MODEM_STATE && SOC_WIFI_SUPPORTED
reject_triggers = sleep_modem_wifi_modem_state_is_enabled() ? PMU_MODEM_WAKEUP_PROTECT : 0;
#endif /* SOC_PM_SUPPORT_PMU_MODEM_STATE */
#endif /* SOC_PM_SUPPORT_PMU_MODEM_STATE && SOC_WIFI_SUPPORTED */
return reject_triggers;
}
bool IRAM_ATTR sleep_modem_wifi_modem_state_skip_light_sleep(void)
{
bool skip = false;
#if SOC_PM_SUPPORT_PMU_MODEM_STATE
#if SOC_PM_SUPPORT_PMU_MODEM_STATE && SOC_WIFI_SUPPORTED
/* To block the system from entering sleep before modem link done. In light
* sleep mode, the system may switch to modem state, which will cause
* hardware to fail to enable RF */
skip = sleep_modem_wifi_modem_state_is_enabled() && !sleep_modem_phy_link_done();
#endif /* SOC_PM_SUPPORT_PMU_MODEM_STATE */
#endif /* SOC_PM_SUPPORT_PMU_MODEM_STATE && SOC_WIFI_SUPPORTED */
return skip;
}
+3
View File
@@ -29,6 +29,9 @@ if(CONFIG_ESP_PHY_ENABLED)
if(CONFIG_SOC_IEEE802154_BLE_ONLY)
list(APPEND srcs "src/phy_init_esp32hxx.c")
if(CONFIG_SOC_PM_SUPPORT_REGDMA_TRIGGERED_PHY)
list(APPEND srcs "${idf_target}/phy_init_data.c")
endif()
else()
list(APPEND srcs "src/phy_init.c")
list(APPEND srcs "${idf_target}/phy_init_data.c")
@@ -0,0 +1,63 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "sdkconfig.h"
#include "soc/soc_caps.h"
#include "phy_init_data.h"
#include "esp_private/phy.h"
#include "esp_check.h"
#if SOC_PM_MODEM_RETENTION_BY_REGDMA && CONFIG_ESP_PHY_HW_SWITCH_RF
#include "esp_private/sleep_retention.h"
static const char* TAG = "phy_sleep";
static esp_err_t sleep_retention_phy_fe_init(void *arg)
{
#define REG_FECOEX_BASE 0x600C0000
#define REG_FECTRL_BASE 0x600C0800
#define REG_FEDATA_BASE 0x600C0400
#define REG_FEDATABLE_BASE 0x600C0C00
#define N_REGS_FE_COEX() (11)
#define N_REGS_FE_CTRL() (26)
#define N_REGS_FE_DATA() (8)
#define N_REGS_FE_DATA_BLE() (2)
const static sleep_retention_entries_config_t phy_fe_regs_retention[] = {
#define PHY_ENTRY() (BIT(SOC_PM_PAU_REGDMA_LINK_IDX_PHY))
[0] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_MODEM_FE_LINK(0), REG_FECOEX_BASE, REG_FECOEX_BASE, N_REGS_FE_COEX(), 0, 0, 0x147e89, 0x0, 0x0, 0x0), .owner = PHY_ENTRY() },
[1] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_MODEM_FE_LINK(1), REG_FECTRL_BASE, REG_FECTRL_BASE, N_REGS_FE_CTRL(), 0, 0, 0x370e100b, 0x7ff8084, 0x0, 0x0), .owner = PHY_ENTRY() },
[2] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_MODEM_FE_LINK(2), REG_FEDATA_BASE, REG_FEDATA_BASE, N_REGS_FE_DATA(), 0, 0, 0x6b805, 0x0, 0x0, 0x0), .owner = PHY_ENTRY() },
[3] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_MODEM_FE_LINK(3), REG_FEDATABLE_BASE, REG_FEDATABLE_BASE, N_REGS_FE_DATA_BLE(), 0, 0, 0x3, 0x0, 0x0, 0x0), .owner = PHY_ENTRY() },
};
esp_err_t err = sleep_retention_entries_create(phy_fe_regs_retention, ARRAY_SIZE(phy_fe_regs_retention), 3, SLEEP_RETENTION_MODULE_PHY_FE);
ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for modem (%s) retention", "PHY FE");
ESP_LOGD(TAG, "PHY FE sleep retention initialization");
return ESP_OK;
}
esp_err_t esp_phy_fe_sleep_data_init(void)
{
sleep_retention_module_init_param_t init_param = {
.cbs = { .create = { .handle = sleep_retention_phy_fe_init, .arg = NULL } },
.attribute = SLEEP_RETENTION_MODULE_ATTR_PASSIVE | SLEEP_RETENTION_MODULE_ATTR_ATTACH
};
esp_err_t err = sleep_retention_module_init(SLEEP_RETENTION_MODULE_PHY_FE, &init_param);
if (err != ESP_OK) {
ESP_LOGW(TAG, "PHY FE sleep retention init failed");
return err;
}
return ESP_OK;
}
void esp_phy_fe_sleep_data_deinit(void)
{
esp_err_t err = sleep_retention_module_deinit(SLEEP_RETENTION_MODULE_PHY_FE);
if (err != ESP_OK) {
ESP_LOGW(TAG, "PHY FE sleep retention deinit failed");
}
}
#endif // SOC_PM_MODEM_RETENTION_BY_REGDMA && CONFIG_ESP_PHY_HW_SWITCH_RF
+5 -1
View File
@@ -217,7 +217,7 @@ void phy_ant_clr_update_flag(void);
*/
void phy_ant_update(void);
#if SOC_PM_SUPPORT_PMU_MODEM_STATE
#if SOC_PM_SUPPORT_REGDMA_TRIGGERED_PHY
/**
* @brief Get the REGDMA config value of the BBPLL in analog i2c master burst mode
*
@@ -291,6 +291,10 @@ void esp_phy_sleep_data_deinit(void);
*/
void phy_wait_freq_hw_hop_done(void);
#if SOC_PM_REGDMA_MODEM_LINK_PROTECT
void phy_regi2c_lock_apply(bool enable);
#endif // SOC_PM_REGDMA_MODEM_LINK_PROTECT
#if CONFIG_ESP_PHY_PLL_TRACK_TEMP_DEBUG
/**
* @brief Set the temperature delta for PHY track pll
-3
View File
@@ -74,9 +74,6 @@ static esp_err_t btbb_sleep_retention_enable(void)
#if (SOC_PM_SUPPORT_PMU_MODEM_STATE && CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP) || CONFIG_ESP_PHY_HW_SWITCH_RF
init_param.depends.bitmap[SLEEP_RETENTION_MODULE_PHY_FE >> 5] |= BIT(SLEEP_RETENTION_MODULE_PHY_FE % 32);
#endif // (SOC_PM_SUPPORT_PMU_MODEM_STATE && CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP) || CONFIG_ESP_PHY_HW_SWITCH_RF
#if SOC_PM_MODEM_LOCK_CLK_WORKAROUND && CONFIG_BT_CTRL_SLEEP_ENABLE
init_param.depends.bitmap[SLEEP_RETENTION_MODULE_POWER >> 5] |= BIT(SLEEP_RETENTION_MODULE_POWER % 32);
#endif
esp_err_t err = sleep_retention_module_init(SLEEP_RETENTION_MODULE_BT_BB, &init_param);
if (err != ESP_OK) {
ESP_LOGW(TAG, "Modem BT BB retention callback register failed");
+22 -1
View File
@@ -54,6 +54,10 @@ typedef struct {
extern void phy_param_track_tot(bool en_wifi, bool en_ble_154);
extern const phy_param_track_result_t* phy_debug_get_track_result();
#if SOC_PM_REGDMA_MODEM_LINK_PROTECT
extern void phy_i2c_enter_critical(void);
extern void phy_i2c_exit_critical(void);
#endif // SOC_PM_REGDMA_MODEM_LINK_PROTECT
static esp_timer_handle_t phy_track_pll_timer;
#if CONFIG_ESP_WIFI_ENABLED
@@ -366,7 +370,7 @@ esp_err_t esp_phy_get_ant(esp_phy_ant_config_t *config)
return ESP_OK;
}
#if SOC_PM_SUPPORT_PMU_MODEM_STATE
#if SOC_PM_SUPPORT_REGDMA_TRIGGERED_PHY
typedef enum {
PHY_I2C_MST_CMD_TYPE_RF_OFF = 0,
PHY_I2C_MST_CMD_TYPE_RF_ON,
@@ -376,8 +380,13 @@ typedef enum {
static uint32_t phy_ana_i2c_master_burst_config(phy_i2c_master_command_attribute_t *attr, int size, phy_i2c_master_command_type_t type)
{
#if CONFIG_IDF_TARGET_ESP32H4
#define I2C0_BURST_VAL(valid, start, end) (((valid) << 15) | ((end) << 7) | (start))
#define I2C1_BURST_VAL(valid, start, end) (((valid) << 31) | ((end) << 23) | ((start) << 16))
#else
#define I2C1_BURST_VAL(en, start, end) (((en) << 31) | ((end) << 22) | ((start) << 16))
#define I2C0_BURST_VAL(en, start, end) (((en) << 15) | ((end) << 6) | ((start) << 0))
#endif // !CONFIG_IDF_TARGET_ESP32H4
uint32_t brust = 0;
for (int i = 0; i < size; i++) {
@@ -436,3 +445,15 @@ __attribute__((weak)) void phy_wait_freq_hw_hop_done(void)
}
return;
}
#if SOC_PM_REGDMA_MODEM_LINK_PROTECT
void IRAM_ATTR phy_regi2c_lock_apply(bool enable)
{
if (enable) {
phy_i2c_enter_critical();
} else {
phy_i2c_exit_critical();
}
}
#endif // SOC_PM_REGDMA_MODEM_LINK_PROTECT
+12 -28
View File
@@ -46,7 +46,7 @@
#if CONFIG_IDF_TARGET_ESP32
#include "soc/dport_reg.h"
#elif SOC_PM_SUPPORT_PMU_MODEM_STATE
#elif SOC_PM_SUPPORT_REGDMA_TRIGGERED_PHY
#include "esp_private/sleep_modem.h"
#endif
#include "hal/efuse_hal.h"
@@ -77,11 +77,6 @@ extern bool pm_get_wifimac_regdma_link_selection(void);
#endif
#endif
#if SOC_PM_REGDMA_MODEM_LINK_PROTECT
extern void phy_i2c_enter_critical(void);
extern void phy_i2c_exit_critical(void);
#endif // SOC_PM_REGDMA_MODEM_LINK_PROTECT
static const char* TAG = "phy_init";
static _lock_t s_phy_access_lock;
@@ -315,16 +310,16 @@ void esp_phy_enable(esp_phy_modem_t modem)
}
bool wifimac_link_is_sel = false;
#if SOC_PM_SUPPORT_PMU_MODEM_STATE && CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP && \
SOC_PM_PAU_REGDMA_LINK_IDX_PHY && SOC_PM_PAU_REGDMA_MODEM_WIFIMAC_WORKAROUND
SOC_PM_PAU_REGDMA_LINK_IDX_PHY && SOC_PM_PAU_REGDMA_MODEM_WIFIMAC_WORKAROUND
/*
* A race exists between SoC wakeup and modem state sleep. After modem initiates sleep,
* SoC may wake up before REGDMA completes RF close, leaving mac_modem_sleep_flag uncleared
* (it depends on regdma done). The stale flag can incorrectly trigger a sleep request
* on the next modem entry, causing abnormal sleep behavior.
*
* Therefore, this workaround ensures that mac_modem_sleep_flag is properly
* cleared by regdma closing RF with wifimac link.
* See WIFI-7246 for details.
* A race exists between SoC wakeup and modem state sleep. After modem initiates sleep,
* SoC may wake up before REGDMA completes RF close, leaving mac_modem_sleep_flag uncleared
* (it depends on regdma done). The stale flag can incorrectly trigger a sleep request
* on the next modem entry, causing abnormal sleep behavior.
*
* Therefore, this workaround ensures that mac_modem_sleep_flag is properly
* cleared by regdma closing RF with wifimac link.
* See WIFI-7246 for details.
*/
wifimac_link_is_sel = pm_get_wifimac_regdma_link_selection();
#endif
@@ -402,7 +397,7 @@ void esp_phy_disable(esp_phy_modem_t modem)
if (!sleep_modem_wifi_modem_state_is_enabled()) {
modem_flags |= SLEEP_MODEM_SKIP_WIFI_RETENTION;
}
bool wifimac_link_is_sel = false;
bool wifimac_link_is_sel = false;
#if SOC_PM_SUPPORT_PMU_MODEM_STATE && CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP && \
SOC_PM_PAU_REGDMA_LINK_IDX_PHY && SOC_PM_PAU_REGDMA_MODEM_WIFIMAC_WORKAROUND
wifimac_link_is_sel = pm_get_wifimac_regdma_link_selection();
@@ -474,17 +469,6 @@ void esp_wifi_bt_power_domain_off(void)
#endif // SOC_PM_SUPPORT_MODEM_PD || SOC_PM_SUPPORT_WIFI_PD
}
#if SOC_PM_REGDMA_MODEM_LINK_PROTECT
void IRAM_ATTR esp_phy_regi2c_lock_apply(bool enable)
{
if (enable) {
phy_i2c_enter_critical();
} else {
phy_i2c_exit_critical();
}
}
#endif // SOC_PM_REGDMA_MODEM_LINK_PROTECT
void esp_phy_modem_init(uint8_t modem)
{
#if SOC_PM_MODEM_RETENTION_BY_BACKUPDMA || CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP || CONFIG_ESP_PHY_HW_SWITCH_RF
@@ -497,7 +481,7 @@ void esp_phy_modem_init(uint8_t modem)
#endif // SOC_PM_MODEM_RETENTION_BY_BACKUPDMA
#if (SOC_PM_SUPPORT_PMU_MODEM_STATE && CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP) || CONFIG_ESP_PHY_HW_SWITCH_RF
#if SOC_PM_REGDMA_MODEM_LINK_PROTECT
pau_regdma_register_modem_link_protect(esp_phy_regi2c_lock_apply);
pau_regdma_register_modem_link_protect(phy_regi2c_lock_apply);
#endif // SOC_PM_REGDMA_MODEM_LINK_PROTECT
if (sleep_modem_phy_init(modem) != ESP_OK) {
ESP_LOGE(TAG, "failed to initialize sleep modem phy");
+106 -4
View File
@@ -10,21 +10,42 @@
#include "esp_private/phy.h"
#include "esp_timer.h"
#include "esp_private/periph_ctrl.h"
#include "esp_log.h"
#if SOC_MODEM_CLOCK_IS_INDEPENDENT
#include "esp_private/esp_modem_clock.h"
#endif
#include "phy_init_deps.h"
#include "esp_private/phy_debug.h"
#if SOC_PM_SUPPORT_REGDMA_TRIGGERED_PHY
#include "esp_private/sleep_modem.h"
#endif // SOC_PM_SUPPORT_REGDMA_TRIGGERED_PHY
#if SOC_PM_REGDMA_MODEM_LINK_PROTECT
#include "esp_private/esp_pau.h"
#endif // SOC_PM_REGDMA_MODEM_LINK_PROTECT
#ifndef PHY_INIT_MODEM_CLOCK_REQUIRED_BITS
#warning "PHY_INIT_MODEM_CLOCK_REQUIRED_BITS not defined; using default value 0"
#define PHY_INIT_MODEM_CLOCK_REQUIRED_BITS 0
#endif
#if CONFIG_ESP_PHY_HW_SWITCH_RF
static const char* TAG = "phy_init";
#if SOC_PM_REGDMA_MODEM_LINK_PROTECT
static uint8_t s_phy_modem_init_ref = 0;
#endif // SOC_PM_REGDMA_MODEM_LINK_PROTECT
#endif // CONFIG_ESP_PHY_HW_SWITCH_RF
static DRAM_ATTR portMUX_TYPE s_phy_int_mux = portMUX_INITIALIZER_UNLOCKED;
extern void phy_version_print(void);
#if CONFIG_BT_CTRL_SLEEP_ETM_TRIGGERED_RF
bool btdm_lp_check_phy_etm_task_triggered(void);
void btdm_lp_disable_etm_phy_retention_task(void);
#endif // CONFIG_BT_CTRL_SLEEP_ETM_TRIGGERED_RF
static _lock_t s_phy_access_lock;
/* Reference count of enabling PHY */
@@ -52,10 +73,34 @@ void IRAM_ATTR phy_exit_critical(uint32_t level)
}
}
#if SOC_PM_SUPPORT_REGDMA_TRIGGERED_PHY
static bool phy_retention_link_is_triggered(void)
{
bool ret = false;
#if CONFIG_BT_CTRL_SLEEP_ETM_TRIGGERED_RF
if (btdm_lp_check_phy_etm_task_triggered()) {
return true;
}
#endif // CONFIG_BT_CTRL_SLEEP_ETM_TRIGGERED_RF
return ret;
}
static void phy_disable_etm_phy_retention_link(void)
{
#if CONFIG_BT_CTRL_SLEEP_ETM_TRIGGERED_RF
btdm_lp_disable_etm_phy_retention_task();
#endif // CONFIG_BT_CTRL_SLEEP_ETM_TRIGGERED_RF
}
#endif // SOC_PM_SUPPORT_REGDMA_TRIGGERED_PHY
void esp_phy_enable(esp_phy_modem_t modem)
{
_lock_acquire(&s_phy_access_lock);
if (phy_get_modem_flag() == 0) {
#if SOC_PM_SUPPORT_REGDMA_TRIGGERED_PHY
phy_disable_etm_phy_retention_link();
#endif // SOC_PM_SUPPORT_REGDMA_TRIGGERED_PHY
#if SOC_MODEM_CLOCK_IS_INDEPENDENT
modem_clock_module_enable(PERIPH_PHY_MODULE);
#endif
@@ -71,7 +116,22 @@ void esp_phy_enable(esp_phy_modem_t modem)
#endif
s_phy_is_enabled = true;
} else {
phy_wakeup_init();
#if SOC_PM_SUPPORT_REGDMA_TRIGGERED_PHY
if (sleep_modem_phy_link_enabled() && sleep_modem_phy_link_done()) {
if (!phy_retention_link_is_triggered()) {
sleep_modem_do_phy_retention(true, false, SLEEP_MODEM_SKIP_I2C_MST_CLK_RETENTION);
}
#if CONFIG_BT_CTRL_SLEEP_ETM_TRIGGERED_RF
else {
pau_regdma_wait_work_done();
pau_regdma_stop_etm_modem_link();
}
#endif // CONFIG_BT_CTRL_SLEEP_ETM_TRIGGERED_RF
} else
#endif // SOC_PM_SUPPORT_REGDMA_TRIGGERED_PHY
{
phy_wakeup_init();
}
}
#if !CONFIG_ESP_PHY_DISABLE_PLL_TRACK
phy_track_pll_init();
@@ -102,9 +162,16 @@ void esp_phy_disable(esp_phy_modem_t modem)
#if !CONFIG_ESP_PHY_DISABLE_PLL_TRACK
phy_track_pll_deinit();
#endif
phy_close_rf();
phy_xpd_tsens();
phy_wait_freq_hw_hop_done();
#if SOC_PM_SUPPORT_REGDMA_TRIGGERED_PHY
if (sleep_modem_phy_link_enabled()) {
sleep_modem_do_phy_retention(false, false, SLEEP_MODEM_SKIP_I2C_MST_CLK_RETENTION);
} else
#endif /* SOC_PM_SUPPORT_REGDMA_TRIGGERED_PHY */
{
phy_close_rf();
phy_xpd_tsens();
phy_wait_freq_hw_hop_done();
}
#if SOC_MODEM_CLOCK_IS_INDEPENDENT
modem_clock_module_disable(PERIPH_PHY_MODULE);
#endif
@@ -116,3 +183,38 @@ _lock_t phy_get_lock(void)
{
return s_phy_access_lock;
}
void esp_phy_modem_init(uint8_t modem)
{
#if CONFIG_ESP_PHY_HW_SWITCH_RF
_lock_acquire(&s_phy_access_lock);
#if SOC_PM_REGDMA_MODEM_LINK_PROTECT
s_phy_modem_init_ref++;
pau_regdma_register_modem_link_protect(phy_regi2c_lock_apply);
#endif // SOC_PM_REGDMA_MODEM_LINK_PROTECT
if (sleep_modem_phy_init(modem) != ESP_OK) {
ESP_LOGE(TAG, "failed to initialize sleep modem phy");
}
_lock_release(&s_phy_access_lock);
#endif // CONFIG_ESP_PHY_HW_SWITCH_RF
}
void esp_phy_modem_deinit(uint8_t modem)
{
#if CONFIG_ESP_PHY_HW_SWITCH_RF
_lock_acquire(&s_phy_access_lock);
#if SOC_PM_REGDMA_MODEM_LINK_PROTECT
if (s_phy_modem_init_ref == 0) {
_lock_release(&s_phy_access_lock);
return;
}
s_phy_modem_init_ref--;
if (s_phy_modem_init_ref == 0) {
pau_regdma_unregister_modem_link_protect();
}
#endif // SOC_PM_REGDMA_MODEM_LINK_PROTECT
sleep_modem_phy_deinit(modem);
_lock_release(&s_phy_access_lock);
#endif // CONFIG_ESP_PHY_HW_SWITCH_RF
}
@@ -1195,6 +1195,18 @@ config SOC_PM_SUPPORT_RTC_PERIPH_PD
bool
default y
config SOC_PM_SUPPORT_REGDMA_TRIGGERED_PHY
bool
default y
config SOC_PM_SUPPORT_PMU_MODEM_STATE
bool
default y
config SOC_PM_REGDMA_MODEM_LINK_PROTECT
bool
default y
config SOC_PM_SUPPORT_PMU_CLK_ICG
bool
default y
@@ -1225,12 +1237,20 @@ config SOC_EXT_MEM_CACHE_TAG_IN_CPU_DOMAIN
config SOC_PM_PAU_LINK_NUM
int
default 4
default 5
config SOC_PM_PAU_REGDMA_LINK_CONFIGURABLE
bool
default y
config SOC_PM_RETENTION_MODULE_NUM
int
default 64
config SOC_PM_PAU_REGDMA_LINK_IDX_PHY
int
default 4
config SOC_PM_TOP_DEPENDS_ON_RTC_PERIPH
bool
default y
@@ -57,6 +57,8 @@ typedef enum periph_retention_module {
SLEEP_RETENTION_MODULE_BT_BB = 32,
SLEEP_RETENTION_MODULE_802154_MAC = 33,
SLEEP_RETENTION_MODULE_POWER = 34,
SLEEP_RETENTION_MODULE_MODEM_PHY = 35,
SLEEP_RETENTION_MODULE_PHY_FE = 36,
SLEEP_RETENTION_MODULE_MAX,
} periph_retention_module_t;
@@ -494,9 +494,11 @@
#define SOC_PM_SUPPORT_MAC_BB_PD (1)
#define SOC_PM_SUPPORT_RTC_PERIPH_PD (1)
// #define SOC_PM_SUPPORT_PMU_MODEM_STATE (1)
#define SOC_PM_SUPPORT_REGDMA_TRIGGERED_PHY (1)
#define SOC_PM_SUPPORT_PMU_MODEM_STATE (1)
// /* macro redefine for pass esp_wifi headers md5sum check */
// #define MAC_SUPPORT_PMU_MODEM_STATE SOC_PM_SUPPORT_PMU_MODEM_STATE
#define SOC_PM_REGDMA_MODEM_LINK_PROTECT (1)
#define SOC_PM_SUPPORT_PMU_CLK_ICG (1)
#define SOC_PM_SUPPORT_PMU_RETENTION_CLK_ICG (1)
@@ -507,8 +509,10 @@
#define SOC_PM_MODEM_RETENTION_BY_REGDMA (1)
#define SOC_EXT_MEM_CACHE_TAG_IN_CPU_DOMAIN (1)
#define SOC_PM_PAU_LINK_NUM (4)
#define SOC_PM_PAU_LINK_NUM (5)
#define SOC_PM_PAU_REGDMA_LINK_CONFIGURABLE (1)
#define SOC_PM_RETENTION_MODULE_NUM (64)
#define SOC_PM_PAU_REGDMA_LINK_IDX_PHY (4) // The range of values for the link index is [0, SOC_PM_PAU_LINK_NUM)
#define SOC_PM_TOP_DEPENDS_ON_RTC_PERIPH (1) // In ESP32H4, RTC_PERIPH should be pd only together with TOP, otherwise there is some current leak.
#define SOC_PM_BBPLL_PD_IN_MODEM_STATE (1)
@@ -33,6 +33,50 @@ This example contains some build configurations. For each configuration, a few c
- `sdkconfig.defaults.esp32h21`: ESP32H21 uses 32kHz XTAL as low power clock in light sleep enabled.
- `sdkconfig.32m.esp32h21`: ESP32H21 uses main XTAL as low power clock in light sleep enabled.
## Menuconfig Options for Power Optimization
Some configurations can reduce system power consumption at the cost of minor RAM overhead and limited auxiliary functions.
### 1. Placing Core Functions in IRAM
Moving frequently executed core code from flash to IRAM improves running efficiency and reduces system power consumption with the trade-off of higher static RAM occupation.
#### Bluetooth Functions in IRAM
**Supported chips: ESP32H4, ESP32S31**
- `CONFIG_BT_CTRL_SLEEP_RELATED_CODE_IN_IRAM`
- `CONFIG_BT_CTRL_LE_ADV_SLEEP_CODE_IN_IRAM`
- `CONFIG_BT_CTRL_LE_CONN_SLEEP_CODE_IN_IRAM`
#### Sleep Related Functions in IRAM
- `CONFIG_PM_SLP_IRAM_OPT`
- `CONFIG_PM_RTOS_IDLE_OPT`
#### FreeRTOS Kernel Functions in IRAM
- `CONFIG_FREERTOS_IN_IRAM`
#### Phy Related Functions in IRAM
**Supported chips: ESP32H4, ESP32H2, ESP32H21**
- `CONFIG_ESP_PHY_INIT_IRAM`
### 2. Unused Peripheral Module Disable Configurations
Turning off unused peripheral modules achieves further power optimization.
#### Disable USB Serial JTAG
- `CONFIG_ESP_CONSOLE_SECONDARY_NONE`
- `CONFIG_USJ_ENABLE_USB_SERIAL_JTAG`
#### Disable Hardware PC Recording Debug Module
- `CONFIG_ESP_SYSTEM_HW_PC_RECORD`
## How to use example
### Hardware Required
@@ -26,6 +26,12 @@ menu "Example Configuration"
default 3 if BLE_SM_IO_CAP_NO_IO
default 4 if BLE_SM_IO_CAP_KEYBOARD_DISP
config EXAMPLE_USE_SCLI
bool
default y if BLE_SM_IO_CAP_DISP_YES_NO || BLE_SM_IO_CAP_KEYBOARD_ONLY || BLE_SM_IO_CAP_KEYBOARD_DISP
default n
select UART_ISR_IN_IRAM
config EXAMPLE_BONDING
bool
default n
@@ -638,9 +638,11 @@ app_main(void)
nimble_port_freertos_init(bleprph_host_task);
#if CONFIG_EXAMPLE_USE_SCLI
/* Initialize command line interface to accept input from user */
rc = scli_init();
if (rc != ESP_OK) {
ESP_LOGE(tag, "scli_init() failed");
}
#endif // CONFIG_EXAMPLE_USE_SCLI
}
@@ -4,12 +4,6 @@ CONFIG_IDF_TARGET="esp32c2"
CONFIG_BT_LE_SLEEP_ENABLE=y
CONFIG_BT_LE_LP_CLK_SRC_MAIN_XTAL=y
#
# Power Management
#
CONFIG_PM_ENABLE=y
CONFIG_PM_DFS_INIT_AUTO=y
# XTAL Freq Config
CONFIG_XTAL_FREQ_26=y
CONFIG_XTAL_FREQ=26
@@ -18,7 +12,3 @@ CONFIG_XTAL_FREQ=26
# Sleep Config
#
CONFIG_ESP_SLEEP_POWER_DOWN_FLASH=y
CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION=y
# RTC clock source
CONFIG_RTC_CLK_SRC_INT_RC=y
@@ -4,20 +4,10 @@ CONFIG_IDF_TARGET="esp32h2"
CONFIG_BT_LE_SLEEP_ENABLE=y
CONFIG_BT_LE_LP_CLK_SRC_MAIN_XTAL=y
#
# Power Management
#
CONFIG_PM_ENABLE=y
CONFIG_PM_DFS_INIT_AUTO=y
CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP=y
# end of Power Management
CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING=y
#
# Sleep Config
#
CONFIG_ESP_SLEEP_POWER_DOWN_FLASH=y
CONFIG_PM_SLP_IRAM_OPT=y
CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION=y
# end of Sleep Config
@@ -4,20 +4,4 @@ CONFIG_IDF_TARGET="esp32h21"
CONFIG_BT_LE_SLEEP_ENABLE=y
CONFIG_BT_LE_LP_CLK_SRC_MAIN_XTAL=y
#
# Power Management
#
CONFIG_PM_ENABLE=y
CONFIG_PM_DFS_INIT_AUTO=y
CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP=y
CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y
# end of Power Management
CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING=y
#
# Sleep Config
#
CONFIG_PM_SLP_IRAM_OPT=y
CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION=y
# end of Sleep Config
@@ -3,21 +3,10 @@ CONFIG_IDF_TARGET="esp32h4"
# Bluetooth Low Power Config
CONFIG_BT_CTRL_SLEEP_ENABLE=y
CONFIG_BT_CTRL_LP_CLK_SRC_MAIN_XTAL=y
CONFIG_BT_CTRL_SLEEP_RELATED_CODE_IN_IRAM=y
CONFIG_BT_CTRL_LE_ADV_SLEEP_CODE_IN_IRAM=y
CONFIG_BT_CTRL_LE_CONN_SLEEP_CODE_IN_IRAM=y
CONFIG_BT_CTRL_SLEEP_ETM_TRIGGERED_RF=y
#
# Power Management
#
CONFIG_PM_ENABLE=y
CONFIG_PM_DFS_INIT_AUTO=y
CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP=y
# end of Power Management
CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING=y
#
# Sleep Config
#
CONFIG_PM_SLP_IRAM_OPT=y
CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION=y
# end of Sleep Config
CONFIG_ESP_PHY_HW_SWITCH_RF=y
@@ -4,22 +4,12 @@ CONFIG_IDF_TARGET="esp32c6"
CONFIG_BT_LE_SLEEP_ENABLE=y
CONFIG_BT_LE_LP_CLK_SRC_MAIN_XTAL=y
#
# Power Management
#
CONFIG_PM_ENABLE=y
CONFIG_PM_DFS_INIT_AUTO=y
CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP=y
# end of Power Management
CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING=y
CONFIG_ESP_PHY_HW_SWITCH_RF=y
#
# Sleep Config
#
CONFIG_ESP_SLEEP_POWER_DOWN_FLASH=y
CONFIG_ESP_PHY_MAC_BB_PD=y
CONFIG_PM_SLP_IRAM_OPT=y
CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION=y
# end of Sleep Config
@@ -4,20 +4,5 @@ CONFIG_IDF_TARGET="esp32c61"
CONFIG_BT_LE_SLEEP_ENABLE=y
CONFIG_BT_LE_LP_CLK_SRC_MAIN_XTAL=y
#
# Power Management
#
CONFIG_PM_ENABLE=y
CONFIG_PM_DFS_INIT_AUTO=y
CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP=y
# end of Power Management
CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING=y
#
# Sleep Config
#
CONFIG_PM_SLP_IRAM_OPT=y
CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION=y
# end of Sleep Config
CONFIG_ESP_PHY_HW_SWITCH_RF=y
@@ -3,21 +3,9 @@ CONFIG_IDF_TARGET="esp32s31"
# Bluetooth Low Power Config
CONFIG_BT_CTRL_SLEEP_ENABLE=y
CONFIG_BT_CTRL_LP_CLK_SRC_MAIN_XTAL=y
CONFIG_BT_CTRL_SLEEP_RELATED_CODE_IN_IRAM=y
CONFIG_BT_CTRL_LE_ADV_SLEEP_CODE_IN_IRAM=y
CONFIG_BT_CTRL_LE_CONN_SLEEP_CODE_IN_IRAM=y
#
# Power Management
#
CONFIG_PM_ENABLE=y
CONFIG_PM_DFS_INIT_AUTO=y
CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP=y
# end of Power Management
CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING=y
#
# Sleep Config
#
CONFIG_PM_SLP_IRAM_OPT=y
CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION=y
# end of Sleep Config
CONFIG_ESP_PHY_HW_SWITCH_RF=y
@@ -4,20 +4,5 @@ CONFIG_IDF_TARGET="esp32c5"
CONFIG_BT_LE_SLEEP_ENABLE=y
CONFIG_BT_LE_LP_CLK_SRC_MAIN_XTAL=y
#
# Power Management
#
CONFIG_PM_ENABLE=y
CONFIG_PM_DFS_INIT_AUTO=y
CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP=y
# end of Power Management
CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING=y
#
# Sleep Config
#
CONFIG_PM_SLP_IRAM_OPT=y
CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION=y
# end of Sleep Config
CONFIG_ESP_PHY_HW_SWITCH_RF=y
@@ -10,6 +10,8 @@ CONFIG_BT_NIMBLE_ENABLED=y
# Enable support for power management
CONFIG_PM_ENABLE=y
CONFIG_PM_DFS_INIT_AUTO=y
CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y
# Enable tickless idle mode
CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
# Set the tick rate at which FreeRTOS does pre-emptive context switching.
@@ -17,3 +19,19 @@ CONFIG_FREERTOS_HZ=1000
# Minimum number of ticks to enter sleep mode for
CONFIG_FREERTOS_IDLE_TIME_BEFORE_SLEEP=3
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=4000
CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING=y
# Place sleep-related PM code in IRAM
CONFIG_PM_SLP_IRAM_OPT=y
# Place RTOS idle and PM ISR related code in IRAM
CONFIG_PM_RTOS_IDLE_OPT=y
# Place FreeRTOS functions in IRAM
CONFIG_FREERTOS_IN_IRAM=y
# Disable secondary console
CONFIG_ESP_CONSOLE_SECONDARY_NONE=y
# Disable USB Serial/JTAG
CONFIG_USJ_ENABLE_USB_SERIAL_JTAG=n
# Disable HW PC recording
CONFIG_ESP_SYSTEM_HW_PC_RECORD=n
# Used QIO Flash SPI mode
CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
@@ -9,9 +9,9 @@ CONFIG_BT_BLUEDROID_ENABLED=n
CONFIG_BT_NIMBLE_ENABLED=y
# Enable support for power management
CONFIG_PM_ENABLE=y
# Enable tickless idle mode
CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
# Set the tick rate at which FreeRTOS does pre-emptive context switching.
CONFIG_FREERTOS_HZ=1000
# Minimum number of ticks to enter sleep mode for
@@ -4,12 +4,6 @@ CONFIG_IDF_TARGET="esp32c2"
CONFIG_BT_LE_SLEEP_ENABLE=y
CONFIG_BT_LE_LP_CLK_SRC_DEFAULT=y
#
# Power Management
#
CONFIG_PM_ENABLE=y
CONFIG_PM_DFS_INIT_AUTO=y
# XTAL Freq Config
CONFIG_XTAL_FREQ_26=y
CONFIG_XTAL_FREQ=26
@@ -18,7 +12,6 @@ CONFIG_XTAL_FREQ=26
# Sleep Config
#
CONFIG_ESP_SLEEP_POWER_DOWN_FLASH=y
CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION=y
# RTC clock source
CONFIG_RTC_CLK_SRC_EXT_OSC=y
@@ -4,24 +4,9 @@ CONFIG_IDF_TARGET="esp32c5"
CONFIG_BT_LE_SLEEP_ENABLE=y
CONFIG_BT_LE_LP_CLK_SRC_DEFAULT=y
#
# Power Management
#
CONFIG_PM_ENABLE=y
CONFIG_PM_DFS_INIT_AUTO=y
CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP=y
CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y
# end of Power Management
CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING=y
#
# Sleep Config
#
CONFIG_PM_SLP_IRAM_OPT=y
CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION=y
# end of Sleep Config
CONFIG_ESP_PHY_HW_SWITCH_RF=y
#
# RTC Clock Config
@@ -4,16 +4,7 @@ CONFIG_IDF_TARGET="esp32c6"
CONFIG_BT_LE_SLEEP_ENABLE=y
CONFIG_BT_LE_LP_CLK_SRC_DEFAULT=y
#
# Power Management
#
CONFIG_PM_ENABLE=y
CONFIG_PM_DFS_INIT_AUTO=y
CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP=y
CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y
# end of Power Management
CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING=y
#
@@ -21,8 +12,8 @@ CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING=y
#
CONFIG_ESP_SLEEP_POWER_DOWN_FLASH=y
CONFIG_ESP_PHY_MAC_BB_PD=y
CONFIG_PM_SLP_IRAM_OPT=y
CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION=y
CONFIG_ESP_PHY_HW_SWITCH_RF=y
# end of Sleep Config
#
@@ -4,24 +4,8 @@ CONFIG_IDF_TARGET="esp32c61"
CONFIG_BT_LE_SLEEP_ENABLE=y
CONFIG_BT_LE_LP_CLK_SRC_DEFAULT=y
#
# Power Management
#
CONFIG_PM_ENABLE=y
CONFIG_PM_DFS_INIT_AUTO=y
CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP=y
CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y
# end of Power Management
CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING=y
#
# Sleep Config
#
CONFIG_PM_SLP_IRAM_OPT=y
CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION=y
# end of Sleep Config
CONFIG_ESP_PHY_HW_SWITCH_RF=y
#
# RTC Clock Config
@@ -4,23 +4,12 @@ CONFIG_IDF_TARGET="esp32h2"
CONFIG_BT_LE_SLEEP_ENABLE=y
CONFIG_BT_LE_LP_CLK_SRC_DEFAULT=y
#
# Power Management
#
CONFIG_PM_ENABLE=y
CONFIG_PM_DFS_INIT_AUTO=y
CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP=y
CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y
# end of Power Management
CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING=y
#
# Sleep Config
#
CONFIG_ESP_SLEEP_POWER_DOWN_FLASH=y
CONFIG_PM_SLP_IRAM_OPT=y
CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION=y
# end of Sleep Config
#
@@ -4,24 +4,8 @@ CONFIG_IDF_TARGET="esp32h21"
CONFIG_BT_LE_SLEEP_ENABLE=y
CONFIG_BT_LE_LP_CLK_SRC_DEFAULT=y
#
# Power Management
#
CONFIG_PM_ENABLE=y
CONFIG_PM_DFS_INIT_AUTO=y
CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP=y
CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y
# end of Power Management
CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING=y
#
# Sleep Config
#
CONFIG_PM_SLP_IRAM_OPT=y
CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION=y
# end of Sleep Config
#
# RTC Clock Config
#
@@ -3,24 +3,13 @@ CONFIG_IDF_TARGET="esp32h4"
# Bluetooth Low Power Config
CONFIG_BT_CTRL_SLEEP_ENABLE=y
CONFIG_BT_CTRL_LP_CLK_SRC_DEFAULT=y
#
# Power Management
#
CONFIG_PM_ENABLE=y
CONFIG_PM_DFS_INIT_AUTO=y
CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP=y
CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y
# end of Power Management
CONFIG_BT_CTRL_SLEEP_RELATED_CODE_IN_IRAM=y
CONFIG_BT_CTRL_LE_ADV_SLEEP_CODE_IN_IRAM=y
CONFIG_BT_CTRL_LE_CONN_SLEEP_CODE_IN_IRAM=y
CONFIG_BT_CTRL_SLEEP_ETM_TRIGGERED_RF=y
CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING=y
#
# Sleep Config
#
CONFIG_PM_SLP_IRAM_OPT=y
CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION=y
# end of Sleep Config
CONFIG_ESP_PHY_HW_SWITCH_RF=y
#
# RTC Clock Config
@@ -3,25 +3,12 @@ CONFIG_IDF_TARGET="esp32s31"
# Bluetooth Low Power Config
CONFIG_BT_CTRL_SLEEP_ENABLE=y
CONFIG_BT_CTRL_LP_CLK_SRC_DEFAULT=y
CONFIG_BT_CTRL_SLEEP_RELATED_CODE_IN_IRAM=y
CONFIG_BT_CTRL_LE_ADV_SLEEP_CODE_IN_IRAM=y
CONFIG_BT_CTRL_LE_CONN_SLEEP_CODE_IN_IRAM=y
#
# Power Management
#
CONFIG_PM_ENABLE=y
CONFIG_PM_DFS_INIT_AUTO=y
CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP=y
CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y
# end of Power Management
CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING=y
#
# Sleep Config
#
CONFIG_PM_SLP_IRAM_OPT=y
CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION=y
# end of Sleep Config
CONFIG_ESP_PHY_HW_SWITCH_RF=y
#
# RTC Clock Config
@@ -35,9 +35,9 @@ CONFIG_BT_NIMBLE_HR_SERVICE=n
CONFIG_BT_NIMBLE_DIS_SERVICE=n
# Enable support for power management
CONFIG_PM_ENABLE=y
# Enable tickless idle mode
CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
# Set the tick rate at which FreeRTOS does pre-emptive context switching.
CONFIG_BT_ALARM_MAX_NUM=15