【蓝牙】什么?还不知道蓝牙协议栈开源了?

一,前述

这年头协议栈开源的太多了,掌握基础蓝牙协议栈作为嵌入式软件工程师的进阶技能。如果有了解并应用的市面上大部分蓝牙芯片,不妨看看如下内容,对于理解并提升蓝牙协议了解有一定帮助。

本次文章主要说明如何去学习蓝牙Host协议栈,controller协议栈仅做参考。(conrtoller涉及PHY层,除非原厂深入,一般我们仅作了解)

二,关于Host协议栈

1, 源码链接

上官方链接:https://mynewt.apache.org/
上Github链接:https://github.com/apache/mynewt-nimble

Apache Mynewt是一个开源项目,其中Mynewt Nimble是开源5.1蓝牙协议栈,包含host&controller协议栈,可完全替代nordic softdevice(跟zephyr一样的)。
网上开源协议栈很多,诸如:btstack,bluez,zephyr等等,但是Nimble属轻量级LE Host协议栈,对于初次了解协议栈的朋友非常友好。

官方介绍:

NimBLE complies with Bluetooth Core Specification 5.0 which makes it an ideal wireless technology for the Internet of Things (IoT).

LE Advertising Extensions

2Msym/s PHY for higher throughput

Coded PHY for LE Long Range

High Duty Cycle Non-Connectable Advertising

Channel Selection Algorithm #2 to utilize channels in more efficient way.

LE Privacy 1.2 for frequent changes to the device address to make it difficult to track for outsiders

LE Secure Connections featuring FIPS-compliant algorithms.

LE Data Length Extension for higher throughput

Coming Soon: Assigning an Internet Protocol (IP) address (compliant with the IPv6 or 6LoWPAN standard) to a Bluetooth device through Internet Protocol Support Profile (IPSP)

The Bluetooth 5 is backward compatible with previous Bluetooth version 4.2 which is also supported by Apache Mynewt.

2,如何跑通Host协议栈

本次主要验证如何跑通Host协议栈以及对应源码的简单介绍。
关于Host的支持项如下:

Host

Logical Link Control and Adaptation Protocol (L2CAP): provides logical channels, named L2CAP channels, which are multiplexed over one or more logical links to provide packet segmentation and reassembly, flow control, error control, streaming, QoS etc.

Security Manager (SM): uses Security Manager Protocol (SMP) for pairing and transport specific key distribution for securing radio communication

Attribute protocol (ATT): allows a device (Server) to expose certain pieces of data, known as Attributes, to another device (Client)

Generic Attribute Profile (GATT): a framework for using the ATT protocol to exchange attributes encapsulated as Characteristics or Services

Generic Access Profile (GAP): a base profile which all Bluetooth devices implement, which in the case of LE, defines the Physical Layer, Link Layer, L2CAP, Security Manager, Attribute Protocol and Generic Attribute Profile.

Host Controller Interface (HCI): the interface between the host and controller either through software API or by a hardware interface such as SPI, UART or USB.

对于一个Linux子设备,如IPC或者网关蓝牙配网提供wifi ssid/token等等,一份简单的host协议栈即可满足需求。(且可配置无需依赖linux kernel)

具体流程如下:

(1)下载源码:

git clone https://github.com/apache/mynewt-nimble

(2)编译源码:

root@ubuntu:/home/timcheng/project/mynewt-nimble-latest# cd porting/examples/linux/

// 默认工具链为GCC,本次编译环境为Ubuntu 16.04
root@ubuntu:/home/timcheng/project/mynewt-nimble-latest/porting/examples/linux# make 

// 生成一个nimble-linux的可执行文件
root@ubuntu:/home/timcheng/project/mynewt-nimble-latest/porting/examples/linux# ls
ble.c  ble.o  include  main.c  main.o  Makefile  nimble-linux  README.md

// 直接执行即可。
// 需说明:由于采用的是HCI SOCKET形式与设备交互,所以如果没有安装驱动需单独安装驱动。
//如果采用市面上的realtk dongle直插,需重新加载驱动,具体如何安装驱动以及驱动程序在我的附件中。

(3)关于蓝牙服务说明:
默认服务还是蛮多的,如果需要添加自己的vendor service,可按照任意一个的服务初始化添加即可,比较简单。同时需注释掉如下服务。
【蓝牙】什么?还不知道蓝牙协议栈开源了?_第1张图片

(4)关于HCI Socket说明:

索引地址:nimble\transport\socket\src\ble_hci_socket.c

由于直接在ubuntu上编译且不依赖Apache Mynewt框架,所以可以选择性浏览一些代码。hci实现形式非常多,对于前期理解可先易后难。

三,关于Host源码说明

1,Host分层

协议栈分层已经是基础了,我们剖析中间每一层去理解更为深刻。Apache Mynewt Nimble完全按照L2CAP->ATT/SM->GATT Server/Client以及GAP分层。注重说明GATT与GAP源码。

2,Host协议栈之GAP

