蓝牙协议框架梳理

8/14/2024 5:06:16 PM
289
0

蓝牙基本概念

Piconet

在蓝牙设备没有跟其他蓝牙设备连线的时候,它自己属于一个piconet。当有连线后,piconet里有两种角色:master 和 slave。发起连线的一方是master,被连接的一方是slave。slave会以master的时钟为参照,以625us为时间单位,与master进行数据收发。每一个piconet里,一个master最多有7个slave。

PHY Mode

LE: LE采用频分多址(FDMA)和时分多址(TDMA),在FDMA中使用了40个(40)物理信道,相隔2 MHz。37,38,39用作主要广播,而另外37个通道用作数据渠道或者次要广播通道。

Basic Rate: 最基本的一种模式,采用GFSK,传输速率是 1Mb/s。

Enhanced Data rate: 增强模式,传输速率是 2Mb/s (π/4-DQPSK)或 3Mb/s(8DPSK),这种模式有两种编码。

BT clock

Clock是蓝牙通信最最基础的一个概念,clock定义了通信的时空范围,定义了这个Piconet时空的坐标系,只有在同一个坐标系里,网络内的各个角色才能相互了解对方的时间线,才知道什么时候发包,什么时候收包。
BT clock是个28bit的计数器,每tick一次是312.5us,所以总共有 (2^28 -1)个tick,算一下大约是(2^28-1)*312.5us/10^6/3600 = 23.3个小时后clock会翻转。

针对Clock有几个重要概念:

CLK0, 312.5us,是一个tick
CLK1, 625us, 是一个slot
CLK2, 1.25ms, 是一个frame(做一次TX 和 RX)
CLK12, 1.28s.
Clock的精确度要求为 +/-250ppm 和 +/-20ppm

蓝牙tx,rx会按时隙为节拍通信,数据以625us一个时隙作为最小单元,有些数据包会超过一个时隙,最多可持续5个时隙。

对于一个连接中的两个设备中,对于主设备,slave_offset应为零,因为CLK与其自身的本地时钟CLKN相同。每个从机应在其CLKN上添加一个适当的slave_offset,以使CLK对应于主机的CLKN,使得主从时钟保持同步尽管设备中的所有CLKN均以相同的标称速率运行,但相互漂移会导致CLK不准确。因此,必须定期更新从机中的偏移,以使CLK大约等于主机的CLKN

Physical Channel(信道)

Spec总共有定义如下5种channel

  • Basic piconet physical channel
  • Adapted piconet physical channel
  • Page scan physical channel
  • Inquiry scan physical channel
  • Synchronization scan physical channel

以Basic piconet physical channel为例,在建立连线后,Slave会以Mater的clock为准。Master和Slave以一个slot为单位进行Tx和Rx,Master在clock为偶数时发包,Slave在clock为偶数时收包,如下图所示

蓝牙核心框架

核心架构

蓝牙核心框架信息量非常大,基本把蓝牙的构架和数据传输方向描述的非常清楚,绿色框图部分是Radio, 蓝牙射频,基带和链路管理放在该部分完成,红色部分称为Host端,俗称蓝牙协议。

Radio分为经典蓝牙,低功耗蓝牙和AMP。我们主要看LE Controller,顺带提一下BR/EDR。

Controller和Host直接的数据传输有几种方式:C/E,SCO,ACL,ISO。

• Synchronous Connection-Oriented (SCO) logical transport
• Extended Synchronous Connection-Oriented (eSCO) logical transport
• Asynchronous Connection-Oriented (ACL) logical transport
• Active Slave Broadcast (ASB) logical transport
• Connectionless Slave Broadcast (CSB) logical transport.

简单来说C/E是HOST和Controller通信方式之一,Command用于下发指令,Event是Host用于接收controller上报指令,SCO和eSCO是经典蓝牙下用于音频传输,ACL为异步数据传输(没有严格同步时间要求的数据传输方式),ISO是蓝牙5.2的最新规范的大数据传输通道,分为基于连接的数据流传输和基于广播的数据流传输。上图中灰色的箭头表示控制指令的传输路径,黑体箭头表示数据流向。

