- 控制层描述
LL层是整个BLE协议栈的核心,也是BLE协议栈的难点和重点。LL层要做的事情非常多,如:识别空口报文,射频通道选择,时序控制(收发报文计划调度、超时处理),数据完整性,重传机制等
- LL报文格式
-
Advertising PDU
Header字段(2byte):
PDU TYPE:
RFU:保留位
Chsel:5.x特有,如发起状态信道算法选择标志,1:启用算法2进行射频信道自适应调制,0:表示使用默认算法1进行射频信道自适应调制。
TxAdd,RxAadd:两个都是说明设备地址的类型的,当某位为“1”时表示 Random Add(随机地址), 当为“0”时表示 Public Add(公共地址),(并不是所有公告报文都使用了该字段)
Length:4.x协议Length占用6 bit(pdu 有效载荷范围2~39byte),5.x协议length占用8bit(pdu有效载荷范围255byte)
-
DATA PDU
Header:占用16bit或者24bit
LLID:链路标识符,
01- L2CAP 消息的延续片段,或者PDU为空
10-L2CAP消息开始或者完整的L2CAP消息
11-控制PDU
MESN:下一个期望序列号
SN:当前消息序列号
MD:更多数据
CP:CTEInfo存在标志-5.x特有
RFU:预留字段
Length:有效载荷长度(4.2以下占用6bit,4.2以上占用8bit)
CTEInfo:CTEInfo字段指示恒定音调扩展的类型和长度-5.x特有
- 射频通道
BLE蓝牙射频频段1.4G ISM频段(2400MHz~2483.5MHz),一共40个信道,4.x:37个数据通道,3个固定广播通道(37,38,39);5.x:37个数据通道也可以用于辅助广播通道,3个主广播通道(37,38,39)。
调频算法用于数据连接中,数据信道有 37 个,具体选择哪一个
如下调频公式(ALG1):
UnmappedChannel:使用的数据通道
lastUnmappedChannel:上一次使用的数据通道(第一次连接事件开始时该值为0)
hopIncrement:调频增量,连接过程由主机指定(范围5~16),且可通过 LL_CHANNEL_MAP_IND 控制报文进行更新
控制层面维护着信道的unkown/dad/good 3种状态,当检测到信道当前信道不可用,则可用信道需要更新,通过一下方式重新计算:
UnmappedChannel = usedChannel[remappingIndex]
remappingIndex:映射index,用于计算选择下一个数据信道
UnmappedChannel:当前使用数据信道
numUsedChannels:所有可用信道得总统计(在连接阶段由主机端CONNECT_REQ
发布)
通过以下流程可以得到下一个数据通道:
举例:ChanelMap=00011110 00000000 11100000 00000110 11111110b
-> usedChannel[]={1,2,3,4,5,6,7,9,10,21,22,23,33,34,35,36}
假设当前数据信道10,选择下一个数据通道:
remappingIndex = 10 % 16 = 10
UnmappedChannel = usedChannel[remappingIndex] = usedChannel[10] = 22
如下调频公式(ALG2):待补充
- LL状态机
链路层的操作可以用状态机来描述,如下为链路层状态机迁移,通过状态迁移实现链路层对流程控制。
STANDBY状态:就绪状态是一个默认的状态,在这个状态是不能进行数据收发的, 它可以进入广播状态、扫描状态和发起状态
ADVERTISE状态:在广播状态下,链路层在广播事件中发送广播 PDU 。广播事件在4.x协议中共有 4 种(具体报文详细如2.1.1.章节):
1)非定向可连接事件(ADV_IND)
2)定向可连接事件(ADV_DIRECT_IND)
3)非定向不可连接事件(ADV_NONCONN_IND)
4)非定向扫描事件(ADV_SCAN_IND)
SCANNING状态:扫描状态分为主动扫描和被动扫描
主动扫描:由扫描端设备主动发起SCAN_REQ扫描请求,获取广告端详细信息具体如下图:
被动扫描:被动收取对等设备广告报文,具体如下图:
Initiating态:发起态进入连接后成为主机设备。它做的工作是在扫描之后发送连接请求(非同一个广告窗口完成)。当接收到了扫描应答后,发送连接请求事件,从而跳出发起态并进入连接状态成为Master。
Connection态:主机端由发起态通过对CONNECT_REQ PDU 的发送进入,从机端通过接收CONNECT_REQ PDU进入(5.x协议回应AUX_CONNECT_RSP),并进入连接事件情节
设备如何进入连接状态成为从机与主机如下:
- Nimble ll代码结构解析
Nimble ll 层主要由以下几大部分组成:
ble_ll_hci :主要对接host接口,接收host cmd解析处理,回应host event,接收与回应data pdu
ble_ll:可理解为ll层中转站,维护着链路层的状态机,通过ll_evq(queue)收取需要ll处理的事件(收取广播与数据报文处理等),收发完成由ll层完成状态迁移等工作
ble_ll_adv:所有的广播处理都在该模块
ble_ll_scan:扫描状态时由该模块负责驱动处理
ble_ll_conn:连接过程处理,以及连接成功后对每一个连接事件处理
ble_ll_ctrl:完成连接之后,对连接事件中收发ctrl pdu处理
ble_ll_sched:ll层计划调度器,定时运行,满足ll层每一个事件(公告事件,扫描事件,连接事件)的调度时间,芯片的射频收发器只有一个,ble支持多链路共存,就会存在不同链路竞争同一个射频收发器的情况,调度器起仲裁者的作用,决定某个时刻资源由哪个链路使用
ble_ll_whitelist:白名单列表,维护设备地址白名单机制,即运行特定设备与本机通信,通过白名单,可以只允许特定的蓝牙设备(白名单中列出的)扫描(Scan)、连接(connect)设备,也可以只扫描、连接特定的蓝牙设备(白名单中列出的)
PHY层由以下几部分组成:
ll_phy:物理层主要负责与硬件打交道,包含发送报文,收发中断处理包含发送完成中断,收包开始与结束中断,超时中断等一系列中断处理,且控制着数据帧之间的传输帧间隔处理
ll_hw:为ll提供操作硬件寄存器的接口,从而完成一些特定的功能,如白名单列表。
基于状态机详解Low Layer层逻辑处理:
- 公告态
每一个完整的公告流程称为一个公告事件,两个关键词advInterval与advDelay:
advInterval:广告间隔,在两个连续广播事件间的时间即为广播时间间隔,为625us的倍数范围(20ms~10.24s)
advDelay:延时随机数,在每一个广播事件中都有,设备间的时钟会有不同程度的漂移,所以这个随机延时的作用不但能消除设备之间时钟漂移,还能避免相同信道及时间点上的冲突。范围(0ms~10ms)
则一个公告事件时间为:T_advEvent = advInterval + advDelay
如下为多个广告事件:
非定向可连接事件以及定向可连接时间事件规定advInterval>=20ms,可扫描的无定向事件类型或不可连接的无定向活动类型,则advInterval>=100 ms。
如下图为ADV_IND公告时间处理要求:
在公告状态下公告可连接或者可扫描的公告时,本端应支持其广告请求或者连接请求处理,并在规定时间范围内完成如下图(可扫描被触发):
如下图(可连接被触发):
LL层公告状态代码处理流程以及关键数据结构:
- 扫描态
当主机指示时,链路层应进入扫描状态。扫描时,链路层应监听主要广告实体PDU类型的信道和主机指示的PHY上的信道。扫描被分为被动扫描与主动扫描,扫描态有两个关键词:扫描窗口与扫描间隔。
scanWindow和scanInterval参数应小于40.96(10.24)秒scanWindow应小于或等于scanInterval。如果主机将scanWindow和scanInterval参数设置为相同的值,则链接层应连续扫描(625us的倍数)
主动扫描:主动扫描在扫描阶段尽量减少来自多个扫描设备的扫描请求PDU的冲突,使用退避过程避免,有两个关键名词backoffCount与upperLimit,用来限制扫描响应PDU上发生冲突时发送的扫描请求PDU的数量。在发送扫描请求PDU之后,链路层侦听来自该广告客户的扫描响应PDU。如果没有从该广告客户接收到扫描响应PDU,则视为失败;每两次连续失败,upperLimit将加倍,直到达到256的值。每连续两次成功,上限值减半,直到达到1的值。在成功或失败接收扫描响应PDU之后,链路层将backoffCount设置为介于1和upperLimit之间的新随机整数
对于每个接收到的ADV_IND、ADV_SCAN_IND或扫描筛选器策略允许的可扫描AUX_ADV_IND PDU,并且要为其发送扫描请求,backoffCount递减1,直到其值为零。扫描请求PDU仅在backoffCount变为零时发送。
- 发起态
发起态的流程比较简短主要和连接态-主机端一起分析
- 连接态-从机
- 连接态-主机