]> granicus.if.org Git - esp-idf/commitdiff
component/bt: implement bluetooth modem sleep mode, one mode for BLE only and another...
authorwangmengyang <wangmengyang@espressif.com>
Sun, 8 Apr 2018 11:19:47 +0000 (19:19 +0800)
committerwangmengyang <wangmengyang@espressif.com>
Sat, 19 May 2018 07:37:26 +0000 (15:37 +0800)
1. provide options for bluetooth low power mode
2. provide two options for bluetooth low power clock: main XTAL and external 32kHz XTAL
3. provide function and callbacks to control bluetooth low power mode, including enable/disable sleep, software wakeup request, low power clock settings, check power state, etc
4. modify vhci API vhci_host_send_packet to use blocking mode
5. note that DFS and bluetooth modem sleep can not be used together currently.

components/bt/Kconfig
components/bt/bt.c
components/bt/include/esp_bt.h
components/bt/lib
components/driver/include/driver/periph_ctrl.h
components/driver/periph_ctrl.c
components/esp32/ld/esp32.rom.ld
components/soc/esp32/include/soc/dport_reg.h
components/soc/esp32/rtc_clk.c
components/soc/esp32/rtc_time.c

index 37d660cf98ff4cb5fdda5cdb630b8e9d11aa0f6c..853265d653b460b3a0bb83b51633bee0ced86bcd 100644 (file)
@@ -64,6 +64,48 @@ config BT_HCI_UART_BAUDRATE
         UART Baudrate for HCI. Please use standard baudrate.
 endmenu
 
+menu "MODEM SLEEP Options"
+    visible if BT_ENABLED
+
+config BTDM_CONTROLLER_MODEM_SLEEP
+    bool "Bluetooth modem sleep"
+    depends on BT_ENABLED
+    default y
+    help
+        Enable/disable bluetooth controller low power mode.
+        Note that currently there is problem in the combination use of bluetooth modem sleep and Dynamic Frequency Scaling(DFS). So do not enable DFS if bluetooth modem sleep is in use.
+
+choice BTDM_MODEM_SLEEP_MODE
+    prompt "Bluetooth Modem sleep mode"
+    depends on BTDM_CONTROLLER_MODEM_SLEEP
+    help
+        To select which strategy to use for modem sleep
+
+config BTDM_MODEM_SLEEP_MODE_ORIG
+    bool "ORIG Mode(sleep with low power clock)"
+    help
+        ORIG mode is a deep sleep mode that can be used for dual mode controller. In this mode, bluetooth controller sleeps between BR/EDR frames and BLE events. A low power clock is used to maintain bluetooth reference clock.
+config BTDM_MODEM_SLEEP_MODE_EVED
+    bool "EVED Mode "
+    help
+        This mode is for BLE only.
+endchoice
+
+choice BTDM_LOW_POWER_CLOCK
+    prompt "Bluetooth low power clock"
+    depends on BTDM_MODEM_SLEEP_MODE_ORIG
+    help
+        Select the low power clock source for bluetooth controller
+
+config BTDM_LPCLK_SEL_MAIN_XTAL
+    bool "Main crystal"
+config BTDM_LPCLK_SEL_EXT_32K_XTAL
+    bool "External 32kHz crystal"
+    depends on ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL
+endchoice
+
+endmenu
+
 menuconfig BLUEDROID_ENABLED
     bool "Bluedroid Enable"
     depends on BTDM_CONTROLLER_HCI_MODE_VHCI
index 3a274a703337556845857c77c119d7e1f24281aa..68f5dee7fda4fd6570c889b4281188a31b98d730 100644 (file)
 #include "esp_pm.h"
 #include "esp_ipc.h"
 #include "driver/periph_ctrl.h"
+#include "soc/rtc.h"
+#include "soc/rtc_cntl_reg.h"
+#include "esp_clk.h"
+
 
 #if CONFIG_BT_ENABLED
 
