Ver código fonte

component/bt : add ble tx power && fix controller deinit mem leak

1. add ble tx power functions
2. add more osi functions.
3. modify bluetooth controller task procedure
4. fix a memory leak when controller deinit
5. add controller disable return value.
Tian Hao 8 anos atrás
pai
commit
006a90e075
3 arquivos alterados com 222 adições e 54 exclusões
  1. 149 47
      components/bt/bt.c
  2. 72 6
      components/bt/include/bt.h
  3. 1 1
      components/bt/lib

+ 149 - 47
components/bt/bt.c

@@ -44,9 +44,8 @@
 
 /* not for user call, so don't put to include file */
 extern void btdm_osi_funcs_register(void *osi_funcs);
-extern void btdm_controller_init(uint32_t config_mask, esp_bt_controller_config_t *config_opts);
-extern void btdm_controller_schedule(void);
-extern void btdm_controller_deinit(void);
+extern int btdm_controller_init(uint32_t config_mask, esp_bt_controller_config_t *config_opts);
+extern int btdm_controller_deinit(void);
 extern int btdm_controller_enable(esp_bt_mode_t mode);
 extern int btdm_controller_disable(esp_bt_mode_t mode);
 extern void btdm_rf_bb_init(void);
@@ -61,6 +60,9 @@ extern bool API_vhci_host_check_send_available(void);
 extern void API_vhci_host_send_packet(uint8_t *data, uint16_t len);
 extern void API_vhci_host_register_callback(const vhci_host_callback_t *callback);
 
+extern int ble_txpwr_set(int power_type, int power_level);
+extern int ble_txpwr_get(int power_type);
+
 #define BT_DEBUG(...)
 #define BT_API_CALL_CHECK(info, api_call, ret) \
 do{\
@@ -71,6 +73,8 @@ do{\
     }\
 } while(0)
 
