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