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

作者:mftang日期:2026/2/11

目录

概述

1 整体交互架构概览

1.1 交互流程总览

1.2 数据平面:PDU传输流程

1.2.1 发送路径:从ATT到空中

1.2.2 接收路径:从空中到ATT

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

1.3.1 连接生命周期交互

1.3.2 关键参数协商流程

1.4 事件与通知机制

1.4.1 链路层事件驱动模型

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

1.5 性能优化交互

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

1.5.2 信道选择算法

1.6 安全交互

1.7 误处理与恢复

1.7.1 丢包重传机制

1.7.2 连接超时与监控

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

2.1 设计原则

2.3 典型交互模式


概述

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

1 整体交互架构概览

1.1 交互流程总览

1.2 数据平面:PDU传输流程

1.2.1 发送路径:从ATT到空中

关键数据结构转换

1// 数据结构转换链
2typedef struct {
3    uint8_t opcode;      // ATT操作码
4    uint16_t handle;     // 属性句柄
5    uint8_t value[8];    // 数据值
6} ATT_PDU;               // 11字节
7
8typedef struct {
9    uint16_t length;     // 负载长度 = 11
10    uint16_t cid;        // CID = 0x0004 (ATT)
11    ATT_PDU att_pdu;     // ATT数据
12} L2CAP_PDU;             // 15字节
13
14typedef struct {
15    uint8_t preamble;    // 10101010 or 01010101
16    uint32_t access_addr; // 连接访问地址
17    uint16_t header;     // LL头(LLID, NESN, SN, MD, ...)
18    L2CAP_PDU payload;   // L2CAP PDU
19    uint24_t crc;        // CRC24
20} LL_PDU;                // 25字节

1.2.2 接收路径:从空中到ATT

数据重组流程

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

1.3.1 连接生命周期交互

连接建立过程

1.3.2 关键参数协商流程

MTU协商交互

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

连接参数更新请求

1.4 事件与通知机制

1.4.1 链路层事件驱动模型

连接事件调度

1// 连接事件状态机
2typedef enum {
3    LL_STATE_SLEEP,          // 休眠状态
4    LL_STATE_WAKEUP,         // 唤醒准备
5    LL_STATE_RX_WINDOW,      // 接收窗口
6    LL_STATE_TX_PREPARE,     // 发送准备
7    LL_STATE_TX,             // 发送数据
8    LL_STATE_WAIT_ACK,       // 等待确认
9    LL_STATE_POST_PROCESS    // 后续处理
10} ll_event_state_t;
11
12// 事件驱动处理
13void ll_connection_event_handler(connection_handle_t handle) {
14    ll_state = LL_STATE_WAKEUP;
15    
16    // 1. 检查是否有待发送数据(来自L2CAP)
17    if (l2cap_has_data_for_ll(handle)) {
18        ll_state = LL_STATE_TX_PREPARE;
19        pdu = l2cap_get_next_pdu(handle);
20        ll_transmit_pdu(pdu);
21        ll_state = LL_STATE_WAIT_ACK;
22    }
23    
24    // 2. 开启接收窗口
25    ll_state = LL_STATE_RX_WINDOW;
26    if (ll_receive_pdu(&rx_pdu)) {
27        // 传递到L2CAP
28        l2cap_deliver_pdu(rx_pdu);
29    }
30    
31    ll_state = LL_STATE_SLEEP;
32}

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

服务器发起通信

1// 服务器主动发送通知(无需客户端轮询)
2void send_attribute_notification(connection_handle_t conn,
3                                 attribute_handle_t handle,
4                                 uint8_t *value,
5                                 uint16_t length) {
6    // 1. ATT层构建通知PDU
7    att_pdu_t pdu = build_notification_pdu(handle, value, length);
8    
9    // 2. L2CAP封装
10    l2cap_pdu_t l2cap_pdu = {
11        .length = pdu.size + ATT_HEADER_SIZE,
12        .cid = ATT_CID,
13        .payload = pdu
14    };
15    
16    // 3. 检查链路层状态
17    if (ll_get_connection_state(conn) == CONNECTED) {
18        // 4. 放入发送队列,等待下一个连接事件
19        ll_schedule_transmission(conn, l2cap_pdu);
20        
21        // 5. 在下一个连接事件中发送
22        // 注意:如果没有使能通知,链路层不应发送
23        if (is_notification_enabled(conn, handle)) {
24            ll_transmit_in_next_event(conn, l2cap_pdu);
25        }
26    }
27}

1.5 性能优化交互

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

最大数据长度协商

1.5.2 信道选择算法

自适应跳频

1// 链路层与L2CAP在跳频上的交互
2void adaptive_frequency_selection(connection_handle_t conn) {
3    // 1. 链路层监控信道质量
4    channel_map_t used_channels = get_current_channel_map();
5    uint8_t bad_channel_list[37];
6    uint8_t bad_channel_count = 0;
7    
8    // 2. 检测不良信道(基于CRC错误率、RSSI等)
9    for (int i = 0; i < 37; i++) {
10        if (channel_quality[i] < THRESHOLD) {
11            bad_channel_list[bad_channel_count++] = i;
12        }
13    }
14    
15    // 3. 更新信道映射
16    if (bad_channel_count > 0) {
17        // 通知对端更新信道映射
18        ll_channel_map_update(conn, bad_channel_list, bad_channel_count);
19        
20        // 4. L2CAP可能受影响(如果正在传输大数据)
21        if (l2cap_is_fragmenting(conn)) {
22            // 可能需要暂停并恢复传输
23            l2cap_handle_channel_change(conn);
24        }
25    }
26}

1.6 安全交互

加密启动流程

1.7 误处理与恢复

1.7.1 丢包重传机制

链路层自动重传

1// 链路层与L2CAP的重传协调
2void ll_handle_packet_loss(connection_handle_t conn) {
3    // 链路层检测到ACK超时
4    if (ll_packet_not_acked(conn, pdu_sequence)) {
5        // 1. 链路层自动重传(最多LL_MAX_NACK次)
6        ll_retransmit_pdu(conn, pdu_sequence);
7        
8        // 2. 超过最大重传次数
9        if (retry_count > LL_MAX_NACK) {
10            // 3. 通知L2CAP连接可能有问题
11            l2cap_notify_connection_issue(conn);
12            
13            // 4. L2CAP可能触发上层恢复机制
14            if (l2cap_should_recover(conn)) {
15                // 例如:重新发送未确认的L2CAP PDU
16                l2cap_retransmit_unacked_data(conn);
17            }
18        }
19    }
20}
21
22// L2CAP的超时处理
23void l2cap_timeout_handler(channel_id_t cid) {
24    // 如果ATT请求超时(无响应)
25    if (cid == ATT_CID) {
26        // 通知ATT层
27        att_handle_timeout();
28        
29        // ATT可能决定重发请求或断开连接
30        if (att_retry_count_exceeded()) {
31            gap_terminate_connection();
32        }
33    }
34}

1.7.2 连接超时与监控

连接监控交互

1// 监控连接状态的交互
2typedef struct {
3    uint32_t last_event_time;
4    uint16_t supervision_timeout;  // 监控超时(如5秒)
5    uint8_t  missed_events;        // 错过的连接事件数
6    bool     connection_valid;
7} connection_monitor_t;
8
9void monitor_connection_health(connection_handle_t conn) {
10    // 链路层监控物理连接
11    if (ll_missed_consecutive_events(conn) > MAX_MISSED_EVENTS) {
12        // 1. 链路层检测到连接丢失
13        ll_report_connection_loss(conn);
14        
15        // 2. 通知L2CAP
16        l2cap_handle_connection_loss(conn);
17        
18        // 3. L2CAP通知ATT和GAP
19        att_connection_lost(conn);
20        gap_connection_terminated(conn, TIMEOUT);
21        
22        // 4. 清理资源
23        l2cap_cleanup_channels(conn);
24    }
25}

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

2.1 设计原则

  1. 事件驱动:所有交互基于连接事件,最大化睡眠时间
  2. 零拷贝设计:尽可能减少内存拷贝,PDU在各层间传递指针
  3. 异步通知:服务器可主动通知,减少轮询开销
  4. 弹性缓冲:根据MTU协商动态调整缓冲区大小
  5. 错误隔离:链路层处理物理错误,上层处理逻辑错误

2.2 优化建议

  1. 匹配连接间隔与数据速率:根据应用需求调整连接参数
  2. 合理设置MTU:平衡吞吐量与内存使用
  3. 利用通知机制:减少主动轮询,节省功耗
  4. 监控连接质量:动态调整参数适应环境变化
  5. 预处理数据:在应用层压缩数据,减少传输量

2.3 典型交互模式

场景链路层角色L2CAP角色ATT角色
周期性数据采集调度连接事件可靠传输通知机制
突发大数据传输支持大包分片流控管理分块读写
低功耗待机最大化从机延迟缓冲管理按需请求
多服务并发单一物理信道多路复用服务发现

BLE协议栈:链路层与ATT/L2CAP的交互详解》 是转载文章,点击查看原文


相关推荐


2026 年或许是中国 AI 社交的元年~
苍何2026/2/2

这是苍何的第 478 篇原创! 大家好,我是苍何。 网上你们经常在哪儿聊天啊? 我妈说在抖音,我弟说在陌陌,但其实我们都是在微信里聊的这个问题。 我自己建了几十个微信群,还加入了一堆的群聊,每天光看信息,就得费我半天老命。 为此,我基于 Ipad 协议开发过微信 AI 助手,能总结群聊消息,能帮回复问题,帮做任务,2021 年卖给了麻省理工学院社团。 一开始,我以为,我能用 AI 助手解决这些问题,但后面,还是避免不了被各种封号,最痛苦的是,我的群直接就被一锅端了。 所以,后面,我没再折腾微信


多网卡如何区分路由,使用宽松模式测试网络
venus602026/1/23

一、什么是 Linux 的“非对称路由” 1️⃣ 定义(先给结论) 非对称路由指的是: 数据包从 A 网卡进来,但回包却从 B 网卡出去 在多网卡、多出口服务器上非常常见,比如: 双网卡 多默认网关 同一台服务器连多个网络 你之前的情况就是典型的非对称路由。 2️⃣ Linux 默认为什么不喜欢非对称路由? 因为它可能意味着: IP 欺骗(spoofing) 流量劫持 路由异常 所以 Linux 默认启用了一个安全机制: 👉


三分钟说清楚 ReAct Agent 的技术实现
indieAI2026/1/15

ReAct Agent 技术实现主要依赖于精心设计的 Prompt 模板、输出解析器和执行循环三大核心机制。 1. 核心 Prompt 工程 LangChain 使用特定的 Prompt 模板引导 LLM 按 Thought → Action → Observation 格式输出: # 简化的 Prompt 结构 template = """ 用以下工具回答问题: 工具: - search: 搜索引擎, 输入: "查询词" - calculator: 计算器, 输入: "算式" 现在开始


基于 Squoosh WASM 的浏览器端图片转换库
jump_jump2026/1/7

在 Web 开发中,图片处理是一个常见需求。传统方案要么依赖服务端处理,要么使用 Canvas API,但前者增加服务器负担,后者在压缩质量上不尽人意。Google 的 Squoosh 项目提供了基于 WASM 的高质量图片编解码器,但直接使用比较繁琐。 于是我封装了 use-squoosh,一个零依赖的浏览器端图片转换库,通过 CDN 按需加载编解码器,开箱即用。 为什么需要这个库 现有方案的局限性 方案优点缺点服务端处理稳定可靠增加


