FR303x 连接之后,如果你想一包数据不分包发送最大值要怎么修改?
-
答:当你MTU交互512字节之后,当你发一包512字节数据,底层可能不是一包就给你发出去,可能是分包发出去,这时候你测吞吐量的话就会影响。那么正确的做法就是使用ble_api_err_t gap_ll_pkt_size_exchange_req(struct gap_ll_pkt_size_exchange_req *req);这个函数去交互用于在链接层上交换最大数据包长度。
-
你这个函数是 LL Data Length Extension (DLE) 的接口,作用是设置本端 Link Layer 最大发送数据包的长度和时间。
我们来拆解一下:
typedef struct gap_ll_pkt_size_exchange_req { uint8_t conidx; //!< 连接索引 uint16_t tx_octets; //!< 最大发送字节数 (payload) uint16_t tx_time; //!< 最大发送时长 (微秒) } gap_ll_pkt_size_exchange_req_t; ble_api_err_t gap_ll_pkt_size_exchange_req(struct gap_ll_pkt_size_exchange_req *req);
关键点
-
tx_octets:想发的最大字节数,单位是字节,最大 251(BLE 规范限制 LL payload ≤ 251)。
- 如果你想在 ATT 层发 512 字节,需要 分片传输(ATT MTU 扩展 + L2CAP 拆包)。
- 这里
tx_octets
不能直接设成 512,而是设成 最大允许的 251。
-
tx_time:允许的最大发送时间,单位是微秒。
-
计算公式大致是:
tx_time ≈ (tx_octets + 14) * 8 (PHY = 1M) tx_time ≈ (tx_octets + 14) * 8 / 2 (PHY = 2M)
(+14 是 Link Layer header + MIC 等开销)
-
举例:
- 1M PHY 下,251 字节:
(251+14)*8 ≈ 2120 us
- 2M PHY 下,251 字节:约
1060 us
- 1M PHY 下,251 字节:
-
你要传 512 字节
- MTU/ATT 层:需要先做
ATT_MTU_EXCHANGE
,把 MTU 提升到 ≥ 517(这样 ATT 一次最多可传 512)。 - LL 层 (DLE):只能设
tx_octets = 251
,剩下的 512 会自动拆成两包传输。
示例代码
gap_ll_pkt_size_exchange_req_t dle_req; dle_req.conidx = 0; // 假设是第 0 个连接 dle_req.tx_octets = 251; // 最大 251,BLE 规范限制 dle_req.tx_time = 2120; // 1M PHY 下,251字节大概需要2120us ble_api_err_t ret = gap_ll_pkt_size_exchange_req(&dle_req); if (ret != BLE_API_OK) { printf("DLE request failed: %d\n", ret); }
总结:
tx_octets
填 251(不是 512)。tx_time
按 PHY 速率算,1M 时约 2120 us。- 想发 512 字节,要配合 ATT MTU 扩展,LL 层只管单包最大字节数(≤ 251)。
-
-
125K(LE Coded S=8)下还是走 DLE 的同一套规则:
tx_octets
的上限依然是 251(LL 层单包最大负载)。tx_time
是“单包最大发送时长(us)”,需要按所用 PHY 的比特率估算。
一个好用的近似公式(够工程使用):
tx_time(µs) ≈ (tx_octets + 14) * 8 / R ,R 为 Mbps(1M=1,2M=2,500K=0.5,125K=0.125)
“+14”是 LL 层头部等开销的常用近似。
以 tx_octets=251 估算得到常用值(四舍五入):PHY 估算 tx_time 1M ≈ 2120 µs 2M ≈ 1060 µs 125K(S=8) ≈ 16960 µs 500K(S=2) ≈ 4240 µs 你的需求:想一次发送 512 字节
- LL 层单包最多 251B,所以 必须分成两包(DLE 只是把单包上限提到 251B)。
- 若想在 ATT 层“一次性”写 512B,还需要 把 MTU 提到 ≥517(ATT 可载荷=MTU-3=512B),底层依然会拆成两包 LL PDU 发送。
125K(S=8)下的调用示例
gap_ll_pkt_size_exchange_req_t req = { .conidx = 0, // 你的连接索引 .tx_octets = 251, // LL 单包最大负载上限 .tx_time = 16960, // 125K 估算值(微秒) }; ble_api_err_t err = gap_ll_pkt_size_exchange_req(&req); if (err != BLE_API_OK) { // 处理错误 }
实战提示
- 有的控制器会自己协商到双方都能接受的最大值;
tx_time
宁可略大不要偏小,125K 下给 17000~18000 µs 也常见。 - 记得在建立连接后:先做 ATT MTU 交换(≥517)→ 再做 DLE(251/16960),最后再发 512B 的应用数据。
- 若用 500K(S=2),把
tx_time
改成 ≈ 4240 µs 即可,tx_octets
仍为 251。