ESP32蓝牙协议栈NIMBLE-HOST协议移植分析
目录
三、 根据ESP32-NIMBLE-blehr的例子分析程序流程
一、 nimble 蓝牙协议栈介绍
关于nimble目录介绍可以参考链接:nimble协议栈源码目录介绍
二 、关于esp32移植的内容分析
我们最需要关心的是 /nimble 目录和 /porting 目录
2.1 关于/porting 目录移植
/porting /npl目录,主要是真的移植操作系统相关
其中移植nimble_npl_os.h文件中的rtos主要接口,移植其他操作系统就需要重新实现。
“freertos/queue.h” //事件队列
“freertos/semphr.h” //信号量 ,互斥信号量
“freertos/task.h” //任务
“freertos/timers.h” //软件定时器
部分中断临界区进入退出接口
针对 esp32采用freertos所以基本已经算移植好了,主要对部分接口进行适配,以及头文件进行修改优化。这部分改动较小,
例如:
/porting /nimble 这个目录 也是针对平台进行适配,改动较大,这里针对主要系统进行说明。
2.2 /nimble 目录移植
host 部分移植:
- a) 主要针对,porting之前移植freertos 任务部分,内存管理接口等部分,
- b) mesh 安全算法部分
-c) esp32 还有一些自定义优化部分
具体ESP32移植目录如下:
三、 根据ESP32-NIMBLE-blehr的例子分析程序流程
3.1 main()函数分析
void blehr_host_task(void *param)
{
ESP_LOGI(tag, "BLE Host Task Started");
/* This function will return only when nimble_port_stop() is executed */
nimble_port_run();
nimble_port_freertos_deinit();
}
void app_main(void)
{
int rc;
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);
ESP_ERROR_CHECK(esp_nimble_hci_and_controller_init()); //HCI传输层初始化
nimble_port_init(); //协议栈HOST初始化
/* Initialize the NimBLE host configuration */
ble_hs_cfg.sync_cb = blehr_on_sync;
ble_hs_cfg.reset_cb = blehr_on_reset;
/* name, period/time, auto reload, timer ID, callback */
blehr_tx_timer = xTimerCreate("blehr_tx_timer", pdMS_TO_TICKS(1000), pdTRUE, (void *)0, blehr_tx_hrate);
rc = gatt_svr_init(); //系统服务初始化
assert(rc == 0);
/* Set the default device name */
rc = ble_svc_gap_device_name_set(device_name);
assert(rc == 0);
/* Start the task */
nimble_port_freertos_init(blehr_host_task); //启动host任务
}
esp_nimble_hci_and_controller_init()//就是之前esp-hci中移植时实现的。
nimble_port_init() //初始化HOST协议栈相关事情
blehr_host_task() ->> nimble_port_run() //运行协议栈HOST程序线程
nimble_port_freertos_init(blehr_host_task)//是操作系统移植时实现的
3.2 移植实现的esp_nimble_hci文件进行分析
/*
HOST ----HCI---------CONTROLLER
HOST--->>CONTROLLER : HCI-CMD //移植采用esp32的发送接口 esp_vhci_host_send_packet
CONTROLLER--->>> HOST : HCI-EVENT,HCI-ACL //移植采用controller回调接口协议栈HCI处理接口
*/
int ble_hci_trans_hs_cmd_tx(uint8_t *cmd)
{
uint16_t len;
uint8_t rc = 0;
assert(cmd != NULL);
*cmd = BLE_HCI_UART_H4_CMD;
len = BLE_HCI_CMD_HDR_LEN + cmd[3] + 1;
if (!esp_vhci_host_check_send_available()) {
ESP_LOGD(TAG, "Controller not ready to receive packets");
}
if (xSemaphoreTake(vhci_send_sem, NIMBLE_VHCI_TIMEOUT_MS / portTICK_PERIOD_MS) == pdTRUE) {
esp_vhci_host_send_packet(cmd, len);
} else {
rc = BLE_HS_ETIMEOUT_HCI;
}
ble_hci_trans_buf_free(cmd);
return rc;
}
esp_err_t esp_nimble_hci_and_controller_init(void)
{
esp_err_t ret;
esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT);
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
if ((ret = esp_bt_controller_init(&bt_cfg)) != ESP_OK) {
return ret;
}
if ((ret = esp_bt_controller_enable(ESP_BT_MODE_BLE)) != ESP_OK) {
return ret;
}
return esp_nimble_hci_init();
}
esp_err_t esp_nimble_hci_init(void)
{
esp_err_t ret;
ret = ble_buf_alloc();
if (ret != ESP_OK) {
goto err;
}
if ((ret = esp_vhci_host_register_callback(&vhci_host_cb)) != ESP_OK) {
goto err;
}
ble_hci_transport_init();
vhci_send_sem = xSemaphoreCreateBinary();
if (vhci_send_sem == NULL) {
ret = ESP_ERR_NO_MEM;
goto err;
}
xSemaphoreGive(vhci_send_sem);
return ret;
err:
ble_buf_free();
return ret;
}
esp_vhci_host_register_callback --->>vhci_host_cb
--->>ble_hci_trans_ll_evt_tx 回调HOST接口返回HOST协议处理
--->>ble_hci_rx_acl 回调HOST接口返回HOST协议处理