@@ -61,7 +65,24 @@ extern int btdm_controller_disable(esp_bt_mode_t mode);
 extern uint8_t btdm_controller_get_mode(void);
 extern const char *btdm_controller_get_compile_version(void);
 extern void btdm_rf_bb_init(void);
-
+extern void btdm_controller_enable_sleep(bool enable);
+
+#define BTDM_MODEM_SLEEP_MODE_NONE          (0)
+#define BTDM_MODEM_SLEEP_MODE_ORIG          (1)
+#define BTDM_MODEM_SLEEP_MODE_EVED          (2)
+extern void btdm_controller_set_sleep_mode(uint8_t mode);
+extern uint8_t btdm_controller_get_sleep_mode(void);
+extern bool btdm_power_state_active(void);
+extern void btdm_wakeup_request(void);
+
+#define BTDM_LPCLK_SEL_XTAL      (0)
+#define BTDM_LPCLK_SEL_XTAL32K   (1)
+#define BTDM_LPCLK_SEL_RTC_SLOW  (2)
+#define BTDM_LPCLK_SEL_8M        (3)
+extern bool btdm_lpclk_select_src(uint32_t sel);
+extern bool btdm_lpclk_set_div(uint32_t div);
+
+#define BTDM_MIN_SLEEP_DURATION  (20)
 /* VHCI function interface */
 typedef struct vhci_host_callback {
     void (*notify_host_send_available)(void);               /*!< callback used to notify that the host can send packet to controller */
@@ -104,7 +125,7 @@ typedef struct {
 
 /* the mode column will be modified by release function to indicate the available region */
 static btdm_dram_available_region_t btdm_dram_available_region[] = {
-    //following is .data 
+    //following is .data
     {ESP_BT_MODE_BTDM,          0x3ffae6e0, 0x3ffaff10},
     //following is memory which HW will use
     {ESP_BT_MODE_BTDM,          0x3ffb0000, 0x3ffb09a8},
@@ -160,14 +181,24 @@ struct osi_funcs_t {
     int32_t (* _read_efuse_mac)(uint8_t mac[6]);
     void (* _srand)(unsigned int seed);
     int (* _rand)(void);
+    uint32_t (* _btdm_lpcycles_2_us)(uint32_t cycles);
+    uint32_t (* _btdm_us_2_lpcycles)(uint32_t us);
+    bool (* _btdm_sleep_check_duration)(uint32_t *slot_cnt);
+    void (* _btdm_sleep_enter)(void);
+    void (* _btdm_sleep_exit)(void);  /* called from ISR */
 };
 
+
 /* Static variable declare */
 static bool btdm_bb_init_flag = false;
 static esp_bt_controller_status_t btdm_controller_status = ESP_BT_CONTROLLER_STATUS_IDLE;
 
 static portMUX_TYPE global_int_mux = portMUX_INITIALIZER_UNLOCKED;
 
+// measured average low power clock period in micro seconds
+static uint32_t btdm_lpcycle_us = 0;
+static uint8_t btdm_lpcycle_us_frac = 0; // number of fractional bit for btdm_lpcycle_us
+
 #ifdef CONFIG_PM_ENABLE
 static esp_pm_lock_handle_t s_pm_lock;
 #endif
@@ -539,6 +570,70 @@ static int IRAM_ATTR rand_wrapper(void)
     return (int)esp_random();
 }
 
+static uint32_t IRAM_ATTR btdm_lpcycles_2_us(uint32_t cycles)
+{
+    // Sanity check. The number of lp cycles should not be too high to avoid overflow. Thrs: 100s (for 32kHz freq)
+    assert(cycles < 3200000);
+
+    // clock measurement is conducted
+    uint64_t us = (uint64_t)btdm_lpcycle_us * cycles;
+    us = (us + (1 << (btdm_lpcycle_us_frac - 1))) >> btdm_lpcycle_us_frac;
+    return (uint32_t)us;
+}
+
+/*
+ * @brief Converts a duration in slots into a number of low power clock cycles.
+ */
+static uint32_t IRAM_ATTR btdm_us_2_lpcycles(uint32_t us)
+{
+    // Sanity check: the number of sleep duration(us) should not be too high to avoid overflow. Thrs: 100s
+    assert(us < 100000000);
+
+    // Compute the sleep duration in us to low power clock cycles, with calibration result applied
+    // clock measurement is conducted
+    uint64_t cycles = ((uint64_t)(us) << btdm_lpcycle_us_frac) / btdm_lpcycle_us;
+
+    return (uint32_t)cycles;
+}
+
+static bool IRAM_ATTR btdm_sleep_check_duration(uint32_t *slot_cnt)
+{
+    if (*slot_cnt < BTDM_MIN_SLEEP_DURATION) {
+        return false;
+    }
+    return true;
+}
+
+static void IRAM_ATTR btdm_sleep_enter_wrapper(void)
+{
+    if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_ORIG) {
+        esp_modem_sleep_enter(MODEM_BLE_MODULE);
+        esp_modem_sleep_enter(MODEM_CLASSIC_BT_MODULE);
+#ifdef CONFIG_PM_ENABLE
+        esp_pm_lock_release(s_pm_lock);
+#endif
+    } else if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_EVED) {
+        esp_modem_sleep_enter(MODEM_BLE_MODULE);
+        // pause bluetooth baseband
+        periph_module_disable(PERIPH_BT_BASEBAND_MODULE);
+    }
+}
+
+static void IRAM_ATTR btdm_sleep_exit_wrapper(void)
+{
+    if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_ORIG) {
+#ifdef CONFIG_PM_ENABLE
+        esp_pm_lock_acquire(s_pm_lock);
+#endif
+        esp_modem_sleep_exit(MODEM_BLE_MODULE);
+        esp_modem_sleep_exit(MODEM_CLASSIC_BT_MODULE);
+    } else if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_EVED) {
+        // resume bluetooth baseband
+        periph_module_enable(PERIPH_BT_BASEBAND_MODULE);
+        esp_modem_sleep_exit(MODEM_BLE_MODULE);
+    }
+}
+
 static struct osi_funcs_t osi_funcs = {
     ._set_isr = xt_set_interrupt_handler,
     ._ints_on = xt_ints_on,
@@ -571,6 +666,11 @@ static struct osi_funcs_t osi_funcs = {
     ._read_efuse_mac = read_mac_wrapper,
     ._srand = srand_wrapper,
     ._rand = rand_wrapper,
+    ._btdm_lpcycles_2_us = btdm_lpcycles_2_us,
+    ._btdm_us_2_lpcycles = btdm_us_2_lpcycles,
+    ._btdm_sleep_check_duration = btdm_sleep_check_duration,
+    ._btdm_sleep_enter = btdm_sleep_enter_wrapper,
+    ._btdm_sleep_exit = btdm_sleep_exit_wrapper,
 };
 
 bool esp_vhci_host_check_send_available(void)
@@ -580,6 +680,9 @@ bool esp_vhci_host_check_send_available(void)
 
 void esp_vhci_host_send_packet(uint8_t *data, uint16_t len)
 {
+    if (!btdm_power_state_active()) {
+        btdm_wakeup_request();
+    }
     API_vhci_host_send_packet(data, len);
 }
 
@@ -723,6 +826,32 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
 
     periph_module_enable(PERIPH_BT_MODULE);
 
+    btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT;
+    btdm_lpcycle_us = 32 << btdm_lpcycle_us_frac;
+    bool select_src_ret = false;
+    bool set_div_ret = false;
+#if CONFIG_BTDM_MODEM_SLEEP_MODE_ORIG
+#if CONFIG_BTDM_LPCLK_SEL_MAIN_XTAL
+    select_src_ret = btdm_lpclk_select_src(BTDM_LPCLK_SEL_XTAL);
+    set_div_ret = btdm_lpclk_set_div(rtc_clk_xtal_freq_get() * 32 - 1);
+    assert(select_src_ret && set_div_ret);
+    btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT;
+    btdm_lpcycle_us = 32 << btdm_lpcycle_us_frac;
+#elif CONFIG_BTDM_LPCLK_SEL_EXT_32K_XTAL
+    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 = esp_clk_slowclk_cal_get();
+    assert(btdm_lpcycle_us != 0);
+#endif // CONFIG_BTDM_LPCLK_SEL_XX
+    btdm_controller_set_sleep_mode(BTDM_MODEM_SLEEP_MODE_ORIG);
+#elif CONFIG_BTDM_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
+
     btdm_cfg_mask = btdm_config_mask_load();
 
     ret = btdm_controller_init(btdm_cfg_mask, cfg);
@@ -758,6 +887,8 @@ esp_err_t esp_bt_controller_deinit(void)
 
     btdm_controller_status = ESP_BT_CONTROLLER_STATUS_IDLE;
 
+    btdm_lpcycle_us = 0;
+    btdm_controller_set_sleep_mode(BTDM_MODEM_SLEEP_MODE_NONE);
 #ifdef CONFIG_PM_ENABLE
     esp_pm_lock_delete(s_pm_lock);
     s_pm_lock = NULL;
@@ -784,12 +915,17 @@ esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode)
 #endif
 
     esp_phy_load_cal_and_init(PHY_BT_MODULE);
