• 第11节-BLE协议HCI层的硬件接口


    本篇博客由韦东山视频整理所得

    如何控制链路层让其发出广播包、数据包?
    通过HCI层向它发出命令,也可以通过ATT层、L2CAP层向LL层发出数据。

    学习资料:

    蓝牙协议core_v5.0.pdf 《Vol 4: Host Controller Interface [Transport Layer]》

    BTStack源码

    回顾一下《开源蓝牙协议栈BTStack框架代码阅读》。

    BLE协议在硬件上分为上下两部件:主机(Host,PC、单片机、Linux板)、控制器(蓝牙模块),如下图所示:

    Host和Controller之间,通过HCI(Host Controller Interface)相连。HCI实现硬件之间的数据传输,HCI的一部分位于Host,另一部分位于Controller(图中的红色区域)。

    HCI有多种,一般有USB口、3线串口(TxD/RxD/Gnd)、5线串口(TxD/RxD/Gnd/CTS/RTS),如下图:

    Host和Controller之间的数据有命令(Command)、事件(Event)、ACL数据等等,如下图:

    在硬件线路上,怎么分辨这些不同的数据?

    在《开源蓝牙协议栈BTStack框架代码阅读》里,我们知道BTStack对每一种硬件接口都抽象出了一个hci_transport_t结构体,里面有send_packet函数,分析这个函数就可以知道在硬件线路上,怎么分辨、传输不同类型的数据。

    参考文件:

    btstack-mastersrchci_transport_h4.c  // 5线串口

    btstack-mastersrchci_transport_h5c   // 3线串口

    btstack-masterplatformwindowshci_transport_h2_winusb.c   // usb

    send_packet函数原型为:

    int    (*send_packet)(uint8_t packet_type, uint8_t *packet, int size);

    其中的packet_type有4种取值,代表4种类型的数据(在BLE中只有3种,不支持SCO),这些值在头文件btstack-mastersrcluetooth.h中定义:

    一、最简单的5线串口:

    参考文件:

    btstack-mastersrchci_transport_h4.c  // 5线串口

    在数据之前加上1字节的头部,然后把头部连同数据一起发送。

    这个头部就用来表示数据类型:

    1字节头部

    表示的数据类型

    0x01

    Command (Host发给Controller)

    0x02

    ACL Data

    0x04

    Event  (Controller发给Host)

    数据在TxD、RxD线路上传输,其中的RTS/CTS只是用来进行流量控制。它们的作用简单介绍一下:

    RTS (Require ToSend,发送请求)为输出信号,用于指示本设备准备好可接收数据,低电平有效,低电平说明本设备可以接收数据。

    CTS (Clear ToSend,发送允许)为输入信号,用于判断是否可以向对方发送数据,低电平有效,低电平说明本设备可以向对方发送数据。

    可以参考btstack-mastersrchci_transport_h4.c的hci_transport_h4_send_packet函数:

    //packet所指的内存区域为要发送的数据,packet_type为数据的类型。如何将类型和数据一起发送出去的呢?

    看代码,如下:

    static int hci_transport_h4_send_packet(uint8_t packet_type, uint8_t * packet, int size){

        // store packet type before actual data and increase size

        size++;

        packet--;  //packet指向一个buffer的首地址,即存放数据的起始地址。然后packet--

    *packet = packet_type;这个地方就将数据类型放在了数据的前面去了。

    ……

    二、3线串口:

    考文件:

    btstack-mastersrchci_transport_h5c   // 3线串口

    在实际产品中,使用3线串口的蓝牙控制器比较少,所以我们不深入分析它。

    3线串口没有硬件流量控制的功能,它使用SLIP协议传输数据,流程如下:

    (参考hci_transport_link_send_queued_packet函数)

    ① 构建头部:

    uint8_t header[4];
    hci_transport_link_calc_header(header, link_seq_nr, link_ack_nr, link_peer_supports_data_integrity_check, 1, hci_packet_type, hci_packet_size);

    构建4字节的头部,里面含有packet_type等信息。

    ② 使用SLIP协议发送头部、数据本身:

    ③ SLIP协议:

    有兴趣的人,可以参考以下文章。

    SLIP协议最好文章:

    SLIP—串行线路上传输数据报的非标准协议

    https://blog.csdn.net/pushilong/article/details/80358485

    https://wenku.baidu.com/view/809a8a8e8bd63186bcebbcae.html

    三、USB:

    参考文件:

    btstack-masterplatformwindowshci_transport_h2_winusb.c   // usb

    (1) 补充一些USB知识:

    一个USB硬件,称之为“设备”(Device);

    一个Device内部,有1种或多种“配置”(Configuration)。比如MP3可以用作U盘,也可以用作播放器,这就是2种配置。同一时间,只能有一个配置起作用。

    一个配置内部,有1个或多个接口(Interface)。比如USB声卡有输出、输入2接口。一配置下的多个接口,可以同时使用。

    一个接口内部,有1个或多个端点(Endpoint)。端点是数据传输的实体。

    当我们说“给USB设备发数据”时,实际上是给某个Device的某个Interface的某个Endpoint发数据。

    Endpint有4种:控制端点、BULK端点(批量传输端点)、中断端点、实时端点。

    每个Endpoint用一个数值表示,控制端点永远是0,其他端点值由硬件决定。Endpoint值的bit7表示方向:1表示输入(usb device传给主机),0表示输出(主机传给usb device)。输出和输入是对于host来说的。

    a. 控制端点可以双向传输数据,其他端点都是单向的。

    b. BULK端点:用于传输非实时数据

    c. 中断端点:用于传输时效性高的数据,比如鼠标、键盘数据

    d. 实时端点:用于传输实时数据,比如视频传输。

    主机跟Endpoint之间传输数据时,对应数据通道就称为Pipe。

    (2) BLE数据在USB接口上的传输:

    不同类型的数据,使用不同的Endpoint传输数据。

    数据类型

    Endpoint

    command

    控制端点

    event

    中断端点

    ACL Data (in, controller传给host)

    BULK输入端点

    ACL Data (out, host传给controller)

    BULK输出端点

    SCO Data(in, controller传给host)

    实时输入端点  (BLE不支持)

    SCO Data (out, host传给controller)

    实时输出端点  (BLE不支持)

    (3) 参考代码:btstack-masterplatformwindowshci_transport_h2_winusb.c

    ① 端点扫描:

    usb_scan_for_bluetooth_endpoints函数

    ② 数据发送:packet_type只是用来调用不同的函数,不会作为数据的一部分发送。

     总结:

    HCI层描述了Host和Controller之间通过什么接口来连接,可以通过串口、usb口等进行连接。

    当通过串口进行传输数据时,可以在数据的前面加上一个字节的头部,用来分辨这个数据是command、event还是acl data。
    对于usb口,在usb硬件里面有多个endpoint,command可以发送给某个端点,event可以从某个端点发给Host,不同的数据使用不同的端点。在硬件上传输这些数据时,就不需要加上头部,只需发送数据本身就可以了。

  • 相关阅读:
    这才是你需要的最基础的.Net基础面试题(通俗易懂,最基础的.Net)2
    这才是你需要的最基础的.Net基础面试题(通俗易懂,最基础的.Net)2
    这才是你需要的最基础的.Net基础面试题(通俗易懂,最基础的.Net)2
    这才是你需要的最基础的.Net基础面试题(通俗易懂,最基础的.Net)1
    这才是你需要的最基础的.Net基础面试题(通俗易懂,最基础的.Net)1
    这才是你需要的最基础的.Net基础面试题(通俗易懂,最基础的.Net)1
    python-函数和函数式编程
    Python错误与异常
    IO系统-文件与目录操作
    IO系统-标准C的I/O和文件I/O
  • 原文地址:https://www.cnblogs.com/-glb/p/11617679.html
Copyright © 2020-2023  润新知