FR303x 连接之后,如果你想一包数据不分包发送最大值要怎么修改?



  • 答:当你MTU交互512字节之后,当你发一包512字节数据,底层可能不是一包就给你发出去,可能是分包发出去,这时候你测吞吐量的话就会影响。那么正确的做法就是使用ble_api_err_t gap_ll_pkt_size_exchange_req(struct gap_ll_pkt_size_exchange_req *req);这个函数去交互用于在链接层上交换最大数据包长度。
    0_1756883411100_a40ce660-3095-43c9-985b-392779fdb2ad-976c370a0a020774e1d056359bae6891.png



  • 你这个函数是 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);
    

    📌 关键点

    1. tx_octets:想发的最大字节数,单位是字节,最大 251(BLE 规范限制 LL payload ≤ 251)。

      • 如果你想在 ATT 层发 512 字节,需要 分片传输(ATT MTU 扩展 + L2CAP 拆包)。
      • 这里 tx_octets 不能直接设成 512,而是设成 最大允许的 251
    2. 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

    📌 你要传 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_octets251(不是 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。