diff --git a/components/bt/controller/esp32h2/Kconfig.in b/components/bt/controller/esp32h2/Kconfig.in index 13395fd30f4..6eef0428e87 100644 --- a/components/bt/controller/esp32h2/Kconfig.in +++ b/components/bt/controller/esp32h2/Kconfig.in @@ -395,6 +395,26 @@ choice BT_LE_WAKEUP_SOURCE Use BLE rtc timer to wakeup CPU endchoice +choice BT_LE_LP_CLK_SRC + prompt "BLE low power clock source" + default BT_LE_LP_CLK_SRC_MAIN_XTAL + config BT_LE_LP_CLK_SRC_MAIN_XTAL + bool "Use main XTAL as RTC clock source" + help + User main XTAL as RTC clock source. + This option is recommended if external 32.768k XTAL is not available. + Using the external 32.768 kHz XTAL will have lower current consumption + in light sleep compared to using the main XTAL. + + config BT_LE_LP_CLK_SRC_DEFAULT + bool "Use system RTC slow clock source" + help + Use the same slow clock source as system RTC + Using any clock source other than external 32.768 kHz XTAL supports only + legacy ADV and SCAN due to low clock accuracy. + +endchoice + config BT_LE_USE_ESP_TIMER bool "Enable Esp Timer for Callout" depends on !BT_NIMBLE_ENABLED diff --git a/components/bt/controller/esp32h2/bt.c b/components/bt/controller/esp32h2/bt.c index 9d7fcc6a309..9e11fc3d0f0 100644 --- a/components/bt/controller/esp32h2/bt.c +++ b/components/bt/controller/esp32h2/bt.c @@ -40,6 +40,10 @@ #include "hci_uart.h" #include "bt_osi_mem.h" +#if SOC_PM_RETENTION_HAS_CLOCK_BUG +#include "esp_private/sleep_retention.h" +#endif + #ifdef CONFIG_BT_BLUEDROID_ENABLED #include "hci/hci_hal.h" #endif // CONFIG_BT_BLUEDROID_ENABLED @@ -49,7 +53,6 @@ #include "esp_private/periph_ctrl.h" #include "esp_sleep.h" - /* Macro definition ************************************************************************ */ @@ -122,9 +125,12 @@ extern void npl_freertos_mempool_deinit(void); extern int os_msys_buf_alloc(void); extern uint32_t r_os_cputime_get32(void); extern uint32_t r_os_cputime_ticks_to_usecs(uint32_t ticks); +#if CONFIG_FREERTOS_USE_TICKLESS_IDLE +extern const sleep_retention_entries_config_t *esp_ble_mac_retention_link_get(uint8_t *size, uint8_t extra); +#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */ extern void ble_lll_rfmgmt_set_sleep_cb(void *s_cb, void *w_cb, void *s_arg, void *w_arg, uint32_t us_to_enabled); -extern void ble_rtc_wake_up_state_clr(void); +extern void r_ble_rtc_wake_up_state_clr(void); extern int os_msys_init(void); extern void os_msys_buf_free(void); extern int ble_sm_alg_gen_dhkey(const uint8_t *peer_pub_key_x, @@ -184,11 +190,13 @@ static DRAM_ATTR esp_pm_lock_handle_t s_pm_lock = NULL; #endif // CONFIG_PM_ENABLE #ifdef CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER -#define BLE_RTC_DELAY_US (1100) +#define BLE_RTC_DELAY_US_LIGHT_SLEEP (5100) +#define BLE_RTC_DELAY_US_MODEM_SLEEP (1500) #endif // CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER #ifdef CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER -#define BLE_RTC_DELAY_US (0) +#define BLE_RTC_DELAY_US_LIGHT_SLEEP (2000) +#define BLE_RTC_DELAY_US_MODEM_SLEEP (0) static void ble_sleep_timer_callback(void *arg); static DRAM_ATTR esp_timer_handle_t s_ble_sleep_timer = NULL; #endif // CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER @@ -427,8 +435,7 @@ IRAM_ATTR void controller_sleep_cb(uint32_t enable_tick, void *arg) if (!s_ble_active) { return; } - -#ifdef CONFIG_PM_ENABLE +#if CONFIG_FREERTOS_USE_TICKLESS_IDLE #ifdef CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER uint32_t delta_tick; uint32_t us_to_sleep; @@ -458,11 +465,14 @@ IRAM_ATTR void controller_sleep_cb(uint32_t enable_tick, void *arg) #ifdef CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER r_ble_rtc_wake_up_state_clr(); #endif // CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER - +#if SOC_PM_RETENTION_HAS_CLOCK_BUG + sleep_retention_do_extra_retention(true); +#endif // SOC_PM_RETENTION_HAS_CLOCK_BUG +#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */ + esp_phy_disable(); +#ifdef CONFIG_PM_ENABLE esp_pm_lock_release(s_pm_lock); #endif // CONFIG_PM_ENABLE - - esp_phy_disable(); s_ble_active = false; } @@ -471,37 +481,58 @@ IRAM_ATTR void controller_wakeup_cb(void *arg) if (s_ble_active) { return; } - esp_phy_enable(); - #ifdef CONFIG_PM_ENABLE +#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER esp_pm_lock_acquire(s_pm_lock); + r_ble_rtc_wake_up_state_clr(); +#endif // CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER +#if CONFIG_FREERTOS_USE_TICKLESS_IDLE && SOC_PM_RETENTION_HAS_CLOCK_BUG + sleep_retention_do_extra_retention(false); +#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE && SOC_PM_RETENTION_HAS_CLOCK_BUG */ #endif //CONFIG_PM_ENABLE - + esp_phy_enable(); s_ble_active = true; } -#ifdef CONFIG_PM_ENABLE +#ifdef CONFIG_FREERTOS_USE_TICKLESS_IDLE #ifdef CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER static void ble_sleep_timer_callback(void * arg) { + esp_pm_lock_acquire(s_pm_lock); +} +#endif // CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER + +static esp_err_t sleep_modem_ble_mac_modem_state_init(uint8_t extra) +{ + uint8_t size; + const sleep_retention_entries_config_t *ble_mac_modem_config = esp_ble_mac_retention_link_get(&size, extra); + esp_err_t err = sleep_retention_entries_create(ble_mac_modem_config, size, REGDMA_LINK_PRI_5, SLEEP_RETENTION_MODULE_BLE_MAC); + if (err == ESP_OK) { + ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Modem BLE MAC retention initialization"); + } + return err; +} +static void sleep_modem_ble_mac_modem_state_deinit(void) +{ + sleep_retention_entries_destroy(SLEEP_RETENTION_MODULE_BLE_MAC); } -#endif // CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER -#endif // CONFIG_PM_ENABLE +#endif // CONFIG_FREERTOS_USE_TICKLESS_IDLE esp_err_t controller_sleep_init(void) { esp_err_t rc = 0; #ifdef CONFIG_BT_LE_SLEEP_ENABLE - ESP_LOGW(NIMBLE_PORT_LOG_TAG, "BLE modem sleep is enabled\n"); + ESP_LOGW(NIMBLE_PORT_LOG_TAG, "BLE modem sleep is enabled"); +#if CONFIG_FREERTOS_USE_TICKLESS_IDLE ble_lll_rfmgmt_set_sleep_cb(controller_sleep_cb, controller_wakeup_cb, 0, 0, - 500 + BLE_RTC_DELAY_US); - -#ifdef CONFIG_PM_ENABLE - esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_ON); -#endif // CONFIG_PM_ENABLE + BLE_RTC_DELAY_US_LIGHT_SLEEP); +#else + ble_lll_rfmgmt_set_sleep_cb(controller_sleep_cb, controller_wakeup_cb, 0, 0, + BLE_RTC_DELAY_US_MODEM_SLEEP); +#endif /* FREERTOS_USE_TICKLESS_IDLE */ #endif // CONFIG_BT_LE_SLEEP_ENABLE #ifdef CONFIG_PM_ENABLE @@ -510,7 +541,7 @@ esp_err_t controller_sleep_init(void) goto error; } esp_pm_lock_acquire(s_pm_lock); - +#if CONFIG_FREERTOS_USE_TICKLESS_IDLE #ifdef CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER esp_timer_create_args_t create_args = { .callback = ble_sleep_timer_callback, @@ -524,20 +555,23 @@ esp_err_t controller_sleep_init(void) ESP_LOGW(NIMBLE_PORT_LOG_TAG, "Enable light sleep, the wake up source is ESP timer"); #endif //CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER + /* Create a new regdma link for BLE related register restoration */ + rc = sleep_modem_ble_mac_modem_state_init(1); + assert(rc == 0); #ifdef CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER esp_sleep_enable_bt_wakeup(); ESP_LOGW(NIMBLE_PORT_LOG_TAG, "Enable light sleep, the wake up source is BLE timer"); #endif // CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER - +#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */ return rc; error: - /*lock should release first and then delete*/ - if (s_pm_lock != NULL) { - esp_pm_lock_release(s_pm_lock); - esp_pm_lock_delete(s_pm_lock); - s_pm_lock = NULL; - } + +#if CONFIG_FREERTOS_USE_TICKLESS_IDLE +#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER + esp_sleep_disable_bt_wakeup(); +#endif // CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER + #ifdef CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER if (s_ble_sleep_timer != NULL) { esp_timer_stop(s_ble_sleep_timer); @@ -545,34 +579,26 @@ esp_err_t controller_sleep_init(void) s_ble_sleep_timer = NULL; } #endif // CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER - -#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER - esp_sleep_disable_bt_wakeup(); -#endif // CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER - -#endif //CONFIG_PM_ENABLE +#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */ + /*lock should release first and then delete*/ + if (s_pm_lock != NULL) { + esp_pm_lock_release(s_pm_lock); + esp_pm_lock_delete(s_pm_lock); + s_pm_lock = NULL; + } +#endif // CONFIG_PM_ENABLE return rc; } void controller_sleep_deinit(void) { -#ifdef CONFIG_PM_ENABLE +#if CONFIG_FREERTOS_USE_TICKLESS_IDLE #ifdef CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER r_ble_rtc_wake_up_state_clr(); esp_sleep_disable_bt_wakeup(); #endif //CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER - - esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_AUTO); - - /* lock should be released first */ - if (s_ble_active) { - esp_pm_lock_release(s_pm_lock); - } - - esp_pm_lock_delete(s_pm_lock); - s_pm_lock = NULL; - + sleep_modem_ble_mac_modem_state_deinit(); #ifdef CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER if (s_ble_sleep_timer != NULL) { esp_timer_stop(s_ble_sleep_timer); @@ -580,6 +606,12 @@ void controller_sleep_deinit(void) s_ble_sleep_timer = NULL; } #endif //CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER +#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */ +#ifdef CONFIG_PM_ENABLE + /* lock should be released first */ + esp_pm_lock_release(s_pm_lock); + esp_pm_lock_delete(s_pm_lock); + s_pm_lock = NULL; #endif //CONFIG_PM_ENABLE } @@ -647,7 +679,27 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) /* Enable BT-related clocks */ modem_clock_module_enable(PERIPH_BT_MODULE); - modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL, 249); +#if CONFIG_BT_LE_LP_CLK_SRC_MAIN_XTAL + ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Using main XTAL as clock source"); + modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL, (320 - 1)); +#else +#if CONFIG_RTC_CLK_SRC_INT_RC + ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Using 136 kHz RC as clock source, can only run legacy ADV or SCAN due to low clock accuracy!"); + modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, MODEM_CLOCK_LPCLK_SRC_RC_SLOW, (5 - 1)); +#elif CONFIG_RTC_CLK_SRC_EXT_CRYS + ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Using external 32.768 kHz XTAL as clock source"); + modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, MODEM_CLOCK_LPCLK_SRC_XTAL32K, (1 - 1)); +#elif CONFIG_RTC_CLK_SRC_INT_RC32K + ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Using 32 kHz RC as clock source, can only run legacy ADV or SCAN due to low clock accuracy!"); + modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, MODEM_CLOCK_LPCLK_SRC_RC32K, (1 - 1)); +#elif CONFIG_RTC_CLK_SRC_EXT_OSC + ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Using 32 kHz oscillator as clock source, can only run legacy ADV or SCAN due to low clock accuracy!"); + modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, MODEM_CLOCK_LPCLK_SRC_EXT32K, (1 - 1)); +#else + ESP_LOGE(NIMBLE_PORT_LOG_TAG, "Unsupported clock source"); + assert(0); +#endif +#endif /* CONFIG_BT_LE_LP_CLK_SRC_MAIN_XTAL */ esp_phy_enable(); esp_btbb_enable(); s_ble_active = true; diff --git a/components/bt/include/esp32h2/include/esp_bt_cfg.h b/components/bt/include/esp32h2/include/esp_bt_cfg.h index 18c08563af0..339417c485a 100644 --- a/components/bt/include/esp32h2/include/esp_bt_cfg.h +++ b/components/bt/include/esp32h2/include/esp_bt_cfg.h @@ -196,7 +196,17 @@ extern "C" { #define BLE_LL_CONN_DEF_AUTH_PYLD_TMO_N (3000) +#if CONFIG_BT_LE_LP_CLK_SRC_MAIN_XTAL +#define RTC_FREQ_N (100000) /* in Hz */ +#else +#if CONFIG_RTC_CLK_SRC_INT_RC +#define RTC_FREQ_N (30000) /* in Hz */ +#elif CONFIG_RTC_CLK_SRC_EXT_CRYS #define RTC_FREQ_N (32768) /* in Hz */ +#else +#define RTC_FREQ_N (32000) /* in Hz */ +#endif +#endif /* CONFIG_BT_LE_LP_CLK_SRC_MAIN_XTAL */ #define BLE_LL_TX_PWR_DBM_N (9) diff --git a/components/esp_hw_support/include/esp_private/esp_regdma.h b/components/esp_hw_support/include/esp_private/esp_regdma.h index b1f01155569..846665c5b41 100644 --- a/components/esp_hw_support/include/esp_private/esp_regdma.h +++ b/components/esp_hw_support/include/esp_private/esp_regdma.h @@ -29,6 +29,7 @@ extern "C" { #define REGDMA_PHY_LINK(_pri) ((0x00 << 8) | _pri) #define REGDMA_PCR_LINK(_pri) ((0x01 << 8) | _pri) #define REGDMA_MODEMSYSCON_LINK(_pri) ((0x02 << 8) | _pri) +#define REGDMA_MODEMLPCON_LINK(_pri) ((0x03 << 8) | _pri) #define REGDMA_INTMTX_LINK(_pri) ((0x0d << 8) | _pri) #define REGDMA_HPSYS_LINK(_pri) ((0x0e << 8) | _pri) diff --git a/components/esp_hw_support/sleep_clock.c b/components/esp_hw_support/sleep_clock.c index 47866bfc32b..f398dc9acc9 100644 --- a/components/esp_hw_support/sleep_clock.c +++ b/components/esp_hw_support/sleep_clock.c @@ -23,6 +23,10 @@ #include "soc/pcr_reg.h" #include "modem/modem_syscon_reg.h" +#if SOC_PM_RETENTION_HAS_REGDMA_POWER_BUG +#include "modem/modem_lpcon_reg.h" +#endif + static __attribute__((unused)) const char *TAG = "sleep_clock"; esp_err_t sleep_clock_system_retention_init(void) @@ -47,9 +51,15 @@ void sleep_clock_system_retention_deinit(void) esp_err_t sleep_clock_modem_retention_init(void) { #define N_REGS_SYSCON() (((MODEM_SYSCON_MEM_CONF_REG - MODEM_SYSCON_TEST_CONF_REG) / 4) + 1) +#if SOC_PM_RETENTION_HAS_REGDMA_POWER_BUG + #define N_REGS_LPCON() (((MODEM_LPCON_MEM_CONF_REG - MODEM_LPCON_TEST_CONF_REG) / 4) + 1) +#endif const static sleep_retention_entries_config_t modem_regs_retention[] = { [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_MODEMSYSCON_LINK(0), MODEM_SYSCON_TEST_CONF_REG, MODEM_SYSCON_TEST_CONF_REG, N_REGS_SYSCON(), 0, 0), .owner = ENTRY(0) | ENTRY(1) }, /* MODEM SYSCON */ +#if SOC_PM_RETENTION_HAS_REGDMA_POWER_BUG + [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_MODEMLPCON_LINK(0), MODEM_LPCON_TEST_CONF_REG, MODEM_LPCON_TEST_CONF_REG, N_REGS_LPCON(), 0, 0), .owner = ENTRY(0) | ENTRY(1) } /* MODEM LPCON */ +#endif }; esp_err_t err = sleep_retention_entries_create(modem_regs_retention, ARRAY_SIZE(modem_regs_retention), REGDMA_LINK_PRI_2, SLEEP_RETENTION_MODULE_CLOCK_MODEM); diff --git a/components/esp_phy/esp32h2/include/btbb_retention_reg.h b/components/esp_phy/esp32h2/include/btbb_retention_reg.h new file mode 100644 index 00000000000..54a3b3d1938 --- /dev/null +++ b/components/esp_phy/esp32h2/include/btbb_retention_reg.h @@ -0,0 +1,24 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +// btbb sleep retention reg + +#define BB_PART_0_SIZE 93 +#define BB_PART_1_SIZE 62 +#define BB_PART_2_SIZE 19 +#define BB_PART_0_ADDR 0x600A2000 +#define BB_PART_1_ADDR 0x600A2800 +#define BB_PART_2_ADDR 0x600A2C00 + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_phy/src/phy_init_esp32hxx.c b/components/esp_phy/src/phy_init_esp32hxx.c index faaf3bc6cb3..36c6f4965a3 100644 --- a/components/esp_phy/src/phy_init_esp32hxx.c +++ b/components/esp_phy/src/phy_init_esp32hxx.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -12,14 +12,13 @@ #define PHY_ENABLE_VERSION_PRINT 1 static DRAM_ATTR portMUX_TYPE s_phy_int_mux = portMUX_INITIALIZER_UNLOCKED; -extern void phy_version_print(void); +extern void phy_version_print(void); static _lock_t s_phy_access_lock; /* Reference count of enabling PHY */ static uint8_t s_phy_access_ref = 0; - -extern void bt_bb_v2_init_cmplx(int print_version); +static bool s_phy_is_enabled = false; uint32_t IRAM_ATTR phy_enter_critical(void) { @@ -47,17 +46,32 @@ void esp_phy_enable(void) { _lock_acquire(&s_phy_access_lock); if (s_phy_access_ref == 0) { - register_chipv7_phy(NULL, NULL, PHY_RF_CAL_FULL); - phy_version_print(); + if (!s_phy_is_enabled) { + register_chipv7_phy(NULL, NULL, PHY_RF_CAL_FULL); + phy_version_print(); + s_phy_is_enabled = true; + } else { + phy_wakeup_init(); + } } s_phy_access_ref++; _lock_release(&s_phy_access_lock); - // ESP32H2-TODO: enable common clk. } void esp_phy_disable(void) { - // ESP32H2-TODO: close rf and disable clk for modem sleep and light sleep + _lock_acquire(&s_phy_access_lock); + + if (s_phy_access_ref) { + s_phy_access_ref--; + } + + if (s_phy_access_ref == 0) { + phy_close_rf(); + phy_xpd_tsens(); + } + + _lock_release(&s_phy_access_lock); } diff --git a/examples/bluetooth/.build-test-rules.yml b/examples/bluetooth/.build-test-rules.yml index b9ee4765de4..2ef0908f8e4 100644 --- a/examples/bluetooth/.build-test-rules.yml +++ b/examples/bluetooth/.build-test-rules.yml @@ -264,6 +264,6 @@ examples/bluetooth/nimble/hci: examples/bluetooth/nimble/power_save: enable: - - if: IDF_TARGET in ["esp32", "esp32c3", "esp32s3"] + - if: IDF_TARGET in ["esp32", "esp32c3", "esp32s3", "esp32h2"] temporary: true reason: the other targets are not tested yet diff --git a/examples/bluetooth/nimble/power_save/README.md b/examples/bluetooth/nimble/power_save/README.md index 83c69083c71..db9c0bccbe2 100644 --- a/examples/bluetooth/nimble/power_save/README.md +++ b/examples/bluetooth/nimble/power_save/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C3 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C3 | ESP32-H2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | Bluetooth Power Save Example ================================= @@ -15,11 +15,13 @@ This example contains five build configurations. For each configuration, a few c - `sdkconfig.esp32c3_40m`: ESP32C3 uses main XTAL as low power clock in light sleep enabled. - `sdkconfig.defaults.esp32s3`: ESP32S3 uses 32kHz XTAL as low power clock in light sleep enabled. - `sdkconfig.40m.esp32s3`: ESP32S3 uses main XTAL as low power clock in light sleep enabled. +- `sdkconfig.defaults.esp32h2`: ESP32H2 uses 32kHz XTAL as low power clock in light sleep enabled. +- `sdkconfig.40m.esp32h2`: ESP32H2 uses main XTAL as low power clock in light sleep enabled. ## How to use example ### Hardware Required -This example should be able to run on any commonly available ESP32/ESP32-C3/ESP32-S3 development board. +This example should be able to run on any commonly available ESP32/ESP32-C3/ESP32-S3/ESP32-H2 development board. ### Configure the project @@ -36,6 +38,8 @@ idf.py menuconfig - `(1000) configTICK_RATE_HZ` - `[*] configUSE_TICKLESS_IDLE` - `(3) configEXPECTED_IDLE_TIME_BEFORE_SLEEP` +#### For Chip ESP32/ESP32-C3/ESP32-S3: + 4. Enable power down MAC and baseband: - `Component config > PHY > [*] Power down MAC and baseband of Wi-Fi and Bluetooth when PHY is disabled` 5. Enable bluetooth modem sleep: @@ -47,6 +51,21 @@ idf.py menuconfig 7. Enable power up main XTAL during light sleep: - `Component config > Bluetooth > Controller Options > MODEM SLEEP Options > [*] power up main XTAL during light sleep` +#### For Chip ESP32-H2 + +4. Enable bluetooth modem sleep: + - `Component config > Bluetooth > Controller Options` + - `[*] Enable BLE sleep` +5. Configure bluetooth low power clock: + - `Component config → Bluetooth → Controller Options → BLE low power clock source` + - Use main XTAL as low power clock source during light sleep: + - `(X) Use main XTAL as RTC clock source` + - Use RTC clock source as low power clock sourceduring light sleep: + - `(X) Use system RTC slow clock source` +6. Power down flash during light sleep: + * `Component config → Hardware Settings → Sleep Config` + * `[*] Power down flash in light sleep when there is no SPIRAM` + ### Build and Flash ``` @@ -101,12 +120,13 @@ I (463) NimBLE: ## Typical current consumption with management enabled -| | max current | modem sleep | light sleep (main XTAL)| light sleep (32KHz XTAL)| -|-------- | ----------- | ------------ | ---------------------- |------------------------ | -| ESP32 | 231 mA | 14.1 mA | X | 1.9 mA | -| ESP32C3 | 262 mA | 12 mA | 2.3 mA | 140 uA | -| ESP32S3 | 240 mA | 17.9 mA | 3.3 mA | 230 uA | -X: This feature is currently not supported. +| | max current | modem sleep | light sleep (main XTAL) | light sleep (32KHz XTAL) | +| ------------------------------------------- | ----------- | ----------- | ----------------------- | ------------------------ | +| ESP32 | 231 mA | 14.1 mA | X | 1.9 mA | +| ESP32C3 | 262 mA | 12 mA | 2.3 mA | 140 uA | +| ESP32S3 | 240 mA | 17.9 mA | 3.3 mA | 230 uA | +| ESP32H2 | 82 mA | 16.0 mA | 4.0 mA | 24 uA | +X: This feature is currently not supported. ## Example Breakdown diff --git a/examples/bluetooth/nimble/power_save/main/Kconfig.projbuild b/examples/bluetooth/nimble/power_save/main/Kconfig.projbuild index 0819133cc1b..0058681e32c 100644 --- a/examples/bluetooth/nimble/power_save/main/Kconfig.projbuild +++ b/examples/bluetooth/nimble/power_save/main/Kconfig.projbuild @@ -2,13 +2,17 @@ menu "Example Configuration" choice EXAMPLE_MAX_CPU_FREQ prompt "Maximum CPU frequency" - default EXAMPLE_MAX_CPU_FREQ_160 + default EXAMPLE_MAX_CPU_FREQ_160 if !IDF_TARGET_ESP32H2 + default EXAMPLE_MAX_CPU_FREQ_96 if IDF_TARGET_ESP32H2 depends on PM_ENABLE help Maximum CPU frequency to use for dynamic frequency scaling. config EXAMPLE_MAX_CPU_FREQ_80 bool "80 MHz" + config EXAMPLE_MAX_CPU_FREQ_96 + bool "96 MHz" + depends on IDF_TARGET_ESP32H2 config EXAMPLE_MAX_CPU_FREQ_160 bool "160 MHz" config EXAMPLE_MAX_CPU_FREQ_240 @@ -19,12 +23,14 @@ menu "Example Configuration" config EXAMPLE_MAX_CPU_FREQ_MHZ int default 80 if EXAMPLE_MAX_CPU_FREQ_80 + default 96 if EXAMPLE_MAX_CPU_FREQ_96 default 160 if EXAMPLE_MAX_CPU_FREQ_160 default 240 if EXAMPLE_MAX_CPU_FREQ_240 choice EXAMPLE_MIN_CPU_FREQ prompt "Minimum CPU frequency" - default EXAMPLE_MIN_CPU_FREQ_40M + default EXAMPLE_MIN_CPU_FREQ_40M if !IDF_TARGET_ESP32H2 + default EXAMPLE_MIN_CPU_FREQ_32M if IDF_TARGET_ESP32H2 depends on PM_ENABLE help Minimum CPU frequency to use for dynamic frequency scaling. @@ -42,6 +48,10 @@ menu "Example Configuration" config EXAMPLE_MIN_CPU_FREQ_40M bool "40 MHz (use with 40MHz XTAL)" depends on XTAL_FREQ_40 || XTAL_FREQ_AUTO + config EXAMPLE_MIN_CPU_FREQ_32M + bool "32 MHz (use with 32MHz XTAL)" + depends on IDF_TARGET_ESP32H2 + depends on XTAL_FREQ_32 || XTAL_FREQ_AUTO config EXAMPLE_MIN_CPU_FREQ_20M bool "20 MHz (use with 40MHz XTAL)" depends on XTAL_FREQ_40 || XTAL_FREQ_AUTO @@ -54,6 +64,7 @@ menu "Example Configuration" int default 80 if EXAMPLE_MIN_CPU_FREQ_80M default 40 if EXAMPLE_MIN_CPU_FREQ_40M + default 32 if EXAMPLE_MIN_CPU_FREQ_32M default 20 if EXAMPLE_MIN_CPU_FREQ_20M default 10 if EXAMPLE_MIN_CPU_FREQ_10M diff --git a/examples/bluetooth/nimble/power_save/sdkconfig.32m.esp32h2 b/examples/bluetooth/nimble/power_save/sdkconfig.32m.esp32h2 new file mode 100644 index 00000000000..272c2592327 --- /dev/null +++ b/examples/bluetooth/nimble/power_save/sdkconfig.32m.esp32h2 @@ -0,0 +1,23 @@ +CONFIG_IDF_TARGET="esp32h2" + +# Bluetooth Low Power Config +CONFIG_BT_LE_SLEEP_ENABLE=y +# CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER is not set +CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER=y +CONFIG_BT_LE_LP_CLK_SRC_MAIN_XTAL=y +# CONFIG_BT_LE_LP_CLK_SRC_DEFAULT is not set + +# +# 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 is not set +# end of Power Management + +# +# Sleep Config +# +CONFIG_ESP_SLEEP_POWER_DOWN_FLASH=y +# end of Sleep Config diff --git a/examples/bluetooth/nimble/power_save/sdkconfig.defaults.esp32h2 b/examples/bluetooth/nimble/power_save/sdkconfig.defaults.esp32h2 new file mode 100644 index 00000000000..d034fa59737 --- /dev/null +++ b/examples/bluetooth/nimble/power_save/sdkconfig.defaults.esp32h2 @@ -0,0 +1,32 @@ +CONFIG_IDF_TARGET="esp32h2" + +# Bluetooth Low Power Config +CONFIG_BT_LE_SLEEP_ENABLE=y +# CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER is not set +CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER=y +# CONFIG_BT_LE_LP_CLK_SRC_MAIN_XTAL is not set +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 + +# +# Sleep Config +# +CONFIG_ESP_SLEEP_POWER_DOWN_FLASH=y +# end of Sleep Config + +# +# RTC Clock Config +# +# CONFIG_RTC_CLK_SRC_INT_RC is not set +CONFIG_RTC_CLK_SRC_EXT_CRYS=y +# CONFIG_RTC_CLK_SRC_EXT_OSC is not set +# CONFIG_RTC_CLK_SRC_INT_RC32K is not set +# end of RTC Clock Config