change(ble): support ble light sleep using ext 32k xtal on C2

pull/13550/head
cjin 2024-03-06 12:29:10 +08:00 zatwierdzone przez BOT
rodzic 5e443311da
commit edb3f70562
8 zmienionych plików z 144 dodań i 53 usunięć

Wyświetl plik

@ -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

Wyświetl plik

@ -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;

Wyświetl plik

@ -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
*/

Wyświetl plik

@ -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
*/

Wyświetl plik

@ -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
*/

Wyświetl plik

@ -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.
- 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

Wyświetl plik

@ -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

Wyświetl plik

@ -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