+#define OSI_FUNCS_TIME_BLOCKING  0xffffffff
+
 struct osi_funcs_t {
     xt_handler (*_set_isr)(int n, xt_handler f, void *arg);
     void (*_ints_on)(unsigned int mask);
@@ -79,11 +83,25 @@ struct osi_funcs_t {
     void (*_task_yield)(void);
     void (*_task_yield_from_isr)(void);
     void *(*_semphr_create)(uint32_t max, uint32_t init);
+    void (*_semphr_delete)(void *semphr);
+    int32_t (*_semphr_take_from_isr)(void *semphr, void *hptw);
     int32_t (*_semphr_give_from_isr)(void *semphr, void *hptw);
     int32_t (*_semphr_take)(void *semphr, uint32_t block_time_ms);
+    int32_t (*_semphr_give)(void *semphr);
     void *(*_mutex_create)(void);
+    void (*_mutex_delete)(void *mutex);
     int32_t (*_mutex_lock)(void *mutex);
     int32_t (*_mutex_unlock)(void *mutex);
+    void *(* _queue_create)(uint32_t queue_len, uint32_t item_size);
+    void (* _queue_delete)(void *queue);
+    int32_t (* _queue_send)(void *queue, void *item, uint32_t block_time_ms);
+    int32_t (* _queue_send_from_isr)(void *queue, void *item, void *hptw);
+    int32_t (* _queue_recv)(void *queue, void *item, uint32_t block_time_ms);
+    int32_t (* _queue_recv_from_isr)(void *queue, void *item, void *hptw);
+    int32_t (* _task_create)(void *task_func, const char *name, uint32_t stack_depth, void *param, uint32_t prio, void *task_handle, uint32_t core_id);
+    void (* _task_delete)(void *task_handle);
+    void *(* _malloc)(uint32_t size);
+    void (* _free)(void *p);
     int32_t (* _read_efuse_mac)(uint8_t mac[6]);
     void (* _srand)(unsigned int seed);
     int (* _rand)(void);
@@ -91,10 +109,7 @@ struct osi_funcs_t {
 
 /* Static variable declare */
 static bool btdm_bb_init_flag = false;
-static xSemaphoreHandle btdm_init_sem;
 static esp_bt_controller_status_t btdm_controller_status = ESP_BT_CONTROLLER_STATUS_IDLE;
-static esp_bt_controller_config_t btdm_cfg_opts;
-static xTaskHandle btControllerTaskHandle;
 
 static portMUX_TYPE global_int_mux = portMUX_INITIALIZER_UNLOCKED;
 
@@ -118,6 +133,16 @@ static void *IRAM_ATTR semphr_create_wrapper(uint32_t max, uint32_t init)
     return (void *)xSemaphoreCreateCounting(max, init);
 }
 
+static void IRAM_ATTR semphr_delete_wrapper(void *semphr)
+{
+    vSemaphoreDelete(semphr);
+}
+
+static int32_t IRAM_ATTR semphr_take_from_isr_wrapper(void *semphr, void *hptw)
+{
+    return (int32_t)xSemaphoreTakeFromISR(semphr, hptw);
+}
+
 static int32_t IRAM_ATTR semphr_give_from_isr_wrapper(void *semphr, void *hptw)
 {
     return (int32_t)xSemaphoreGiveFromISR(semphr, hptw);
@@ -125,7 +150,16 @@ static int32_t IRAM_ATTR semphr_give_from_isr_wrapper(void *semphr, void *hptw)
 
 static int32_t IRAM_ATTR semphr_take_wrapper(void *semphr, uint32_t block_time_ms)
 {
-    return (int32_t)xSemaphoreTake(semphr, block_time_ms / portTICK_PERIOD_MS);
+    if (block_time_ms == OSI_FUNCS_TIME_BLOCKING) {
+        return (int32_t)xSemaphoreTake(semphr, portMAX_DELAY);
+    } else {
+        return (int32_t)xSemaphoreTake(semphr, block_time_ms / portTICK_PERIOD_MS);
+    }
+}
+
+static int32_t IRAM_ATTR semphr_give_wrapper(void *semphr)
+{
+    return (int32_t)xSemaphoreGive(semphr);
 }
 
 static void *IRAM_ATTR mutex_create_wrapper(void)
@@ -133,6 +167,11 @@ static void *IRAM_ATTR mutex_create_wrapper(void)
     return (void *)xSemaphoreCreateMutex();
 }
 
+static void IRAM_ATTR mutex_delete_wrapper(void *mutex)
+{
+    vSemaphoreDelete(mutex);
+}
+
 static int32_t IRAM_ATTR mutex_lock_wrapper(void *mutex)
 {
     return (int32_t)xSemaphoreTake(mutex, portMAX_DELAY);
@@ -143,6 +182,54 @@ static int32_t IRAM_ATTR mutex_unlock_wrapper(void *mutex)
     return (int32_t)xSemaphoreGive(mutex);
 }
 
+static void *IRAM_ATTR queue_create_wrapper(uint32_t queue_len, uint32_t item_size)
+{
+    return (void *)xQueueCreate(queue_len, item_size);
+}
+
+static void IRAM_ATTR queue_delete_wrapper(void *queue)
+{
+    vQueueDelete(queue);
+}
+
+static int32_t IRAM_ATTR queue_send_wrapper(void *queue, void *item, uint32_t block_time_ms)
+{
+    if (block_time_ms == OSI_FUNCS_TIME_BLOCKING) {
+        return (int32_t)xQueueSend(queue, item, portMAX_DELAY);
+    } else {
+        return (int32_t)xQueueSend(queue, item, block_time_ms / portTICK_PERIOD_MS);
+    }
+}
+
+static int32_t IRAM_ATTR queue_send_from_isr_wrapper(void *queue, void *item, void *hptw)
+{
+    return (int32_t)xQueueSendFromISR(queue, item, hptw);
+}
+
+static int32_t IRAM_ATTR queue_recv_wrapper(void *queue, void *item, uint32_t block_time_ms)
+{
+    if (block_time_ms == OSI_FUNCS_TIME_BLOCKING) {
+        return (int32_t)xQueueReceive(queue, item, portMAX_DELAY);
+    } else {
+        return (int32_t)xQueueReceive(queue, item, block_time_ms / portTICK_PERIOD_MS);
+    }
+}
+
+static int32_t IRAM_ATTR queue_recv_from_isr_wrapper(void *queue, void *item, void *hptw)
+{
+    return (int32_t)xQueueReceiveFromISR(queue, item, hptw);
+}
+
+static int32_t IRAM_ATTR task_create_wrapper(void *task_func, const char *name, uint32_t stack_depth, void *param, uint32_t prio, void *task_handle, uint32_t core_id)
+{
+    return (uint32_t)xTaskCreatePinnedToCore(task_func, name, stack_depth, param, prio, task_handle, (core_id < portNUM_PROCESSORS ? core_id : tskNO_AFFINITY));
+}
+
+static void IRAM_ATTR task_delete_wrapper(void *task_handle)
+{
+    vTaskDelete(task_handle);
+}
+
 static int32_t IRAM_ATTR read_mac_wrapper(uint8_t mac[6])
 {
     return esp_read_mac(mac, ESP_MAC_BT);
@@ -166,11 +253,25 @@ static struct osi_funcs_t osi_funcs = {
     ._task_yield = vPortYield,
     ._task_yield_from_isr = task_yield_from_isr,
     ._semphr_create = semphr_create_wrapper,
+    ._semphr_delete = semphr_delete_wrapper,
+    ._semphr_take_from_isr = semphr_take_from_isr_wrapper,
     ._semphr_give_from_isr = semphr_give_from_isr_wrapper,
     ._semphr_take = semphr_take_wrapper,
+    ._semphr_give = semphr_give_wrapper,
     ._mutex_create = mutex_create_wrapper,
+    ._mutex_delete = mutex_delete_wrapper,
     ._mutex_lock = mutex_lock_wrapper,
     ._mutex_unlock = mutex_unlock_wrapper,
+    ._queue_create = queue_create_wrapper,
+    ._queue_delete = queue_delete_wrapper,
+    ._queue_send = queue_send_wrapper,
+    ._queue_send_from_isr = queue_send_from_isr_wrapper,
+    ._queue_recv = queue_recv_wrapper,
+    ._queue_recv_from_isr = queue_recv_from_isr_wrapper,
+    ._task_create = task_create_wrapper,
+    ._task_delete = task_delete_wrapper,
+    ._malloc = malloc,
+    ._free = free,
     ._read_efuse_mac = read_mac_wrapper,
     ._srand = srand_wrapper,
     ._rand = rand_wrapper,
@@ -207,29 +308,10 @@ static uint32_t btdm_config_mask_load(void)
     return mask;
 }
 
-static void bt_controller_task(void *pvParam)
-{
-    uint32_t btdm_cfg_mask = 0;
-
-    btdm_cfg_mask = btdm_config_mask_load();
-
-    btdm_osi_funcs_register(&osi_funcs);
-
-    btdm_controller_init(btdm_cfg_mask, &btdm_cfg_opts);
-
-    btdm_controller_status = ESP_BT_CONTROLLER_STATUS_INITED;
-
-    xSemaphoreGive(btdm_init_sem);
-
-    /* Loop */
-    btdm_controller_schedule();
-
-    /* never run here */
-}
-
 esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
 {
     BaseType_t ret;
+    uint32_t btdm_cfg_mask = 0;
 
     if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_IDLE) {
         return ESP_ERR_INVALID_STATE;
@@ -239,34 +321,36 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
         return ESP_ERR_INVALID_ARG;
     }
 
-    btdm_init_sem = xSemaphoreCreateBinary();
-    if (btdm_init_sem == NULL) {
-        return ESP_ERR_NO_MEM;
+    if (cfg->controller_task_prio != ESP_TASK_BT_CONTROLLER_PRIO
+            || cfg->controller_task_stack_size < ESP_TASK_BT_CONTROLLER_STACK) {
+        return ESP_ERR_INVALID_ARG;
     }
 
-    memcpy(&btdm_cfg_opts, cfg, sizeof(esp_bt_controller_config_t));
+    btdm_osi_funcs_register(&osi_funcs);
 
-    ret = xTaskCreatePinnedToCore(bt_controller_task, "btController",
-                            ESP_TASK_BT_CONTROLLER_STACK, NULL,
-                            ESP_TASK_BT_CONTROLLER_PRIO, &btControllerTaskHandle, CONFIG_BTDM_CONTROLLER_RUN_CPU);
+    btdm_cfg_mask = btdm_config_mask_load();
 
-    if (ret != pdPASS) {
-        memset(&btdm_cfg_opts, 0x0, sizeof(esp_bt_controller_config_t));
-        vSemaphoreDelete(btdm_init_sem);
+    ret = btdm_controller_init(btdm_cfg_mask, cfg);
+    if (ret) {
         return ESP_ERR_NO_MEM;
     }
 
-    xSemaphoreTake(btdm_init_sem, BTDM_INIT_PERIOD/portTICK_PERIOD_MS);
-    vSemaphoreDelete(btdm_init_sem);
-
+    btdm_controller_status = ESP_BT_CONTROLLER_STATUS_INITED;
     return ESP_OK;
 }
 
-void esp_bt_controller_deinit(void)
+esp_err_t esp_bt_controller_deinit(void)
 {
-    memset(&btdm_cfg_opts, 0x0, sizeof(esp_bt_controller_config_t));
-    vTaskDelete(btControllerTaskHandle);
+    if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_INITED) {
+        return ESP_ERR_INVALID_STATE;
+    }
+
+    if (btdm_controller_deinit() != 0) {
+        return ESP_ERR_NO_MEM;
+    }
+
     btdm_controller_status = ESP_BT_CONTROLLER_STATUS_IDLE;
+    return ESP_OK;
 }
 
 esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode)
@@ -311,13 +395,14 @@ esp_err_t esp_bt_controller_disable(esp_bt_mode_t mode)
     }
 
     ret = btdm_controller_disable(mode);
-    if (ret) {
+    if (ret < 0) {
         return ESP_ERR_INVALID_STATE;
     }
 
-    esp_phy_rf_deinit();
-
-    btdm_controller_status = ESP_BT_CONTROLLER_STATUS_INITED;
+    if (ret == ESP_BT_MODE_IDLE) {
+        esp_phy_rf_deinit();
+        btdm_controller_status = ESP_BT_CONTROLLER_STATUS_INITED;
+    }
 
     return ESP_OK;
 }
@@ -327,4 +412,21 @@ esp_bt_controller_status_t esp_bt_controller_get_status(void)
     return btdm_controller_status;
 }
 
