CC2640R2F BLE5.0 BLE一包数据到底能发多少
来源:互联网 发布:手机卫星电视软件 编辑:程序博客网 时间:2024/04/28 18:05
BLE一次能传多少数据
BLE到底一包能够收发多少数据。这是我们很多开发者都会关心的,正如我们知道BLE5.0物理层设计2Mpbs的码元率,实际我们的数据传输速率远远到不了这个级别,主要原因就是我们没有办法直接单次发送1M或者1K数据,必须按照我们知道的ATT_MTU
作为最大值进行拆包发送,不断拆包的过程中导致整体蓝牙有效数据吞吐量下降。本章节,我们实用性触发研究如何究竟蓝牙一包能够发送多少数据。
以下是GAPP Client 进行特征值写请求的完整抓包,AttValue
表示写入的值,该值的最大长度到底是多少呢,本文将详细研究并且验证。
本文的正确打开姿势,我们希望你已经仔细阅读并理解协议栈的L2CAP,和BLE4.2/5.0全新支持的 LE 数据扩展功能:
- Logical Link Control and Adaptation Layer Protocol (L2CAP)
- LE Data Length Extension
术语
分析
在 BLE PHY 包格式由以下组成,排除 前导码、访问地址、CRC地址 对于BLE4.0/BLE4.1 上层协议(LL)最大可以包含39字节长度的PDU(协议数据单元)。
但是更新后的BLE4.2/BLE5.0 直接升级硬件,将这一长度扩展到257。但是默认了兼容BLE4.0/4.1还是采用了上面的39设计。
注意:PHY 的数据包最大长度直接由硬件决定,也是限制我们BLE 数据包大小的根本原因。换句话说,PHY的硬件寄存器/存储器/FIFO 等直接决定了我们蓝牙数据包最大长度。
对于蓝牙协议分层设计来看,逻辑链路层是最底层,已经正常连接的两个设备之间通信PDU主要由LL Data PDU
组成。这里的LL Playload
作为我们上层协议的负载。
逻辑链路层再往上就是L2CAP——逻辑逻辑链路控制适配协议,如下的Basic L2CAP Header+Information Payload组成我们这里的基本帧(B-frame)。
L2CAP协议再上就是我们操作特征值的ATT层,这一层数据长度被 最大传输单元 ATT_MTU
限制,ATT_Payload由Attribute OPCode
+Attribute Parames
+Authentication Signature
(可选)组成。排除12字节可选的认证签名,和一个字节属性操作码。
对于我们这里的写属性值,其Attribute Parameters
=其Attribute Handle
(2) + Attribute Value
,Attribute Value
就是我们操作属性的值,其最大长度=ATT_MTU
-Attribute OPCode
(1)-Attribute Handle
(2)=ATT_MTU
-3。
同样地,对于读操作属性,主要包含在ReadResponse 操作码。最大长度=ATT_MTU
-Attribute OPCode
(1)=ATT_MTU
-1。
再总结下,读写属性值最大有效数据长度直接由ATT_MTU
决定,但是根本收LL PDU
大小限制
更改simpler_peripheral 配置更大MTU
对于simpler_peripheral工程我们的开发板作为GATT Server决定 ATT_MTU
的最大值。通过以下宏配置。
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,表示生效。
注意: 对于
GATT_ExchangeMTU()
操作,我们只能由GATT Client发起,并且GATT服务端返回实际支持最大ATT_MTU。
参考《运行第一个例程》,我们直接更改最大ATT_MTU到251,并且通过《 BTool》配置客户端ATT_MTU到251,并且更改simple_peripheral characteristic 5数组为251。属性为可读可写。
更改工程
- 更改配置宏
//source\ti\ble5stack\icall\inc\ble_user_config.h MAX_PDU_SIZE Line 214// Maximum size in bytes of the BLE HCI PDU. Valid range: 27 to 255// The maximum ATT_MTU is MAX_PDU_SIZE - 4.#ifndef MAX_PDU_SIZE#if defined(BLE_V42_FEATURES) && (BLE_V42_FEATURES & SECURE_CONNS_CFG) #define MAX_PDU_SIZE 255#else #define MAX_PDU_SIZE 27#endif //(BLE_V42_FEATURES & SECURE_CONNS_CFG)#endif
我们配置L2CAP MAX_PDU_SIZE
为255, ATT_MTU
最大 为251 读写特征值最大长度应该ATT_MTU
-3=248;
//source\ti\blestack\profiles\simple_profile\simple_gatt_profile.h SIMPLEPROFILE_CHAR5_LEN Line 85#define SIMPLEPROFILE_CHAR5_LEN 248
因为我们增加了特征值5的大小为240,对于参考特征的栈空间也得增加,对应着我们的任务栈,否则程序可能会跑飞。
//examples\rtos\CC2640R2_LAUNCHXL\blestack\simple_peripheral\src\app\simple_peripheral.c SBP_TASK_STACK_SIZE Line 180#ifndef SBP_TASK_STACK_SIZE#define SBP_TASK_STACK_SIZE 1024#endif
注意:这里之所以要加大任务栈否则任务要跑飞,是因为部分任务直接分配了栈空间进行特征值拷贝。
同时为了更好测试,我们直接将特诊5的属性更改为直接读写,不需要配对连接。
//source\ti\blestack\profiles\simple_profile\cc26xx\simple_gatt_profile.c Characteristic Value 5 Line 323 // Characteristic Value 5 { { ATT_BT_UUID_SIZE, simpleProfilechar5UUID }, GATT_PERMIT_READ|GATT_PERMIT_WRITE, 0, simpleProfileChar5 },
但是simple_peripheral默认没有进行Characteristic Value 5 写操作,所以我们需要更改。
//source\ti\blestack\profiles\simple_profile\cc26xx\simple_gatt_profile.c simpleProfile_WriteAttrCB Line660 case SIMPLEPROFILE_CHAR5_UUID: if(len+offset>SIMPLEPROFILE_CHAR5_LEN) { status = ATT_ERR_INVALID_VALUE_SIZE; } //Write the value if ( status == SUCCESS ) { uint8 *pCurVal = (uint8 *)pAttr->pValue; for(uint8 i=0;i<len;i++) { *(pCurVal+offset+i)=*(pValue+i); } if(pAttr->pValue == simpleProfileChar5) { notifyApp = SIMPLEPROFILE_CHAR5; } } break;
同时我们要在应用程序回调处理Characteristic Value 5的写入操作,方便打印到串口调试。
//examples\rtos\CC2640R2_LAUNCHXL\blestack\simple_peripheral\src\app\simple_peripheral.c SimpleBLEPeripheral_processCharValueChangeEvt Line 1183 case SIMPLEPROFILE_CHAR5: SimpleProfile_GetParameter(SIMPLEPROFILE_CHAR5, newValue); sprintf(sprintChar,"%s","Char 5: "); //!< 大概没60个字符要换一行 line=7; index=8; for(uint8_t i=0;i<SIMPLEPROFILE_CHAR5_LEN;i++) { sprintf(sprintChar+index, "%02X", *(newValue+i)); index=index+2; //!< 每60个字符进行换行打印。 if(index%60==0) { index=0; Display_print1(dispHandle,line++ ,0,"%s",sprintChar); } } if(index>0) { Display_print1(dispHandle,line,0,"%s",sprintChar); } break;
现象
simple_periphearal 打印进入广播状态
BTool 扫描连接
配对
交换MTU,设置到GATT 服务端编译支持的最大 251。
注意:此过程一定要发生在读取特征值之前,否则回超时。
--------------------------------------------------------------------[26] : <Rx> - 05:28:39.401-Type : 0x04 (Event)-EventCode : 0x00FF (HCI_LE_ExtEvent)-Data Length : 0x06 (6) bytes(s) Event : 0x067F (1663) (GAP_HCI_ExtentionCommandStatus) Status : 0x00 (0) (Success) OpCode : 0xFD02 (ATT_ExchangeMTUReq) DataLength : 0x00 (0)Dump(Rx):0000:04 FF 06 7F 06 00 02 FD 00 .........--------------------------------------------------------------------[27] : <Rx> - 05:28:39.511-Type : 0x04 (Event)-EventCode : 0x00FF (HCI_LE_ExtEvent)-Data Length : 0x08 (8) bytes(s) Event : 0x0503 (1283) (ATT_ExchangeMTURsp) Status : 0x00 (0) (Success) ConnHandle : 0x0000 (0) PduLen : 0x02 (2) ServerRxMTU : 0x00FB (251)Dump(Rx):0000:04 FF 08 03 05 00 00 00 02 FB 00 ...........--------------------------------------------------------------------[28] : <Rx> - 05:28:39.521-Type : 0x04 (Event)-EventCode : 0x00FF (HCI_LE_ExtEvent)-Data Length : 0x08 (8) bytes(s) Event : 0x057F (1407) (ATT_MtuUpdatedEvt) Status : 0x00 (0) (Success) ConnHandle : 0x0000 (0) PduLen : 0x02 (2) MTU : 0x00FB (251)Dump(Rx):0000:04 FF 08 7F 05 00 00 00 02 FB 00 ...........--------------------------------------------------------------------
读取特征值
成功写入,我们将读取Attribute Value 前面和后面都改成
FFFFFF03
和C6FFFF
总结
尽管我们通过GATT 服务端配置更大MTU,通过GATT Client 交换,成功读取200字节的特征值,但是在我们抓包分析不难发现在Controller,的链路层还是被拆分为最大长度27字节发送。通过前面分析我们已经不难理解,BLE4.2/5.0为了兼容 BLE4.0/4.1设备,所以默认TX PDU 设计成了27字节。尽管我们再Host配置更了更大的ATT_MTU,其实只是L2CAP帮我们进行了拆分和重组。为了获取到更大数据吞吐量,我们继续研究 BLE4.2/5.0新增功能 LE Data Extence。
Troubleshooting
写入数据失败,提示找不到Attribute Handle。
我们需要添加特诊值 5的 写回调处理,否则会直接提示找不到句柄。读取特征值超时
因为我们更改的GATT 服务端也就是simple_peripheral 工程的默认MTU 大小,所以正常读写特征值前我们需要进行ATT_Exchange_MTU_Req
请求。否则会直接失败。
LE Data Extension
LE Data Length Extension 文章我们详细讲解过,BLE4.2/5.0 已经硬件支持257的LL Data Payload Size。但是为了兼容BLE4.1/4.0所以默认保留该功能, 现在我们详细讲解如何使能该功能,实现真正意义的最大ATT_MTU
发送,同时体验BLE4.2/5.0全新速率。
对于BLE4.2/5.0设备,默认支持TX_PDU大小为了兼容BLE4.1/4.0 设备,默认设置为27字节/328us,同时又为了又为了兼容BLE4.2/5.0RX PDU默认设置为251字节/2152us。对于默认使能 251/2120us。只需要主从收发的任意一方设置自己的TX_PDU为251字节/2120us,那么收发双发就会直接发起协商功能。
所以这里我们直接设置Peripheral/Salve TX_PDU为251字节/2120us。在我们simple_peripheral工程 SimpleBLEPeripheral_init
加入以下代码
#define APP_SUGGESTED_PDU_SIZE 251 #define APP_SUGGESTED_TX_TIME 2120 //This API is documented in hci.h HCI_LE_WriteSuggestedDefaultDataLenCmd(APP_SUGGESTED_PDU_SIZE ,APP_SUGGESTED_TX_TIME);
抓包分析
- M->S LL_LENGTH_REQ (Rx/Tx)(251、2120) (27、318)
+----------------------------------------------------+----------------- - - -| Packet sniffer frame header |+----+-------------+-------------------------+-------+|info| Packet nbr. | Time stamp | Length| Packet data+----+-------------+-------------------------+-------+----------------- - - -| 01 | E1 00 00 00 | 29 0C 05 0E 02 00 00 00 | 15 00 | 14 BD AA 6D C4 0F 09 **14** ** FB 00 48 08 1B 00 48 01 ** 75 9A 9B 2A 9A+----+-------------+-------------------------+-------+----------------- - - -
- S->M LL_LENGTH_REQ (Rx/Tx)(251、2120) (27、318)
+----------------------------------------------------+----------------- - - -| Packet sniffer frame header |+----+-------------+-------------------------+-------+|info| Packet nbr. | Time stamp | Length| Packet data+----+-------------+-------------------------+-------+----------------- - - -| 01 | E2 00 00 00 | C2 0A 07 0E 02 00 00 00 | 15 00 | 14 BD AA 6D C4 0B 09 **14** ** FB 00 48 08 1B 00 48 01** B3 1B C9 2E 9A+----+-------------+-------------------------+-------+----------------- - - -
- S->M
+----------------------------------------------------+----------------- - - -| Packet sniffer frame header |+----+-------------+-------------------------+-------+|info| Packet nbr. | Time stamp | Length| Packet data+----+-------------+-------------------------+-------+----------------- - - -| 01 | E3 00 00 00 | 3C 0B 85 10 02 00 00 00 | 15 00 | 14 BD AA 6D C4 03 09 **15** **FB 00 48 08 1B 00 48 01** C7 83 7F 26 82+----+-------------+-------------------------+-------+----------------- - - -
- M->S LL_LENGTH_REQ (Rx/Tx)(251、2120) (27、318)
+----------------------------------------------------+----------------- - - -| Packet sniffer frame header |+----+-------------+-------------------------+-------+|info| Packet nbr. | Time stamp | Length| Packet data+----+-------------+-------------------------+-------+----------------- - - -| 01 | E4 00 00 00 | D7 09 87 10 02 00 00 00 | 15 00 | 14 BD AA 6D C4 07 09 **15** **FB 00 48 08 1B 00 48 01** 01 02 2D 34 82+----+-------------+-------------------------+-------+----------------- - - -
加入我们
文章所有代码、工具、文档开源。加入我们QQ群 591679055获取更多支持,共同研究CC2640R2F&BLE5.0。
© Copyright 2017, 成都乐控畅联科技有限公司.
- CC2640R2F BLE5.0 BLE一包数据到底能发多少
- CC2640R2F BLE5.0 BLE Device Monitor用户指南
- CC2640R2F BLE5.0 PacketSniffer BLE 抓包
- CC2640R2F BLE5.0 BLE吞吐量测试
- CC2640R2F BLE5.0 BLE连接参数更新过程详解
- CC2640R2F BLE5.0 CC2640R2F UART驱动
- CC2640R2F BLE5.0 CC2640R2F的存储架构
- CC2640R2F BLE5.0 CC2640R2F软硬件架构概述
- CC2640R2F BLE5.0 CC2640R2F硬件架构
- CC2640R2F BLE5.0 CC2640R2F软件架构
- CC2640R2F BLE5.0 CC2640R2F SPI驱动实现
- CC2640R2F BLE5.0 CC2640R2F/BLE5.0 距离测试
- CC2640R2F BLE5.0 开发向导
- CC2640R2F BLE5.0 应用程序框架
- CC2640R2F BLE5.0 蓝牙概述
- CC2640R2F BLE5.0 开发向导
- CC2640R2F BLE5.0 CC2640R2&BLE5.0开发文档
- CC2640R2F BLE5.0 安装BLE5-Stack 1.00.00
- 获取苹果手机UDID方法
- 【 hdu 6053】 TrickGCD 【数论 容斥 + 莫比乌斯函数 】
- 自己动手写C语言编译器(暂停)
- 郝彬英语
- FatMouse's Speed HDU
- CC2640R2F BLE5.0 BLE一包数据到底能发多少
- Dijkstra算法变异 poj 1797
- 如何搞30等角视图.斜45度说法不合理
- spring framework体系结构及内部各模块jar之间的maven依赖关系
- android应用前期开发之经验总结
- Android常见问题--横竖屏onConfigurationChanged方法失效
- opengl里面的矩阵栈
- ModelAndView详解
- Mybatis逆向工程