-    esp_modem_sleep_register(MODEM_BLE_MODULE);
 
-    /* TODO: Classic BT should be registered once it supports 
-     * modem sleep */
+    if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_ORIG) {
+        esp_modem_sleep_register(MODEM_BLE_MODULE);
+        esp_modem_sleep_register(MODEM_CLASSIC_BT_MODULE);
+    } else if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_EVED) {
+        esp_modem_sleep_register(MODEM_BLE_MODULE);
+    }
 
-    esp_modem_sleep_exit(MODEM_BLE_MODULE);
+    if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_ORIG) {
+        btdm_controller_enable_sleep(true);
+    }
 
     if (btdm_bb_init_flag == false) {
         btdm_bb_init_flag = true;
@@ -798,7 +934,12 @@ esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode)
 
     ret = btdm_controller_enable(mode);
     if (ret) {
-        esp_modem_sleep_deregister(MODEM_BLE_MODULE);
+        if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_ORIG) {
+            esp_modem_sleep_deregister(MODEM_BLE_MODULE);
+            esp_modem_sleep_deregister(MODEM_CLASSIC_BT_MODULE);
+        } else if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_EVED) {
+            esp_modem_sleep_deregister(MODEM_BLE_MODULE);
+        }
         esp_phy_rf_deinit(PHY_BT_MODULE);
         return ESP_ERR_INVALID_STATE;
     }
