从零实现BLE协议栈(6-3)实验:06_phy_data_channel

6-3 动手实验:编译运行 06_phy_data_channel

本篇是第 6 章的配套实验,将 6-1 和 6-2 中讲解的 LL Data PDU 与 L2CAP 分片重组完整跑通。


一、概述

06_phy_data_channel 在 Demo 05 的稳定连接基础上,增加了数据通道功能:

  1. LL Data PDU 解析:识别 LLID=01(Start/Complete)和 LLID=10(Continue)片段
  2. L2CAP 重组:多个 LL PDU 片段拼接为完整的 L2CAP Basic Frame
  3. Echo 回传:将收到的 L2CAP 数据原样分片回传给对端(验证双向数据通路)
  4. TX 队列:最多 4 个待发送片段,每连接事件发一个

通过本实验,你将验证 LL→L2CAP 的分层解析以及 BLE 4.0 默认 27 字节 MTU 下的分片过程。


二、编译与烧录

west build -b nrf52dk/nrf52832 .\write-BLE-stack-from-scratch\06_phy_data_channel\ -p
west flash

编译产物:

Memory region         Used Size  Region Size  %age Used
           FLASH:       99672 B       512 KB     19.01%
             RAM:       19648 B        64 KB     29.98%

RAM 增加约 640B(L2CAP 重组缓冲区 + TX 队列)。


三、运行测试

测试 1:基础连接(bumble_connect.py)

.\write-BLE-stack-from-scratch\tools\venv\Scripts\python.exe `
  .\write-BLE-stack-from-scratch\tools\bumble_connect.py `
  --transport usb:2FE3:000B `
  --target 66:55:44:33:22:11 `
  --duration 15

Bumble 侧:连接稳定保持 15 秒。bumble_connect.py 只做 LL 控制过程(Version/Feature Exchange),不发送 L2CAP 数据,echo 计数为 0。

测试 2:L2CAP Echo(bumble_l2cap_echo.py)

# 单 PDU echo (16 字节 payload, 适合单个 LL PDU)
.\write-BLE-stack-from-scratch\tools\venv\Scripts\python.exe `
  .\write-BLE-stack-from-scratch\tools\bumble_l2cap_echo.py `
  --transport usb:2FE3:000B `
  --target 66:55:44:33:22:11 `
  --count 5 --size 16
  [SEND] #0 | 16B | head=00000000a0a1a2a3
  [ECHO] #0 OK | 16B | latency=32.0ms | recv=1/1
  [SEND] #1 | 16B | head=01000000a0a1a2a3
  [ECHO] #1 OK | 16B | latency=47.0ms | recv=2/2
  ...
  L2CAP ECHO TEST REPORT
  Sent         : 5
  Received     : 5
  Match (OK)   : 5
  Success rate : 100.0%
  Latency (ms) : avg=42.0  min=32.0  max=47.0
# 多分片 echo (40 字节 payload → L2CAP 44 字节 → 2 个 LL PDU)
.\write-BLE-stack-from-scratch\tools\venv\Scripts\python.exe `
  .\write-BLE-stack-from-scratch\tools\bumble_l2cap_echo.py `
  --transport usb:2FE3:000B `
  --target 66:55:44:33:22:11 `
  --count 3 --size 40
  [SEND] #0 | 40B | head=00000000a0a1a2a3
  [ECHO] #0 OK | 40B | latency=140.0ms | recv=1/1
  ...
  LL fragments : 2 per frame (MTU=27)
  Sent         : 3
  Received     : 3
  Success rate : 100.0%
  Latency (ms) : avg=156.0  min=140.0  max=188.0

多分片延迟更高(~150ms vs ~42ms),因为 2 个 LL PDU 需要分别在不同连接事件中传输(每事件 50ms)。


四、串口日志

连接事件循环(bumble_connect.py)

