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:
Jiang Jiang Jian 2019-05-31 18:51:10 +08:00
commit b859584f91
4 changed files with 94 additions and 11 deletions

View file

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

View file

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

View file

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