+
+/* extra functions */
+esp_err_t esp_ble_tx_power_set(esp_ble_power_type_t power_type, esp_power_level_t power_level)
+{
+    if (ble_txpwr_set(power_type, power_level) != 0) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    return ESP_OK;
+}
+
+esp_power_level_t esp_ble_tx_power_get(esp_ble_power_type_t power_type)
+{
+    return (esp_power_level_t)ble_txpwr_get(power_type);
+}
+
+
 #endif

+ 72 - 6
components/bt/include/bt.h

@@ -19,6 +19,7 @@
 #include <stdbool.h>
 #include "esp_err.h"
 #include "sdkconfig.h"
+#include "esp_task.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -30,8 +31,10 @@ extern "C" {
  *        some options or parameters of some functions enabled by config mask.
  */
 typedef struct {
-    uint8_t hci_uart_no;            /*!< If use UART1/2 as HCI IO interface, indicate UART number */
-    uint32_t hci_uart_baudrate;     /*!< If use UART1/2 as HCI IO interface, indicate UART baudrate */
+    uint16_t controller_task_stack_size;    /*!< Bluetooth controller task stack size */
+    uint8_t controller_task_prio;           /*!< Bluetooth controller task priority */
+    uint8_t hci_uart_no;                    /*!< If use UART1/2 as HCI IO interface, indicate UART number */
+    uint32_t hci_uart_baudrate;             /*!< If use UART1/2 as HCI IO interface, indicate UART baudrate */
 } esp_bt_controller_config_t;
 
 #ifdef CONFIG_BT_ENABLED