[CONN] #1 ch=11 OK | ww=5 | rx=1/1 l2cap_rx=0 tx=0
[CONN] #2 ch=22 OK | ww=5 | rx=2/2 l2cap_rx=0 tx=0
[CONN] #3 ch=33 OK | ww=5 | rx=3/3 l2cap_rx=0 tx=0
...
[CONN] #300 ch=14 OK | ww=5 | rx=297/300 l2cap_rx=0 tx=0

L2CAP Echo 日志(bumble_l2cap_echo.py)

[CONN] #1 ch=15 OK | ww=5 | rx=1/1 l2cap_rx=0 tx=0
[CONN] #2 ch=30 OK | ww=5 | rx=2/2 l2cap_rx=0 tx=0
...
[L2CAP] RX #1: CID=0x0040 len=16 → echo 1 frags
[L2CAP] RX #2: CID=0x0040 len=16 → echo 1 frags
[L2CAP] RX #3: CID=0x0040 len=16 → echo 1 frags

连接总结(echo 测试)

========== Connection Summary ==========
  Total events:       152
  RX OK:              149
  RX timeout:         3
  RX CRC error:       0
  L2CAP RX:           3
  L2CAP TX echo:      3
  Anchor updates:     149
  Max consec miss:    1

日志解读

  • bumble_connect.py 测试l2cap_rx=0 tx=0,因为 LL Feature/Version Exchange 走 LLID=Control(0x03),不经过 L2CAP
  • bumble_l2cap_echo.py 测试L2CAP RX: 3, TX echo: 3,3 帧全部正确接收并 echo 回传
  • 延迟日志打印[L2CAP] RX #N: ... 出现在连接事件之间(而非事件内部),避免阻塞 SW TIFS
  • RX OK: 149/152 = 98%:连接稳定性与 Demo 05 一致

五、关键概念图

LL Data PDU 格式

┌──────────┬──────┬───────────────────────────────────┐
│ Header   │ Len  │ Payload (最多 27 字节, BLE 4.0)   │
│ (2 bytes)│      │                                    │
├──────────┼──────┤                                    │
│ LLID(2b) │      │ [L2CAP Header(4B)] [L2CAP Data]   │
│  01 = Start/Complete                                 │
│  10 = Continue fragment                              │
│  11 = LL Control PDU                                 │
└──────────┴──────┴───────────────────────────────────┘

L2CAP 重组流程

    LL PDU #1 (LLID=01, Start)         LL PDU #2 (LLID=10, Continue)
  ┌────────────────────────────┐   ┌────────────────────────────┐
  │ L2CAP Hdr │ Data Part 1    │   │ Data Part 2 (续)           │
  │ Len=40    │ (23 bytes)     │   │ (17 bytes)                 │
  │ CID=0x0004│                │   │                             │
  └────────────────────────────┘   └────────────────────────────┘
              │                              │
              └──────── 拼接到 reassembly buffer ─────────┘
                            │
                    ┌───────▼────────┐
                    │ 完整 L2CAP Frame│
                    │ 40 字节 payload │
                    │ CID = ATT       │
                    └───────┬────────┘
                            │ echo
                    ┌───────▼────────┐
                    │ 分片为 2 个      │
                    │ LL Data PDUs    │
                    │ 放入 TX Queue   │
                    └────────────────┘

Echo 数据流

  Master (Bumble)                    Slave (nRF52)
       │                                  │
       │── LL Data PDU (LLID=01) ──────→ │ reassemble
       │── LL Data PDU (LLID=10) ──────→ │ → complete L2CAP frame
       │                                  │    ↓ echo
       │←── LL Data PDU (LLID=01) ────── │ segment
       │←── LL Data PDU (LLID=10) ────── │
       │                                  │

本系列教程同款硬件:👇
芯片: nRF 52832 开发板
工具: nRF 52840 BLE Dongle 蓝牙嗅探器
工具: 逻辑分析仪
工具: BPA low energy 蓝牙分析仪

posted @ 2026-04-02 10:16  ixbwer  阅读(7)  评论(0)    收藏  举报