链路层详解
参考书籍:《低功耗蓝牙开发权威指南》
脑图软件:XMind ZEN 2020
OverView
1. 链路层状态机
共有5中状态:
- 就绪态:中心状态,任何状态都可以转换为它;
- 广播态:使用广播报文
- 扫描态:使用广播报文,不可连接
- 发起态:使用广播报文,随机发起连接
- 连接态:使用数据报文;
2. 报文
报文结构:
更加具体的看这里:https://blog.csdn.net/qq_34740116/article/details/106274889
3. 信道
3.1 跳频
跳频算法应用于数据连接中。数据信道共37个,以下为其公式:
f
n
+
1
=
(
f
n
+
h
o
p
)
m
o
d
37
f_{n+1}=(f_n + hop) \;mod\;37
fn+1=(fn+hop)mod37
其中
h
o
p
hop
hop是一个5~16范围的值,每次跳频之后中心频率加
h
o
p
hop
hop并模37。
3.2 自适应跳频
自适应跳频能够将一个已知的坏信道映射到一个已知的好信道,从而减少其他设备对数据报文传送的干扰。主设备至少将两个数据信道标记为好信道。
4. 设备发现
- 通用广播:通过广播设备能够被扫描设备扫描到,或者在接收到连接请求时作为从设备进入一个连接。通用广播设备可以在没有 连接的情况下发出,也就是说没有主从设备之分。
- 定向广播: 定向广播事件为了尽快建立连接。该报文包含广播者的地址和发起者的地址。
- 不可连接广播:这种设备只想广播设备而不想被连接。比如在某商场内,一些传感器广播温度和导向信息。
- 可发现广播:这种广播不可以发起连接,但允许其他设备扫描该广播设备。这意味着该设备可以被发现,既可以广播数据,又可以响应扫描,但不可以建立连接。这是一种适用于广播数据的广播形式,动态广播可以包含于广播数据之中,而静态数据可以包含于扫面响应数据之中。
5. 广播
在广播时,广播报文需要打上标签,以便设备理解。通过使用“长度:类型:数据" 这样的格式,无法理解特定数据类型的设备就会根据该数据片段的长度选择跳过该片段,从而不影响对后续数据片段的解析。
6. 建立连接
-
接入地址:由主设备随机生成,地址的随机性确保了不同主从设备之间发生的碰撞概率会很低。随机性也增强了设备的隐私性,使得扫描设备无法获知哪两个设备在通信。
-
CRC初始化:由主设备随机产生。随机的意义在于,在同一个区域内有两个主设备在和不同的从设备通信,那么使用相同的接入地址的概率会很低。如果发生了这种情况,从设备会从错误的主设备收到干扰包。因此,为每个设备再设置随机CRC初始值,主从设备同时具有相同的接入地址和CRC初始值的概率就会变得微乎其微。
-
发送窗口:
这里有两个参数:窗口大小和窗口间隔;
当链接请求数据包发送完毕,存在一个1.25ms的强制时延,紧接着发送窗口偏移和发送窗口。【这里书上写的不太清晰,前后名词不对应,待查证!!!】 -
连接事件:一个连接事件是指主设备和从设备之间相互发送数据包的过程。连接事件的进行始终位于一个频率的通道,每个数据包在上个数据包发完之后必须等待150us再发送。
连接间隔决定了主设备和从设备的交互间隔;它是指两个连续的连接事件开始处的时间距离,可以是7.5ms~4s内的任意值,但必须是1.25ms的整数倍。
但是实际的连接间隔还有一个影响因素:从机延迟;这里注意,从设备的延迟必须短于监督超时的时间。举个栗子:
若连接间隔为100ms,从设备延迟是9, 那么从设备就必须侦听第10个连接事件。也就是从设备必须每秒侦听一次( 100 m s ∗ 10 = 1000 m s = 1 s 100ms*10=1000ms=1s 100ms∗10=1000ms=1s),而此时监控超时的最小值应该为1010ms。反过来,一个极端的例子是,如果监控超时使用了32s的最大值,对于间隔为100ms的链路,从设备延时必须小于等于319:( 32 ∗ 1000 m s / 100 m s = 320 , 320 − 1 = 329 32*1000ms / 100ms = 320, 320-1 = 329 32∗1000ms/100ms=320,320−1=329,也就是每隔329次连接事件,从设备侦听一次;换句话说,第320个连接事件从设备必须侦听。)
但是若将从设备延迟设置为可行的最大值,那么从设备在监控超时发生前只有一次机会侦听主设备,我承认这有赌的成分。为了更加安全,建议至少给从设备留出6次侦听的机会。
-
信道图: 自适应跳频信道图是数据信道的位掩码,用来标记信道的好坏。若某一位设置为1,表示信道良好,可以用于数据传输;若有一位设置为0,表示该信道很糟,不能用于数据通信。
-
睡眠时钟精度:主设备发送给从设备的信息中还包括睡眠时钟精度值。该值定义了时钟能够保证的精度范围。
7. 发送数据
-
数据报头
-
逻辑链路标识符:用于判断数据报文属于下列哪种类型:
– 逻辑链路层空中报文(11)------用于管理连接;
– 高层报文开始(10) ------也可用于一个完整的报文;
– 高层报文延续(01) -
序列号(SN):为了使得数据传输变得可靠,所有的数据包都带有序列号。
-
确认(NESN):NESN的发送方用其通知对方的自己期望接收的数据包的序列号。
-
更多数据(M):用来通知对端设备自己还有其他的数据准备发送。
这三个是一套机制,下面举例说明;
总结:
可以简单认为主设备Master只更新SN,而从设备Slaver只更新NESN。
主设备接收与发送,
若接收数据包中NESN ! = ! = != 本地SN,认为正确接收(ack),此时更新本地SN;
若接收数据包中NESN = = == ==本地SN,认为没有正确接收(nack),需要重新发送该数据。从设备接收与发送,
若数据包中SN ! = ! = != 本地NESN,则认为是重传包(old data),此时不需要更新本地NESN;
若数据包中SN = = == == 本地NESN,则认为是新的数据包(old data),此时更新本地NESN;可理解为:
Master只更新SNSlave只更新NESN
一、判断是不是新的数据包
当Slave收到一包,NESN == SN时,认为是新包;
当Master收到一包, NESN和SN不同,认为是新包;
二、判断是否为重发包(可用于流控):
当Slave收到一包,NESN != SN时,认为是重发包;
当Master收到一包, NESN和SN相同时,Master重传上一包;
此处参考博客:https://www.cnblogs.com/tutengkwwl/p/7154532.html
8. 加密
AES
加密净荷数据
消息完整性校验
9. 连接管理
-
连接参数的更新
连接建立时,主设备通过连接请求数据包发送连接参数,而当连接活跃了一段时间后发现原连接参数已经不适合当前的传输要求。因此,主设备需要在链路中更新参数。主设备向从设备发送链接更新请求,从设备或者接受和使用他们,或者断开链路。
这里有一个新的连接参数:瞬时(instant),该参数决定了连接更新的开始时刻。发送消息时,主设备为连接更新选定一个未来的时间点。接收到消息后,从设备会记录这个未来的时间点,到时再切换至新的连接参数。在低功耗蓝牙中,由于没有时钟,瞬时实际上是一个连接参数的计数器,相应的连接事件到来时就使用新的连接参数。
下图是执行连接参数更新的规程:
-
自适应跳频
-
启动加密
-
重启加密
-
版本交换
-
功能交换
-
终止链接
10. 鲁棒性
自适应跳频
强CRC
11. 为低功耗优化
- 低开销
- 确认机制
- 单信道连接事件:从设备的每次传输使用与主设备相同的信道。
- 亚速率连接事件:解决低延迟和低功耗的矛盾。解决办法是设置从机延迟,让从设备忽略大部分的事件。但是从机延迟有一些限制,比如不能超过监督超时时间,又不能让从设备和主设备重新同步的机会少于 6 个。
- 离线加密:低功耗蓝牙把数据加密和验证码的计算放在了后台。一个数据包在发送之前就己经完成了加密,此时无线电仍是关闭状态。