feat(ble): support ble sleep using 136 kHz RC on ESP32-C6

This commit is contained in:
cjin
2025-04-18 11:11:13 +08:00
parent 8ca72da03f
commit cc6f25ea3a
3 changed files with 89 additions and 8 deletions

View File

@ -525,6 +525,23 @@ config BT_LE_LL_SCA
help help
Sleep clock accuracy of our device (in ppm) Sleep clock accuracy of our device (in ppm)
config BT_LE_LL_PEER_SCA_SET_ENABLE
bool "Enable to set constant peer SCA"
default n
help
Enable setting of constant peer SCA, use this if peer device has SCA larger than 500 PPM.
Enable this option, the controller will always use BT_LE_LL_PEER_SCA as the peer SCA value
to calculate the window widening instead of the value received from peer device.
config BT_LE_LL_PEER_SCA
int "Constant peer sleep clock accuracy value"
range 0 10000
depends on BT_LE_LL_PEER_SCA_SET_ENABLE
default 0
help
Set the sleep clock accuracy of peer device
config BT_LE_MAX_CONNECTIONS config BT_LE_MAX_CONNECTIONS
int "Maximum number of concurrent connections" int "Maximum number of concurrent connections"
depends on !BT_NIMBLE_ENABLED depends on !BT_NIMBLE_ENABLED

View File

