Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
蓝牙BLE
RTT平台 zephyr_polling软件包 SPI Bluenrg2芯片宕机问题与修复
发布于 2023-09-23 21:04:31 浏览:692
订阅该版
[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
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
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
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
DMA
USB
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
I2C_IIC
cubemx
UART
ESP8266
WIZnet_W5500
BSP
ota在线升级
PWM
flash
packages_软件包
freemodbus
潘多拉开发板_Pandora
ADC
GD32
定时器
编译报错
flashDB
keil_MDK
socket
中断
rt_mq_消息队列_msg_queue
Debug
ulog
SFUD
msh
C++_cpp
at_device
本月问答贡献
出出啊
1524
个答案
343
次被采纳
小小李sunny
1444
个答案
290
次被采纳
张世争
818
个答案
179
次被采纳
crystal266
555
个答案
162
次被采纳
whj467467222
1222
个答案
149
次被采纳
本月文章贡献
出出啊
1
篇文章
1
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
1
次点赞
crystal266
2
篇文章
1
次点赞
whj467467222
2
篇文章
1
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部