索引地址:nimble\Host\src\ble_gap.c

// 着重注意GAT Event,每一个GAP Event将会通过回调机制返回状态。
static int gap_event_cb(struct ble_gap_event *event, void *arg)

// 具体包含如下GAP Event事件
#define BLE_GAP_EVENT_CONNECT               0
#define BLE_GAP_EVENT_DISCONNECT            1
/* Reserved                                 2 */
#define BLE_GAP_EVENT_CONN_UPDATE           3
...
#define BLE_GAP_EVENT_PERIODIC_SYNC_LOST    22
#define BLE_GAP_EVENT_SCAN_REQ_RCVD         23
#define BLE_GAP_EVENT_PERIODIC_TRANSFER     24

// 关于GAP接口可参考文件内信息,着重说明如下几个常用接口
// 开启广播
int ble_gap_adv_start(uint8_t own_addr_type, const ble_addr_t *direct_addr,
                      int32_t duration_ms,
                      const struct ble_gap_adv_params *adv_params,
                      ble_gap_event_fn *cb, void *cb_arg);

// 关闭广播
int ble_gap_adv_stop(void);

// 设置广播信息
int ble_gap_adv_set_data(const uint8_t *data, int data_len);
int ble_gap_adv_rsp_set_data(const uint8_t *data, int data_len);

// 连接子设备
int ble_gap_connect(uint8_t own_addr_type, const ble_addr_t *peer_addr,
                    int32_t duration_ms,
                    const struct ble_gap_conn_params *params,
                    ble_gap_event_fn *cb, void *cb_arg);

// 开启扫描
int ble_gap_disc(uint8_t own_addr_type, int32_t duration_ms,
                 const struct ble_gap_disc_params *disc_params,
                 ble_gap_event_fn *cb, void *cb_arg);

// 关闭扫描
int ble_gap_disc_cancel(void);

3,Host协议栈之GATT

Server索引地址:nimble\Host\src\ble_gatts.c
Client索引地址:nimble\Host\src\ble_gatts.c

// 常用读写notify接口
int ble_gattc_write_no_rsp(uint16_t conn_handle, uint16_t attr_handle,
                           struct os_mbuf *om);
                           
int ble_gattc_write(uint16_t conn_handle, uint16_t attr_handle,
                    struct os_mbuf *om,
                    ble_gatt_attr_fn *cb, void *cb_arg);

int ble_gattc_notify_custom(uint16_t conn_handle, uint16_t att_handle,
                            struct os_mbuf *om);

int ble_gattc_indicate_custom(uint16_t conn_handle, uint16_t chr_val_handle, struct os_mbuf *txom);

int ble_gattc_read_by_uuid(uint16_t conn_handle, uint16_t start_handle,
                           uint16_t end_handle, const ble_uuid_t *uuid,
                           ble_gatt_attr_fn *cb, void *cb_arg);

// 常用Client端发现服务等接口
int ble_gattc_disc_all_svcs(uint16_t conn_handle,
                            ble_gatt_disc_svc_fn *cb, void *cb_arg);

int ble_gattc_disc_svc_by_uuid(uint16_t conn_handle, const ble_uuid_t *uuid, ble_gatt_disc_svc_fn *cb, void *cb_arg);

int ble_gattc_find_inc_svcs(uint16_t conn_handle, uint16_t start_handle,
uint16_t end_handle, ble_gatt_disc_svc_fn *cb, void *cb_arg);
                            
int ble_gattc_disc_all_chrs(uint16_t conn_handle, uint16_t start_handle,
uint16_t end_handle, ble_gatt_chr_fn *cb, void *cb_arg);

int ble_gattc_disc_chrs_by_uuid(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle, const ble_uuid_t *uuid,
ble_gatt_chr_fn *cb, void *cb_arg);

int ble_gattc_disc_all_dscs(uint16_t conn_handle, uint16_t start_handle,
uint16_t end_handle, ble_gatt_dsc_fn *cb, void *cb_arg);

4,关于Host的一些宏定义

// 决定了你发送数据/广播/新增服务等的buffer大小
MYNEWT_VAL_MSYS_1_BLOCK_COUNT

// 决定了你接收数据的buffer大小
MYNEWT_VAL_BLE_ACL_BUF_COUNT

// 决定了你接收的hci事件的buffer大小,如果包含扫描,务必设定较大。
MYNEWT_VAL_BLE_HCI_EVT_HI_BUF_COUNT
MYNEWT_VAL_BLE_HCI_EVT_LO_BUF_COUNT

四,最后说明

开源协议栈框架仅仅是作为一个基础模型,真正做产品还是需要多加打磨的。无论是协议交互还是内存管理,都需要深度理解,才能打造好的产品。

关于如何制作Controller与驱动以及协议栈内存管理分配,可参考另外篇幅。

如果有相关需求,可以联系本人(vx:timcheng93)。可有偿提供整套协议栈服务。

你可能感兴趣的:(蓝牙,协议栈,蓝牙,物联网)