diff --git a/components/bt/bt.c b/components/bt/bt.c index 86f757ad2..17ad26f99 100644 --- a/components/bt/bt.c +++ b/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) { + 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; + } + + btdm_osi_funcs_register(&osi_funcs); + + btdm_cfg_mask = btdm_config_mask_load(); + + ret = btdm_controller_init(btdm_cfg_mask, cfg); + if (ret) { return ESP_ERR_NO_MEM; } - memcpy(&btdm_cfg_opts, cfg, sizeof(esp_bt_controller_config_t)); - - ret = xTaskCreatePinnedToCore(bt_controller_task, "btController", - ESP_TASK_BT_CONTROLLER_STACK, NULL, - ESP_TASK_BT_CONTROLLER_PRIO, &btControllerTaskHandle, CONFIG_BTDM_CONTROLLER_RUN_CPU); - - if (ret != pdPASS) { - memset(&btdm_cfg_opts, 0x0, sizeof(esp_bt_controller_config_t)); - vSemaphoreDelete(btdm_init_sem); - 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 diff --git a/components/bt/include/bt.h b/components/bt/include/bt.h index 5a244e0c8..e2d7d842e 100644 --- a/components/bt/include/bt.h +++ b/components/bt/include/bt.h @@ -19,6 +19,7 @@ #include #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 diff --git a/components/bt/lib b/components/bt/lib index 30a3ab11c..18d9d90fe 160000 --- a/components/bt/lib +++ b/components/bt/lib @@ -1 +1 @@ -Subproject commit 30a3ab11c441630e3e76fbf30212e546db377e8e +Subproject commit 18d9d90fe1e8adf4d11a5a4bc36501525eb4a211