Synchronous Connection Oriented (SCO)

  • Circuit switched typically used for voice
  • Symmetric, synchronous service
  • Slot reservation at fixed intervals
  • Point-to-point

Asynchronous Connectionless Link (ACL)

  • Packet switched
  • Symmetric or asymmetric, asynchronous service
    Polling mechanism between master and slave(s)
  • Point-to-point and point-to-multipoint

以设置LE设备广播为例,LE 设备上电后,host发送reset command重启蓝牙设备,发送广播参数command,配置广播内容,使能广播command,完成蓝牙设备的广播设置command。

(```)
########################################################
## Legacy Adv Command
########################################################
#reset
Send_HCI_Reset
Wait_HCI_Command_Complete_Reset_Event 5000, any, HCI_Reset, 0x00

# set Adv parameter
Send_HCI_LE_Set_Advertising_Parameters 800, 800, 0x00, 0x00, 0x00, "01:02:03:04:05:06", "0x07", "0x00"
Wait_HCI_Command_Complete_LE_Set_Advertising_Parameters_Event 5000, any, HCI_LE_Set_Advertising_Parameters, 

# set Adv data Payload
Send_HCI_LE_Set_Advertising_Data 0x10, "00:01:02:03:04:05:06:07:08:09:0A:0B:0C:0D:0E:0F"
Wait_HCI_Command_Complete_LE_Set_Advertising_Data_Event 5000, any, HCI_LE_Set_Advertising_Data, 

# set Scan rsp data Payload
Send_HCI_LE_Set_Scan_Response_Data 0x10, "00:01:02:03:04:05:06:07:08:09:0A:0B:0C:0D:0E:0F"
Wait_HCI_Command_Complete_LE_Set_Scan_Response_Data_Event 5000, any, HCI_LE_Set_Scan_Response_Data, 

# enable adv
Send_HCI_LE_Set_Advertise_Enable 0x01
Wait_HCI_Command_Complete_LE_Set_Advertise_Enable_Event 5000, any, HCI_LE_Set_Advertise_Enable, 
(```)

完整的Command/Event交互LOG如下:

20:23:26.378 * Script Started: “C:\Users\xcoder\Documents\Texas Instruments\HCI TESTER\hci_tester\controller scripts\adv.txt” *
20:23:26.378 –
20:23:26.378 Packet “HCI_Reset”, Opcode 0x0c03
20:23:26.378 –
20:23:26.378 Outgoing Dump:
20:23:26.378 0000: 01 03 0c 00 ….
20:23:26.398 Incoming Dump:
20:23:26.398 0000: 04 0e 04 01 03 0c 00 …….
20:23:26.398 –
20:23:26.398 Packet “HCI_Command_Complete_Reset_Event”, Opcode 0x0c03
20:23:26.398 Parameters:
20:23:26.398 | Number HCI commands : 0x01
20:23:26.398 | Command Opcode : 0x0c03
20:23:26.398 | Status : 0x00 (Success)
20:23:26.398 –
20:23:26.398 –
20:23:26.398 Packet “HCI_LE_Set_Advertising_Parameters”, Opcode 0x2006
20:23:26.398 Parameters:
20:23:26.398 | Advertise Min Interval : 800
20:23:26.398 | Advertise Max Interval : 800
20:23:26.398 | Advertising Type : 0x00 (Connectable Undirected Event)
20:23:26.398 | Own Address Type : 0x00 (Public Device Address)
20:23:26.398 | Direct Address Type : 0x00 (Public Device Address)
20:23:26.398 | Direct Address : “01:02:03:04:05:06”
20:23:26.398 | Advertising Channel Map : 0x07
20:23:26.398 | Advertising Filter Policy : 0x00
20:23:26.398 –
20:23:26.398 Outgoing Dump:
20:23:26.398 0000: 01 06 20 0f 20 03 20 03 00 00 00 06 05 04 03 02 .. . . ………
20:23:26.398 0010: 01 07 00 …
20:23:26.418 Incoming Dump:
20:23:26.418 0000: 04 0e 04 01 06 20 00 ….. .
20:23:26.418 –
20:23:26.418 Packet “HCI_Command_Complete_LE_Set_Advertising_Parameters_Event”, Opcode 0x2006
20:23:26.418 Parameters:
20:23:26.418 | Number HCI commands : 0x01
20:23:26.418 | Command Opcode : 0x2006
20:23:26.418 | Status : 0x00 (Success)
20:23:26.418 –
20:23:26.418 –
20:23:26.418 Packet “HCI_LE_Set_Advertising_Data”, Opcode 0x2008
20:23:26.418 Parameters:
20:23:26.418 | Data Length : 0x10
20:23:26.418 | Advertising data : “00:01:02:03:04:05:06:07:08:09:0A:0B:0C:0D:0E:0F”
20:23:26.418 –
20:23:26.418 Outgoing Dump:
20:23:26.418 0000: 01 08 20 11 10 00 01 02 03 04 05 06 07 08 09 0a .. ………….
20:23:26.418 0010: 0b 0c 0d 0e 0f …..
20:23:26.428 Incoming Dump:
20:23:26.428 0000: 04 0e 04 01 08 20 00 ….. .
20:23:26.428 –
20:23:26.428 Packet “HCI_Command_Complete_LE_Set_Advertising_Data_Event”, Opcode 0x2008
20:23:26.428 Parameters:
20:23:26.428 | Number HCI commands : 0x01
20:23:26.428 | Command Opcode : 0x2008
20:23:26.428 | Status : 0x00 (Success)
20:23:26.428 –
20:23:26.428 –
20:23:26.428 Packet “HCI_LE_Set_Scan_Response_Data”, Opcode 0x2009
20:23:26.428 Parameters:
20:23:26.428 | Data Length : 0x10
20:23:26.428 | Data : “00:01:02:03:04:05:06:07:08:09:0A:0B:0C:0D:0E:0F”
20:23:26.428 –
20:23:26.428 Outgoing Dump:
20:23:26.428 0000: 01 09 20 11 10 00 01 02 03 04 05 06 07 08 09 0a .. ………….
20:23:26.428 0010: 0b 0c 0d 0e 0f …..
20:23:26.448 Incoming Dump:
20:23:26.448 0000: 04 0e 04 01 09 20 00 ….. .
20:23:26.448 –
20:23:26.448 Packet “HCI_Command_Complete_LE_Set_Scan_Response_Data_Event”, Opcode 0x2009
20:23:26.448 Parameters:
20:23:26.448 | Number HCI commands : 0x01
20:23:26.448 | Command Opcode : 0x2009
20:23:26.448 | Status : 0x00 (Success)
20:23:26.448 –
20:23:26.448 –
20:23:26.448 Packet “HCI_LE_Set_Advertise_Enable”, Opcode 0x200a
20:23:26.448 Parameters:
20:23:26.448 | Advertise Enable : 0x01 (Enable)
20:23:26.448 –
20:23:26.448 Outgoing Dump:
20:23:26.448 0000: 01 0a 20 01 01 .. ..
20:23:26.468 Incoming Dump:
20:23:26.468 0000: 04 0e 04 01 0a 20 00 ….. .
20:23:26.468 –
20:23:26.468 Packet “HCI_Command_Complete_LE_Set_Advertise_Enable_Event”, Opcode 0x200a
20:23:26.468 Parameters:
20:23:26.468 | Number HCI commands : 0x01
20:23:26.468 | Command Opcode : 0x200a
20:23:26.468 | Status : 0x00 (Success)
20:23:26.468 –
20:23:26.468 –
20:23:26.468  Script End