@@ -816,15 +957,29 @@ esp_err_t esp_bt_controller_disable(void)
         return ESP_ERR_INVALID_STATE;
     }
 
+    // disable modem sleep and wake up from sleep mode
+    if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_ORIG) {
+        btdm_controller_enable_sleep(false);
+        if (!btdm_power_state_active()) {
+            btdm_wakeup_request();
+        }
+        while (!btdm_power_state_active()) {
+            ets_delay_us(1000);
+        }
+    }
+
     ret = btdm_controller_disable(btdm_controller_get_mode());
     if (ret < 0) {
         return ESP_ERR_INVALID_STATE;
     }
 
     if (ret == ESP_BT_MODE_IDLE) {
-        /* TODO: Need to de-register classic BT once it supports
-         * modem sleep */
-        esp_modem_sleep_deregister(MODEM_BLE_MODULE);
+        if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_ORIG) {
+            esp_modem_sleep_deregister(MODEM_BLE_MODULE);
+            esp_modem_sleep_deregister(MODEM_CLASSIC_BT_MODULE);
+        } else if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_EVED) {
+            esp_modem_sleep_deregister(MODEM_BLE_MODULE);
+        }
         esp_phy_rf_deinit(PHY_BT_MODULE);
         btdm_controller_status = ESP_BT_CONTROLLER_STATUS_INITED;
     }
