diff --git a/components/bt/controller/esp32c2/Kconfig.in b/components/bt/controller/esp32c2/Kconfig.in index 05e15708f1..9e33fc8d7b 100644 --- a/components/bt/controller/esp32c2/Kconfig.in +++ b/components/bt/controller/esp32c2/Kconfig.in @@ -421,6 +421,26 @@ config BT_LE_SLEEP_ENABLE help Enable BLE sleep +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 at pin0 supports only + legacy ADV and SCAN due to low clock accuracy. + +endchoice + config BT_LE_USE_ESP_TIMER bool "Use Esp Timer for callout" depends on !BT_NIMBLE_ENABLED diff --git a/components/bt/controller/esp32c2/bt.c b/components/bt/controller/esp32c2/bt.c index f8f3e0e532..4309aa3e73 100644 --- a/components/bt/controller/esp32c2/bt.c +++ b/components/bt/controller/esp32c2/bt.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -54,12 +54,14 @@ #include "freertos/task.h" #include "esp_private/periph_ctrl.h" +#include "esp_private/esp_clk.h" #include "esp_sleep.h" #include "soc/syscon_reg.h" #include "soc/dport_access.h" #include "hal/efuse_ll.h" +#include "soc/rtc.h" /* Macro definition ************************************************************************ */ @@ -78,6 +80,11 @@ #define ACL_DATA_MBUF_LEADINGSPCAE 4 #endif // CONFIG_BT_BLUEDROID_ENABLED +typedef enum ble_rtc_slow_clk_src { + BT_SLOW_CLK_SRC_MAIN_XTAL, + BT_SLOW_CLK_SRC_32K_XTAL_ON_PIN0, +} ble_rtc_slow_clk_src_t; + /* Types definition ************************************************************************ */ @@ -487,7 +494,7 @@ IRAM_ATTR void controller_wakeup_cb(void *arg) s_ble_active = true; } -esp_err_t controller_sleep_init(void) +esp_err_t controller_sleep_init(ble_rtc_slow_clk_src_t slow_clk_src) { esp_err_t rc = 0; #ifdef CONFIG_BT_LE_SLEEP_ENABLE @@ -495,7 +502,11 @@ esp_err_t controller_sleep_init(void) r_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); + if (slow_clk_src == BT_SLOW_CLK_SRC_MAIN_XTAL) { + esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_ON); + } else { + esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_AUTO); + } #endif // CONFIG_PM_ENABLE #endif // CONFIG_BT_LE_SLEEP_ENABLE @@ -546,37 +557,74 @@ void controller_sleep_deinit(void) #endif //CONFIG_PM_ENABLE } -void ble_rtc_clk_init(void) +static void esp_bt_rtc_slow_clk_select(ble_rtc_slow_clk_src_t slow_clk_src) { - // modem_clkrst_reg - // LP_TIMER_SEL_XTAL32K -> 0 - // LP_TIMER_SEL_XTAL -> 1 - // LP_TIMER_SEL_8M -> 0 - // LP_TIMER_SEL_RTC_SLOW -> 0 - SET_PERI_REG_BITS(MODEM_CLKRST_MODEM_LP_TIMER_CONF_REG, 1, 0, MODEM_CLKRST_LP_TIMER_SEL_XTAL32K_S); - SET_PERI_REG_BITS(MODEM_CLKRST_MODEM_LP_TIMER_CONF_REG, 1, 1, MODEM_CLKRST_LP_TIMER_SEL_XTAL_S); - SET_PERI_REG_BITS(MODEM_CLKRST_MODEM_LP_TIMER_CONF_REG, 1, 0, MODEM_CLKRST_LP_TIMER_SEL_8M_S); - SET_PERI_REG_BITS(MODEM_CLKRST_MODEM_LP_TIMER_CONF_REG, 1, 0, MODEM_CLKRST_LP_TIMER_SEL_RTC_SLOW_S); - + /* Select slow clock source for BT momdule */ + switch (slow_clk_src) { + case BT_SLOW_CLK_SRC_MAIN_XTAL: + ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Using main XTAL as clock source"); + SET_PERI_REG_BITS(MODEM_CLKRST_MODEM_LP_TIMER_CONF_REG, 1, 0, MODEM_CLKRST_LP_TIMER_SEL_XTAL32K_S); + SET_PERI_REG_BITS(MODEM_CLKRST_MODEM_LP_TIMER_CONF_REG, 1, 1, MODEM_CLKRST_LP_TIMER_SEL_XTAL_S); + SET_PERI_REG_BITS(MODEM_CLKRST_MODEM_LP_TIMER_CONF_REG, 1, 0, MODEM_CLKRST_LP_TIMER_SEL_8M_S); + SET_PERI_REG_BITS(MODEM_CLKRST_MODEM_LP_TIMER_CONF_REG, 1, 0, MODEM_CLKRST_LP_TIMER_SEL_RTC_SLOW_S); #ifdef CONFIG_XTAL_FREQ_26 - // LP_TIMER_CLK_DIV_NUM -> 130 - SET_PERI_REG_BITS(MODEM_CLKRST_MODEM_LP_TIMER_CONF_REG, MODEM_CLKRST_LP_TIMER_CLK_DIV_NUM, 129, MODEM_CLKRST_LP_TIMER_CLK_DIV_NUM_S); + SET_PERI_REG_BITS(MODEM_CLKRST_MODEM_LP_TIMER_CONF_REG, MODEM_CLKRST_LP_TIMER_CLK_DIV_NUM, 129, MODEM_CLKRST_LP_TIMER_CLK_DIV_NUM_S); #else - // LP_TIMER_CLK_DIV_NUM -> 250 - SET_PERI_REG_BITS(MODEM_CLKRST_MODEM_LP_TIMER_CONF_REG, MODEM_CLKRST_LP_TIMER_CLK_DIV_NUM, 249, MODEM_CLKRST_LP_TIMER_CLK_DIV_NUM_S); + SET_PERI_REG_BITS(MODEM_CLKRST_MODEM_LP_TIMER_CONF_REG, MODEM_CLKRST_LP_TIMER_CLK_DIV_NUM, 249, MODEM_CLKRST_LP_TIMER_CLK_DIV_NUM_S); #endif // CONFIG_XTAL_FREQ_26 - - // MODEM_CLKRST_ETM_CLK_ACTIVE -> 1 - // MODEM_CLKRST_ETM_CLK_SEL -> 0 + break; + case BT_SLOW_CLK_SRC_32K_XTAL_ON_PIN0: + ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Using external 32.768 kHz XTAL as clock source"); + SET_PERI_REG_BITS(MODEM_CLKRST_MODEM_LP_TIMER_CONF_REG, 1, 1, MODEM_CLKRST_LP_TIMER_SEL_XTAL32K_S); + SET_PERI_REG_BITS(MODEM_CLKRST_MODEM_LP_TIMER_CONF_REG, 1, 0, MODEM_CLKRST_LP_TIMER_SEL_XTAL_S); + SET_PERI_REG_BITS(MODEM_CLKRST_MODEM_LP_TIMER_CONF_REG, 1, 0, MODEM_CLKRST_LP_TIMER_SEL_8M_S); + SET_PERI_REG_BITS(MODEM_CLKRST_MODEM_LP_TIMER_CONF_REG, 1, 0, MODEM_CLKRST_LP_TIMER_SEL_RTC_SLOW_S); + SET_PERI_REG_BITS(MODEM_CLKRST_MODEM_LP_TIMER_CONF_REG, MODEM_CLKRST_LP_TIMER_CLK_DIV_NUM, 0, MODEM_CLKRST_LP_TIMER_CLK_DIV_NUM_S); + break; + default: + ESP_LOGE(NIMBLE_PORT_LOG_TAG, "Unsupported slow clock"); + assert(0); + break; + } SET_PERI_REG_BITS(MODEM_CLKRST_ETM_CLK_CONF_REG, 1, 1, MODEM_CLKRST_ETM_CLK_ACTIVE_S); SET_PERI_REG_BITS(MODEM_CLKRST_ETM_CLK_CONF_REG, 1, 0, MODEM_CLKRST_ETM_CLK_SEL_S); +} +static ble_rtc_slow_clk_src_t ble_rtc_clk_init(esp_bt_controller_config_t *cfg) +{ + ble_rtc_slow_clk_src_t slow_clk_src; + +#if CONFIG_BT_LE_LP_CLK_SRC_MAIN_XTAL +#ifdef CONFIG_XTAL_FREQ_26 + cfg->rtc_freq = 40000; +#else + cfg->rtc_freq = 32000; +#endif // CONFIG_XTAL_FREQ_26 + slow_clk_src = BT_SLOW_CLK_SRC_MAIN_XTAL; +#else + if (rtc_clk_slow_src_get() == SOC_RTC_SLOW_CLK_SRC_OSC_SLOW) { + cfg->rtc_freq = 32768; + slow_clk_src = BT_SLOW_CLK_SRC_32K_XTAL_ON_PIN0; + } else { + ESP_LOGW(NIMBLE_PORT_LOG_TAG, "32.768kHz XTAL not detected, fall back to main XTAL as Bluetooth sleep clock"); +#ifdef CONFIG_XTAL_FREQ_26 + cfg->rtc_freq = 40000; +#else + cfg->rtc_freq = 32000; +#endif // CONFIG_XTAL_FREQ_26 + slow_clk_src = BT_SLOW_CLK_SRC_MAIN_XTAL; + } +#endif /* CONFIG_BT_LE_LP_CLK_SRC_MAIN_XTAL */ + esp_bt_rtc_slow_clk_select(slow_clk_src); + return slow_clk_src; } esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) { esp_err_t ret = ESP_OK; ble_npl_count_info_t npl_info; + ble_rtc_slow_clk_src_t rtc_clk_src; + memset(&npl_info, 0, sizeof(ble_npl_count_info_t)); if (ble_controller_status != ESP_BT_CONTROLLER_STATUS_IDLE) { ESP_LOGW(NIMBLE_PORT_LOG_TAG, "invalid controller state"); @@ -588,7 +636,7 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) return ESP_ERR_INVALID_ARG; } - ble_rtc_clk_init(); + rtc_clk_src = ble_rtc_clk_init(cfg); ret = esp_register_ext_funcs(&ext_funcs_ro); if (ret != ESP_OK) { @@ -644,7 +692,6 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) #if CONFIG_SW_COEXIST_ENABLE coex_init(); #endif - ret = ble_controller_init(cfg); if (ret != ESP_OK) { ESP_LOGW(NIMBLE_PORT_LOG_TAG, "ble_controller_init failed %d", ret); @@ -675,7 +722,7 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) } #endif // CONFIG_BT_CONTROLLER_LOG_ENABLED - ret = controller_sleep_init(); + ret = controller_sleep_init(rtc_clk_src); if (ret != ESP_OK) { ESP_LOGW(NIMBLE_PORT_LOG_TAG, "controller_sleep_init failed %d", ret); goto free_controller; diff --git a/components/bt/controller/esp32c2/esp_bt_cfg.h b/components/bt/controller/esp32c2/esp_bt_cfg.h index 308d79e3eb..1f0d74e1e2 100644 --- a/components/bt/controller/esp32c2/esp_bt_cfg.h +++ b/components/bt/controller/esp32c2/esp_bt_cfg.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ diff --git a/components/bt/controller/esp32c6/bt.c b/components/bt/controller/esp32c6/bt.c index dbb6ed23e6..1197bf7f40 100644 --- a/components/bt/controller/esp32c6/bt.c +++ b/components/bt/controller/esp32c6/bt.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ diff --git a/components/bt/controller/esp32h2/bt.c b/components/bt/controller/esp32h2/bt.c index f5e31e69a3..b36cc28fa5 100644 --- a/components/bt/controller/esp32h2/bt.c +++ b/components/bt/controller/esp32h2/bt.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ diff --git a/examples/bluetooth/nimble/power_save/README.md b/examples/bluetooth/nimble/power_save/README.md index de9c6e5e1c..bfad7b536d 100644 --- a/examples/bluetooth/nimble/power_save/README.md +++ b/examples/bluetooth/nimble/power_save/README.md @@ -20,7 +20,9 @@ This example contains some build configurations. For each configuration, a few c - `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.32m.esp32h2`: ESP32H2 uses main XTAL as low power clock in light sleep enabled. -- `sdkconfig.defaults.esp32c2`: ESP32C2 uses main XTAL as low power clock in light sleep enabled. +- `sdkconfig.defaults.esp32c2`: ESP32C2 uses 32kHz XTAL as low power clock in light sleep enabled. +- `sdkconfig.26m.esp32c2`: ESP32C2 uses main XTAL as low power clock in light sleep enabled. + ## How to use example ### Hardware Required @@ -39,9 +41,10 @@ idf.py menuconfig - `Component config > Power Management > [*] Support for power management` 3. Configure FreeRTOS: - `Component config > FreeRTOS > Kernel` - - `(1000) configTICK_RATE_HZ` - - `[*] configUSE_TICKLESS_IDLE` - - `(3) configEXPECTED_IDLE_TIME_BEFORE_SLEEP` + - `(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: @@ -55,28 +58,19 @@ 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-C6/ESP32-H2 +#### For Chip ESP32-C6/ESP32-H2/ESP32-C2 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 RTC clock source as low power clock sourceduring light sleep: + - Use RTC clock source as low power clock source during 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` -#### For Chip ESP32-C2 - -4. Enable bluetooth modem sleep: - - `Component config > Bluetooth > Controller Options` - - `[*] Enable BLE sleep` -5. 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 ``` @@ -102,7 +96,7 @@ See the Getting Started Guide for full steps to configure and use ESP-IDF to bui ## Example Output -When you run this example, the prints the following at the very begining: +When you run this example, the prints the following at the very beginning: ``` I (333) cpu_start: Starting scheduler. @@ -131,17 +125,19 @@ 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 | -| ESP32C6 | 240 mA | 22 mA | 3.3 mA | 34 uA | -| ESP32H2 | 82 mA | 16.0 mA | 4.0 mA | 24 uA | -| ESP32C2 | 130 mA | 18.0 mA | 2.5 mA | X | +| | 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 | +| ESP32C6 | 240 mA | 22 mA | 3.3 mA | 34 uA | +| ESP32H2 | 82 mA | 16.0 mA | 4.0 mA | 24 uA | +| ESP32C2 | 130 mA | 18.0 mA | 2.5 mA | 169 uA | + X: This feature is currently not supported. ## Example Breakdown - ESP32 does not support the use of main XTAL in light sleep mode, so an external 32kHz crystal is required. -- ESP32C2 does not support the use of 32KHz XTAL in light sleep mode, the XTAL frequency is set to 26MHz in default. \ No newline at end of file +- ESP32C2 support XTAL frequency of 26MHz and 40MHz, the XTAL frequency is set to 26MHz in default. +- ESP32C2 support external 32kHz crystal by connecting the crystal to the chip through pin0 \ No newline at end of file diff --git a/examples/bluetooth/nimble/power_save/sdkconfig.26m.esp32c2 b/examples/bluetooth/nimble/power_save/sdkconfig.26m.esp32c2 new file mode 100644 index 0000000000..b9121b6153 --- /dev/null +++ b/examples/bluetooth/nimble/power_save/sdkconfig.26m.esp32c2 @@ -0,0 +1,24 @@ +CONFIG_IDF_TARGET="esp32c2" + +# Bluetooth Low Power Config +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 + +# +# 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.defaults.esp32c2 b/examples/bluetooth/nimble/power_save/sdkconfig.defaults.esp32c2 index 00b2b40f9d..55320c019a 100644 --- a/examples/bluetooth/nimble/power_save/sdkconfig.defaults.esp32c2 +++ b/examples/bluetooth/nimble/power_save/sdkconfig.defaults.esp32c2 @@ -1,7 +1,8 @@ -CONFIG_IDF_TARGET="esp32h2" +CONFIG_IDF_TARGET="esp32c2" # Bluetooth Low Power Config CONFIG_BT_LE_SLEEP_ENABLE=y +CONFIG_BT_LE_LP_CLK_SRC_DEFAULT=y # # Power Management @@ -18,3 +19,6 @@ CONFIG_XTAL_FREQ=26 # CONFIG_ESP_SLEEP_POWER_DOWN_FLASH=y CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION=y + +# RTC clock source +CONFIG_RTC_CLK_SRC_EXT_OSC=y