读写特征值的响应
Hi TI的前辈们!
我在simpleBLECentral工程中,在用户的任务里调用函数GATT_WriteCharValue();写特征值。
正常情况下,隔一小段时间都会有个响应事件发生,并跑到simpleBLECentralProcessGATTMsg()函数。
其中包括读/写、异常的响应:
else if ( ( pMsg->method == ATT_WRITE_RSP ) ||
( ( pMsg->method == ATT_ERROR_RSP ) &&
( pMsg->msg.errorRsp.reqOpcode == ATT_WRITE_REQ ) ) )//写特征值及写特征值异常
{
}
正常来说,就是每写一次特征值,则会对应地产生一次响应事件。
现在,我较频繁地写特征值(约1s两次),发现有时会没有产生这个响应事件,相应地,从机那边就收不到数据了。
请问:这种丢包是怎么回事,是由于连接间隔决定的吗?用户在写特征值时应该注意什么样的问题来避免丢数据呢?
shaokai,
发生这个事件的时候,你能把error code给得到吗?
Yan:
不是写入特征值时产生错误,而是没有响应。
我在simpleBLECentralProcessGATTMsg() 这个函数的各个分支都加入了打印。我个人的感觉就是:
上一次写特征值的响应还没有完成,我就调用GATT_WriteCharValue()这个函数对同一个特征值再次进行写入操作。
我这样问吧:
如果主从机的连接间隔是100ms,但是我在主机中每20ms就调用GATT_WriteCharValue() 这个函数写从机
的某个特征值。这样会造成什么问题?是否最终从机能收到的只是 离连接事件最近 的一次发送的数据呢?
shaokai,
正常情况下,根据蓝牙协议,用GATT_WriteCharValue() 操作一个特征值,必须等到ATT层的write response之后才能对它进行下一步操作,没收到response之前,不能进行第二次操作。CC254x 的代码也是这么要求的。所以正确的做法是你在进行第二次写入之前,必须先等待第一次response收到之后.
另外,在如上所述正确的操作的前提下,如果你的connection interval 是100ms, 你每隔 20ms 发送数据,那绝对有问题。通常情况下,由于MCU需要处理数据,往往要等到下一个connection event才能回复 write response,这就间隔了100ms了,所以,你中间发的20ms数据,就会有问题。
你可以试一下 GATT_WriteNoRsp(), 这个是不需要peripheral 回复 response的写请求。但是请注意,由于你的connection interval 是 100ms, 所以你每隔20ms写下去的内容,会被缓存,每100ms 才能发送出去。
Yan
That is the Answer I want.Thanks~
另外,我还想咨询下:
主从连接间隔100ms的情况下,每20ms写入特征值。我猜想,在下一个连接事件到来之前,前面的数据会被后面的数据覆盖,对吗?
为确保可靠传输,我还是老老实实 在收到Response之后再继续写一下次的数据吧~
shaokai,
数据不会被覆盖。
LL层有buffer,会把收到的发送请求一个个缓存起来,按顺序发送。每次发送,都认为是新数据。
Yan
OK,Thanks。
不过,如果长期如此,会不会把RAM给爆掉啊?~
shaokai,
当然不会:)有足够的内存配额:)
LL层分配了一定数额的buffer,如果满的话会报错,这个也是蓝牙协议规定必须要有的,HCI层错误代码: 0x07, Memory Capacity Exceeded
Yan
OK.Thanks。
那我能否截获到这样的错误呢?
因为我测试时,这边调用GATT_WriteCharValue() 总共6次,但从机真正收到数据只有2~3次。
shaokai,
一般情况下你是看不到这样的错误。因为有足够大的缓存空间在下面。
你说的这个情况,如果是在正常收到write response之后再写后续数据的话,最好的方法是用packet sniffer抓包看一下。看一下空中是否有真正发出去。
Yan:
我用Packet Sniffer抓包后,真正发送出去的数据包 跟从机工程接收到的数据包的个数是一致的。
并且发送出去的数据包Req都会对应一个响应包Rsp。
也就是说真正的漏包还是在主机这边。
另外,Packet Sniffer抓包时可否屏蔽连接事件啊?哗啦啦,一大堆的~不是很方便。
shaokai,
那么你就得检查一下你的关于write的代码了。
正常情况下是不会丢包的,肯定有什么地方有问题了。
packet sniffer 会抓到所有的包,这个没法屏蔽,但是可以做筛选显示,在工具的下方有选项:)
我碰到了同样的问题,现在在翻这些老帖子,发现解决方法都在里面。确实需要等到收到write response后才能再调用GATT_WriteCharValue()来给slave写数据。