@@ -884,4 +1039,68 @@ esp_err_t esp_bredr_tx_power_get(esp_power_level_t *min_power_level, esp_power_l
     return ESP_OK;
 }
 
+esp_err_t esp_bt_sleep_enable (void)
+{
+    esp_err_t status;
+    if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED) {
+        return ESP_ERR_INVALID_STATE;
+    }
+    if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_ORIG) {
+        esp_modem_sleep_register(MODEM_BLE_MODULE);
+        esp_modem_sleep_register(MODEM_CLASSIC_BT_MODULE);
+        btdm_controller_enable_sleep (true);
+        status = ESP_OK;
+    } else if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_EVED) {
+        esp_modem_sleep_register(MODEM_BLE_MODULE);
+        btdm_controller_enable_sleep (true);
+        status = ESP_OK;
+    } else {
+        status = ESP_ERR_NOT_SUPPORTED;
+    }
+
+    return status;
+}
+
+esp_err_t esp_bt_sleep_disable (void)
+{
+    esp_err_t status;
+    if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED) {
+        return ESP_ERR_INVALID_STATE;
+    }
+    if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_ORIG) {
+        esp_modem_sleep_deregister(MODEM_BLE_MODULE);
+        esp_modem_sleep_deregister(MODEM_CLASSIC_BT_MODULE);
+        btdm_controller_enable_sleep (false);
+        status = ESP_OK;
+    } else if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_EVED) {
+        esp_modem_sleep_deregister(MODEM_BLE_MODULE);
+        btdm_controller_enable_sleep (false);
+        status = ESP_OK;
+    } else {
+        status = ESP_ERR_NOT_SUPPORTED;
+    }
+
+    return status;
+}
+
+bool esp_bt_controller_is_sleeping(void)
+{
+    if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED ||
+        btdm_controller_get_sleep_mode() != BTDM_MODEM_SLEEP_MODE_ORIG) {
+        return false;
+    }
+
+    return !btdm_power_state_active();
+}
+
+void esp_bt_controller_wakeup_request(void)
+{
+    if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED ||
+        btdm_controller_get_sleep_mode() != BTDM_MODEM_SLEEP_MODE_ORIG) {
+        return;
+    }
+
+    btdm_wakeup_request();
+}
+
 #endif /*  CONFIG_BT_ENABLED */