@ -40,6 +40,7 @@
#include "esp_pm.h" #include "esp_pm.h"
#include "esp_phy_init.h" #include "esp_phy_init.h"
#include "esp_private/periph_ctrl.h" #include "esp_private/periph_ctrl.h"
#include "esp_private/esp_clk_tree_common.h"
#include "bt_osi_mem.h" #include "bt_osi_mem.h"
#if SOC_PM_RETENTION_HAS_CLOCK_BUG #if SOC_PM_RETENTION_HAS_CLOCK_BUG
@ -150,7 +151,9 @@ extern void r_priv_sdk_config_insert_proc_time_set(uint16_t insert_proc_time);
extern sleep_retention_entries_config_t *r_esp_ble_mac_retention_link_get(uint8_t *size, uint8_t extra); extern sleep_retention_entries_config_t *r_esp_ble_mac_retention_link_get(uint8_t *size, uint8_t extra);
extern void r_esp_ble_set_wakeup_overhead(uint32_t overhead); extern void r_esp_ble_set_wakeup_overhead(uint32_t overhead);
#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */ #endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */
extern void r_esp_ble_change_rtc_freq(uint32_t freq); #if CONFIG_BT_LE_LL_PEER_SCA_SET_ENABLE
extern void r_ble_ll_customize_peer_sca_set(uint16_t peer_sca);
#endif // CONFIG_BT_LE_LL_PEER_SCA_SET_ENABLE
extern int ble_sm_alg_gen_dhkey(const uint8_t *peer_pub_key_x, extern int ble_sm_alg_gen_dhkey(const uint8_t *peer_pub_key_x,
const uint8_t *peer_pub_key_y, const uint8_t *peer_pub_key_y,
const uint8_t *our_priv_key, uint8_t *out_dhkey); const uint8_t *our_priv_key, uint8_t *out_dhkey);
@ -421,8 +424,12 @@ static bool s_ble_active = false;
#ifdef CONFIG_PM_ENABLE #ifdef CONFIG_PM_ENABLE
static DRAM_ATTR esp_pm_lock_handle_t s_pm_lock = NULL; static DRAM_ATTR esp_pm_lock_handle_t s_pm_lock = NULL;
#endif // CONFIG_PM_ENABLE #endif // CONFIG_PM_ENABLE
#define MAIN_XTAL_FREQ_HZ (40000000)
#define MAIN_XTAL_FREQ_HZ_WORKROUND (500000)
static DRAM_ATTR modem_clock_lpclk_src_t s_bt_lpclk_src = MODEM_CLOCK_LPCLK_SRC_INVALID; static DRAM_ATTR modem_clock_lpclk_src_t s_bt_lpclk_src = MODEM_CLOCK_LPCLK_SRC_INVALID;
#define BLE_RTC_DELAY_US_LIGHT_SLEEP (2500) static DRAM_ATTR uint32_t s_bt_lpclk_freq = 100000;
#define BLE_RTC_DELAY_US_LIGHT_SLEEP (3200)
#define BLE_RTC_DELAY_US_MODEM_SLEEP (500) #define BLE_RTC_DELAY_US_MODEM_SLEEP (500)
#define BLE_CONTROLLER_MALLOC_CAPS (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT|MALLOC_CAP_DMA) #define BLE_CONTROLLER_MALLOC_CAPS (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT|MALLOC_CAP_DMA)
@ -549,16 +556,21 @@ void esp_bt_rtc_slow_clk_select(uint8_t slow_clk_src)
/* Select slow clock source for BT momdule */ /* Select slow clock source for BT momdule */
switch (slow_clk_src) { switch (slow_clk_src) {
case MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL: case MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL:
ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Using main XTAL as clock source"); #if SOC_BLE_USE_WIFI_PWR_CLK_WORKAROUND
uint32_t chip_version = efuse_hal_chip_revision(); uint32_t chip_version = efuse_hal_chip_revision();
ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Using main XTAL as clock source, chip ver: %d", chip_version);
if (chip_version == 0) { if (chip_version == 0) {
modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, slow_clk_src, (400 - 1)); modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, slow_clk_src, (MAIN_XTAL_FREQ_HZ/s_bt_lpclk_freq - 1));
} else{ } else{
modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, slow_clk_src, (5 - 1)); modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, slow_clk_src, (MAIN_XTAL_FREQ_HZ_WORKROUND/s_bt_lpclk_freq - 1));
} }
#else
ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Using main XTAL as clock source");
modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, slow_clk_src, (MAIN_XTAL_FREQ_HZ/s_bt_lpclk_freq - 1));
#endif // SOC_BLE_USE_WIFI_PWR_CLK_WORKAROUND
break; break;
case MODEM_CLOCK_LPCLK_SRC_RC_SLOW: case MODEM_CLOCK_LPCLK_SRC_RC_SLOW:
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!"); ESP_LOGW(NIMBLE_PORT_LOG_TAG, "Using 136 kHz RC as clock source, use with caution as it may not maintain ACL or Sync process due to low clock accuracy!");
modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, slow_clk_src, (5 - 1)); modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, slow_clk_src, (5 - 1));
break; break;
case MODEM_CLOCK_LPCLK_SRC_XTAL32K: case MODEM_CLOCK_LPCLK_SRC_XTAL32K:
@ -584,6 +596,10 @@ modem_clock_lpclk_src_t esp_bt_get_lpclk_src(void)
void esp_bt_set_lpclk_src(modem_clock_lpclk_src_t clk_src) void esp_bt_set_lpclk_src(modem_clock_lpclk_src_t clk_src)
{ {
if (ble_controller_status != ESP_BT_CONTROLLER_STATUS_IDLE) {
return;
}
if (clk_src >= MODEM_CLOCK_LPCLK_SRC_MAX) { if (clk_src >= MODEM_CLOCK_LPCLK_SRC_MAX) {
return; return;
} }
@ -591,6 +607,38 @@ void esp_bt_set_lpclk_src(modem_clock_lpclk_src_t clk_src)
s_bt_lpclk_src = clk_src; s_bt_lpclk_src = clk_src;
} }
uint32_t esp_bt_get_lpclk_freq(void)
{
return s_bt_lpclk_freq;
}
void esp_bt_set_lpclk_freq(uint32_t clk_freq)
{
uint32_t xtal_freq;
if (ble_controller_status != ESP_BT_CONTROLLER_STATUS_IDLE) {
return;
}
if (!clk_freq) {
return;
}
xtal_freq = MAIN_XTAL_FREQ_HZ;
#if SOC_BLE_USE_WIFI_PWR_CLK_WORKAROUND
uint32_t chip_version = efuse_hal_chip_revision();
if (chip_version == 1) {
xtal_freq = MAIN_XTAL_FREQ_HZ_WORKROUND;
}
#endif // SOC_BLE_USE_WIFI_PWR_CLK_WORKAROUND
if (xtal_freq % clk_freq) {
return;
}
s_bt_lpclk_freq = clk_freq;
}
IRAM_ATTR void controller_sleep_cb(uint32_t enable_tick, void *arg) IRAM_ATTR void controller_sleep_cb(uint32_t enable_tick, void *arg)
{ {
if (!s_ble_active) { if (!s_ble_active) {
@ -612,10 +660,17 @@ IRAM_ATTR void controller_wakeup_cb(void *arg)
return; return;
} }
#ifdef CONFIG_PM_ENABLE #ifdef CONFIG_PM_ENABLE
esp_pm_config_t pm_config;
esp_pm_lock_acquire(s_pm_lock); esp_pm_lock_acquire(s_pm_lock);
esp_pm_get_configuration(&pm_config);
assert(esp_rom_get_cpu_ticks_per_us() == pm_config.max_freq_mhz);
r_ble_rtc_wake_up_state_clr(); r_ble_rtc_wake_up_state_clr();
#endif //CONFIG_PM_ENABLE #endif //CONFIG_PM_ENABLE
esp_phy_enable(PHY_MODEM_BT); esp_phy_enable(PHY_MODEM_BT);
if (s_bt_lpclk_src == MODEM_CLOCK_LPCLK_SRC_RC_SLOW) {
uint32_t *clk_freq = (uint32_t *)arg;
*clk_freq = esp_clk_tree_lp_slow_get_freq_hz(ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED) / 5;
}
s_ble_active = true; s_ble_active = true;
} }
@ -846,11 +901,12 @@ static void ble_rtc_clk_init(esp_bt_controller_config_t *cfg)
} }
if (s_bt_lpclk_src == MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL) { if (s_bt_lpclk_src == MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL) {
cfg->rtc_freq = 100000; cfg->rtc_freq = s_bt_lpclk_freq;
} else if (s_bt_lpclk_src == MODEM_CLOCK_LPCLK_SRC_XTAL32K) { } else if (s_bt_lpclk_src == MODEM_CLOCK_LPCLK_SRC_XTAL32K) {
cfg->rtc_freq = 32768; cfg->rtc_freq = 32768;
} else if (s_bt_lpclk_src == MODEM_CLOCK_LPCLK_SRC_RC_SLOW) { } else if (s_bt_lpclk_src == MODEM_CLOCK_LPCLK_SRC_RC_SLOW) {
cfg->rtc_freq = 30000; cfg->rtc_freq = esp_clk_tree_lp_slow_get_freq_hz(ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED) / 5;
cfg->ble_ll_sca = 3000;
} else if (s_bt_lpclk_src == MODEM_CLOCK_LPCLK_SRC_RC32K) { } else if (s_bt_lpclk_src == MODEM_CLOCK_LPCLK_SRC_RC32K) {
cfg->rtc_freq = 32000; cfg->rtc_freq = 32000;
} else if (s_bt_lpclk_src == MODEM_CLOCK_LPCLK_SRC_EXT32K) { } else if (s_bt_lpclk_src == MODEM_CLOCK_LPCLK_SRC_EXT32K) {
@ -949,6 +1005,10 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
goto modem_deint; goto modem_deint;
} }
#if CONFIG_BT_LE_LL_PEER_SCA_SET_ENABLE
r_ble_ll_customize_peer_sca_set(CONFIG_BT_LE_LL_PEER_SCA);
#endif // CONFIG_BT_LE_LL_PEER_SCA_SET_ENABLE
ret = ble_stack_initEnv(); ret = ble_stack_initEnv();
if (ret != ESP_OK) { if (ret != ESP_OK) {
ESP_LOGW(NIMBLE_PORT_LOG_TAG, "ble_stack_initEnv failed %d", ret); ESP_LOGW(NIMBLE_PORT_LOG_TAG, "ble_stack_initEnv failed %d", ret);

View File

@ -440,6 +440,10 @@ modem_clock_lpclk_src_t esp_bt_get_lpclk_src(void);
void esp_bt_set_lpclk_src(modem_clock_lpclk_src_t clk_src); void esp_bt_set_lpclk_src(modem_clock_lpclk_src_t clk_src);
uint32_t esp_bt_get_lpclk_freq(void);
void esp_bt_set_lpclk_freq(uint32_t clk_freq);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif