这里会显示出您选择的修订版和当前版本之间的差别。
后一修订版 | 前一修订版 | ||
cc2640r2f:exchange_mtu [2017/08/31 16:30] 127.0.0.1 外部编辑 |
cc2640r2f:exchange_mtu [2021/06/22 23:14] (当前版本) |
||
---|---|---|---|
行 1: | 行 1: | ||
< | < | ||
- | # BLE一次能传多少数据 # | + | # BLE 一次能传多少数据 # |
- | BLE到底一包能够收发多少数据。这是我们很多开发者都会关心的,正如我们知道BLE5.0物理层设计2Mpbs的码元率,实际我们的数据传输速率远远到不了这个级别,主要原因就是我们没有办法直接单次发送1M或者1K数据,必须按照我们知道的`ATT_MTU`作为最大值进行拆包发送,不断拆包的过程中导致整体蓝牙有效数据吞吐量下降。本章节,我们实用性触发研究如何究竟蓝牙一包能够发送多少数据。 | + | BLE 到底一包能够收发多少数据是很多开发者都会关心的。我们知道 |
- | 以下是GAPP Client 进行特征值写请求的完整抓包,`AttValue`表示写入的值,该值的最大长度到底是多少呢,本文将详细研究并且验证。 | + | 以下是 GAPP Client 进行特征值写请求的完整抓包,`AttValue` 表示写入的值,该值的最大长度到底是多少呢?本文将详细研究并且验证。 |
![](http:// | ![](http:// | ||
- | 本文的正确打开姿势,我们希望你已经仔细阅读并理解协议栈的L2CAP,和BLE4.2/ | + | 本文的正确打开姿势,我们希望你已经仔细阅读并理解协议栈的 L2CAP,和 BLE4.2/5.0 全新支持的 LE 数据扩展功能。 |
- | * <a href=" | + | * <a href="http://docs.leconiot.com/doku.php? |
- | * <a href=" | + | * <a href="http://docs.leconiot.com/doku.php? |
## 术语 ## | ## 术语 ## | ||
行 17: | 行 17: | ||
|术语|解释| | |术语|解释| | ||
|---|----| | |---|----| | ||
- | |PDU|Potocal Data Unit 协议数据单元,对于协议栈数据单元我们应该理解为蓝牙协议分层的消息实体的完整封装,例如LL PDU表示我们 | + | |PDU|Potocal Data Unit 协议数据单元,对于协议栈数据单元我们应该理解为蓝牙协议分层的消息实体的完整封装,例如 LL PDU 表示逻辑链路层的协议消息的完整封装| |
- | |MTU|Maximum Transmission Unit 最大传输单元,和本文研究的BLE数据包的最大长度意思接近| | + | |MTU|Maximum Transmission Unit 最大传输单元,和本文研究的 BLE 数据包的最大长度意思接近| |
|LL|Logic Link 逻辑链路层| | |LL|Logic Link 逻辑链路层| | ||
|PHY| physical layer 物理层 蓝牙协议的最底层| | |PHY| physical layer 物理层 蓝牙协议的最底层| | ||
## 分析 ## | ## 分析 ## | ||
- | 在 BLE PHY 包格式由以下组成,排除 前导码、访问地址、CRC地址 对于BLE4.0/ | + | 在 BLE PHY 包格式由以下组成:排除 前导码、访问地址、CRC 地址 对于 BLE4.0/ |
![](http:// | ![](http:// | ||
- | 但是更新后的BLE4.2/ | + | 更新后的 BLE4.2/ |
![](http:// | ![](http:// | ||
- | > | + | > |
- | 对于蓝牙协议分层设计来看,逻辑链路层是最底层,已经正常连接的两个设备之间通信PDU主要由`LL Data PDU`组成。这里的`LL Playload`作为我们上层协议的负载。 | + | 从蓝牙协议分层设计来看,逻辑链路层是最底层,已经正常连接的两个设备之间通信 PDU 主要由 `LL Data PDU` 组成。`LL Playload` 作为上层协议的负载。 |
![](http:// | ![](http:// | ||
- | 逻辑链路层再往上就是L2CAP——逻辑逻辑链路控制适配协议, | + | 逻辑链路层再往上就是 L2CAP ——逻辑逻辑链路控制适配协议, |
![](http:// | ![](http:// | ||
- | L2CAP协议再上就是我们操作特征值的ATT层,这一层数据长度被 最大传输单元 `ATT_MTU`限制,ATT_Payload由`Attribute OPCode`+`Attribute Parames`+`Authentication Signature`(可选)组成。排除12字节可选的认证签名,和一个字节属性操作码。 | + | L2CAP 协议再上就是操作特征值的 ATT 层,这一层数据长度被最大传输单元 `ATT_MTU` 限制,ATT_Payload 由 `Attribute OPCode` + `Attribute Parames` + `Authentication Signature`(可选)组成。排除 12 字节可选的认证签名,和一个字节属性操作码。 |
![](http:// | ![](http:// | ||
- | 对于我们这里的写属性值,其`Attribute Parameters`=其`Attribute Handle`(2) + `Attribute Value`,`Attribute Value`就是我们操作属性的值,其最大长度=`ATT_MTU`-`Attribute OPCode`(1)-`Attribute Handle`(2)=`ATT_MTU`-3。 | + | 对于写属性值,`Attribute Parameters` = `Attribute Handle`(2) + `Attribute Value` |
![](http:// | ![](http:// | ||
- | 同样地,对于读操作属性,主要包含在ReadResponse 操作码。最大长度=`ATT_MTU`-`Attribute OPCode`(1)=`ATT_MTU`-1。 | + | 同样地,对于读操作属性,主要包含在 ReadResponse 操作码。最大长度 = `ATT_MTU` - `Attribute OPCode`(1) = `ATT_MTU`-1 。 |
![](http:// | ![](http:// | ||
- | 再总结下,对于Host部分 读写属性值最大有效数据长度直接由`ATT_MTU`决定,但是根本受 Controller `LL PDU` 大小限制 | + | 总之,对于 Host 部分读写属性值最大有效数据长度直接由 `ATT_MTU` 决定的,但根本是受 Controller `LL PDU` 大小限制。 |
- | > | + | > |
- | ## 更改simpler_peripheral 配置更大MTU ## | + | ## 更改 simpler_peripheral 配置更大 MTU ## |
![](http:// | ![](http:// | ||
- | 对于simpler_peripheral工程我们的< | + | 对于 simpler_peripheral 工程我们的< |
- | simpler_peripheral默认的`ATT_MTU`为23,也就是我们实际写属性值最大长度为20。GATT 服务端`ATT_MTU`由以上宏定义,GATT客户端可以通过`GATT_ExchangeMTU()`命令配置。GATT服务端根据当前的配置的ATT_MTU决定是否生效。例如我们这里的`simple_peripheral`作为GATT服务端,以更改宏`L2CAP_MTU_SIZE`为150,` GATT_ExchangeMTU()`需要配置到200,我们将返回150,表示生效。 | + | simpler_peripheral 默认的 `ATT_MTU` 为 23 ,即实际写属性值最大长度为 20 。GATT 服务端 `ATT_MTU` 由以上宏定义,GATT 客户端可以通过`GATT_ExchangeMTU()` 命令配置。 GATT 服务端根据当前的配置的 ATT_MTU 决定是否生效。例如我们这里的 `simple_peripheral` 作为 GATT 服务端,以更改宏 `L2CAP_MTU_SIZE` 为 150 ,` GATT_ExchangeMTU()` 需要配置到 200,返回 150 表示生效。 |
- | > | + | > |
- | 参考《< | + | 参考《< |
### 更改工程 ### | ### 更改工程 ### | ||
* 更改配置宏 | * 更改配置宏 | ||
+ | |||
```C | ```C | ||
// | // | ||
行 86: | 行 87: | ||
#endif | #endif | ||
``` | ``` | ||
- | 我们配置`L2CAP MAX_PDU_SIZE` 为255, `ATT_MTU` 最大 为251 读写特征值最大长度应该`ATT_MTU`-3=248; | + | 配置`L2CAP MAX_PDU_SIZE` 为255, `ATT_MTU` 最大 为251 读写特征值最大长度应该`ATT_MTU`-3=248; |
```C | ```C | ||
// | // | ||
行 92: | 行 93: | ||
``` | ``` | ||
- | 因为我们增加了特征值5的大小为240,对于参考特征的栈空间也得增加,对应着我们的任务栈,否则程序可能会跑飞。 | + | 由于增加了特征值 5 的大小为 |
``` | ``` | ||
// | // | ||
行 102: | 行 103: | ||
- | 同时为了更好测试,我们直接将特诊5的属性更改为直接读写,不需要配对连接。 | + | 同时为了更好测试,直接将特征 5 的属性更改为直接读写,不需要配对连接。 |
```C | ```C | ||
// | // | ||
行 113: | 行 115: | ||
}, | }, | ||
``` | ``` | ||
- | 但是simple_peripheral默认没有进行Characteristic Value 5 写操作,所以我们需要更改。 | + | 但是 simple_peripheral 默认没有进行 Characteristic Value 5 写操作,所以需要更改。 |
```C | ```C | ||
// | // | ||
行 133: | 行 136: | ||
| | ||
``` | ``` | ||
- | 同时我们要在应用程序回调处理Characteristic Value 5的写入操作,方便打印到串口调试。 | + | 同时要在应用程序回调处理 Characteristic Value 5 的写入操作,方便打印到串口调试。 |
```C | ```C | ||
// | // | ||
行 140: | 行 144: | ||
| | ||
sprintf(sprintChar," | sprintf(sprintChar," | ||
- | //!< 大概没60个字符要换一行 | + | //!< 大概每 60 个字符要换一行 |
line=7; | line=7; | ||
index=8; | index=8; | ||
行 159: | 行 163: | ||
### 现象 ### | ### 现象 ### | ||
* simple_periphearal 打印进入广播状态 | * simple_periphearal 打印进入广播状态 | ||
+ | |||
![](http:// | ![](http:// | ||
+ | |||
* BTool 扫描连接 | * BTool 扫描连接 | ||
+ | |||
![](http:// | ![](http:// | ||
+ | |||
* 配对 | * 配对 | ||
+ | |||
![](http:// | ![](http:// | ||
- | * 交换MTU,设置到GATT 服务端编译支持的最大 251。 | + | |
- | > | + | * 交换MTU,设置到 GATT 服务端编译支持的最大 251 。 |
+ | > | ||
![](http:// | ![](http:// | ||
行 206: | 行 216: | ||
-------------------------------------------------------------------- | -------------------------------------------------------------------- | ||
``` | ``` | ||
+ | | ||
![](http:// | ![](http:// | ||
+ | | ||
* 读取特征值 | * 读取特征值 | ||
+ | |||
![](http:// | ![](http:// | ||
- | * 成功写入,我们将读取Attribute Value 前面和后面都改成`FFFFFF03`和`C6FFFF` | + | |
+ | * 成功写入,将读取 Attribute Value 前面和后面都改成 `FFFFFF03` 和 `C6FFFF` | ||
行 216: | 行 230: | ||
### 总结 ### | ### 总结 ### | ||
- | 尽管我们通过GATT 服务端配置更大MTU,通过GATT Client 交换,成功读取200字节的特征值,但是在我们抓包分析不难发现在Controller,的链路层还是被拆分为最大长度27字节发送。通过前面分析我们已经不难理解,BLE4.2/ | + | 尽管通过 GATT 服务端配置更大 MTU ,再通过 GATT Client 交换,成功读取 200 字节的特征值。但在抓包分析中不难发现在 Controller 的链路层还是被拆分为最大长度 27 字节发送。 |
+ | 通过前面分析已经不难理解:BLE4.2/5.0 为了兼容 BLE4.0/ | ||
+ | |||
+ | 为了获取到更大数据吞吐量,我们继续研究 BLE4.2/5.0 新增功能 LE Data Extence。 | ||
![](http:// | ![](http:// | ||
+ | |||
### Troubleshooting ### | ### Troubleshooting ### | ||
- | * 写入数据失败,提示找不到Attribute Handle。 | + | * 写入数据失败,提示找不到 Attribute Handle。 |
![](http:// | ![](http:// | ||
- | 我们需要添加特诊值 5的 写回调处理,否则会直接提示找不到句柄。 | + | |
+ | 需要添加特征值 5 的写回调处理,否则会直接提示找不到句柄。 | ||
行 228: | 行 249: | ||
![](http:// | ![](http:// | ||
- | 因为我们更改的GATT 服务端也就是simple_peripheral 工程的默认MTU 大小,所以正常读写特征值前我们需要进行`ATT_Exchange_MTU_Req` 请求。否则会直接失败。 | + | 因为更改的 GATT 服务端也就是 simple_peripheral 工程的默认 MTU 大小,正常读写特征值前需要进行 `ATT_Exchange_MTU_Req` 请求,否则会直接失败。 |
## LE Data Extension ## | ## LE Data Extension ## | ||
- | <a href=" | + | <a href="http://docs.leconiot.com/doku.php? |
- | 对于BLE4.2/ | + | BLE4.2/5.0 设备默认支持 TX_PDU 大小,为了兼容 BLE4.1/4.0 设备,默认设置为 27 字节/ |
- | 所以这里我们直接设置Peripheral/ | + | 所以直接设置 Peripheral/ |
```C | ```C | ||
行 246: | 行 267: | ||
### 抓包分析 ### | ### 抓包分析 ### | ||
+ | |||
* M-> | * M-> | ||
+ | |||
``` | ``` | ||
+----------------------------------------------------+----------------- - - - | +----------------------------------------------------+----------------- - - - | ||
行 258: | 行 281: | ||
* S-> | * S-> | ||
+ | |||
``` | ``` | ||
+----------------------------------------------------+----------------- - - - | +----------------------------------------------------+----------------- - - - | ||
行 267: | 行 291: | ||
+----+-------------+-------------------------+-------+----------------- - - - | +----+-------------+-------------------------+-------+----------------- - - - | ||
``` | ``` | ||
+ | |||
* S-> | * S-> | ||
+ | |||
``` | ``` | ||
+----------------------------------------------------+----------------- - - - | +----------------------------------------------------+----------------- - - - | ||
行 278: | 行 304: | ||
``` | ``` | ||
+ | |||
* M-> | * M-> | ||
+ | |||
``` | ``` | ||
+----------------------------------------------------+----------------- - - - | +----------------------------------------------------+----------------- - - - | ||
行 287: | 行 315: | ||
| 01 | E4 00 00 00 | D7 09 87 10 02 00 00 00 | 15 00 | 14 BD AA 6D C4 07 09 **15** | | 01 | E4 00 00 00 | D7 09 87 10 02 00 00 00 | 15 00 | 14 BD AA 6D C4 07 09 **15** | ||
+----+-------------+-------------------------+-------+----------------- - - - | +----+-------------+-------------------------+-------+----------------- - - - | ||
+ | |||
``` | ``` | ||
## 加入我们 ## | ## 加入我们 ## | ||
- | 文章所有代码、工具、文档开源。加入我们[**QQ群 591679055**](http:// | + | |
+ | 文章所有代码、工具、文档开源。加入我们[**QQ群 591679055**](http:// | ||
<div> | <div> | ||
<p align=" | <p align=" | ||
- | <a target=" | + | <a target=" |
- | © Copyright 2017, 成都乐控畅联科技有限公司. | + | |
</p> | </p> | ||
</ | </ | ||
- | </ | ||
+ | </ |