RTT zephyr_polling SPI Bluenrg2数据传输测试

电子说

1.2w人已加入

描述

RTT 那边的 Kconfig 配置完成,项目的基本开发内容就完成了。然后再对协议栈在 Bluenrg2 芯片上采用 SPI 作为 HCI 的数据传输进行测试。

数据传输使用的是 zephyr_polling 的 thoughput Example。

配置

软件包配置

数据传输

数据吞吐例程内部逻辑是将接收到的数据转发回中心设备。主要提供了两个 GATT 服务:write 和 notify。前者用于接收中心设备发来的数据,后者用于向连接的中心设备发送数据。

输入zephyr运行Example。

手机端使用 BLE调试宝(类似的BLE APP应该都行)连接设备,开启notify服务:

定时器

数据传输

数据吞吐例程内部逻辑是将接收到的数据转发回中心设备。主要提供了两个 GATT 服务:write 和 notify。前者用于接收中心设备发来的数据,后者用于向连接的中心设备发送数据。

输入zephyr运行Example。

手机端使用 BLE调试宝(类似的BLE APP应该都行)连接设备,开启notify服务:

定时器

连续发送数据:

定时器

收发数据没有丢包。

串口打印如下:

initialize rti_board_start:0 done
initialize drv_pm_hw_init:0 done
initialize rt_hw_spi_init:0 done
| /

RT - Thread Operating System
/ | 5.0.1 build Sep 20 2023 22:39:47
2006 - 2022 Copyright by RT-Thread team
do components initialization.
initialize rti_board_end:0 done
initialize stm32l4_hw_lptim_init:0 done
initialize finsh_system_init:0 done
msh >zephyr
zephyr_polling_init
bt_init_hci_driver
SPI_init_process device_name: spi10, spi_name: spi1, rate: 1000000, databits: 8, LSB_MSB: 1, Master_Slave: 0, CPOL: 0, CPHA: 1
SPI_init_process cs_pin_num: 1, irq_pin_num: 0
hci_driver_open, SPI_config_finish
I: (bt_hci_core)hci_init():3230: work start.
msh >prepare_event_process, step: 1
prepare_event_process, step: 2
prepare_event_process, step: 3
prepare_event_process, step: 4
prepare_event_process, step: 5
I: (bt_hci_core)hci_init_end():3205: work end.
E: (bt_smp)smp_self_test():5695: smp_self_test start
I: (bt_hci_core)bt_dev_show_info():3008: Identity: 02:80:e1:00:00:f5 (public)
I: (bt_hci_core)bt_dev_show_info():3042: HCI: version 5.2 (0x0b) revision 0x1222, manufacturer 0x0030
I: (bt_hci_core)bt_dev_show_info():3044: LMP: version 5.2 (0x0b) subver 0x0015
Bluetooth initialized
throughput_svc_init()
Advertising successfully started
I: (bt_hci_core)bt_sleep_prepare_work():4040: start
I: (bt_hci_core)bt_sleep_prepare_work():4046: end
I: (bt_hci_core)bt_sleep_wakeup_work_start():4058: start
I: (bt_hci_core)bt_sleep_wakeup_work_start():4061: end
I: (bt_hci_core)bt_sleep_wakeup_work_end():4072: start
I: (bt_hci_core)bt_sleep_wakeup_work_end():4074: end
Connected

数据传输测试

数据传输测试首先是保证传输的稳定性,保证没有丢包误码。在保证可靠的前提下,再对数据传输的速率进行测试。测试包括双工的收发速率测试和单口的传输速率测试。

测试传输的单个数据包大小为 20 字节。

这里有一个测试方案的问题,一开始使用的方案不对,测得的数据不能保证准确性(没有保证可靠传输),在社区导师的帮助下才得到了比较准确的测试结果。

测试单口传输速率
单口传输的话需要把 thoughput 例程中的发送关闭。此时由于没有给 APP 端反馈,为了保证可靠传输,需要在接收处对接收的数据进行计数,并启动一个软件定时器,定时打印计数。将打印得到的接收字节数与 APP 端的发送字节数对比,二者相符则可以基本保证可靠传输。再根据打印的计数,计算传输速率。

exampleperipheral_throughputthroughput_service.c
关闭发送:

static void throughput_tx_ccc_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value)
{
bool notif_enabled = (value == BT_GATT_CCC_NOTIFY);
// tx_enable = notif_enabled;
// 修改为
tx_enable = 0;
}
在接收处添加计数

static ssize_t data_rx(struct bt_conn *conn, const struct bt_gatt_attr *attr, const void *buf,
uint16_t len, uint16_t offset, uint8_t flags)
{
...
recv_count += len;
return len;
}
使用协议栈的软件定时器打印计数:

struct k_timer count_work;
...
void count_timeout(struct k_timer *timer)
{
printf("count_timeout(): %dn", recv_count);
recv_count = 0;
}
...
k_timer_init(&count_work, count_timeout, NULL);
k_timer_start(&count_work, K_SECONDS(25), K_SECONDS(50)); // 25s后第一次执行 之后50s为周期执行

这里存在一个如何同步计数的问题。人点击APP端发送的开始和停止时需要反应时间的,需要回避开始和结束。

首先是计数速率的时候,只能取不包含开始和结束的时间段内的计数来计算。

而可靠性保证的时候,并不需要在一次计数完成的时候刚好结束,往后再计数一个周期,将全部的计数结果加起来,能与APP端相符即可。

采取的方案是启动协议栈,并在 APP 端连接后,开始连续发送测试数据包。计数的打印为 25s 后第一次执行,之后 50s 为周期执行。四次打印后结束发送,等待最后一次打印。将 5 次打印的计数求和,与APP端的发送数对比。然后取中间三次 50s 打印的字节数计算传输速率。

经过实际测试,APP 端 2 ms 发送间隔下,在长时间的连续发送下会产生丢包,需要将发送间隔上调至 3 ms 才能保证压测之下没有丢包。

20字节 间隔 2ms 传输持续 200s

协议栈端计数接收到 1494160 字节数据,但 APP 端发出 75046 个数据包,1500920 字节数据。

存在丢包情况。此时速率为 1494160 / 200 = 7470.8 byte/s

单个数据包大小为 20 字节,APP 端 3ms 发送间隔,测试打印:

[16:49:11.997]收←◆Connected
[16:49:26.163]收←◆count_timeout(): 17180
[16:50:16.110]收←◆count_timeout(): 213960
[16:51:06.061]收←◆count_timeout(): 211220
[16:51:56.016]收←◆count_timeout(): 212000
[16:52:45.978]收←◆count_timeout(): 57080

接收到的数据包为 17180+213960+211220+212000+57080 = 711440 字节,与APP端相符。

定时器

当前条件下的可靠传输速率为 (213960+211220+212000) / (50 * 3) = 4247.87 byte/s

测试双工的收发速率

数据吞吐例程内部逻辑是将接收到的数据转发回中心设备。在APP端保证发出和收到的字节数相同就能基本保证可靠性,然后再计数固定时间内传输的字节数即可得到传输速率。

同时收发的条件下,需要将发送间隔设置到 25ms 才能保证传输不丢包。

[00:11:22.697]收←◆Connected
[00:11:37.647]收←◆count_timeout(): 4280
[00:12:27.610]收←◆count_timeout(): 36400
[00:13:17.572]收←◆count_timeout(): 36400
[00:14:07.530]收←◆count_timeout(): 36320
[00:14:57.484]收←◆count_timeout(): 36360
[00:15:47.440]收←◆count_timeout(): 1900

APP端收发数相符,没有丢包。打印的计数和为151600,与APP端相符。

速率为 (36400+36400+36320+36360)/200 = 726.95 byte/s

双工传输的速率并不理想,查看传输时的时序图,发现传输所占用的时间比例很少,协议栈有很大的优化空间。

定时器

问题

首先是从时序图可以看到 SPI 通信口的利用率不高,有优化空间。

此外 APP 端给芯片发送数据的时候是通过 write GATT 服务进行的,写入的时候会检查接收缓冲区大小,如果满了,应当等待有空闲才会发送(实际去查看APP端的日志,即使将间隔设定为 1 ms,发送的间隔也不会是 1 ms,而是会根据实际情况浮动)。这种机制下,丢包是不应该的。

这两个问题有待之后去改进。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分