Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
蓝牙BLE
RTT平台 zephyr_polling软件包 SPI Bluenrg2芯片宕机问题与修复
发布于 2023-09-23 21:04:31 浏览:87
订阅该版
[tocm] # RTT zephyr_polling SPI Bluenrg2芯片宕机问题与修复 >“开源之夏”“蓝牙HOST协议栈zephyr_polling完善” 项目个人记录 菜鸡参与项目的个人记录 项目软件包地址:https://github.com/bobwenstudy/RTT_PACKAGE_zephyr_polling 项目的代码测试完成之后,准备收尾时,出现了问题。清除掉开发过程中用来调试的print打印之后,zephyr_polling 的 HCI 突然不能正常工作了,之前测试可用的 zephyr_polling 中的各个例程都不再能运行。 这个时候是去掉了 print 打印的,不能从日志找问题。经过一个一个尝试之后定位到了 SPI 接收操作完成之后的一个 print。将其去掉之后,芯片运行会宕机,但若是替换为一个 2 ticks (即2ms)的时延,例程都能正常运行。但是显然不能这样处理这个问题,这样一是治标不治本 (只是在这个环境下避免了时序问题的发生,当条件改变,问题还可能出现),二是影响性能。 于是使用这个(不太好用的)逻辑分析仪开始寻找问题。 ## 1.是否接收header发送的太频繁 先考虑问题是否出在轮询接收,发送 header 过于频繁,导致芯片down。 根据逻辑时序图,很多地方都是发起接收之后直接读取芯片的待发数据大小。而此时芯片并不一定准备好了做接收,读到的数据大小很大,导致重复多次地读取无用 byte。  官方例程里没有这个问题是因为接收时中断调用的,芯片那边主动要求接收数据,一定准备好发送了。轮询的话则应该等待芯片做好准备,拉高irq线再发送recv_header **处理**: 在接收操作发送 header 前加入 !IsDataAvailable() 校验,确认芯片准备好了再发 header 确定要接收的数据量。 加入判断机制后大大减少了启动用时,提高了效率。 但是去掉print芯片还是down了。 ## 2.是否是拉高cs_pin后irq_pin响应太慢 考虑是否是拉高cs后irq_pin响应太慢 观察时序图发现,MCU 拉高 cs 希望发送数据之后,过了较长一段等待时间后 irq 才拉高进行 header 传输。  测试这种情况:cs 拉高再拉低,等待较长一段时间才 irq 拉高,此时传输数据,芯片并没有 down:  ## 3.是否不能在发送header之后同时收发 在接收处加入校验后的代码,去掉 print 芯片还是 down 了。观察其最后的时序,发现其发送了发送 header 之后,同时进行了收发,然后 down 了。 没有delay 发送接收碰撞 后续芯片 down 了, spi 通信失败:   并且,反复测试之后,芯片都是在这一次传输之后宕机。这里发送的命令`01:0c:fc:03:2c:01:01`是关闭芯片自带 host。同时传输的是 `04:ff:03:01:00:01:06` 厂商事件包,应该是一个 6 字节的心跳包。最后的那一个 `06` 是因为 host 要传输的命令是 7 个字节,最后有个随机的电平。协议栈不会对芯片的特殊厂商事件包进行处理,即使被塞入接收队列,最后协议栈处理的时候也会将其丢弃。 **考虑是否不能同时收发**。对比观察正常的收发的时序。 带 2 ticks delay 的接收  带 2 ticks delay 的接收,无待传数据   对比发现,正常的工作的传输并不会出现收发同时的情况。 抛开这个宕机问题不谈,在发送的事务流程中,对于传输数据过程中芯片发过来的数据是直接丢弃的,而这将导致丢包。虽然这里丢失的是厂商事件包,本来就不会对其处理,但是处于普适性应该将其纠正。 ## 解决同时收发的问题 观察时序图发现,发送 header 之后不进行数据传输时被芯片允许的。尝试在实际发送之前检查 send_header 响应中接收缓冲区数据量,如果不为 0,结束当此发送流程,先做一次完整接收,并将接收到的数据塞到接收队列里,再重新发送 send_header (使用while循环,直到待接收数据为0),继续当前数据的发送。 直接在 send_header 传输完成之后加入判断,进行一次接收: ```C /* Read header */ rt_spi_transfer(ble_spi, &header_master, &header_slave, HEADER_SIZE); rx_bytes = (((uint16_t)header_slave[2])<<8) | ((uint16_t)header_slave[1]); uint16_t byte_count = (header_slave[4] << 8)| header_slave[3]; if (byte_count > 0) { hci_driver_init_loop(); result = -2; } else { if(rx_bytes >= size) { /* Buffer is big enough */ rt_spi_transfer(ble_spi, buffer, &read_char_buf, size); } else { /* Buffer is too small */ result = -2; } /* Release CS line */ rt_pin_write(hci_config.cs_pin_num, PIN_HIGH); } ``` 测试发现并不行,这时想起我没拉高 CS 结束这一次发送传输事务就直接启动了一次接收,肯定会出错。加入这一句:`rt_pin_write(HCI_TL_SPI_CS_PIN, PIN_HIGH);`。 但加入后仍然不能正常使用。发送超时了,也就是在发起接收的时候, cs 拉低之后,irq 一直没有拉高 ```shel \ | / - RT - Thread Operating System / | \ 5.0.1 build Sep 9 2023 21:50:28 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 >SPI Send timeout 101 E: (bt_hci_core)hci_send_cmd():2928: Unable to send to driver (err -1) ``` 查看时序图:  发现后续irq_pin直到超时了都没动一下,怀疑是前一次的发送流程没有被芯片认定结束。 经过一系列尝试和测试之后,发现要想结束当次发送流程,需要将 cs 拉高一定的时间,才能让 chipset 觉得这次发送完了: ```c if (byte_count > 0) { /* Release CS line */ rt_pin_write(HCI_TL_SPI_CS_PIN, PIN_HIGH); /* to end the send, we need a delay */ rt_thread_delay(1); hci_driver_init_loop(); result = -2; } ``` 虽然这里引入了时延,但是收发撞到一起的情况属于特殊情况,对于整体的性能影响不大。 修改后芯片down掉的问题得到解决: ```shel \ | / - RT - Thread Operating System / | \ 5.0.1 build Sep 9 2023 21:50:28 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 Advertising successfully started Connected HRS notifications enabled HRS notifications disabled Disconnected (reason 0x13) ```
0
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
paradox
这家伙很懒,什么也没写!
文章
7
回答
1
被采纳
0
关注TA
发私信
相关文章
1
rtthread小程序“WIFI配网助手”进行蓝牙连接失败
2
透传的BLE蓝牙模块解析
3
柿饼派能实现蓝牙配网吗
4
ab32的notify的内容如何修改?
5
RT-Thread对低功耗蓝牙的支持
6
请问蓝牙mesh开发中如何实现ble部分
7
未知的寄存器名“r3”
8
BSP/nrf52832已经具备BLE协议栈串口透传DEMO
9
nrf52832 softdevice添加出错
10
蓝牙sdk,与art-pi的板子来回数据;类似项目使用protobuf来传输数据,求助其他方式
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
机器人操作系统 (ROS2) 和 RT-Thread 通信
4
五分钟玩转RT-Thread新社区
5
国产MCU移植系列教程汇总,欢迎查看!
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
LWIP
Env
AT
SPI
Bootloader
FinSH
ART-Pi
CAN总线
Hardfault
USB
文件系统
RT-Thread
DMA
SCons
线程
MQTT
RT-Thread Nano
STM32
RTC
rt-smart
ESP8266
flash
ota在线升级
WIZnet_W5500
FAL
I2C
packages_软件包
UART
cubemx
freemodbus
潘多拉开发板_Pandora
定时器
BSP
PWM
ADC
socket
中断
rt_mq_消息队列_msg_queue
keil_MDK
SDIO
Debug
AB32VG1
MicroPython
编译报错
C++_cpp
msh
ulog
QEMU
本月问答贡献
出出啊
1501
个答案
338
次被采纳
小小李sunny
1390
个答案
276
次被采纳
张世争
715
个答案
157
次被采纳
crystal266
522
个答案
153
次被采纳
whj467467222
1216
个答案
146
次被采纳
本月文章贡献
出出啊
1
篇文章
12
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
2
篇文章
2
次点赞
crystal266
2
篇文章
5
次点赞
whj467467222
2
篇文章
1
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部