Merge branch 'feature/esp32c2_support_ble_sleep' into 'master'

Support ESP32C2 BLE modem sleep and lightsleep

See merge request espressif/esp-idf!18432
This commit is contained in:
Jiang Jiang Jian 2022-06-15 15:39:55 +08:00
commit 20e5a989a2
6 changed files with 111 additions and 99 deletions

View File

@ -330,3 +330,24 @@ config BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF
default 0 if !BT_NIMBLE_ENABLED
default 1 if BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EN
default 0 if BT_LE_COEX_PHY_CODED_TX_RX_TLIM_DIS
config BT_LE_SLEEP_ENABLE
bool "Enable BLE sleep"
default n
help
Enable BLE sleep
choice BT_LE_WAKEUP_SOURCE
prompt "BLE light sleep wakeup source"
depends on BT_LE_SLEEP_ENABLE
default BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER
config BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER
bool "Use ESP timer to wakeup CPU"
help
Use esp timer to wakeup CPU
config BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER
bool "Use BLE rtc timer to wakeup CPU"
help
Use BLE rtc timer to wakeup CPU
endchoice

View File

@ -53,6 +53,7 @@
#include "freertos/task.h"
#include "esp_private/periph_ctrl.h"
#include "esp_sleep.h"
/* Macro definition
************************************************************************
@ -105,7 +106,6 @@ struct ext_funcs_t {
************************************************************************
*/
extern int ble_plf_set_log_level(int level);
extern int ble_osi_coex_funcs_register(struct osi_coex_funcs_t *coex_funcs);
extern int coex_core_ble_conn_dyn_prio_get(bool *low, bool *high);
extern int ble_controller_init(struct esp_bt_controller_config_t *cfg);
@ -122,7 +122,8 @@ extern void bt_bb_v2_init_cmplx(uint8_t i);
extern int os_msys_buf_alloc(void);
extern uint32_t r_os_cputime_get32(void);
extern uint32_t r_os_cputime_ticks_to_usecs(uint32_t ticks);
extern void r_ble_ll_rfmgmt_set_sleep_cb(void *s_cb, void *w_cb, void *s_arg, void *w_arg, uint32_t us_to_enabled);
extern void r_ble_lll_rfmgmt_set_sleep_cb(void *s_cb, void *w_cb, void *s_arg, void *w_arg, uint32_t us_to_enabled);
extern void r_ble_rtc_wake_up_state_clr(void);
extern int os_msys_init(void);
extern void os_msys_buf_free(void);
@ -157,29 +158,24 @@ extern int ble_sm_alg_gen_key_pair(uint8_t *pub, uint8_t *priv);
/* Static variable declare */
static DRAM_ATTR esp_bt_controller_status_t ble_controller_status = ESP_BT_CONTROLLER_STATUS_IDLE;
static bool s_is_sleep_state = false;
#ifdef CONFIG_PM_ENABLE
#ifdef CONFIG_BT_NIMBLE_WAKEUP_SOURCE_CPU_RTC_TIMER
uint32_t s_sleep_tick;
#endif
#endif
#ifdef CONFIG_PM_ENABLE
static DRAM_ATTR esp_timer_handle_t s_btdm_slp_tmr = NULL;
static DRAM_ATTR esp_pm_lock_handle_t s_pm_lock = NULL;
static bool s_pm_lock_acquired = true;
static DRAM_ATTR bool s_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;
static void btdm_slp_tmr_callback(void *arg);
#define BTDM_MIN_TIMER_UNCERTAINTY_US (200)
#endif /* #ifdef CONFIG_PM_ENABLE */
#ifdef CONFIG_BT_NIMBLE_WAKEUP_SOURCE_BLE_RTC_TIMER
#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER
#define BLE_RTC_DELAY_US (1100)
#else
#endif
#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER
#define BLE_RTC_DELAY_US (0)
static void btdm_slp_tmr_callback(void *arg);
static DRAM_ATTR esp_timer_handle_t s_btdm_slp_tmr = NULL;
#endif
static const struct osi_coex_funcs_t s_osi_coex_funcs_ro = {
@ -400,26 +396,32 @@ static int esp_intr_free_wrapper(void **ret_handle)
IRAM_ATTR void controller_sleep_cb(uint32_t enable_tick, void *arg)
{
if (s_is_sleep_state) {
ESP_LOGW(NIMBLE_PORT_LOG_TAG, "sleep state error");
assert(0);
}
s_is_sleep_state = true;
esp_phy_disable();
#ifdef CONFIG_PM_ENABLE
#ifdef CONFIG_BT_NIMBLE_WAKEUP_SOURCE_CPU_RTC_TIMER
uint32_t tick_invalid = *(uint32_t *)(arg);
if (!tick_invalid) {
s_sleep_tick = r_os_cputime_get32();
assert(enable_tick >= s_sleep_tick);
#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER
uint32_t tick_invalid = *(uint32_t*)(arg);
assert(arg != NULL);
if(!tick_invalid) {
uint32_t sleep_tick = r_os_cputime_get32();
if(enable_tick <= sleep_tick) {
return;
}
// start a timer to wake up and acquire the pm_lock before modem_sleep awakes
uint32_t us_to_sleep = os_cputime_ticks_to_usecs(enable_tick - s_sleep_tick);
uint32_t us_to_sleep = r_os_cputime_ticks_to_usecs(enable_tick - sleep_tick);
assert(us_to_sleep > BTDM_MIN_TIMER_UNCERTAINTY_US);
if (esp_timer_start_once(s_btdm_slp_tmr, us_to_sleep - BTDM_MIN_TIMER_UNCERTAINTY_US) != ESP_OK) {
ESP_LOGW(NIMBLE_PORT_LOG_TAG, "timer start failed");
esp_err_t err = esp_timer_start_once(s_btdm_slp_tmr, us_to_sleep - BTDM_MIN_TIMER_UNCERTAINTY_US);
if (err != ESP_OK) {
ESP_LOGW(NIMBLE_PORT_LOG_TAG, "ESP timer start failed\n");
return;
}
}
#endif // CONFIG_NIMBLE_WAKEUP_SOURCE_CPU_RTC_TIMER
#endif // CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER
#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER
r_ble_rtc_wake_up_state_clr();
#endif
if (s_pm_lock_acquired) {
assert(s_pm_lock != NULL);
esp_pm_lock_release(s_pm_lock);
s_pm_lock_acquired = false;
}
@ -429,60 +431,49 @@ IRAM_ATTR void controller_sleep_cb(uint32_t enable_tick, void *arg)
IRAM_ATTR void controller_wakeup_cb(void *arg)
{
if (!s_is_sleep_state) {
ESP_LOGW(NIMBLE_PORT_LOG_TAG, "wake up state error");
assert(0);
}
s_is_sleep_state = false;
// need to check if need to call pm lock here
esp_phy_enable();
// need to check if need to call pm lock here
#ifdef CONFIG_PM_ENABLE
assert(s_pm_lock != NULL);
if (!s_pm_lock_acquired) {
s_pm_lock_acquired = true;
esp_pm_lock_acquire(s_pm_lock);
}
#ifdef CONFIG_BT_NIMBLE_WAKEUP_SOURCE_CPU_RTC_TIMER
if (esp_sleep_get_wakeup_cause() != ESP_SLEEP_WAKEUP_TIMER) {
ESP_LOGW(NIMBLE_PORT_LOG_TAG, "wake up source %d", esp_sleep_get_wakeup_cause());
}
#endif
#ifdef CONFIG_BT_NIMBLE_WAKEUP_SOURCE_BLE_RTC_TIMER
if (esp_sleep_get_wakeup_cause() != ESP_SLEEP_WAKEUP_BT) {
ESP_LOGW(NIMBLE_PORT_LOG_TAG, "wake up source %d", esp_sleep_get_wakeup_cause());
}
#endif
#endif
#endif //CONFIG_PM_ENABLE
}
#ifdef CONFIG_PM_ENABLE
#ifdef CONFIG_BT_NIMBLE_WAKEUP_SOURCE_CPU_RTC_TIMER
static void btdm_slp_tmr_callback(void *arg)
#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER
static void btdm_slp_tmr_callback(void * arg)
{
(void)(arg);
if (!s_pm_lock_acquired) {
assert(s_pm_lock != NULL);
s_pm_lock_acquired = true;
esp_pm_lock_acquire(s_pm_lock);
}
}
#endif
#endif // CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER
#endif // CONFIG_PM_ENABLE
void controller_sleep_init(void)
{
#ifdef CONFIG_NIMBLE_SLEEP_ENABLE
s_is_sleep_state = false;
#ifdef CONFIG_PM_ENABLE
s_btdm_allow_light_sleep = true;
#endif // CONFIG_PM_ENABLE
ESP_LOGW(NIMBLE_PORT_LOG_TAG, "BLE modem sleep is enabled");
// register sleep callbacks
r_ble_ll_rfmgmt_set_sleep_cb(controller_sleep_cb, controller_wakeup_cb, 0, 0, 500 + BLE_RTC_DELAY_US);
#else
#ifdef CONFIG_PM_ENABLE
s_btdm_allow_light_sleep = false;
#endif // CONFIG_PM_ENABLE
#endif // CONFIG_NIMBLE_SLEEP_ENABLE
#ifdef CONFIG_BT_LE_SLEEP_ENABLE
ESP_LOGW(NIMBLE_PORT_LOG_TAG, "BLE modem sleep is enabled\n");
r_ble_lll_rfmgmt_set_sleep_cb(controller_sleep_cb, controller_wakeup_cb, 0, 0, 500 + BLE_RTC_DELAY_US);
#ifdef CONFIG_PM_ENABLE
s_btdm_allow_light_sleep = true;
esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_ON);
#endif // CONFIG_PM_ENABLE
#endif // CONFIG_BT_LE_SLEEP_ENABLE
// enable light sleep
#ifdef CONFIG_PM_ENABLE
@ -494,22 +485,22 @@ void controller_sleep_init(void)
if (esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "bt", &s_pm_lock) != ESP_OK) {
goto error;
}
#ifdef CONFIG_BT_NIMBLE_WAKEUP_SOURCE_CPU_RTC_TIMER
#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER
esp_timer_create_args_t create_args = {
.callback = btdm_slp_tmr_callback,
.arg = NULL,
.name = "btSlp"
};
if ( esp_timer_create(&create_args, &s_btdm_slp_tmr) != ESP_OK) {
if (esp_timer_create(&create_args, &s_btdm_slp_tmr) != ESP_OK) {
goto error;
}
ESP_LOGW(NIMBLE_PORT_LOG_TAG, "light sleep enable success, CPU RTC timer wake up");
#endif //CONFIG_NIMBLE_WAKEUP_SOURCE_CPU_RTC_TIMER
ESP_LOGW(NIMBLE_PORT_LOG_TAG, "Enable light sleep, the wake up source is ESP timer\n");
#endif //CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER
#ifdef CONFIG_BT_NIMBLE_WAKEUP_SOURCE_BLE_RTC_TIMER
#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER
esp_sleep_enable_bt_wakeup();
ESP_LOGW(NIMBLE_PORT_LOG_TAG, "light sleep enable success, BLE RTC timer wake up");
#endif // CONFIG_NIMBLE_WAKEUP_SOURCE_BLE_RTC_TIMER
ESP_LOGW(NIMBLE_PORT_LOG_TAG, "Enable light sleep, the wake up source is BLE timer\n");
#endif // CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER
s_pm_lock_acquired = true;
@ -533,22 +524,28 @@ error:
esp_pm_lock_delete(s_pm_lock);
s_pm_lock = NULL;
}
#ifdef CONFIG_BT_NIMBLE_WAKEUP_SOURCE_CPU_RTC_TIMER
#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER
if (s_btdm_slp_tmr != NULL) {
esp_timer_delete(s_btdm_slp_tmr);
s_btdm_slp_tmr = NULL;
}
#endif // CONFIG_BT_NIMBLE_WAKEUP_SOURCE_CPU_RTC_TIMER
#ifdef CONFIG_BT_NIMBLE_WAKEUP_SOURCE_BLE_RTC_TIMER
#endif // CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER
#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER
esp_sleep_disable_bt_wakeup();
#endif // CONFIG_BT_NIMBLE_WAKEUP_SOURCE_BLE_RTC_TIMER
#endif
#endif // CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER
#endif //CONFIG_PM_ENABLE
}
void controller_sleep_deinit(void)
{
#ifdef CONFIG_PM_ENABLE
#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER
r_ble_rtc_wake_up_state_clr();
#endif
esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_AUTO);
if (!s_btdm_allow_light_sleep) {
if (s_light_sleep_pm_lock != NULL) {
esp_pm_lock_delete(s_light_sleep_pm_lock);
@ -559,8 +556,8 @@ void controller_sleep_deinit(void)
esp_pm_lock_delete(s_pm_lock);
s_pm_lock = NULL;
}
#ifdef CONFIG_BT_NIMBLE_WAKEUP_SOURCE_CPU_RTC_TIMER
if (s_btdm_slp_tmr != NULL) {
#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER
if(s_btdm_slp_tmr != NULL) {
esp_timer_stop(s_btdm_slp_tmr);
esp_timer_delete(s_btdm_slp_tmr);
s_btdm_slp_tmr = NULL;

View File

@ -1061,8 +1061,8 @@ config BT_MAX_DEVICE_NAME_LEN
config BT_BLE_RPA_SUPPORTED
bool "Update RPA to Controller"
depends on BT_BLUEDROID_ENABLED
default y if (IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3)
default n if IDF_TARGET_ESP32
default y
help
This enables controller RPA list function.
For ESP32, ESP32 only support network privacy mode. If this option is enabled, ESP32 will only accept
@ -1072,8 +1072,8 @@ config BT_BLE_RPA_SUPPORTED
cannot be used. This option is disabled by default on ESP32, please enable or disable this option according
to your own needs.
For ESP32C3 and esp32s3, devices support network privacy mode and device privacy mode, users can switch the
two modes according to their own needs. So this option is enabled by default.
For ESP32C3, ESP32S3, ESP32H2 and ESP32C2, devices support network privacy mode and device privacy mode,
users can switch the two modes according to their own needs. So this option is enabled by default.
config BT_BLE_50_FEATURES_SUPPORTED
bool "Enable BLE 5.0 features"

View File

@ -618,28 +618,6 @@ config BT_NIMBLE_TEST_THROUGHPUT_TEST
help
Enable the throughput test mode
config BT_NIMBLE_SLEEP_ENABLE
bool "Enable BLE sleep"
depends on BT_NIMBLE_ENABLED
default n
help
Enable BLE sleep
choice BT_NIMBLE_WAKEUP_SOURCE
prompt "BLE light sleep wakeup source"
depends on BT_NIMBLE_SLEEP_ENABLE
default BT_NIMBLE_WAKEUP_SOURCE_CPU_RTC_TIMER
config BT_NIMBLE_WAKEUP_SOURCE_CPU_RTC_TIMER
bool "Use CPU rtc timer to wakeup CPU"
help
Use CPU rtc timer to wakeup CPU
config BT_NIMBLE_WAKEUP_SOURCE_BLE_RTC_TIMER
bool "Use BLE rtc timer to wakeup CPU"
help
Use BLE rtc timer to wakeup CPU
endchoice
config BT_NIMBLE_BLUFI_ENABLE
bool "Enable blufi functionality"
depends on BT_NIMBLE_ENABLED

View File

@ -195,8 +195,8 @@ typedef struct esp_bt_controller_config_t esp_bt_controller_config_t;
#define BLE_LL_SCAN_PHY_NUMBER_N (1)
#endif
#ifdef CONFIG_BT_NIMBLE_SLEEP_ENABLE
#define NIMBLE_SLEEP_ENABLE CONFIG_BT_NIMBLE_SLEEP_ENABLE
#ifdef CONFIG_BT_LE_SLEEP_ENABLE
#define NIMBLE_SLEEP_ENABLE CONFIG_BT_LE_SLEEP_ENABLE
#else
#define NIMBLE_SLEEP_ENABLE 0
#endif

View File

@ -298,6 +298,22 @@ esp_err_t esp_sleep_enable_gpio_wakeup(void);
*/
esp_err_t esp_sleep_enable_uart_wakeup(int uart_num);
/**
* @brief Enable wakeup by bluetooth
* @return
* - ESP_OK on success
* - ESP_ERR_NOT_SUPPORTED if wakeup from bluetooth is not supported
*/
esp_err_t esp_sleep_enable_bt_wakeup(void);
/**
* @brief Disable wakeup by bluetooth
* @return
* - ESP_OK on success
* - ESP_ERR_NOT_SUPPORTED if wakeup from bluetooth is not supported
*/
esp_err_t esp_sleep_disable_bt_wakeup(void);
/**
* @brief Enable wakeup by WiFi MAC
* @return