BLE协议栈:链路层与ATT/L2CAP的交互详解

目录

概述

[1 整体交互架构概览](#1 整体交互架构概览)

[1.1 交互流程总览](#1.1 交互流程总览)

[1.2 数据平面:PDU传输流程](#1.2 数据平面:PDU传输流程)

[1.2.1 发送路径:从ATT到空中](#1.2.1 发送路径:从ATT到空中)

[1.2.2 接收路径:从空中到ATT](#1.2.2 接收路径:从空中到ATT)

[1.3 控制平面:连接与参数管理](#1.3 控制平面:连接与参数管理)

[1.3.1 连接生命周期交互](#1.3.1 连接生命周期交互)

[1.3.2 关键参数协商流程](#1.3.2 关键参数协商流程)

[1.4 事件与通知机制](#1.4 事件与通知机制)

[1.4.1 链路层事件驱动模型](#1.4.1 链路层事件驱动模型)

[1.4.2 ATT通知/指示与链路层交互](#1.4.2 ATT通知/指示与链路层交互)

[1.5 性能优化交互](#1.5 性能优化交互)

[1.5.1 数据长度扩展交互(BLE 4.2+)](#1.5.1 数据长度扩展交互(BLE 4.2+))

[1.5.2 信道选择算法](#1.5.2 信道选择算法)

[1.6 安全交互](#1.6 安全交互)

[1.7 误处理与恢复](#1.7 误处理与恢复)

[1.7.1 丢包重传机制](#1.7.1 丢包重传机制)

[1.7.2 连接超时与监控](#1.7.2 连接超时与监控)

[2 链路层与ATT/L2CAP的协同设计](#2 链路层与ATT/L2CAP的协同设计)

[2.1 设计原则](#2.1 设计原则)

[2.3 典型交互模式](#2.3 典型交互模式)


概述

链路层(Link Layer)与ATT/L2CAP的交互是BLE协议栈的核心通信枢纽。他们三者的紧密协作,使BLE能在极低功耗下实现可靠通信,这是BLE协议栈设计的精髓所在。以下是它们之间交互的全面解析:

1 整体交互架构概览

1.1 交互流程总览

1.2 数据平面:PDU传输流程

1.2.1 发送路径:从ATT到空中

关键数据结构转换

cpp 复制代码
// 数据结构转换链
typedef struct {
    uint8_t opcode;      // ATT操作码
    uint16_t handle;     // 属性句柄
    uint8_t value[8];    // 数据值
} ATT_PDU;               // 11字节

typedef struct {
    uint16_t length;     // 负载长度 = 11
    uint16_t cid;        // CID = 0x0004 (ATT)
    ATT_PDU att_pdu;     // ATT数据
} L2CAP_PDU;             // 15字节

typedef struct {
    uint8_t preamble;    // 10101010 or 01010101
    uint32_t access_addr; // 连接访问地址
    uint16_t header;     // LL头(LLID, NESN, SN, MD, ...)
    L2CAP_PDU payload;   // L2CAP PDU
    uint24_t crc;        // CRC24
} LL_PDU;                // 25字节

1.2.2 接收路径:从空中到ATT

数据重组流程

1.3 控制平面:连接与参数管理

1.3.1 连接生命周期交互

连接建立过程

1.3.2 关键参数协商流程

MTU协商交互

cpp 复制代码
// MTU协商的详细交互
void mtu_exchange_procedure(connection_t *conn) {
    // 1. 客户端发送MTU交换请求
    att_mtu_req_t mtu_req = {
        .client_rx_mtu = DEFAULT_MTU  // 默认23,可更大
    };
    
    // 通过L2CAP/链路层发送
    send_att_pdu(conn, ATT_OP_MTU_REQ, &mtu_req, sizeof(mtu_req));
    
    // 2. 服务器响应
    // 链路层接收,L2CAP分发,ATT处理
    // 服务器计算协商后的MTU = min(客户端MTU, 服务器MTU)
    
    // 3. 更新L2CAP参数
    l2cap_update_mtu(conn->cid, negotiated_mtu);
    
    // 4. 影响链路层行为
    if (negotiated_mtu > 27) {  // 超过默认链路层有效载荷
        // 可能触发链路层数据包分片
        ll_update_tx_payload_size(conn->handle, 
                                 negotiated_mtu + L2CAP_HEADER_SIZE);
    }
}

连接参数更新请求

1.4 事件与通知机制

1.4.1 链路层事件驱动模型

连接事件调度

cpp 复制代码
// 连接事件状态机
typedef enum {
    LL_STATE_SLEEP,          // 休眠状态
    LL_STATE_WAKEUP,         // 唤醒准备
    LL_STATE_RX_WINDOW,      // 接收窗口
    LL_STATE_TX_PREPARE,     // 发送准备
    LL_STATE_TX,             // 发送数据
    LL_STATE_WAIT_ACK,       // 等待确认
    LL_STATE_POST_PROCESS    // 后续处理
} ll_event_state_t;

// 事件驱动处理
void ll_connection_event_handler(connection_handle_t handle) {
    ll_state = LL_STATE_WAKEUP;
    
    // 1. 检查是否有待发送数据(来自L2CAP)
    if (l2cap_has_data_for_ll(handle)) {
        ll_state = LL_STATE_TX_PREPARE;
        pdu = l2cap_get_next_pdu(handle);
        ll_transmit_pdu(pdu);
        ll_state = LL_STATE_WAIT_ACK;
    }
    
    // 2. 开启接收窗口
    ll_state = LL_STATE_RX_WINDOW;
    if (ll_receive_pdu(&rx_pdu)) {
        // 传递到L2CAP
        l2cap_deliver_pdu(rx_pdu);
    }
    
    ll_state = LL_STATE_SLEEP;
}

1.4.2 ATT通知/指示与链路层交互

服务器发起通信

cpp 复制代码
// 服务器主动发送通知(无需客户端轮询)
void send_attribute_notification(connection_handle_t conn,
                                 attribute_handle_t handle,
                                 uint8_t *value,
                                 uint16_t length) {
    // 1. ATT层构建通知PDU
    att_pdu_t pdu = build_notification_pdu(handle, value, length);
    
    // 2. L2CAP封装
    l2cap_pdu_t l2cap_pdu = {
        .length = pdu.size + ATT_HEADER_SIZE,
        .cid = ATT_CID,
        .payload = pdu
    };
    
    // 3. 检查链路层状态
    if (ll_get_connection_state(conn) == CONNECTED) {
        // 4. 放入发送队列,等待下一个连接事件
        ll_schedule_transmission(conn, l2cap_pdu);
        
        // 5. 在下一个连接事件中发送
        // 注意:如果没有使能通知,链路层不应发送
        if (is_notification_enabled(conn, handle)) {
            ll_transmit_in_next_event(conn, l2cap_pdu);
        }
    }
}

1.5 性能优化交互

1.5.1 数据长度扩展交互(BLE 4.2+)

最大数据长度协商

1.5.2 信道选择算法

自适应跳频

cpp 复制代码
// 链路层与L2CAP在跳频上的交互
void adaptive_frequency_selection(connection_handle_t conn) {
    // 1. 链路层监控信道质量
    channel_map_t used_channels = get_current_channel_map();
    uint8_t bad_channel_list[37];
    uint8_t bad_channel_count = 0;
    
    // 2. 检测不良信道(基于CRC错误率、RSSI等)
    for (int i = 0; i < 37; i++) {
        if (channel_quality[i] < THRESHOLD) {
            bad_channel_list[bad_channel_count++] = i;
        }
    }
    
    // 3. 更新信道映射
    if (bad_channel_count > 0) {
        // 通知对端更新信道映射
        ll_channel_map_update(conn, bad_channel_list, bad_channel_count);
        
        // 4. L2CAP可能受影响(如果正在传输大数据)
        if (l2cap_is_fragmenting(conn)) {
            // 可能需要暂停并恢复传输
            l2cap_handle_channel_change(conn);
        }
    }
}

1.6 安全交互

加密启动流程

1.7 误处理与恢复

1.7.1 丢包重传机制

链路层自动重传

cpp 复制代码
// 链路层与L2CAP的重传协调
void ll_handle_packet_loss(connection_handle_t conn) {
    // 链路层检测到ACK超时
    if (ll_packet_not_acked(conn, pdu_sequence)) {
        // 1. 链路层自动重传(最多LL_MAX_NACK次)
        ll_retransmit_pdu(conn, pdu_sequence);
        
        // 2. 超过最大重传次数
        if (retry_count > LL_MAX_NACK) {
            // 3. 通知L2CAP连接可能有问题
            l2cap_notify_connection_issue(conn);
            
            // 4. L2CAP可能触发上层恢复机制
            if (l2cap_should_recover(conn)) {
                // 例如:重新发送未确认的L2CAP PDU
                l2cap_retransmit_unacked_data(conn);
            }
        }
    }
}

// L2CAP的超时处理
void l2cap_timeout_handler(channel_id_t cid) {
    // 如果ATT请求超时(无响应)
    if (cid == ATT_CID) {
        // 通知ATT层
        att_handle_timeout();
        
        // ATT可能决定重发请求或断开连接
        if (att_retry_count_exceeded()) {
            gap_terminate_connection();
        }
    }
}

1.7.2 连接超时与监控

连接监控交互

cpp 复制代码
// 监控连接状态的交互
typedef struct {
    uint32_t last_event_time;
    uint16_t supervision_timeout;  // 监控超时(如5秒)
    uint8_t  missed_events;        // 错过的连接事件数
    bool     connection_valid;
} connection_monitor_t;

void monitor_connection_health(connection_handle_t conn) {
    // 链路层监控物理连接
    if (ll_missed_consecutive_events(conn) > MAX_MISSED_EVENTS) {
        // 1. 链路层检测到连接丢失
        ll_report_connection_loss(conn);
        
        // 2. 通知L2CAP
        l2cap_handle_connection_loss(conn);
        
        // 3. L2CAP通知ATT和GAP
        att_connection_lost(conn);
        gap_connection_terminated(conn, TIMEOUT);
        
        // 4. 清理资源
        l2cap_cleanup_channels(conn);
    }
}

2 链路层与ATT/L2CAP的协同设计

2.1 设计原则

  1. 事件驱动:所有交互基于连接事件,最大化睡眠时间

  2. 零拷贝设计:尽可能减少内存拷贝,PDU在各层间传递指针

  3. 异步通知:服务器可主动通知,减少轮询开销

  4. 弹性缓冲:根据MTU协商动态调整缓冲区大小

  5. 错误隔离:链路层处理物理错误,上层处理逻辑错误

2.2 优化建议

  1. 匹配连接间隔与数据速率:根据应用需求调整连接参数

  2. 合理设置MTU:平衡吞吐量与内存使用

  3. 利用通知机制:减少主动轮询,节省功耗

  4. 监控连接质量:动态调整参数适应环境变化

  5. 预处理数据:在应用层压缩数据,减少传输量

2.3 典型交互模式

场景 链路层角色 L2CAP角色 ATT角色
周期性数据采集 调度连接事件 可靠传输 通知机制
突发大数据传输 支持大包分片 流控管理 分块读写
低功耗待机 最大化从机延迟 缓冲管理 按需请求
多服务并发 单一物理信道 多路复用 服务发现
相关推荐
嵌入式小企鹅21 天前
蓝牙学习系列(八):BLE L2CAP 协议详解
网络·学习·蓝牙·ble·协议栈·l2cap
deepwater_zone22 天前
主流开源BLE协议栈
ble协议栈
mftang4 个月前
BLE 协议栈中的 L2CAP层详解
l2cap·信道标识符
奔跑吧 android1 年前
【android bluetooth 案例分析 03】【PTS 测试 】【PBAP/PCE/SSM/BV-02-C】
android·pts·l2cap·pbap·bqb测试
奔跑吧 android1 年前
【android bluetooth 协议分析 06】【l2cap详解 11】【l2cap连接超时处理逻辑介绍】
android·bluetooth·l2cap·gd·aosp13
byte轻骑兵1 年前
【SPP】深入解析蓝牙 L2CAP 协议在SPP中的互操作性要求 —— 构建可靠的蓝牙串口通信基础
spp·蓝牙技术·l2cap
CXDNW2 年前
【网络篇】计算机网络——链路层详述(笔记)
网络·笔记·智能路由器·以太网·局域网·链路层