Merge branch 'feature/btdm_modem_sleep_with_32K_XTAL_under_light_sleep' into 'master'
Feature/btdm modem sleep with 32 k xtal under light sleep See merge request idf/esp-idf!4744
This commit is contained in:
commit
b859584f91
4 changed files with 94 additions and 11 deletions
|
@ -161,23 +161,65 @@ menu Bluetooth
|
|||
prompt "Bluetooth low power clock"
|
||||
depends on BTDM_MODEM_SLEEP_MODE_ORIG
|
||||
help
|
||||
Select the low power clock source for bluetooth controller
|
||||
Select the low power clock source for bluetooth controller. Bluetooth low power clock is
|
||||
the clock source to maintain time in sleep mode.
|
||||
|
||||
- "Main crystal" option provides good accuracy and can support Dynamic Frequency Scaling
|
||||
to be used with Bluetooth modem sleep. Light sleep is not supported.
|
||||
- "External 32kHz crystal" option allows user to use a 32.768kHz crystal as Bluetooth low
|
||||
power clock. This option is allowed as long as External 32kHz crystal is configured as
|
||||
the system RTC clock source. This option provides good accuracy and supports Bluetooth
|
||||
modem sleep to be used alongside Dynamic Frequency Scaling or light sleep.
|
||||
|
||||
config BTDM_LPCLK_SEL_MAIN_XTAL
|
||||
bool "Main crystal"
|
||||
help
|
||||
Main crystal can be used as low power clock for bluetooth modem sleep. If this option is
|
||||
selected, bluetooth modem sleep can work under Dynamic Frequency Scaling(DFS) enabled, but
|
||||
cannot work when light sleep is enabled. Main crystal has a relatively better performance than
|
||||
other bluetooth low power clock sources.
|
||||
cannot work when light sleep is enabled. Main crystal has a good performance in accuracy as
|
||||
the bluetooth low power clock source.
|
||||
|
||||
config BTDM_LPCLK_SEL_EXT_32K_XTAL
|
||||
bool "External 32kHz crystal"
|
||||
depends on ESP32_RTC_CLK_SRC_EXT_CRYS
|
||||
help
|
||||
External 32kHz crystal has a nominal frequency of 32.768kHz and provides good frequency
|
||||
stability. If used as Bluetooth low power clock, External 32kHz can support Bluetooth
|
||||
modem sleep to be used with both DFS and light sleep.
|
||||
endchoice
|
||||
|
||||
endmenu
|
||||
|
||||
choice BTDM_BLE_SLEEP_CLOCK_ACCURACY
|
||||
prompt "BLE Sleep Clock Accuracy"
|
||||
depends on BTDM_CTRL_MODE_BLE_ONLY || BTDM_CTRL_MODE_BTDM
|
||||
default BTDM_BLE_DEFAULT_SCA_250PPM
|
||||
help
|
||||
BLE Sleep Clock Accuracy(SCA) for the local device is used to estimate window widening in BLE
|
||||
connection events. With a lower level of clock accuracy(e.g. 500ppm over 250ppm), the slave
|
||||
needs a larger RX window to synchronize with master in each anchor point, thus resulting in an
|
||||
increase of power consumption but a higher level of robustness in keeping connected. According
|
||||
to the requirements of Bluetooth Core specification 4.2, the worst-case accuracy of Classic
|
||||
Bluetooth low power oscialltor(LPO) is +/-250ppm in STANDBY and in low power modes such as
|
||||
sniff. For BLE the worst-case SCA is +/-500ppm.
|
||||
|
||||
- "151ppm to 250ppm" option is the default value for Bluetooth Dual mode
|
||||
- "251ppm to 500ppm" option can be used in BLE only mode when using external 32kHz crystal as
|
||||
low power clock. This option is provided in case that BLE sleep clock has a lower level of
|
||||
accuracy, or other error sources contribute to the inaccurate timing during sleep.
|
||||
|
||||
config BTDM_BLE_DEFAULT_SCA_500PPM
|
||||
bool "251ppm to 500ppm"
|
||||
depends on BTDM_LPCLK_SEL_EXT_32K_XTAL && BTDM_CTRL_MODE_BLE_ONLY
|
||||
config BTDM_BLE_DEFAULT_SCA_250PPM
|
||||
bool "151ppm to 250ppm"
|
||||
endchoice
|
||||
config BTDM_BLE_SLEEP_CLOCK_ACCURACY_INDEX_EFF
|
||||
int
|
||||
default 0 if BTDM_BLE_DEFAULT_SCA_500PPM
|
||||
default 1 if BTDM_BLE_DEFAULT_SCA_250PPM
|
||||
default 1
|
||||
|
||||
config BTDM_BLE_SCAN_DUPL
|
||||
bool "BLE Scan Duplicate Options"
|
||||
depends on (BTDM_CTRL_MODE_BTDM || BTDM_CTRL_MODE_BLE_ONLY)
|
||||
|
|
|
@ -79,6 +79,14 @@
|
|||
#define BTDM_MIN_SLEEP_DURATION (12) // threshold of interval in slots to allow to fall into modem sleep
|
||||
#define BTDM_MODEM_WAKE_UP_DELAY (4) // delay in slots of modem wake up procedure, including re-enable PHY/RF
|
||||
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
#ifndef CONFIG_BTDM_LPCLK_SEL_MAIN_XTAL
|
||||
#define BTDM_ALLOW_LIGHT_SLEEP 1
|
||||
#else
|
||||
#define BTDM_ALLOW_LIGHT_SLEEP 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define BT_DEBUG(...)
|
||||
#define BT_API_CALL_CHECK(info, api_call, ret) \
|
||||
do{\
|
||||
|
@ -373,8 +381,11 @@ static DRAM_ATTR uint8_t btdm_lpcycle_us_frac = 0; // number of fractional bit f
|
|||
#ifdef CONFIG_PM_ENABLE
|
||||
static DRAM_ATTR esp_timer_handle_t s_btdm_slp_tmr;
|
||||
static DRAM_ATTR esp_pm_lock_handle_t s_pm_lock;
|
||||
static DRAM_ATTR esp_pm_lock_handle_t s_light_sleep_pm_lock; // pm_lock to prevent light sleep due to incompatibility currently
|
||||
static DRAM_ATTR QueueHandle_t s_pm_lock_sem = NULL;
|
||||
#if !BTDM_ALLOW_LIGHT_SLEEP
|
||||
// pm_lock to prevent light sleep when using main crystal as Bluetooth low power clock
|
||||
static DRAM_ATTR esp_pm_lock_handle_t s_light_sleep_pm_lock;
|
||||
#endif /* #if !BTDM_ALLOW_LIGHT_SLEEP */
|
||||
static void btdm_slp_tmr_callback(void *arg);
|
||||
#endif
|
||||
|
||||
|
@ -807,7 +818,7 @@ static void btdm_sleep_enter_phase1_wrapper(uint32_t lpcycles)
|
|||
// start a timer to wake up and acquire the pm_lock before modem_sleep awakes
|
||||
uint32_t us_to_sleep = btdm_lpcycles_2_us(lpcycles);
|
||||
|
||||
#define BTDM_MIN_TIMER_UNCERTAINTY_US (1800)
|
||||
#define BTDM_MIN_TIMER_UNCERTAINTY_US (500)
|
||||
assert(us_to_sleep > BTDM_MIN_TIMER_UNCERTAINTY_US);
|
||||
// allow a maximum time uncertainty to be about 488ppm(1/2048) at least as clock drift
|
||||
// and set the timer in advance
|
||||
|
@ -1093,9 +1104,11 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
|
|||
#endif
|
||||
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
#if !BTDM_ALLOW_LIGHT_SLEEP
|
||||
if ((err = esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "btLS", &s_light_sleep_pm_lock)) != ESP_OK) {
|
||||
goto error;
|
||||
}
|
||||
#endif /* #if !BTDM_ALLOW_LIGHT_SLEEP */
|
||||
if ((err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "bt", &s_pm_lock)) != ESP_OK) {
|
||||
goto error;
|
||||
}
|
||||
|
@ -1135,7 +1148,8 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
|
|||
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 = esp_clk_slowclk_cal_get();
|
||||
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);
|
||||
#endif // CONFIG_BTDM_LPCLK_SEL_XX
|
||||
btdm_controller_set_sleep_mode(BTDM_MODEM_SLEEP_MODE_ORIG);
|
||||
|
@ -1158,10 +1172,12 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
|
|||
|
||||
error:
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
#if !BTDM_ALLOW_LIGHT_SLEEP
|
||||
if (s_light_sleep_pm_lock != NULL) {
|
||||
esp_pm_lock_delete(s_light_sleep_pm_lock);
|
||||
s_light_sleep_pm_lock = NULL;
|
||||
}
|
||||
#endif /* #if !BTDM_ALLOW_LIGHT_SLEEP */
|
||||
if (s_pm_lock != NULL) {
|
||||
esp_pm_lock_delete(s_pm_lock);
|
||||
s_pm_lock = NULL;
|
||||
|
@ -1189,8 +1205,10 @@ esp_err_t esp_bt_controller_deinit(void)
|
|||
periph_module_disable(PERIPH_BT_MODULE);
|
||||
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
#if !BTDM_ALLOW_LIGHT_SLEEP
|
||||
esp_pm_lock_delete(s_light_sleep_pm_lock);
|
||||
s_light_sleep_pm_lock = NULL;
|
||||
#endif /* #if !BTDM_ALLOW_LIGHT_SLEEP */
|
||||
esp_pm_lock_delete(s_pm_lock);
|
||||
s_pm_lock = NULL;
|
||||
esp_timer_stop(s_btdm_slp_tmr);
|
||||
|
@ -1231,7 +1249,9 @@ esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
#if !BTDM_ALLOW_LIGHT_SLEEP
|
||||
esp_pm_lock_acquire(s_light_sleep_pm_lock);
|
||||
#endif /* #if !BTDM_ALLOW_LIGHT_SLEEP */
|
||||
esp_pm_lock_acquire(s_pm_lock);
|
||||
#endif
|
||||
|
||||
|
@ -1269,7 +1289,9 @@ esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode)
|
|||
}
|
||||
esp_phy_rf_deinit(PHY_BT_MODULE);
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
#if !BTDM_ALLOW_LIGHT_SLEEP
|
||||
esp_pm_lock_release(s_light_sleep_pm_lock);
|
||||
#endif /* #if !BTDM_ALLOW_LIGHT_SLEEP */
|
||||
esp_pm_lock_release(s_pm_lock);
|
||||
#endif
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
|
@ -1310,7 +1332,9 @@ esp_err_t esp_bt_controller_disable(void)
|
|||
btdm_controller_status = ESP_BT_CONTROLLER_STATUS_INITED;
|
||||
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
#if !BTDM_ALLOW_LIGHT_SLEEP
|
||||
esp_pm_lock_release(s_light_sleep_pm_lock);
|
||||
#endif /* #if !BTDM_ALLOW_LIGHT_SLEEP */
|
||||
esp_pm_lock_release(s_pm_lock);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -37,6 +37,21 @@ typedef enum {
|
|||
ESP_BT_MODE_BTDM = 0x03, /*!< Run dual mode */
|
||||
} esp_bt_mode_t;
|
||||
|
||||
/**
|
||||
* @brief BLE sleep clock accuracy(SCA), values for ble_sca field in esp_bt_controller_config_t,
|
||||
* currently only ESP_BLE_SCA_500PPM and ESP_BLE_SCA_250PPM are supported
|
||||
*/
|
||||
enum {
|
||||
ESP_BLE_SCA_500PPM = 0, /*!< BLE SCA at 500ppm */
|
||||
ESP_BLE_SCA_250PPM, /*!< BLE SCA at 250ppm */
|
||||
ESP_BLE_SCA_150PPM, /*!< BLE SCA at 150ppm */
|
||||
ESP_BLE_SCA_100PPM, /*!< BLE SCA at 100ppm */
|
||||
ESP_BLE_SCA_75PPM, /*!< BLE SCA at 75ppm */
|
||||
ESP_BLE_SCA_50PPM, /*!< BLE SCA at 50ppm */
|
||||
ESP_BLE_SCA_30PPM, /*!< BLE SCA at 30ppm */
|
||||
ESP_BLE_SCA_20PPM, /*!< BLE SCA at 20ppm */
|
||||
};
|
||||
|
||||
#ifdef CONFIG_BT_ENABLED
|
||||
/* While scanning, if the free memory value in controller is less than SCAN_SEND_ADV_RESERVED_SIZE,
|
||||
the adv packet will be discarded until the memory is restored. */
|
||||
|
@ -106,15 +121,16 @@ the adv packet will be discarded until the memory is restored. */
|
|||
.hci_uart_no = BT_HCI_UART_NO_DEFAULT, \
|
||||
.hci_uart_baudrate = BT_HCI_UART_BAUDRATE_DEFAULT, \
|
||||
.scan_duplicate_mode = SCAN_DUPLICATE_MODE, \
|
||||
.scan_duplicate_type = SCAN_DUPLICATE_TYPE_VALUE, \
|
||||
.scan_duplicate_type = SCAN_DUPLICATE_TYPE_VALUE, \
|
||||
.normal_adv_size = NORMAL_SCAN_DUPLICATE_CACHE_SIZE, \
|
||||
.mesh_adv_size = MESH_DUPLICATE_SCAN_CACHE_SIZE, \
|
||||
.send_adv_reserved_size = SCAN_SEND_ADV_RESERVED_SIZE, \
|
||||
.controller_debug_flag = CONTROLLER_ADV_LOST_DEBUG_BIT, \
|
||||
.mode = BTDM_CONTROLLER_MODE_EFF, \
|
||||
.ble_max_conn = CONFIG_BTDM_CTRL_BLE_MAX_CONN_EFF, \
|
||||
.bt_max_acl_conn = CONFIG_BTDM_CTRL_BR_EDR_MAX_ACL_CONN_EFF, \
|
||||
.bt_max_sync_conn = CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN_EFF, \
|
||||
.ble_max_conn = CONFIG_BTDM_CTRL_BLE_MAX_CONN_EFF, \
|
||||
.bt_max_acl_conn = CONFIG_BTDM_CTRL_BR_EDR_MAX_ACL_CONN_EFF, \
|
||||
.bt_max_sync_conn = CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN_EFF, \
|
||||
.ble_sca = CONFIG_BTDM_BLE_SLEEP_CLOCK_ACCURACY_INDEX_EFF, \
|
||||
.magic = ESP_BT_CONTROLLER_CONFIG_MAGIC_VAL, \
|
||||
};
|
||||
|
||||
|
@ -150,6 +166,7 @@ typedef struct {
|
|||
* So, do not modify the value when esp_bt_controller_init()
|
||||
*/
|
||||
uint8_t bt_max_sync_conn; /*!< BR/EDR maximum ACL connection numbers. Effective in menuconfig */
|
||||
uint8_t ble_sca; /*!< BLE low power crystal accuracy index */
|
||||
uint32_t magic; /*!< Magic number */
|
||||
} esp_bt_controller_config_t;
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 70d6a277d7adb468fc4dbeed92a64144569bf080
|
||||
Subproject commit be2b20bbfc75f5644551eae135fa7547f82377aa
|
Loading…
Reference in a new issue