蓝牙Host和controller层通过HCI Command/Event交互数据,在早期的BR/EDR蓝牙中,Controller和Host会分开两颗芯片,再蓝牙4.x以后,芯片原厂已经把两颗芯片集成到一颗SOC中,hci层只有在蓝牙测试时候会单独用到,工程中,往往已经看不到hci层(已经打包在lib里),这一章有了一个层级间数据传输的感性认识,下面了解蓝牙协议的全貌。

蓝牙协议架构

从OSI(Open System Interconnection)模型的角度看,蓝牙是一个比较简单的协议,它仅仅提供了物理层(Physical Layer)和数据链路层(Data Link Layer )两个OSI层次,细化可分为如图所示的物理层(Physical Layer)、逻辑层(Logical Layer)、L2CAP Layer。

物理层,负责提供数据传输的物理通道(通常称为信道)。通常情况下,一个通信系统中存在几种不同类型的信道,如控制信道、数据信道、语音信道等等。
逻辑层,在物理层的基础上,提供两个或多个设备之间、和物理无关的逻辑传输通道(也称作逻辑链路)。
L2CAP层,L2CAP是逻辑链路控制和适配协议(Logical Link Control and Adaptation Protocol)的缩写,负责管理逻辑层提供的逻辑链路。基于该协议,不同Application可共享同一个逻辑链路。类似TCP/IP中端口(port)的概念。

在l2cap之上还可以有profile层,理解蓝牙协议的profile,基于L2CAP提供的channel,实现各种各样的应用功能。Profile是蓝牙协议的特有概念,为了实现不同平台下的不同设备的互联互通,蓝牙协议不止规定了核心规范(称作Bluetooth core),也为各种不同的应用场景,定义了各种Application规范。

数据和指令的传输通过C/E,SCO,ACL,ISO几个通道穿梭在不同层协议,既保证了蓝牙协议层级间的独立,又完成了蓝牙数据的交互。

蓝牙层级间的数据交互

蓝牙协议层级间的指令数据传输需要靠通道相互连接,操作系统消息传递机制以及callback函承担了实现层级间的数据通信和交互的桥梁。

我们以TI CC2541(真的很老了)的软件架构来讲述数据传输方式,工程内有多个线程同时工作:LL,HAL,HCI,L2CAP,GAP,SM,GATT,GAPROLE,GAPBondMgr,GATTServApp,SimpleBLEPeripheral。线程之间采用command/event方式交互数据。

(```)
void osalInitTasks( void )
{
  uint8 taskID = 0;

  tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt);
  osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt));

  /* LL Task */
  LL_Init( taskID++ );

  /* Hal Task */
  Hal_Init( taskID++ );

  /* HCI Task */
  HCI_Init( taskID++ );

#if defined ( OSAL_CBTIMER_NUM_TASKS )
  /* Callback Timer Tasks */
  osal_CbTimerInit( taskID );
  taskID += OSAL_CBTIMER_NUM_TASKS;
#endif

  /* L2CAP Task */
  L2CAP_Init( taskID++ );

  /* GAP Task */
  GAP_Init( taskID++ );

  /* SM Task */
  SM_Init( taskID++ );

  /* GATT Task */
  GATT_Init( taskID++ );

  /* Profiles */
  GAPRole_Init( taskID++ );
  GAPBondMgr_Init( taskID++ );

  GATTServApp_Init( taskID++ );

  /* Application */
  SimpleBLEPeripheral_Init( taskID );
}
(```)

HOST端层级之间数据交互通道

HCI下层和controller的部分逻辑和上层host一样,只是在hci层做了一层数据传输的task,HCI_task作为host和controller的衔接,进行发送,解析指令,传输数据。

​HCI command packet format: cmd

  • Packet Type + Command opcode + lengh + command payload
  • | 1 octet | 2 | 1 | n |

HCI data packet format: eco acl

  • Packet Type + Conn Handle + lengh + data payload
  • | 1 octet | 2 | 2 | n |

总结

弄清楚了基本概念,弄清楚了框架和数据流向和软件实施办法,就基本对蓝牙协议有了一个宏观认识,对于理解软件代码有一定帮助。

全部评论



提问