在蓝牙设备没有跟其他蓝牙设备连线的时候,它自己属于一个piconet。当有连线后,piconet里有两种角色:master 和 slave。发起连线的一方是master,被连接的一方是slave。slave会以master的时钟为参照,以625us为时间单位,与master进行数据收发。每一个piconet里,一个master最多有7个slave。
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),这种模式有两种编码。
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
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 |
弄清楚了基本概念,弄清楚了框架和数据流向和软件实施办法,就基本对蓝牙协议有了一个宏观认识,对于理解软件代码有一定帮助。
本文链接:https://blog.nnwk.net/article/1562
有问题请留言。版权所有,转载请在显眼位置处保留文章出处,并留下原文连接
Leave your question and I'll get back to you as soon as I see it. All rights reserved. Please keep the source and links
友情链接:
子卿全栈
全部评论