diff --git a/components/bt/controller/esp32h4/Kconfig.in b/components/bt/controller/esp32h4/Kconfig.in index bd11cf72a86..a0efc23fae9 100644 --- a/components/bt/controller/esp32h4/Kconfig.in +++ b/components/bt/controller/esp32h4/Kconfig.in @@ -1 +1,5 @@ source "$IDF_PATH/components/bt/porting_btdm/Kconfig.in" + +config BT_CTRL_SUPPORT_ETM_WAKEUP + bool + default y diff --git a/components/bt/controller/lib_esp32h4/esp32h4-bt-lib b/components/bt/controller/lib_esp32h4/esp32h4-bt-lib index 9358cd13cc5..5864c2e027e 160000 --- a/components/bt/controller/lib_esp32h4/esp32h4-bt-lib +++ b/components/bt/controller/lib_esp32h4/esp32h4-bt-lib @@ -1 +1 @@ -Subproject commit 9358cd13cc50ed6bb099170eddd314ec3abfc76e +Subproject commit 5864c2e027e6a1d90e47517185907fffac7cba65 diff --git a/components/bt/controller/lib_esp32s31/esp32s31-bt-lib b/components/bt/controller/lib_esp32s31/esp32s31-bt-lib index 3d8cee57c4c..10cdb57fe6b 160000 --- a/components/bt/controller/lib_esp32s31/esp32s31-bt-lib +++ b/components/bt/controller/lib_esp32s31/esp32s31-bt-lib @@ -1 +1 @@ -Subproject commit 3d8cee57c4ccff603d4f52fe16be1f04ece78ede +Subproject commit 10cdb57fe6b01088170d041f3e00e0276c3f7cc6 diff --git a/components/bt/controller/linker_esp_btdm_controller.lf b/components/bt/controller/linker_esp_btdm_controller.lf index 05111c9dd1d..6684d21e69a 100644 --- a/components/bt/controller/linker_esp_btdm_controller.lf +++ b/components/bt/controller/linker_esp_btdm_controller.lf @@ -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), diff --git a/components/bt/include/esp32h4/include/esp_bt.h b/components/bt/include/esp32h4/include/esp_bt.h index 7ecc5dfeb6c..350ae79cb21 100644 --- a/components/bt/include/esp32h4/include/esp_bt.h +++ b/components/bt/include/esp32h4/include/esp_bt.h @@ -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, \ }, \ } diff --git a/components/bt/include/esp32s31/include/esp_bt.h b/components/bt/include/esp32s31/include/esp_bt.h index 6370d5c4d00..d232309e8f9 100644 --- a/components/bt/include/esp32s31/include/esp_bt.h +++ b/components/bt/include/esp32s31/include/esp_bt.h @@ -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 diff --git a/components/bt/porting_btdm/Kconfig.in b/components/bt/porting_btdm/Kconfig.in index 956a0d69078..3526f491f09 100644 --- a/components/bt/porting_btdm/Kconfig.in +++ b/components/bt/porting_btdm/Kconfig.in @@ -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 diff --git a/components/bt/porting_btdm/controller/ble/include/ble_priv.h b/components/bt/porting_btdm/controller/ble/include/ble_priv.h index 2671178223a..d138af79695 100644 --- a/components/bt/porting_btdm/controller/ble/include/ble_priv.h +++ b/components/bt/porting_btdm/controller/ble/include/ble_priv.h @@ -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); diff --git a/components/bt/porting_btdm/controller/ble/src/ble.c b/components/bt/porting_btdm/controller/ble/src/ble.c index 5d222efefb4..89691bc79ca 100644 --- a/components/bt/porting_btdm/controller/ble/src/ble.c +++ b/components/bt/porting_btdm/controller/ble/src/ble.c @@ -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 = diff --git a/components/bt/porting_btdm/controller/bredr/include/bredr_priv.h b/components/bt/porting_btdm/controller/bredr/include/bredr_priv.h index 155a41ea98f..93e48560d4c 100644 --- a/components/bt/porting_btdm/controller/bredr/include/bredr_priv.h +++ b/components/bt/porting_btdm/controller/bredr/include/bredr_priv.h @@ -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); diff --git a/components/bt/porting_btdm/controller/bredr/src/bredr.c b/components/bt/porting_btdm/controller/bredr/src/bredr.c index abb87781d69..4c75ce40946 100644 --- a/components/bt/porting_btdm/controller/bredr/src/bredr.c +++ b/components/bt/porting_btdm/controller/bredr/src/bredr.c @@ -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); diff --git a/components/bt/porting_btdm/controller/btdm_common/include/btdm_user_cfg.h b/components/bt/porting_btdm/controller/btdm_common/include/btdm_user_cfg.h index 43664af4995..a0f0d2e9f75 100644 --- a/components/bt/porting_btdm/controller/btdm_common/include/btdm_user_cfg.h +++ b/components/bt/porting_btdm/controller/btdm_common/include/btdm_user_cfg.h @@ -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 } diff --git a/components/bt/porting_btdm/controller/btdm_common/src/btdm_lp.c b/components/bt/porting_btdm/controller/btdm_common/src/btdm_lp.c index 99f618c1419..d492c78e748 100644 --- a/components/bt/porting_btdm/controller/btdm_common/src/btdm_lp.c +++ b/components/bt/porting_btdm/controller/btdm_common/src/btdm_lp.c @@ -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 +} diff --git a/components/esp_hal_pmu/esp32h4/include/hal/pau_etm_ll.h b/components/esp_hal_pmu/esp32h4/include/hal/pau_etm_ll.h new file mode 100644 index 00000000000..b2a5e282064 --- /dev/null +++ b/components/esp_hal_pmu/esp32h4/include/hal/pau_etm_ll.h @@ -0,0 +1,51 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#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 diff --git a/components/esp_hal_pmu/esp32h4/include/hal/pau_ll.h b/components/esp_hal_pmu/esp32h4/include/hal/pau_ll.h index 4f7bbf77168..2e4f42463dc 100644 --- a/components/esp_hal_pmu/esp32h4/include/hal/pau_ll.h +++ b/components/esp_hal_pmu/esp32h4/include/hal/pau_ll.h @@ -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 diff --git a/components/esp_hal_pmu/esp32h4/pau_hal.c b/components/esp_hal_pmu/esp32h4/pau_hal.c index e14160d6016..b0f9266df7e 100644 --- a/components/esp_hal_pmu/esp32h4/pau_hal.c +++ b/components/esp_hal_pmu/esp32h4/pau_hal.c @@ -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); +} diff --git a/components/esp_hal_pmu/esp32s31/include/hal/pau_ll.h b/components/esp_hal_pmu/esp32s31/include/hal/pau_ll.h index 87f4ed0a617..9d34b48c0f2 100644 --- a/components/esp_hal_pmu/esp32s31/include/hal/pau_ll.h +++ b/components/esp_hal_pmu/esp32s31/include/hal/pau_ll.h @@ -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 diff --git a/components/esp_hal_pmu/esp32s31/pau_hal.c b/components/esp_hal_pmu/esp32s31/pau_hal.c index 682d85b3541..a9551baca74 100644 --- a/components/esp_hal_pmu/esp32s31/pau_hal.c +++ b/components/esp_hal_pmu/esp32s31/pau_hal.c @@ -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); +} diff --git a/components/esp_hal_pmu/include/hal/pau_hal.h b/components/esp_hal_pmu/include/hal/pau_hal.h index 2494c0e7bf6..235899dfe90 100644 --- a/components/esp_hal_pmu/include/hal/pau_hal.h +++ b/components/esp_hal_pmu/include/hal/pau_hal.h @@ -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 diff --git a/components/esp_hw_support/include/esp_private/esp_pau.h b/components/esp_hw_support/include/esp_private/esp_pau.h index 2a4e8a78bcf..7112fe0cf0d 100644 --- a/components/esp_hw_support/include/esp_private/esp_pau.h +++ b/components/esp_hw_support/include/esp_private/esp_pau.h @@ -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 diff --git a/components/esp_hw_support/include/esp_private/sleep_modem.h b/components/esp_hw_support/include/esp_private/sleep_modem.h index 2430d3f9ce6..1f5d614faf1 100644 --- a/components/esp_hw_support/include/esp_private/sleep_modem.h +++ b/components/esp_hw_support/include/esp_private/sleep_modem.h @@ -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 diff --git a/components/esp_hw_support/lowpower/port/esp32h4/sleep_phy.c b/components/esp_hw_support/lowpower/port/esp32h4/sleep_phy.c new file mode 100644 index 00000000000..2ea1baf1e69 --- /dev/null +++ b/components/esp_hw_support/lowpower/port/esp32h4/sleep_phy.c @@ -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 */ diff --git a/components/esp_hw_support/lowpower/port/esp32s31/sleep_phy.c b/components/esp_hw_support/lowpower/port/esp32s31/sleep_phy.c index 115bd8493f2..58106763f5e 100644 --- a/components/esp_hw_support/lowpower/port/esp32s31/sleep_phy.c +++ b/components/esp_hw_support/lowpower/port/esp32s31/sleep_phy.c @@ -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; diff --git a/components/esp_hw_support/port/pau_regdma.c b/components/esp_hw_support/port/pau_regdma.c index a64c43c80e0..44106206f11 100644 --- a/components/esp_hw_support/port/pau_regdma.c +++ b/components/esp_hw_support/port/pau_regdma.c @@ -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 diff --git a/components/esp_hw_support/sleep_modem.c b/components/esp_hw_support/sleep_modem.c index f7c19fac44d..782b0d0d4ff 100644 --- a/components/esp_hw_support/sleep_modem.c +++ b/components/esp_hw_support/sleep_modem.c @@ -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; } diff --git a/components/esp_phy/CMakeLists.txt b/components/esp_phy/CMakeLists.txt index fbf224e32b8..83745e906f3 100644 --- a/components/esp_phy/CMakeLists.txt +++ b/components/esp_phy/CMakeLists.txt @@ -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") diff --git a/components/esp_phy/esp32h4/phy_init_data.c b/components/esp_phy/esp32h4/phy_init_data.c new file mode 100644 index 00000000000..79f30e86be6 --- /dev/null +++ b/components/esp_phy/esp32h4/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 diff --git a/components/esp_phy/include/esp_private/phy.h b/components/esp_phy/include/esp_private/phy.h index 25723d993f4..df9a800ee79 100644 --- a/components/esp_phy/include/esp_private/phy.h +++ b/components/esp_phy/include/esp_private/phy.h @@ -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 diff --git a/components/esp_phy/src/btbb_init.c b/components/esp_phy/src/btbb_init.c index 57e4f5e8846..8ba54e7daba 100644 --- a/components/esp_phy/src/btbb_init.c +++ b/components/esp_phy/src/btbb_init.c @@ -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"); diff --git a/components/esp_phy/src/phy_common.c b/components/esp_phy/src/phy_common.c index 91c2dcf0360..3f2efccdd10 100644 --- a/components/esp_phy/src/phy_common.c +++ b/components/esp_phy/src/phy_common.c @@ -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 diff --git a/components/esp_phy/src/phy_init.c b/components/esp_phy/src/phy_init.c index ac87a92e2bf..f6794e07e8c 100644 --- a/components/esp_phy/src/phy_init.c +++ b/components/esp_phy/src/phy_init.c @@ -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"); diff --git a/components/esp_phy/src/phy_init_esp32hxx.c b/components/esp_phy/src/phy_init_esp32hxx.c index 0f56118e3b3..cdbe998e899 100644 --- a/components/esp_phy/src/phy_init_esp32hxx.c +++ b/components/esp_phy/src/phy_init_esp32hxx.c @@ -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 +} diff --git a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in index 62118091eb7..7496b4a11ce 100644 --- a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in @@ -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 diff --git a/components/soc/esp32h4/include/soc/retention_periph_defs.h b/components/soc/esp32h4/include/soc/retention_periph_defs.h index b08ce1af922..758b7b65b36 100644 --- a/components/soc/esp32h4/include/soc/retention_periph_defs.h +++ b/components/soc/esp32h4/include/soc/retention_periph_defs.h @@ -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; diff --git a/components/soc/esp32h4/include/soc/soc_caps.h b/components/soc/esp32h4/include/soc/soc_caps.h index 5c3f8c27b94..62c88617f95 100644 --- a/components/soc/esp32h4/include/soc/soc_caps.h +++ b/components/soc/esp32h4/include/soc/soc_caps.h @@ -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) diff --git a/examples/bluetooth/nimble/power_save/README.md b/examples/bluetooth/nimble/power_save/README.md index c042c1a7403..62ce2a31556 100644 --- a/examples/bluetooth/nimble/power_save/README.md +++ b/examples/bluetooth/nimble/power_save/README.md @@ -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 diff --git a/examples/bluetooth/nimble/power_save/main/Kconfig.projbuild b/examples/bluetooth/nimble/power_save/main/Kconfig.projbuild index 70dcff8042b..815c9c0f1dc 100644 --- a/examples/bluetooth/nimble/power_save/main/Kconfig.projbuild +++ b/examples/bluetooth/nimble/power_save/main/Kconfig.projbuild @@ -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 diff --git a/examples/bluetooth/nimble/power_save/main/main.c b/examples/bluetooth/nimble/power_save/main/main.c index e80f56c8e6f..f30f8c6a7e9 100644 --- a/examples/bluetooth/nimble/power_save/main/main.c +++ b/examples/bluetooth/nimble/power_save/main/main.c @@ -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 } diff --git a/examples/bluetooth/nimble/power_save/sdkconfig.26m.esp32c2 b/examples/bluetooth/nimble/power_save/sdkconfig.26m.esp32c2 index b9121b61531..a75f6f84c5e 100644 --- a/examples/bluetooth/nimble/power_save/sdkconfig.26m.esp32c2 +++ b/examples/bluetooth/nimble/power_save/sdkconfig.26m.esp32c2 @@ -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 diff --git a/examples/bluetooth/nimble/power_save/sdkconfig.32m.esp32h2 b/examples/bluetooth/nimble/power_save/sdkconfig.32m.esp32h2 index 3bb77bf4312..99e3f409fcb 100644 --- a/examples/bluetooth/nimble/power_save/sdkconfig.32m.esp32h2 +++ b/examples/bluetooth/nimble/power_save/sdkconfig.32m.esp32h2 @@ -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 diff --git a/examples/bluetooth/nimble/power_save/sdkconfig.32m.esp32h21 b/examples/bluetooth/nimble/power_save/sdkconfig.32m.esp32h21 index 6ce9b30f6ac..e0e5fd62dfa 100644 --- a/examples/bluetooth/nimble/power_save/sdkconfig.32m.esp32h21 +++ b/examples/bluetooth/nimble/power_save/sdkconfig.32m.esp32h21 @@ -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 diff --git a/examples/bluetooth/nimble/power_save/sdkconfig.32m.esp32h4 b/examples/bluetooth/nimble/power_save/sdkconfig.32m.esp32h4 index 21bfb62ff6e..bbec9a105d1 100644 --- a/examples/bluetooth/nimble/power_save/sdkconfig.32m.esp32h4 +++ b/examples/bluetooth/nimble/power_save/sdkconfig.32m.esp32h4 @@ -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 diff --git a/examples/bluetooth/nimble/power_save/sdkconfig.40m.esp32c6 b/examples/bluetooth/nimble/power_save/sdkconfig.40m.esp32c6 index 26534a800fb..f97fdd58094 100644 --- a/examples/bluetooth/nimble/power_save/sdkconfig.40m.esp32c6 +++ b/examples/bluetooth/nimble/power_save/sdkconfig.40m.esp32c6 @@ -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 diff --git a/examples/bluetooth/nimble/power_save/sdkconfig.40m.esp32c61 b/examples/bluetooth/nimble/power_save/sdkconfig.40m.esp32c61 index ba02349c378..16b51a56bed 100644 --- a/examples/bluetooth/nimble/power_save/sdkconfig.40m.esp32c61 +++ b/examples/bluetooth/nimble/power_save/sdkconfig.40m.esp32c61 @@ -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 diff --git a/examples/bluetooth/nimble/power_save/sdkconfig.40m.esp32s31 b/examples/bluetooth/nimble/power_save/sdkconfig.40m.esp32s31 index 43b606164ab..503033ff656 100644 --- a/examples/bluetooth/nimble/power_save/sdkconfig.40m.esp32s31 +++ b/examples/bluetooth/nimble/power_save/sdkconfig.40m.esp32s31 @@ -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 diff --git a/examples/bluetooth/nimble/power_save/sdkconfig.48m.esp32c5 b/examples/bluetooth/nimble/power_save/sdkconfig.48m.esp32c5 index 756a841b708..2704996a6f1 100644 --- a/examples/bluetooth/nimble/power_save/sdkconfig.48m.esp32c5 +++ b/examples/bluetooth/nimble/power_save/sdkconfig.48m.esp32c5 @@ -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 diff --git a/examples/bluetooth/nimble/power_save/sdkconfig.defaults b/examples/bluetooth/nimble/power_save/sdkconfig.defaults index ab387f2ed7f..fc798bf2f07 100644 --- a/examples/bluetooth/nimble/power_save/sdkconfig.defaults +++ b/examples/bluetooth/nimble/power_save/sdkconfig.defaults @@ -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 diff --git a/examples/bluetooth/nimble/power_save/sdkconfig.defaults.dram_optimised b/examples/bluetooth/nimble/power_save/sdkconfig.defaults.dram_optimised index bc9d17faa50..6b2ffff0126 100644 --- a/examples/bluetooth/nimble/power_save/sdkconfig.defaults.dram_optimised +++ b/examples/bluetooth/nimble/power_save/sdkconfig.defaults.dram_optimised @@ -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 diff --git a/examples/bluetooth/nimble/power_save/sdkconfig.defaults.esp32c2 b/examples/bluetooth/nimble/power_save/sdkconfig.defaults.esp32c2 index 55320c019ab..38c1c78fa28 100644 --- a/examples/bluetooth/nimble/power_save/sdkconfig.defaults.esp32c2 +++ b/examples/bluetooth/nimble/power_save/sdkconfig.defaults.esp32c2 @@ -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 diff --git a/examples/bluetooth/nimble/power_save/sdkconfig.defaults.esp32c5 b/examples/bluetooth/nimble/power_save/sdkconfig.defaults.esp32c5 index 6f545ebec6b..9ec8259355a 100644 --- a/examples/bluetooth/nimble/power_save/sdkconfig.defaults.esp32c5 +++ b/examples/bluetooth/nimble/power_save/sdkconfig.defaults.esp32c5 @@ -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 diff --git a/examples/bluetooth/nimble/power_save/sdkconfig.defaults.esp32c6 b/examples/bluetooth/nimble/power_save/sdkconfig.defaults.esp32c6 index 582f7034d12..3577f097f61 100644 --- a/examples/bluetooth/nimble/power_save/sdkconfig.defaults.esp32c6 +++ b/examples/bluetooth/nimble/power_save/sdkconfig.defaults.esp32c6 @@ -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 # diff --git a/examples/bluetooth/nimble/power_save/sdkconfig.defaults.esp32c61 b/examples/bluetooth/nimble/power_save/sdkconfig.defaults.esp32c61 index b037beb4f95..2f38dfb5703 100644 --- a/examples/bluetooth/nimble/power_save/sdkconfig.defaults.esp32c61 +++ b/examples/bluetooth/nimble/power_save/sdkconfig.defaults.esp32c61 @@ -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 diff --git a/examples/bluetooth/nimble/power_save/sdkconfig.defaults.esp32h2 b/examples/bluetooth/nimble/power_save/sdkconfig.defaults.esp32h2 index d1234542f76..bfa5f08980b 100644 --- a/examples/bluetooth/nimble/power_save/sdkconfig.defaults.esp32h2 +++ b/examples/bluetooth/nimble/power_save/sdkconfig.defaults.esp32h2 @@ -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 # diff --git a/examples/bluetooth/nimble/power_save/sdkconfig.defaults.esp32h21 b/examples/bluetooth/nimble/power_save/sdkconfig.defaults.esp32h21 index a7baac63834..fc6eb500248 100644 --- a/examples/bluetooth/nimble/power_save/sdkconfig.defaults.esp32h21 +++ b/examples/bluetooth/nimble/power_save/sdkconfig.defaults.esp32h21 @@ -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 # diff --git a/examples/bluetooth/nimble/power_save/sdkconfig.defaults.esp32h4 b/examples/bluetooth/nimble/power_save/sdkconfig.defaults.esp32h4 index d0629a1af3b..86b0c595ed3 100644 --- a/examples/bluetooth/nimble/power_save/sdkconfig.defaults.esp32h4 +++ b/examples/bluetooth/nimble/power_save/sdkconfig.defaults.esp32h4 @@ -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 diff --git a/examples/bluetooth/nimble/power_save/sdkconfig.defaults.esp32s31 b/examples/bluetooth/nimble/power_save/sdkconfig.defaults.esp32s31 index 590402d0b61..91f2a5c6e2c 100644 --- a/examples/bluetooth/nimble/power_save/sdkconfig.defaults.esp32s31 +++ b/examples/bluetooth/nimble/power_save/sdkconfig.defaults.esp32s31 @@ -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 diff --git a/examples/bluetooth/nimble/power_save/sdkconfig.defaults.mini b/examples/bluetooth/nimble/power_save/sdkconfig.defaults.mini index 6c21af060fc..a7ab560511e 100644 --- a/examples/bluetooth/nimble/power_save/sdkconfig.defaults.mini +++ b/examples/bluetooth/nimble/power_save/sdkconfig.defaults.mini @@ -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