@@ -48,9 +51,11 @@ typedef struct {
 #define BT_HCI_UART_BAUDRATE_DEFAULT 921600
 #endif /* BT_HCI_UART_BAUDRATE_DEFAULT */
 
-#define BT_CONTROLLER_INIT_CONFIG_DEFAULT() { \
-    .hci_uart_no = BT_HCI_UART_NO_DEFAULT,\
-    .hci_uart_baudrate = BT_HCI_UART_BAUDRATE_DEFAULT,\
+#define BT_CONTROLLER_INIT_CONFIG_DEFAULT() {                       \
+    .controller_task_stack_size = ESP_TASK_BT_CONTROLLER_STACK,     \
+    .controller_task_prio = ESP_TASK_BT_CONTROLLER_PRIO,            \
+    .hci_uart_no = BT_HCI_UART_NO_DEFAULT,                          \
+    .hci_uart_baudrate = BT_HCI_UART_BAUDRATE_DEFAULT,              \
 };
 #else
 #define BT_CONTROLLER_INIT_CONFIG_DEFAULT() {0}; _Static_assert(0, "please enable bluetooth in menuconfig to use bt.h");
@@ -76,6 +81,66 @@ typedef enum {
     ESP_BT_CONTROLLER_STATUS_NUM,
 } esp_bt_controller_status_t;
 