index 0d85465e1645de117d16f295d2d1bf62cc5b0e56..9924420f6f0318d5c7f963cce8fe98a0827fe77c 100644 (file)
@@ -27,7 +27,7 @@ extern "C" {
 
 /**
  * @brief Controller config options, depend on config mask.
- *        Config mask indicate which functions enabled, this means 
+ *        Config mask indicate which functions enabled, this means
  *        some options or parameters of some functions enabled by config mask.
  */
 typedef struct {
@@ -260,6 +260,62 @@ void esp_vhci_host_register_callback(const esp_vhci_host_callback_t *callback);
  */
 esp_err_t esp_bt_controller_mem_release(esp_bt_mode_t mode);
 
+/**
+ * @brief enable bluetooth to enter modem sleep
+ *
+ * Note that this function shall not be invoked before esp_bt_controller_enable()
+ *
+ * There are currently two options for bluetooth modem sleep, one is ORIG mode, and another is EVED Mode. EVED Mode is intended for BLE only.
+ *
+ * For ORIG mode:
+ * Bluetooth modem sleep is enabled in controller start up by default if CONFIG_BTDM_CONTROLLER_MODEM_SLEEP is set and "ORIG mode" is selected. In ORIG modem sleep mode, bluetooth controller will switch off some components and pause to work every now and then, if there is no event to process; and wakeup according to the scheduled interval and resume the work. It can also wakeup earlier upon external request using function "esp_bt_controller_wakeup_request".
+ * Note that currently there is problem in the combination use of bluetooth modem sleep and Dynamic Frequency Scaling(DFS). So do not enable DFS if bluetooth modem sleep is in use.
+ *
+ * @return
+ *                  - ESP_OK : success
+ *                  - other  : failed
+ */
+esp_err_t esp_bt_sleep_enable(void);
+
+
+/**
+ * @brief disable bluetooth modem sleep
+ *
+ * Note that this function shall not be invoked before esp_bt_controller_enable()
+ *
+ * If esp_bt_sleep_disable() is called, bluetooth controller will not be allowed to enter modem sleep;
+ *
+ * If ORIG modem sleep mode is in use, if this function is called, bluetooth controller may not immediately wake up if it is dormant then.
+ * In this case, esp_bt_controller_wakeup_request() can be used to shorten the time for wakeup.
+ *
+ * @return
+ *                  - ESP_OK : success
+ *                  - other  : failed
+ */
+esp_err_t esp_bt_sleep_disable(void);
+
+/**
+ * @brief to check whether bluetooth controller is sleeping at the instant, if modem sleep is enabled
+ *
+ * Note that this function shall not be invoked before esp_bt_controller_enable()
+ * This function is supposed to be used ORIG mode of modem sleep
+ *
+ * @return  true if in modem sleep state, false otherwise
+ */
+bool esp_bt_controller_is_sleeping(void);
+
+/**
+ * @brief request controller to wakeup from sleeping state during sleep mode
+ *
+ * Note that this function shall not be invoked before esp_bt_controller_enable()
+ * Note that this function is supposed to be used ORIG mode of modem sleep
+ * Note that after this request, bluetooth controller may again enter sleep as long as the modem sleep is enabled
+ *
+ * Profiling shows that it takes several milliseconds to wakeup from modem sleep after this request.
+ * Generally it takes longer if 32kHz XTAL is used than the main XTAL, due to the lower frequncy of the former as the bluetooth low power clock source.
+ */
+void esp_bt_controller_wakeup_request(void);
+
 #ifdef __cplusplus
 }
 #endif
index a3e98f83144ee46c6ec9b53b1c838bcefdf26e97..700d2bc914b755b840a0adeaa9d1ff45b398b6fa 160000 (submodule)
@@ -1 +1 @@
-Subproject commit a3e98f83144ee46c6ec9b53b1c838bcefdf26e97
+Subproject commit 700d2bc914b755b840a0adeaa9d1ff45b398b6fa
index b418100902e3b76e854f8a4c81397155cdd45de0..82a328d6790745d1a17709d0b2151f32539e8ae8 100644 (file)
@@ -53,6 +53,8 @@ typedef enum {
     PERIPH_WIFI_MODULE,
     PERIPH_BT_MODULE,
     PERIPH_WIFI_BT_COMMON_MODULE,
+    PERIPH_BT_BASEBAND_MODULE,
+    PERIPH_BT_LC_MODULE,
 } periph_module_t;
 
 /**
index 59baf48311c25c04c8871f7a6c4fc7b683bf486e..376444a2cadc34436b676376a8dce65c76990795 100644 (file)
@@ -114,6 +114,10 @@ static uint32_t get_clk_en_mask(periph_module_t periph)
             return DPORT_WIFI_CLK_BT_EN_M;
         case PERIPH_WIFI_BT_COMMON_MODULE:
             return DPORT_WIFI_CLK_WIFI_BT_COMMON_M;
+        case PERIPH_BT_BASEBAND_MODULE:
+            return DPORT_BT_BASEBAND_EN;
+        case PERIPH_BT_LC_MODULE:
+            return DPORT_BT_LC_EN;
         default:
             return 0;
     }
@@ -177,6 +181,8 @@ static uint32_t get_rst_en_mask(periph_module_t periph)
         case PERIPH_WIFI_MODULE:
         case PERIPH_BT_MODULE:
         case PERIPH_WIFI_BT_COMMON_MODULE:
+        case PERIPH_BT_BASEBAND_MODULE:
+        case PERIPH_BT_LC_MODULE:
             return 0;
         default:
             return 0;
@@ -195,6 +201,8 @@ static bool is_wifi_clk_peripheral(periph_module_t periph)
     case PERIPH_WIFI_MODULE:
     case PERIPH_BT_MODULE:
     case PERIPH_WIFI_BT_COMMON_MODULE:
+    case PERIPH_BT_BASEBAND_MODULE:
+    case PERIPH_BT_LC_MODULE:
         return true;
     default:
         return false;
index c1c1df0884e496682d6ec004ebaf802327bf32c9..6529aacb9752161f7eedb255e0911bddce42a7c4 100644 (file)
@@ -169,6 +169,7 @@ PROVIDE ( hci_cmd_desc_tab_testing = 0x3ff97a98 );
 PROVIDE ( hci_cmd_desc_tab_vs = 0x3ff97714 );
 PROVIDE ( hci_command_handler = 0x4004c928 );
 PROVIDE ( hci_env = 0x3ffb9350 );
+PROVIDE ( rwip_env = 0x3ffb8bcc );
 PROVIDE ( hci_evt_dbg_desc_tab = 0x3ff9750c );
 PROVIDE ( hci_evt_desc_tab = 0x3ff9751c );
 PROVIDE ( hci_evt_le_desc_tab = 0x3ff974b4 );
index ecb1cf3a29076ff80b692f9cc535b8997a97b10b..6c23dfe6393f2bc70edaf5d36a0c2c21d8ade2f5 100644 (file)
 #define DPORT_WIFI_CLK_BT_EN_S  11
 /* Mask for clock bits used by both WIFI and Bluetooth, bit 0, 3, 6, 7, 8, 9 */
 #define DPORT_WIFI_CLK_WIFI_BT_COMMON_M 0x000003c9
+//bluetooth baseband bit11
+#define DPORT_BT_BASEBAND_EN  BIT(11)
+//bluetooth LC bit16 and bit17
+#define DPORT_BT_LC_EN  (BIT(16)|BIT(17))
 
 /* Remaining single bit clock masks */
 #define DPORT_WIFI_CLK_SDIOSLAVE_EN  BIT(4)
index dc5f71db21cf274c855666374d9346ec92bd7aaa..d919bb822da199f307dc6d2c5f425a8178994e3c 100644 (file)
@@ -242,6 +242,10 @@ void rtc_clk_apll_enable(bool enable, uint32_t sdm0, uint32_t sdm1, uint32_t sdm
 void rtc_clk_slow_freq_set(rtc_slow_freq_t slow_freq)
 {
     REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL, slow_freq);
+
+    REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN,
+            (slow_freq == RTC_SLOW_FREQ_32K_XTAL) ? 1 : 0);
+
     ets_delay_us(DELAY_SLOW_CLK_SWITCH);
 }
 
index 6f354f88495380d236f176dc323537c5b5a98b3b..94002f79dba5e62dd9b9d469a8cdeea3a7533cf9 100644 (file)
 static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
 {
     /* Enable requested clock (150k clock is always on) */
-    if (cal_clk == RTC_CAL_32K_XTAL) {
-        SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN);
+    int dig_32k_xtal_state = REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN);
+    if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_state) {
+        REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN, 1);
     }
+
     if (cal_clk == RTC_CAL_8MD256) {
         SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_D256_EN);
     }
@@ -79,9 +81,9 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
         timeout_us--;
         ets_delay_us(1);
     }
-    if (cal_clk == RTC_CAL_32K_XTAL) {
-        CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN);
-    }
+
+    REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN, dig_32k_xtal_state);
+
     if (cal_clk == RTC_CAL_8MD256) {
         CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_D256_EN);
     }