RTT 那邊的 Kconfig 配置完成,項目的基本開發(fā)內(nèi)容就完成了。然后再對協(xié)議棧在 Bluenrg2 芯片上采用 SPI 作為 HCI 的數(shù)據(jù)傳輸進行測試。
數(shù)據(jù)傳輸使用的是 zephyr_polling 的 thoughput Example。
配置
軟件包配置
數(shù)據(jù)傳輸
數(shù)據(jù)吞吐例程內(nèi)部邏輯是將接收到的數(shù)據(jù)轉發(fā)回中心設備。主要提供了兩個 GATT 服務:write 和 notify。前者用于接收中心設備發(fā)來的數(shù)據(jù),后者用于向連接的中心設備發(fā)送數(shù)據(jù)。
輸入zephyr運行Example。
手機端使用 BLE調(diào)試寶(類似的BLE APP應該都行)連接設備,開啟notify服務:
數(shù)據(jù)傳輸
數(shù)據(jù)吞吐例程內(nèi)部邏輯是將接收到的數(shù)據(jù)轉發(fā)回中心設備。主要提供了兩個 GATT 服務:write 和 notify。前者用于接收中心設備發(fā)來的數(shù)據(jù),后者用于向連接的中心設備發(fā)送數(shù)據(jù)。
輸入zephyr運行Example。
手機端使用 BLE調(diào)試寶(類似的BLE APP應該都行)連接設備,開啟notify服務:
連續(xù)發(fā)送數(shù)據(jù):
收發(fā)數(shù)據(jù)沒有丟包。
串口打印如下:
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
數(shù)據(jù)傳輸測試
數(shù)據(jù)傳輸測試首先是保證傳輸?shù)姆€(wěn)定性,保證沒有丟包誤碼。在保證可靠的前提下,再對數(shù)據(jù)傳輸?shù)乃俾蔬M行測試。測試包括雙工的收發(fā)速率測試和單口的傳輸速率測試。
測試傳輸?shù)膯蝹€數(shù)據(jù)包大小為 20 字節(jié)。
這里有一個測試方案的問題,一開始使用的方案不對,測得的數(shù)據(jù)不能保證準確性(沒有保證可靠傳輸),在社區(qū)導師的幫助下才得到了比較準確的測試結果。
測試單口傳輸速率
單口傳輸?shù)脑捫枰?thoughput 例程中的發(fā)送關閉。此時由于沒有給 APP 端反饋,為了保證可靠傳輸,需要在接收處對接收的數(shù)據(jù)進行計數(shù),并啟動一個軟件定時器,定時打印計數(shù)。將打印得到的接收字節(jié)數(shù)與 APP 端的發(fā)送字節(jié)數(shù)對比,二者相符則可以基本保證可靠傳輸。再根據(jù)打印的計數(shù),計算傳輸速率。
exampleperipheral_throughputthroughput_service.c
關閉發(fā)送:
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;
}
在接收處添加計數(shù)
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;
}
使用協(xié)議棧的軟件定時器打印計數(shù):
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后第一次執(zhí)行 之后50s為周期執(zhí)行
這里存在一個如何同步計數(shù)的問題。人點擊APP端發(fā)送的開始和停止時需要反應時間的,需要回避開始和結束。
首先是計數(shù)速率的時候,只能取不包含開始和結束的時間段內(nèi)的計數(shù)來計算。
而可靠性保證的時候,并不需要在一次計數(shù)完成的時候剛好結束,往后再計數(shù)一個周期,將全部的計數(shù)結果加起來,能與APP端相符即可。
采取的方案是啟動協(xié)議棧,并在 APP 端連接后,開始連續(xù)發(fā)送測試數(shù)據(jù)包。計數(shù)的打印為 25s 后第一次執(zhí)行,之后 50s 為周期執(zhí)行。四次打印后結束發(fā)送,等待最后一次打印。將 5 次打印的計數(shù)求和,與APP端的發(fā)送數(shù)對比。然后取中間三次 50s 打印的字節(jié)數(shù)計算傳輸速率。
經(jīng)過實際測試,APP 端 2 ms 發(fā)送間隔下,在長時間的連續(xù)發(fā)送下會產(chǎn)生丟包,需要將發(fā)送間隔上調(diào)至 3 ms 才能保證壓測之下沒有丟包。
20字節(jié) 間隔 2ms 傳輸持續(xù) 200s
協(xié)議棧端計數(shù)接收到 1494160 字節(jié)數(shù)據(jù),但 APP 端發(fā)出 75046 個數(shù)據(jù)包,1500920 字節(jié)數(shù)據(jù)。
存在丟包情況。此時速率為 1494160 / 200 = 7470.8 byte/s
單個數(shù)據(jù)包大小為 20 字節(jié),APP 端 3ms 發(fā)送間隔,測試打印:
[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
接收到的數(shù)據(jù)包為 17180+213960+211220+212000+57080 = 711440 字節(jié),與APP端相符。
當前條件下的可靠傳輸速率為 (213960+211220+212000) / (50 * 3) = 4247.87 byte/s
測試雙工的收發(fā)速率
數(shù)據(jù)吞吐例程內(nèi)部邏輯是將接收到的數(shù)據(jù)轉發(fā)回中心設備。在APP端保證發(fā)出和收到的字節(jié)數(shù)相同就能基本保證可靠性,然后再計數(shù)固定時間內(nèi)傳輸?shù)淖止?jié)數(shù)即可得到傳輸速率。
同時收發(fā)的條件下,需要將發(fā)送間隔設置到 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端收發(fā)數(shù)相符,沒有丟包。打印的計數(shù)和為151600,與APP端相符。
速率為 (36400+36400+36320+36360)/200 = 726.95 byte/s
雙工傳輸?shù)乃俾什⒉焕硐?,查看傳輸時的時序圖,發(fā)現(xiàn)傳輸所占用的時間比例很少,協(xié)議棧有很大的優(yōu)化空間。
問題
首先是從時序圖可以看到 SPI 通信口的利用率不高,有優(yōu)化空間。
此外 APP 端給芯片發(fā)送數(shù)據(jù)的時候是通過 write GATT 服務進行的,寫入的時候會檢查接收緩沖區(qū)大小,如果滿了,應當?shù)却锌臻e才會發(fā)送(實際去查看APP端的日志,即使將間隔設定為 1 ms,發(fā)送的間隔也不會是 1 ms,而是會根據(jù)實際情況浮動)。這種機制下,丟包是不應該的。
這兩個問題有待之后去改進。
-
接收器
+關注
關注
15文章
2595瀏覽量
75575 -
定時器
+關注
關注
23文章
3347瀏覽量
120955 -
SPI接口
+關注
關注
0文章
271瀏覽量
36130 -
BLE技術
+關注
關注
0文章
34瀏覽量
6865 -
RTThread
+關注
關注
8文章
132瀏覽量
42281
發(fā)布評論請先 登錄
RTT_Zephyr_Polling BlueNRG2 SPI使用說明

RTT平臺zephyr_polling軟件包SPI Bluenrg2芯片宕機問題與修復

RTT zephyr_polling軟件包 Bluenrg2藍牙芯片啟動流程

如何用Ubuntu qemu跑zephyr_polling的藍牙?

SPI數(shù)據(jù)傳輸緩慢問題求解
DSP2812的SPI數(shù)據(jù)傳輸
關于數(shù)據(jù)傳輸接口
基于SPI總線的無線數(shù)據(jù)傳輸系統(tǒng)設計

數(shù)據(jù)傳輸速率是什么意思
SPI是什么 SPI數(shù)據(jù)傳輸
SPI數(shù)據(jù)傳輸有哪些方式

RT-Thread平臺 zephyr_polling軟件包 Bluenrg2 藍牙芯片啟動流程

RTT平臺zephyr_polling軟件包SPI Bluenrg2丟包問題排查

評論