+
+/**
+ * @brief BLE tx power type
+ *        ESP_BLE_PWR_TYPE_CONN_HDL0-9: for each connection, and only be set after connetion completed.
+ *                                      when disconnect, the correspond TX power is not effected.
+ *        ESP_BLE_PWR_TYPE_ADV : for advertising/scan response.
+ *        ESP_BLE_PWR_TYPE_SCAN : for scan.
+ *        ESP_BLE_PWR_TYPE_DEFAULT : if each connection's TX power is not set, it will use this default value.
+ *                                   if neither in scan mode nor in adv mode, it will use this default value.
+ *        If none of power type is set, system will use ESP_PWR_LVL_P1 as default for ADV/SCAN/CONN0-9.
+ */
+typedef enum {
+    ESP_BLE_PWR_TYPE_CONN_HDL0  = 0,            /*!< For connection handle 0 */
+    ESP_BLE_PWR_TYPE_CONN_HDL1  = 1,            /*!< For connection handle 1 */
+    ESP_BLE_PWR_TYPE_CONN_HDL2  = 2,            /*!< For connection handle 2 */
+    ESP_BLE_PWR_TYPE_CONN_HDL3  = 3,            /*!< For connection handle 3 */
+    ESP_BLE_PWR_TYPE_CONN_HDL4  = 4,            /*!< For connection handle 4 */
+    ESP_BLE_PWR_TYPE_CONN_HDL5  = 5,            /*!< For connection handle 5 */
+    ESP_BLE_PWR_TYPE_CONN_HDL6  = 6,            /*!< For connection handle 6 */
+    ESP_BLE_PWR_TYPE_CONN_HDL7  = 7,            /*!< For connection handle 7 */
+    ESP_BLE_PWR_TYPE_CONN_HDL8  = 8,            /*!< For connection handle 8 */
+    ESP_BLE_PWR_TYPE_CONN_HDL9  = 9,            /*!< For connection handle 9 */
+    ESP_BLE_PWR_TYPE_ADV        = 10,           /*!< For advertising */
+    ESP_BLE_PWR_TYPE_SCAN       = 11,           /*!< For scan */
+    ESP_BLE_PWR_TYPE_DEFAULT    = 12,           /*!< For default, if not set other, it will use default value */
+    ESP_BLE_PWR_TYPE_NUM        = 13,           /*!< TYPE numbers */
+} esp_ble_power_type_t;
+
+/**
+ * @brief Bluetooth TX power level(index), it's just a index corresponding to power(dbm).
+ */
+typedef enum {
+    ESP_PWR_LVL_N14 = 0,            /*!< Corresponding to -14dbm */
+    ESP_PWR_LVL_N11 = 1,            /*!< Corresponding to -11dbm */
+    ESP_PWR_LVL_N8  = 2,            /*!< Corresponding to  -8dbm */
+    ESP_PWR_LVL_N5  = 3,            /*!< Corresponding to  -5dbm */
+    ESP_PWR_LVL_N2  = 4,            /*!< Corresponding to  -2dbm */
+    ESP_PWR_LVL_P1  = 5,            /*!< Corresponding to   1dbm */
+    ESP_PWR_LVL_P4  = 6,            /*!< Corresponding to   4dbm */
+    ESP_PWR_LVL_P7  = 7,            /*!< Corresponding to   7dbm */
+} esp_power_level_t;
+
+/**
+ * @brief  Set BLE TX power
+ *         Connection Tx power should only be set after connection created.
+ * @param  power_type : The type of which tx power, could set Advertising/Connection/Default and etc
+ * @param  power_level: Power level(index) corresponding to absolute value(dbm)
+ * @return              ESP_OK - success, other - failed
+ */
+esp_err_t esp_ble_tx_power_set(esp_ble_power_type_t power_type, esp_power_level_t power_level);
+
+/**
+ * @brief  Get BLE TX power
+ *         Connection Tx power should only be get after connection created.
+ * @param  power_type : The type of which tx power, could set Advertising/Connection/Default and etc
+ * @return             >= 0 - Power level, < 0 - Invalid
+ */
+esp_power_level_t esp_ble_tx_power_get(esp_ble_power_type_t power_type);
+
+
 /**
  * @brief  Initialize BT controller to allocate task and other resource.
  * @param  cfg: Initial configuration of BT controller.
@@ -89,8 +154,9 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg);
  *
  * This function should be called only once, after any other BT functions are called.
  * This function is not whole completed, esp_bt_controller_init cannot called after this function.
+ * @return  ESP_OK - success, other - failed
  */
-void esp_bt_controller_deinit(void);
+esp_err_t esp_bt_controller_deinit(void);
 
 /**
  * @brief Enable BT controller

+ 1 - 1
components/bt/lib

@@ -1 +1 @@
-Subproject commit 30a3ab11c441630e3e76fbf30212e546db377e8e
+Subproject commit 18d9d90fe1e8adf4d11a5a4bc36501525eb4a211