微调—— LlamaFactory工具:使用WebUI微调
华如锦2025/12/29

启动web Ui面板 进入到LLaMA-Factory目录下,执行以下命令启动web ui面板: cd LLaMA-Factory llamafactory-cli webui llamafactory-cli webui 进入web ui面板 微调前准备 1. 数据准备 LLaMA-Factory 自带数据集以 .json 格式存放在项目根目录的 LLaMA-Factory/data 文件夹中,在图形化微调界面中可直接通过下拉框选择这些数据集。)。


Python入门指南(五) - 为什么选择 FastAPI?
吴佳浩2025/12/20

Python入门指南(五) - 为什么选择 FastAPI? 欢迎来到Python入门指南的第五部分!在上一章中,我们完成了Python开发环境的初始化配置。现在,让我们进入实战阶段——选择合适的Web框架来构建我们的API服务。 本章将深入对比 Flask 和 FastAPI,帮助你理解为什么在现代Python开发中,FastAPI正在成为越来越多开发者的首选。 ** 为什么需要Web框架?** 在进入对比之前,先理解Web框架的核心作用: 处理HTTP请求和响应:接收用户请求,返回处理


【转载】为什么我们选择GPT-5.2作为Augment Code Review的模型
是魔丸啊2025/12/12

转载 2025年12月11日 Augment Code Review在唯一的AI辅助代码审查公共基准测试中取得了最高的准确度,在整体质量上比Cursor Bugbot、CodeRabbit等其他系统高出约10个百分点。一个关键原因是什么?我们选择GPT-5.2作为代码审查的基础模型——以及我们的模型无关方法让我们能够为软件开发生命周期的每个阶段选择最佳工具。Augment Code Review最初基于GPT-5构建,但随着我们观察到OpenAI最新推理模型的质量提升,我们升级到了5.2版本。


C++单元测试框架选型与实战速查手册
码事漫谈2025/12/3

在C++项目的质量护城河中,单元测试框架的选择如同挑选一把趁手的兵器,它直接决定了测试的效率、可维护性以及与开发流程的契合度。GoogleTest、Catch2和doctest,这三款当今最主流的选择,各有其鲜明的武功路数。本文将为你揭开它们的核心秘籍与实战优劣势,助你一招制胜。 一、框架核心价值定位 1.1 三大框架战略定位分析 维度GoogleTest (v1.14+)Catch2 (v3.5+)doctest


LiteOps:轻量级CI/CD平台,重塑开发运维新体验
YL_jia2026/2/19

LiteOps:轻量级CI/CD平台,重塑开发运维新体验 在效率至上的时代,LiteOps正以“简洁易用”和“开箱即用”的理念,重新定义自动化部署流程。 一、LiteOps:为何成为开发运维的新宠? 在软件开发的快速迭代中,持续集成和持续部署(CI/CD) 已成为提升开发效率和软件质量的关键手段。 然而传统CI/CD工具往往配置复杂、学习曲线陡峭。LiteOps作为一个专注于实用性的轻量级CI/CD平台,应运而生,它开源免费,能够为开发团队提供高效、便捷的自动化构建和部署解决方案。 1.1


纯 CSS 实现弹性文字效果
掘金安东尼2026/2/28

原文:How to Create a CSS-only Elastic Text Effect 翻译:TUARAN 欢迎关注 前端周刊,每周更新国外论坛的前端热门文章,紧跟时事,掌握前端技术动态。 每个字母单独动画的文字效果总是很酷、很吸睛。这类错峰动画通常依赖 JavaScript 库实现,对我们要实现的这种相对轻量的设计效果来说,代码往往偏重。本文将探索只用 CSS、无需 JavaScript 实现 fancy 文字效果的技巧(意味着需要手动拆分字符)。 截至撰写时,仅 Chrome 和

首页编辑器站点地图

本站内容在 CC BY-SA 4.0 协议下发布

Copyright © 2026 XYZ博客