|
|
|
@ -40,6 +40,10 @@
|
|
|
|
|
#include "hci_uart.h"
|
|
|
|
|
#include "bt_osi_mem.h"
|
|
|
|
|
|
|
|
|
|
#if SOC_PM_RETENTION_HAS_CLOCK_BUG
|
|
|
|
|
#include "esp_private/sleep_retention.h"
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef CONFIG_BT_BLUEDROID_ENABLED
|
|
|
|
|
#include "hci/hci_hal.h"
|
|
|
|
|
#endif // CONFIG_BT_BLUEDROID_ENABLED
|
|
|
|
@ -49,7 +53,6 @@
|
|
|
|
|
|
|
|
|
|
#include "esp_private/periph_ctrl.h"
|
|
|
|
|
#include "esp_sleep.h"
|
|
|
|
|
|
|
|
|
|
/* Macro definition
|
|
|
|
|
************************************************************************
|
|
|
|
|
*/
|
|
|
|
@ -122,9 +125,12 @@ extern void npl_freertos_mempool_deinit(void);
|
|
|
|
|
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);
|
|
|
|
|
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
|
|
|
|
|
extern const sleep_retention_entries_config_t *esp_ble_mac_retention_link_get(uint8_t *size, uint8_t extra);
|
|
|
|
|
#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */
|
|
|
|
|
extern void 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 ble_rtc_wake_up_state_clr(void);
|
|
|
|
|
extern void r_ble_rtc_wake_up_state_clr(void);
|
|
|
|
|
extern int os_msys_init(void);
|
|
|
|
|
extern void os_msys_buf_free(void);
|
|
|
|
|
extern int ble_sm_alg_gen_dhkey(const uint8_t *peer_pub_key_x,
|
|
|
|
@ -184,11 +190,13 @@ static DRAM_ATTR esp_pm_lock_handle_t s_pm_lock = NULL;
|
|
|
|
|
#endif // CONFIG_PM_ENABLE
|
|
|
|
|
|
|
|
|
|
#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER
|
|
|
|
|
#define BLE_RTC_DELAY_US (1100)
|
|
|
|
|
#define BLE_RTC_DELAY_US_LIGHT_SLEEP (5100)
|
|
|
|
|
#define BLE_RTC_DELAY_US_MODEM_SLEEP (1500)
|
|
|
|
|
#endif // CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER
|
|
|
|
|
|
|
|
|
|
#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER
|
|
|
|
|
#define BLE_RTC_DELAY_US (0)
|
|
|
|
|
#define BLE_RTC_DELAY_US_LIGHT_SLEEP (2000)
|
|
|
|
|
#define BLE_RTC_DELAY_US_MODEM_SLEEP (0)
|
|
|
|
|
static void ble_sleep_timer_callback(void *arg);
|
|
|
|
|
static DRAM_ATTR esp_timer_handle_t s_ble_sleep_timer = NULL;
|
|
|
|
|
#endif // CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER
|
|
|
|
@ -427,8 +435,7 @@ IRAM_ATTR void controller_sleep_cb(uint32_t enable_tick, void *arg)
|
|
|
|
|
if (!s_ble_active) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef CONFIG_PM_ENABLE
|
|
|
|
|
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
|
|
|
|
|
#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER
|
|
|
|
|
uint32_t delta_tick;
|
|
|
|
|
uint32_t us_to_sleep;
|
|
|
|
@ -458,11 +465,14 @@ IRAM_ATTR void controller_sleep_cb(uint32_t enable_tick, void *arg)
|
|
|
|
|
#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER
|
|
|
|
|
r_ble_rtc_wake_up_state_clr();
|
|
|
|
|
#endif // CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER
|
|
|
|
|
|
|
|
|
|
#if SOC_PM_RETENTION_HAS_CLOCK_BUG
|
|
|
|
|
sleep_retention_do_extra_retention(true);
|
|
|
|
|
#endif // SOC_PM_RETENTION_HAS_CLOCK_BUG
|
|
|
|
|
#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */
|
|
|
|
|
esp_phy_disable();
|
|
|
|
|
#ifdef CONFIG_PM_ENABLE
|
|
|
|
|
esp_pm_lock_release(s_pm_lock);
|
|
|
|
|
#endif // CONFIG_PM_ENABLE
|
|
|
|
|
|
|
|
|
|
esp_phy_disable();
|
|
|
|
|
s_ble_active = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -471,37 +481,58 @@ IRAM_ATTR void controller_wakeup_cb(void *arg)
|
|
|
|
|
if (s_ble_active) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
esp_phy_enable();
|
|
|
|
|
|
|
|
|
|
#ifdef CONFIG_PM_ENABLE
|
|
|
|
|
#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER
|
|
|
|
|
esp_pm_lock_acquire(s_pm_lock);
|
|
|
|
|
r_ble_rtc_wake_up_state_clr();
|
|
|
|
|
#endif // CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER
|
|
|
|
|
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE && SOC_PM_RETENTION_HAS_CLOCK_BUG
|
|
|
|
|
sleep_retention_do_extra_retention(false);
|
|
|
|
|
#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE && SOC_PM_RETENTION_HAS_CLOCK_BUG */
|
|
|
|
|
#endif //CONFIG_PM_ENABLE
|
|
|
|
|
|
|
|
|
|
esp_phy_enable();
|
|
|
|
|
s_ble_active = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef CONFIG_PM_ENABLE
|
|
|
|
|
#ifdef CONFIG_FREERTOS_USE_TICKLESS_IDLE
|
|
|
|
|
#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER
|
|
|
|
|
static void ble_sleep_timer_callback(void * arg)
|
|
|
|
|
{
|
|
|
|
|
esp_pm_lock_acquire(s_pm_lock);
|
|
|
|
|
}
|
|
|
|
|
#endif // CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER
|
|
|
|
|
|
|
|
|
|
static esp_err_t sleep_modem_ble_mac_modem_state_init(uint8_t extra)
|
|
|
|
|
{
|
|
|
|
|
uint8_t size;
|
|
|
|
|
const sleep_retention_entries_config_t *ble_mac_modem_config = esp_ble_mac_retention_link_get(&size, extra);
|
|
|
|
|
esp_err_t err = sleep_retention_entries_create(ble_mac_modem_config, size, REGDMA_LINK_PRI_5, SLEEP_RETENTION_MODULE_BLE_MAC);
|
|
|
|
|
if (err == ESP_OK) {
|
|
|
|
|
ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Modem BLE MAC retention initialization");
|
|
|
|
|
}
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif // CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER
|
|
|
|
|
#endif // CONFIG_PM_ENABLE
|
|
|
|
|
static void sleep_modem_ble_mac_modem_state_deinit(void)
|
|
|
|
|
{
|
|
|
|
|
sleep_retention_entries_destroy(SLEEP_RETENTION_MODULE_BLE_MAC);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif // CONFIG_FREERTOS_USE_TICKLESS_IDLE
|
|
|
|
|
|
|
|
|
|
esp_err_t controller_sleep_init(void)
|
|
|
|
|
{
|
|
|
|
|
esp_err_t rc = 0;
|
|
|
|
|
|
|
|
|
|
#ifdef CONFIG_BT_LE_SLEEP_ENABLE
|
|
|
|
|
ESP_LOGW(NIMBLE_PORT_LOG_TAG, "BLE modem sleep is enabled\n");
|
|
|
|
|
ESP_LOGW(NIMBLE_PORT_LOG_TAG, "BLE modem sleep is enabled");
|
|
|
|
|
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
|
|
|
|
|
ble_lll_rfmgmt_set_sleep_cb(controller_sleep_cb, controller_wakeup_cb, 0, 0,
|
|
|
|
|
500 + BLE_RTC_DELAY_US);
|
|
|
|
|
|
|
|
|
|
#ifdef CONFIG_PM_ENABLE
|
|
|
|
|
esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_ON);
|
|
|
|
|
#endif // CONFIG_PM_ENABLE
|
|
|
|
|
BLE_RTC_DELAY_US_LIGHT_SLEEP);
|
|
|
|
|
#else
|
|
|
|
|
ble_lll_rfmgmt_set_sleep_cb(controller_sleep_cb, controller_wakeup_cb, 0, 0,
|
|
|
|
|
BLE_RTC_DELAY_US_MODEM_SLEEP);
|
|
|
|
|
#endif /* FREERTOS_USE_TICKLESS_IDLE */
|
|
|
|
|
#endif // CONFIG_BT_LE_SLEEP_ENABLE
|
|
|
|
|
|
|
|
|
|
#ifdef CONFIG_PM_ENABLE
|
|
|
|
@ -510,7 +541,7 @@ esp_err_t controller_sleep_init(void)
|
|
|
|
|
goto error;
|
|
|
|
|
}
|
|
|
|
|
esp_pm_lock_acquire(s_pm_lock);
|
|
|
|
|
|
|
|
|
|
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
|
|
|
|
|
#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER
|
|
|
|
|
esp_timer_create_args_t create_args = {
|
|
|
|
|
.callback = ble_sleep_timer_callback,
|
|
|
|
@ -524,20 +555,23 @@ esp_err_t controller_sleep_init(void)
|
|
|
|
|
ESP_LOGW(NIMBLE_PORT_LOG_TAG, "Enable light sleep, the wake up source is ESP timer");
|
|
|
|
|
#endif //CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER
|
|
|
|
|
|
|
|
|
|
/* Create a new regdma link for BLE related register restoration */
|
|
|
|
|
rc = sleep_modem_ble_mac_modem_state_init(1);
|
|
|
|
|
assert(rc == 0);
|
|
|
|
|
#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER
|
|
|
|
|
esp_sleep_enable_bt_wakeup();
|
|
|
|
|
ESP_LOGW(NIMBLE_PORT_LOG_TAG, "Enable light sleep, the wake up source is BLE timer");
|
|
|
|
|
#endif // CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER
|
|
|
|
|
|
|
|
|
|
#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */
|
|
|
|
|
return rc;
|
|
|
|
|
|
|
|
|
|
error:
|
|
|
|
|
/*lock should release first and then delete*/
|
|
|
|
|
if (s_pm_lock != NULL) {
|
|
|
|
|
esp_pm_lock_release(s_pm_lock);
|
|
|
|
|
esp_pm_lock_delete(s_pm_lock);
|
|
|
|
|
s_pm_lock = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
|
|
|
|
|
#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER
|
|
|
|
|
esp_sleep_disable_bt_wakeup();
|
|
|
|
|
#endif // CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER
|
|
|
|
|
|
|
|
|
|
#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER
|
|
|
|
|
if (s_ble_sleep_timer != NULL) {
|
|
|
|
|
esp_timer_stop(s_ble_sleep_timer);
|
|
|
|
@ -545,34 +579,26 @@ error:
|
|
|
|
|
s_ble_sleep_timer = NULL;
|
|
|
|
|
}
|
|
|
|
|
#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_LE_WAKEUP_SOURCE_BLE_RTC_TIMER
|
|
|
|
|
|
|
|
|
|
#endif //CONFIG_PM_ENABLE
|
|
|
|
|
#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */
|
|
|
|
|
/*lock should release first and then delete*/
|
|
|
|
|
if (s_pm_lock != NULL) {
|
|
|
|
|
esp_pm_lock_release(s_pm_lock);
|
|
|
|
|
esp_pm_lock_delete(s_pm_lock);
|
|
|
|
|
s_pm_lock = NULL;
|
|
|
|
|
}
|
|
|
|
|
#endif // CONFIG_PM_ENABLE
|
|
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void controller_sleep_deinit(void)
|
|
|
|
|
{
|
|
|
|
|
#ifdef CONFIG_PM_ENABLE
|
|
|
|
|
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
|
|
|
|
|
#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER
|
|
|
|
|
r_ble_rtc_wake_up_state_clr();
|
|
|
|
|
esp_sleep_disable_bt_wakeup();
|
|
|
|
|
#endif //CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER
|
|
|
|
|
|
|
|
|
|
esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_AUTO);
|
|
|
|
|
|
|
|
|
|
/* lock should be released first */
|
|
|
|
|
if (s_ble_active) {
|
|
|
|
|
esp_pm_lock_release(s_pm_lock);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
esp_pm_lock_delete(s_pm_lock);
|
|
|
|
|
s_pm_lock = NULL;
|
|
|
|
|
|
|
|
|
|
sleep_modem_ble_mac_modem_state_deinit();
|
|
|
|
|
#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER
|
|
|
|
|
if (s_ble_sleep_timer != NULL) {
|
|
|
|
|
esp_timer_stop(s_ble_sleep_timer);
|
|
|
|
@ -580,6 +606,12 @@ void controller_sleep_deinit(void)
|
|
|
|
|
s_ble_sleep_timer = NULL;
|
|
|
|
|
}
|
|
|
|
|
#endif //CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER
|
|
|
|
|
#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */
|
|
|
|
|
#ifdef CONFIG_PM_ENABLE
|
|
|
|
|
/* lock should be released first */
|
|
|
|
|
esp_pm_lock_release(s_pm_lock);
|
|
|
|
|
esp_pm_lock_delete(s_pm_lock);
|
|
|
|
|
s_pm_lock = NULL;
|
|
|
|
|
#endif //CONFIG_PM_ENABLE
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -647,7 +679,27 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
|
|
|
|
|
|
|
|
|
|
/* Enable BT-related clocks */
|
|
|
|
|
modem_clock_module_enable(PERIPH_BT_MODULE);
|
|
|
|
|
modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL, 249);
|
|
|
|
|
#if CONFIG_BT_LE_LP_CLK_SRC_MAIN_XTAL
|
|
|
|
|
ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Using main XTAL as clock source");
|
|
|
|
|
modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL, (320 - 1));
|
|
|
|
|
#else
|
|
|
|
|
#if CONFIG_RTC_CLK_SRC_INT_RC
|
|
|
|
|
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!");
|
|
|
|
|
modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, MODEM_CLOCK_LPCLK_SRC_RC_SLOW, (5 - 1));
|
|
|
|
|
#elif CONFIG_RTC_CLK_SRC_EXT_CRYS
|
|
|
|
|
ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Using external 32.768 kHz XTAL as clock source");
|
|
|
|
|
modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, MODEM_CLOCK_LPCLK_SRC_XTAL32K, (1 - 1));
|
|
|
|
|
#elif CONFIG_RTC_CLK_SRC_INT_RC32K
|
|
|
|
|
ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Using 32 kHz RC as clock source, can only run legacy ADV or SCAN due to low clock accuracy!");
|
|
|
|
|
modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, MODEM_CLOCK_LPCLK_SRC_RC32K, (1 - 1));
|
|
|
|
|
#elif CONFIG_RTC_CLK_SRC_EXT_OSC
|
|
|
|
|
ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Using 32 kHz oscillator as clock source, can only run legacy ADV or SCAN due to low clock accuracy!");
|
|
|
|
|
modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, MODEM_CLOCK_LPCLK_SRC_EXT32K, (1 - 1));
|
|
|
|
|
#else
|
|
|
|
|
ESP_LOGE(NIMBLE_PORT_LOG_TAG, "Unsupported clock source");
|
|
|
|
|
assert(0);
|
|
|
|
|
#endif
|
|
|
|
|
#endif /* CONFIG_BT_LE_LP_CLK_SRC_MAIN_XTAL */
|
|
|
|
|
esp_phy_enable();
|
|
|
|
|
esp_btbb_enable();
|
|
|
|
|
s_ble_active = true;
|
|
|
|
|