mirror of
https://github.com/espressif/esp-idf
synced 2025-03-09 17:19:09 -04:00
Merge branch 'feat/esp32_set_get_bt_lpclk_src_v5.2' into 'release/v5.2'
feat(bt): Added API to get/set low power clock source(v5.2) See merge request espressif/esp-idf!36565
This commit is contained in:
commit
a15149b557
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@ -446,7 +446,11 @@ static DRAM_ATTR uint8_t btdm_lpcycle_us_frac = 0; // number of fractional bit f
|
|||||||
|
|
||||||
#if CONFIG_BTDM_CTRL_MODEM_SLEEP_MODE_ORIG
|
#if CONFIG_BTDM_CTRL_MODEM_SLEEP_MODE_ORIG
|
||||||
// used low power clock
|
// used low power clock
|
||||||
static DRAM_ATTR uint8_t btdm_lpclk_sel;
|
#if CONFIG_BTDM_CTRL_LPCLK_SEL_EXT_32K_XTAL
|
||||||
|
static DRAM_ATTR uint8_t btdm_lpclk_sel = ESP_BT_SLEEP_CLOCK_EXT_32K_XTAL;
|
||||||
|
#else
|
||||||
|
static DRAM_ATTR uint8_t btdm_lpclk_sel = ESP_BT_SLEEP_CLOCK_MAIN_XTAL;
|
||||||
|
#endif /* CONFIG_BTDM_CTRL_LPCLK_SEL_EXT_32K_XTAL */
|
||||||
#endif /* #ifdef CONFIG_BTDM_CTRL_MODEM_SLEEP_MODE_ORIG */
|
#endif /* #ifdef CONFIG_BTDM_CTRL_MODEM_SLEEP_MODE_ORIG */
|
||||||
|
|
||||||
static DRAM_ATTR QueueHandle_t s_wakeup_req_sem = NULL;
|
static DRAM_ATTR QueueHandle_t s_wakeup_req_sem = NULL;
|
||||||
@ -1488,6 +1492,117 @@ static void hli_queue_setup_pinned_to_core(int core_id)
|
|||||||
}
|
}
|
||||||
#endif /* CONFIG_BTDM_CTRL_HLI */
|
#endif /* CONFIG_BTDM_CTRL_HLI */
|
||||||
|
|
||||||
|
// init low-power control resources
|
||||||
|
static esp_err_t btdm_low_power_mode_init(void)
|
||||||
|
{
|
||||||
|
esp_err_t err = ESP_OK;
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM_ENABLE
|
||||||
|
s_btdm_allow_light_sleep = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// set default sleep clock cycle and its fractional bits
|
||||||
|
btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT;
|
||||||
|
btdm_lpcycle_us = 2 << (btdm_lpcycle_us_frac);
|
||||||
|
|
||||||
|
#if CONFIG_BTDM_CTRL_MODEM_SLEEP_MODE_ORIG
|
||||||
|
if (btdm_lpclk_sel == ESP_BT_SLEEP_CLOCK_EXT_32K_XTAL) {
|
||||||
|
// check whether or not EXT_CRYS is working
|
||||||
|
if (rtc_clk_slow_src_get() == SOC_RTC_SLOW_CLK_SRC_XTAL32K) {
|
||||||
|
#ifdef CONFIG_PM_ENABLE
|
||||||
|
s_btdm_allow_light_sleep = true;
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
ESP_LOGW(BTDM_LOG_TAG, "32.768kHz XTAL not detected, fall back to main XTAL as Bluetooth sleep clock\n"
|
||||||
|
"light sleep mode will not be able to apply when bluetooth is enabled");
|
||||||
|
btdm_lpclk_sel = ESP_BT_SLEEP_CLOCK_MAIN_XTAL; // set default value
|
||||||
|
}
|
||||||
|
} else if (btdm_lpclk_sel != ESP_BT_SLEEP_CLOCK_MAIN_XTAL) {
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool select_src_ret __attribute__((unused));
|
||||||
|
bool set_div_ret __attribute__((unused));
|
||||||
|
if (btdm_lpclk_sel == ESP_BT_SLEEP_CLOCK_MAIN_XTAL) {
|
||||||
|
select_src_ret = btdm_lpclk_select_src(BTDM_LPCLK_SEL_XTAL);
|
||||||
|
set_div_ret = btdm_lpclk_set_div(esp_clk_xtal_freq() * 2 / MHZ - 1);
|
||||||
|
assert(select_src_ret && set_div_ret);
|
||||||
|
btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT;
|
||||||
|
btdm_lpcycle_us = 2 << (btdm_lpcycle_us_frac);
|
||||||
|
} else { // btdm_lpclk_sel == BTDM_LPCLK_SEL_XTAL32K
|
||||||
|
select_src_ret = btdm_lpclk_select_src(BTDM_LPCLK_SEL_XTAL32K);
|
||||||
|
set_div_ret = btdm_lpclk_set_div(0);
|
||||||
|
assert(select_src_ret && set_div_ret);
|
||||||
|
btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT;
|
||||||
|
btdm_lpcycle_us = (RTC_CLK_CAL_FRACT > 15) ? (1000000 << (RTC_CLK_CAL_FRACT - 15)) :
|
||||||
|
(1000000 >> (15 - RTC_CLK_CAL_FRACT));
|
||||||
|
assert(btdm_lpcycle_us != 0);
|
||||||
|
}
|
||||||
|
btdm_controller_set_sleep_mode(BTDM_MODEM_SLEEP_MODE_ORIG);
|
||||||
|
|
||||||
|
#elif CONFIG_BTDM_CTRL_MODEM_SLEEP_MODE_EVED
|
||||||
|
btdm_controller_set_sleep_mode(BTDM_MODEM_SLEEP_MODE_EVED);
|
||||||
|
#else
|
||||||
|
btdm_controller_set_sleep_mode(BTDM_MODEM_SLEEP_MODE_NONE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM_ENABLE
|
||||||
|
if (!s_btdm_allow_light_sleep) {
|
||||||
|
if ((err = esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "btLS", &s_light_sleep_pm_lock)) != ESP_OK) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "bt", &s_pm_lock)) != ESP_OK) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
esp_timer_create_args_t create_args = {
|
||||||
|
.callback = btdm_slp_tmr_callback,
|
||||||
|
.arg = NULL,
|
||||||
|
.name = "btSlp"
|
||||||
|
};
|
||||||
|
if ((err = esp_timer_create(&create_args, &s_btdm_slp_tmr)) != ESP_OK) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
s_pm_lock_acquired = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_bt_sleep_clock_t esp_bt_get_lpclk_src(void)
|
||||||
|
{
|
||||||
|
#if CONFIG_BTDM_CTRL_MODEM_SLEEP_MODE_ORIG
|
||||||
|
if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_INITED &&
|
||||||
|
btdm_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED) {
|
||||||
|
return ESP_BT_SLEEP_CLOCK_NONE;
|
||||||
|
}
|
||||||
|
return btdm_lpclk_sel;
|
||||||
|
#else
|
||||||
|
return ESP_BT_SLEEP_CLOCK_NONE;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_bt_set_lpclk_src(esp_bt_sleep_clock_t lpclk)
|
||||||
|
{
|
||||||
|
#if CONFIG_BTDM_CTRL_MODEM_SLEEP_MODE_ORIG
|
||||||
|
if (lpclk < ESP_BT_SLEEP_CLOCK_MAIN_XTAL || lpclk > ESP_BT_SLEEP_CLOCK_EXT_32K_XTAL) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (btdm_controller_status == ESP_BT_CONTROLLER_STATUS_INITED ||
|
||||||
|
btdm_controller_status == ESP_BT_CONTROLLER_STATUS_ENABLED) {
|
||||||
|
ESP_LOGW(BTDM_LOG_TAG, "Please set the Bluetooth sleep clock source before Bluetooth initialization");
|
||||||
|
return ESP_ERR_INVALID_STATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
btdm_lpclk_sel = lpclk;
|
||||||
|
return ESP_OK;
|
||||||
|
#else
|
||||||
|
return ESP_ERR_NOT_SUPPORTED;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
|
esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
|
||||||
{
|
{
|
||||||
esp_err_t err;
|
esp_err_t err;
|
||||||
@ -1552,84 +1667,16 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
|
|||||||
periph_module_enable(PERIPH_BT_MODULE);
|
periph_module_enable(PERIPH_BT_MODULE);
|
||||||
periph_module_reset(PERIPH_BT_MODULE);
|
periph_module_reset(PERIPH_BT_MODULE);
|
||||||
|
|
||||||
#ifdef CONFIG_PM_ENABLE
|
|
||||||
s_btdm_allow_light_sleep = false;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// set default sleep clock cycle and its fractional bits
|
|
||||||
btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT;
|
|
||||||
btdm_lpcycle_us = 2 << (btdm_lpcycle_us_frac);
|
|
||||||
|
|
||||||
#if CONFIG_BTDM_CTRL_MODEM_SLEEP_MODE_ORIG
|
|
||||||
|
|
||||||
btdm_lpclk_sel = BTDM_LPCLK_SEL_XTAL; // set default value
|
|
||||||
#if CONFIG_BTDM_CTRL_LPCLK_SEL_EXT_32K_XTAL
|
|
||||||
// check whether or not EXT_CRYS is working
|
|
||||||
if (rtc_clk_slow_src_get() == SOC_RTC_SLOW_CLK_SRC_XTAL32K) {
|
|
||||||
btdm_lpclk_sel = BTDM_LPCLK_SEL_XTAL32K; // External 32kHz XTAL
|
|
||||||
#ifdef CONFIG_PM_ENABLE
|
|
||||||
s_btdm_allow_light_sleep = true;
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
ESP_LOGW(BTDM_LOG_TAG, "32.768kHz XTAL not detected, fall back to main XTAL as Bluetooth sleep clock\n"
|
|
||||||
"light sleep mode will not be able to apply when bluetooth is enabled");
|
|
||||||
btdm_lpclk_sel = BTDM_LPCLK_SEL_XTAL; // set default value
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
btdm_lpclk_sel = BTDM_LPCLK_SEL_XTAL; // set default value
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool select_src_ret __attribute__((unused));
|
|
||||||
bool set_div_ret __attribute__((unused));
|
|
||||||
if (btdm_lpclk_sel == BTDM_LPCLK_SEL_XTAL) {
|
|
||||||
select_src_ret = btdm_lpclk_select_src(BTDM_LPCLK_SEL_XTAL);
|
|
||||||
set_div_ret = btdm_lpclk_set_div(esp_clk_xtal_freq() * 2 / MHZ - 1);
|
|
||||||
assert(select_src_ret && set_div_ret);
|
|
||||||
btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT;
|
|
||||||
btdm_lpcycle_us = 2 << (btdm_lpcycle_us_frac);
|
|
||||||
} else { // btdm_lpclk_sel == BTDM_LPCLK_SEL_XTAL32K
|
|
||||||
select_src_ret = btdm_lpclk_select_src(BTDM_LPCLK_SEL_XTAL32K);
|
|
||||||
set_div_ret = btdm_lpclk_set_div(0);
|
|
||||||
assert(select_src_ret && set_div_ret);
|
|
||||||
btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT;
|
|
||||||
btdm_lpcycle_us = (RTC_CLK_CAL_FRACT > 15) ? (1000000 << (RTC_CLK_CAL_FRACT - 15)) :
|
|
||||||
(1000000 >> (15 - RTC_CLK_CAL_FRACT));
|
|
||||||
assert(btdm_lpcycle_us != 0);
|
|
||||||
}
|
|
||||||
btdm_controller_set_sleep_mode(BTDM_MODEM_SLEEP_MODE_ORIG);
|
|
||||||
|
|
||||||
#elif CONFIG_BTDM_CTRL_MODEM_SLEEP_MODE_EVED
|
|
||||||
btdm_controller_set_sleep_mode(BTDM_MODEM_SLEEP_MODE_EVED);
|
|
||||||
#else
|
|
||||||
btdm_controller_set_sleep_mode(BTDM_MODEM_SLEEP_MODE_NONE);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if CONFIG_BTDM_CTRL_HCI_UART_FLOW_CTRL_EN
|
#if CONFIG_BTDM_CTRL_HCI_UART_FLOW_CTRL_EN
|
||||||
sdk_config_set_uart_flow_ctrl_enable(true);
|
sdk_config_set_uart_flow_ctrl_enable(true);
|
||||||
#else
|
#else
|
||||||
sdk_config_set_uart_flow_ctrl_enable(false);
|
sdk_config_set_uart_flow_ctrl_enable(false);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_PM_ENABLE
|
if ((err = btdm_low_power_mode_init()) != ESP_OK) {
|
||||||
if (!s_btdm_allow_light_sleep) {
|
ESP_LOGE(BTDM_LOG_TAG, "Low power module initialization failed");
|
||||||
if ((err = esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "btLS", &s_light_sleep_pm_lock)) != ESP_OK) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "bt", &s_pm_lock)) != ESP_OK) {
|
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
esp_timer_create_args_t create_args = {
|
|
||||||
.callback = btdm_slp_tmr_callback,
|
|
||||||
.arg = NULL,
|
|
||||||
.name = "btSlp"
|
|
||||||
};
|
|
||||||
if ((err = esp_timer_create(&create_args, &s_btdm_slp_tmr)) != ESP_OK) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
s_pm_lock_acquired = true;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if CONFIG_SW_COEXIST_ENABLE
|
#if CONFIG_SW_COEXIST_ENABLE
|
||||||
coex_init();
|
coex_init();
|
||||||
@ -1669,10 +1716,9 @@ esp_err_t esp_bt_controller_deinit(void)
|
|||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bt_controller_deinit_internal(void)
|
// deinit low power control resources
|
||||||
|
static void btdm_low_power_mode_deinit(void)
|
||||||
{
|
{
|
||||||
periph_module_disable(PERIPH_BT_MODULE);
|
|
||||||
|
|
||||||
#ifdef CONFIG_PM_ENABLE
|
#ifdef CONFIG_PM_ENABLE
|
||||||
if (!s_btdm_allow_light_sleep) {
|
if (!s_btdm_allow_light_sleep) {
|
||||||
esp_pm_lock_delete(s_light_sleep_pm_lock);
|
esp_pm_lock_delete(s_light_sleep_pm_lock);
|
||||||
@ -1693,6 +1739,16 @@ static void bt_controller_deinit_internal(void)
|
|||||||
s_pm_lock_acquired = false;
|
s_pm_lock_acquired = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
btdm_lpcycle_us = 0;
|
||||||
|
btdm_controller_set_sleep_mode(BTDM_MODEM_SLEEP_MODE_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bt_controller_deinit_internal(void)
|
||||||
|
{
|
||||||
|
periph_module_disable(PERIPH_BT_MODULE);
|
||||||
|
|
||||||
|
btdm_low_power_mode_deinit();
|
||||||
|
|
||||||
if (s_wakeup_req_sem) {
|
if (s_wakeup_req_sem) {
|
||||||
semphr_delete_wrapper(s_wakeup_req_sem);
|
semphr_delete_wrapper(s_wakeup_req_sem);
|
||||||
s_wakeup_req_sem = NULL;
|
s_wakeup_req_sem = NULL;
|
||||||
@ -1705,9 +1761,6 @@ static void bt_controller_deinit_internal(void)
|
|||||||
|
|
||||||
btdm_controller_status = ESP_BT_CONTROLLER_STATUS_IDLE;
|
btdm_controller_status = ESP_BT_CONTROLLER_STATUS_IDLE;
|
||||||
|
|
||||||
btdm_lpcycle_us = 0;
|
|
||||||
btdm_controller_set_sleep_mode(BTDM_MODEM_SLEEP_MODE_NONE);
|
|
||||||
|
|
||||||
esp_bt_power_domain_off();
|
esp_bt_power_domain_off();
|
||||||
|
|
||||||
esp_phy_modem_deinit();
|
esp_phy_modem_deinit();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@ -393,6 +393,15 @@ typedef enum {
|
|||||||
ESP_SCO_DATA_PATH_PCM = 1, /*!< data over PCM interface */
|
ESP_SCO_DATA_PATH_PCM = 1, /*!< data over PCM interface */
|
||||||
} esp_sco_data_path_t;
|
} esp_sco_data_path_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Bluetooth sleep clock
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
ESP_BT_SLEEP_CLOCK_NONE = 0, /*!< Sleep clock not configured */
|
||||||
|
ESP_BT_SLEEP_CLOCK_MAIN_XTAL = 1, /*!< SoC main crystal */
|
||||||
|
ESP_BT_SLEEP_CLOCK_EXT_32K_XTAL = 2, /*!< External 32.768kHz crystal/oscillator */
|
||||||
|
} esp_bt_sleep_clock_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Initialize the Bluetooth Controller to allocate tasks and other resources
|
* @brief Initialize the Bluetooth Controller to allocate tasks and other resources
|
||||||
*
|
*
|
||||||
@ -705,6 +714,29 @@ void esp_wifi_bt_power_domain_on(void);
|
|||||||
*/
|
*/
|
||||||
void esp_wifi_bt_power_domain_off(void);
|
void esp_wifi_bt_power_domain_off(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the Bluetooth module sleep clock source.
|
||||||
|
*
|
||||||
|
* @note This function should be called after `esp_bt_controller_init()`
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - Clock source used in Bluetooth low power mode
|
||||||
|
*/
|
||||||
|
esp_bt_sleep_clock_t esp_bt_get_lpclk_src(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the Bluetooth module sleep clock source.
|
||||||
|
*
|
||||||
|
* @note This function should be called before `esp_bt_controller_init()`
|
||||||
|
*
|
||||||
|
* @param[in] lpclk Bluetooth sleep clock source
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK: Success
|
||||||
|
* - ESP_ERR_INVALID_ARG: Invalid argument
|
||||||
|
*/
|
||||||
|
esp_err_t esp_bt_set_lpclk_src(esp_bt_sleep_clock_t lpclk);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user