4. 链路层控制:LLID、SN/NESN机制、MD位、流控与重传、CRC校验
链路层(Link Layer)是 BLE 协议栈里最忙的层。它不负责你传的是什么数据,只关心一件事——怎么把数据包可靠地送到对端。说白了,它就是那个在嘈杂的 2.4GHz 环境里,帮你把消息“挤”过去的搬运工。
我刚开始调 BLE 的时候,总觉得链路层就是个“传包”的,没什么技术含量。直到有一次产品在电梯里断连,我才意识到——链路层的流控和重传机制,才是整个连接稳定的基石。今天我们就把它彻底拆开看看。
4.1 LLID:这个包是干嘛用的?
每个 BLE 数据包的开头,都有一个 2 位的字段叫 LLID(Logical Link Identifier)。它告诉接收方:这个包是控制命令,还是普通数据,或者是数据包的结尾。
| LLID 值 | 含义 | 典型场景 |
|---|---|---|
| 00 | LL 控制 PDU | 连接参数更新、频道映射、终止连接 |
| 01 | LL 数据 PDU(续帧) | 大数据分片传输,非最后一包 |
| 10 | LL 数据 PDU(起始或完整帧) | 单包数据,或分片的第一包 |
| 11 | 保留 | 暂未使用 |
4.2 SN/NESN:怎么确认对方收到了?
BLE 的确认机制不靠单独的 ACK 包,而是靠两个 1 位的标志位:SN(Sequence Number)和 NESN(Next Expected Sequence Number)。
你想想看,每次发一个包,SN 就翻转一次(0→1→0→1...)。接收方收到后,把 NESN 也翻转一次,表示“我收到了,请发下一个”。如果发送方发现 NESN 没变,就知道包丢了,得重传。
核心逻辑:
- 发送方:SN 表示当前包的序号
- 接收方:NESN 表示期望收到的下一个 SN
- 如果 SN == NESN,说明是重传包(对方没收到)
- 如果 SN != NESN,说明是新包(对方收到了上一个)
我记得第一次看协议栈源码时,被这两个位的逻辑绕晕了。后来画了个状态机才明白——其实就是个“你发我回”的乒乓游戏。
4.3 MD 位:还有数据要发吗?
MD(More Data)位只有 1 位,但它决定了连接事件(Connection Event)什么时候结束。每次数据交互后,发送方通过 MD 位告诉对方:“我还有数据,别急着收工。”
- MD = 0:我没数据了,这个连接事件可以结束了
- MD = 1:我还有数据,继续发
这个机制在 BLE 4.2 的数据长度扩展(DLE)之后变得特别重要。因为一个连接事件里可以连续发多个包,MD 位就是那个“再来一包”的信号。
4.4 流控与重传:怎么保证不丢包?
BLE 的流控是“停等协议”(Stop-and-Wait)的变种。说白了就是:发一个,等确认,再发下一个。虽然效率不高,但在低功耗场景下够用了。
重传的逻辑也很简单:
- 发送方发出一个包,启动一个定时器(T_IFS + 一点点余量)
- 如果在下一个连接事件里收到 NESN 翻转,说明对方收到了
- 如果没收到,或者 NESN 没变,就重传
- 重传次数超过上限(默认 4 次),就断开连接
4.5 CRC 校验:数据到底有没有被篡改?
每个 BLE 数据包末尾都有 3 字节的 CRC(Cyclic Redundancy Check)。它覆盖了 PDU 头和数据部分,但不包括接入地址(Access Address)。
CRC 的生成多项式是固定的:
CRC24 多项式: x^24 + x^10 + x^9 + x^6 + x^4 + x^3 + x + 1
初始值: 0x555555
接收方收到包后,用同样的多项式重新计算 CRC。如果结果和包里的 CRC 不一致,就直接丢弃这个包,不会触发任何重传——因为链路层根本不知道这个包来过。
关键点:
- CRC 校验失败 → 静默丢弃 → 发送方超时重传
- CRC 校验通过 → 处理包内容 → 翻转 NESN 确认
- CRC 只检错,不纠错
嗯,这里要注意:CRC 校验失败不一定会导致断连。只要在重传次数内成功一次,连接就能继续。但如果信道质量太差,连续丢包就会触发“连接超时”(Connection Supervision Timeout)。
4.6 整体流程:一个连接事件里发生了什么?
下面这张图展示了主从设备在一个连接事件里的典型交互流程:
4.7 实际调试中的常见问题
| 现象 | 可能原因 | 排查方法 |
|---|---|---|
| 连接频繁断开 | 重传超限 / 连接超时 | 抓空包看 SN/NESN 是否正常翻转 |
| 数据吞吐量低 | MD 位未正确设置 | 检查应用层是否及时填充发送队列 |
| 偶发数据错误 | CRC 校验失败但未触发重传 | 检查射频环境,降低连接间隔 |
| 从设备不响应 | LLID 为 00 的控制 PDU 被忽略 | 确认 opcode 是否被协议栈支持 |
链路层控制是 BLE 连接稳定性的核心。LLID 告诉你包的类型,SN/NESN 保证不丢包,MD 位控制传输节奏,CRC 确保数据完整。这四个机制配合起来,才让 BLE 在嘈杂的 2.4GHz 环境里还能可靠工作。