Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
SPI
蓝牙BLE
RTT平台 zephyr_polling软件包 BLUENRG2 蓝牙芯片 SPI 接口开发
发布于 2023-09-23 22:56:00 浏览:617
订阅该版
[tocm] # BLUENRG2 蓝牙芯片 SPI 接口开发 >“开源之夏”“蓝牙HOST协议栈zephyr_polling完善” 项目个人记录 菜鸡参与项目的个人记录 项目软件包地址:[RTT_PACKAGE_zephyr_polling](https://github.com/bobwenstudy/RTT_PACKAGE_zephyr_polling) ## BLUENRG2 BlueNRG-2是一颗具有超低功耗蓝牙BLE的SoC单芯片,符合Bluetooth标准规范,同时带有SPI, UART, I2C等标准外设通讯接口。 [bluenrg2官方页面](https://www.st.com/zh/wireless-connectivity/bluenrg-2.html),可以在这里找到芯片的详细规格参数。[芯片的文档中心](https://www.st.com/zh/wireless-connectivity/bluenrg-2.html#documentation)。 [Bluenrg芯片介绍](https://blog.csdn.net/wenbo13579/article/details/131210272?spm=1001.2014.3001.5502) [bluenrg-2n](https://www.st.com/zh/wireless-connectivity/bluenrg-2n.html#documentation)文档 实际使用的BLE模块:[x-nucleo-bnrg2a1](https://www.st.com/en/ecosystems/x-nucleo-bnrg2a1.html#documentation), 对应的[接口说明](https://www.st.com/resource/en/design_tip/dm00547290-how-to-configure-the-bluenrg1-and-bluenrg2-devices-in-network-coprocessor-mode-stmicroelectronics.pdf)。[模块固件烧录说明](https://www.st.com/resource/en/application_note/an5651-update-procedure-and-configuration-in-dtm-firmware-for-xnucleobnrg2a1-stmicroelectronics.pdf) ## BLUENRG2 的 SPI 通信流程 从ST官网给出的文档,先了解通信的流程: 在[数据手册](https://www.st.com/zh/wireless-connectivity/bluenrg-2n.html)中,查阅到芯片的 SPI 参数如下: ![2023-08-24 215759.png](https://oss-club.rt-thread.org/uploads/20230923/ce6b647e53ba7118551ada77e6b885c6.png.webp) ![2023-09-22-20-51-36.png](https://oss-club.rt-thread.org/uploads/20230923/b4bb37736b287c044952e0eb728efee4.png.webp) 所以应该设定SPI波特率1MHz,CPOL为0,CPHA为1。controller 通过 CS_PIN 唤醒BLUENRG-2N,并进行传输;而 BLUENRG-2N 通过 IRQ_PIN 通知 uC 有传输事务。 SPI 通信的时序: ![2023-09-22-21-03-01.png](https://oss-club.rt-thread.org/uploads/20230923/12148892dd6bf13eeaf098b6d60765d6.png.webp) ![2023-09-22-21-03-39.png](https://oss-club.rt-thread.org/uploads/20230923/639654ead5c760fc046ecf0ea97e27c0.png.webp) ![2023-09-22-21-04-32.png](https://oss-club.rt-thread.org/uploads/20230923/2dc75810e250f3f40003245615ea29b9.png.webp) 主要涉及以下关键点: - SPI 事务由 CS 信号的下降沿到下一个 CS 信号的上升沿决定。每个 SPI 事务必须只包含一个数据帧。每个数据帧应该包含至少5个字节的报头,并且可以包含 0 到 N 个字节的数据。 - IRQ 信号显示着当前 BlueNRG-2N 的状态,发送时 IRQ 拉高标识 BlueNRG-2N 已准备就绪;接收时 IRQ 拉高标识 BlueNRG-2N 有待传数据。 - CS 下降沿到 IRQ 上升沿的时间根据 BlueNRG-2N 的状态变化,包括唤醒 BlueNRG-2N 和准备帧的报头部分等花的时间。 - 报头由一个控制字节(CTRL)和四个字节的 0x00 组成。CTRL 字段只能为 0x0A (SPI写)或0x0B (SPI读)。当 BlueNRG-2N 拉高 SPI IRQ信号时,返回的报头数据就准备好了,否则,BlueNRG-2N 并未初始化好。外部 uC 必须等待 IRQ 线变高,进行一次 5 字节的传输。 - 报头中 WBUF 和 RBUF 的端序是 LSB 优先。WBUF 中的值表示主机可以向 BlueNRG-2N 写入多少字节。RBUF 中的值表示有多少字节在 BlueNRG-2N 中等待外部 uC 读取 - 外部 uC必须等待 IRQ 降低,然后再升高 CS 信号以标志通信结束。 简而言之,通信的流程: - 外部 uC 发 BLUENRG-2N 收: - CS 拉低,唤醒 BLUENRG-2N。等待 IRQ 拉高之后, 外部 uC 向 BLUENRG-2N 传输一个 5 bytes 的 header(起头为 0x0A 的 CTRL,后四字节为 0x00)。此时 BLUENRG-2N 发来的 5 bytes 依次是一字节的 DUMMY head,两字节的写入缓存区大小(WBUFF),两字节的读取区缓存大小(RBUFF)。 - 外部 uC 根据读取到的写入缓存区大小,经过判断后,开始传输数据。 - 传输完成后等待 IRQ 拉低(如果此时还没有拉低),最后拉高 CS 结束通信。 - 外部 uC 收 BLUENRG-2N 发: - IRQ 拉高,等待 CS 拉低之后,传输一个 5 bytes 的 header(起头为 0x0B 的 CTRL,后四字节为 0x00),外部 uC 从 BLUENRG-2N 处获取缓冲区大小信息。 - 外部 uC 根据读取到的读取缓存区大小,经过判断后,开始传输数据。 - 传输完成后等待 IRQ 拉低(如果此时还没有拉低),最后拉高 CS 结束通信。 SPI 状态机: ![2023-09-22-21-05-38.png](https://oss-club.rt-thread.org/uploads/20230923/cde33282df9fde3f78a2bf89658792f7.png.webp) ![2023-09-22-21-06-53.png](https://oss-club.rt-thread.org/uploads/20230923/1d60147eea3b72fb821d7830d988accf.png.webp) ## HCI 包 Host 和 Controller 通过 HCI 接口进行通信。HCI协议本身只有5种接口。包括Command、Event、ACL、SCO以及ISO接口。BLE只支持Command、Event、ACL和ISO数据通道。 在Sig提供的 [Core Spec5.3](https://www.bluetooth.com/specifications/specs/core-specification-5-3/) 中的第四节中对 HCI 层有详细说明,重点说明了各个通道的包格式以及HCI command和events。 ST 官方也给出了[BlueNRG-2N 的 ACI 命令格式](https://www.st.com/resource/en/user_manual/um2805-the-bluenrg2n-aci-command-data-format-stmicroelectronics.pdf), - HCI 命令包 当外部设备向 BlueNRG-2N 发送命令时,该命令必须以 HCI command的格式发送。BlueNRG-2N 只接收 HCI 命令报文,不发送。 ![2023-09-22-21-50-47.png](https://oss-club.rt-thread.org/uploads/20230923/81ace3a8bb2cab66d37d432ebed7091b.png.webp) - 每个 HCI 命令包使用一个 2 字节的 OpCode 来唯一标识不同类型的命令。OpCode分为两个字段: OpCode 组字段(OGF) 和 OpCode 命令字段(OCF)。OpCode 的高6位是 OGF,低 10 位是 OCF。 - 根据OGF的不同,这些命令可以分为3组: 1. 标准 HCI 命令: OGF 值不是 0x3F 的命令。这些命令是为控制器设计的。蓝牙规范中明确定义了所有标准HCI命令。 2. 厂商特定的(VS) HCI 命令: OGF 值为 0x3F 的命令,这些命令也是为控制器设计的。每个厂商都可以根据硬件实现定义自己的VS命令。 3. 厂商特定的(VS) ACI 命令: 也具有OGF值0x3F,但是这些命令为控制/访问主机而设计。蓝牙规范没有为主机定义任何命令,因此所有 ACI 命令都是由供应商设定的。 - 为了区分,用于控制控制器的命令称为 HCI 命令,用来控制主机的命令称为ACI命令。但是,ACI 和 HCI 命令都是通过 ACI 接口从外部设备接收的命令,并且有着相同的数据格式,其实并不需要区分二者。因为实际上,无论是HCI还是ACI命令,都对应着特定的唯一的 OpCode 值。 - 蓝牙规范对 OpCode 使用 LSB 序格式。 - HCI 事件包 BlueNRG-2N使用事件包来确认命令或通知其状态已更新到用户应用程序。BlueNRG-2N只发送HCI事件报文,不接收HCI事件报文。 ![2023-09-22-22-15-32.png](https://oss-club.rt-thread.org/uploads/20230923/97b9aee3d5798ab1416fcf6d6f3e88ff.png) - HCI ACL 数据包 用于数据传输。 ![2023-09-22-22-04-12.png](https://oss-club.rt-thread.org/uploads/20230923/f1b1fd994cb95738daed2599b0300da3.png) - 厂商特定的(VS)命令包 BlueNRG-2N 的 Vendor specific (VS) commands 的 OpCode 的 OCF 字段进一步分为两个字段: 3 位 CGID (Command Group ID) 和 7位 CID (Command ID)。 ![2023-09-22-22-09-57.png](https://oss-club.rt-thread.org/uploads/20230923/87dc99cb428d624e8203e36f1d315f7b.png.webp) - CGID 被 BlueNRG-2N ACI 接口用来将命令路由到不同的逻辑层,例如: cap、GAP、GATT等。它还有助于用更清晰的结构对 VS 命令进行分类。 - CID 决定了每条命令的 ID。每个CGID组最多可以有 128 个 VS 命令。 ![2023-09-22-22-31-57.png](https://oss-club.rt-thread.org/uploads/20230923/88f26893e8b90d80308ff35357bc9383.png.webp) - 厂商特定的(VS)事件包 VS event 的格式也与标准 HCI event 略有不同: - VS事件的8位事件码始终为0xFF值 - 16位的事件 parameter 0 (参数0是 HCI 事件报文中继参数长度字段之后的第一个返回参数) 有不同的格式。 ![2023-09-22-22-34-30.png](https://oss-club.rt-thread.org/uploads/20230923/9f06dd2d21f5db7d9c5b0d50ffe60917.png) parameter 0 的两个字节被定义为 BlueNRG-2N 事件码(ECODE)。ECODE 进一步分为两段:事件组 ID (EGIO) 和 事件ID (EID)。 BlueNRG-2N 使用 EGID 将事件组合成逻辑组。EID 用于指定组中的事件。EGID 占 ECODE 字段的6位,EID 占剩余的10位。 ## bluenrg1-dk 软件 官方给出的 [bluenrg-dk 软件](https://www.st.com/en/embedded-software/stsw-bluenrg1-dk.html#overview),本身是提供 bluenrg1、bluenrg2 的演示、例程等。它的文件目录包含了一系列相关文档的目录,相对于在官网上找,其文档访问更加遍历。此外,虽然它使用的开发板是特定的,但仍然可以借鉴里面的代码。 `BlueNRG-1_2 DK 3.2.3\Docs\index.html`: ![2023-09-22-22-54-53.png](https://oss-club.rt-thread.org/uploads/20230923/1a1a26943811a4c017596161363780ca.png.webp) 其中`SDK & HAL drivers documentation` 可以方便的打开借鉴代码,`BlueNRG-1,2 Network Coprocessor (SPI & UART mode)`可以方便的查看接口的文档。 ## HAL 库下的 SPI 通信实现 先计划直接在 CubeIDE 创建的 NUCLEO-L476RG 工程中实现与 BlueNRG2 的通信。 测试发送最简单的 HCI command: reset 命令包。 - 发送:reset包为`01:03:0c:00`。其中 `01` 标识其为 HCI command 包,`030c`是它的 OpCode,`00` 表示长度为0(因为没有别的内容了)。 - 接收:应当接收到来自芯片的成功事件包。查询 [Core Spec v5.3](https://www.bluetooth.com/specifications/specs/core-specification-5-3/), 可以得到命令接收的成功事件包应为`04:0e:04:01:03:0c:00`。其中事件包标头为`04`, 命令完成的 Event code 是`0e`, 参数载荷为成功的 reset 命令`01030c00`, 所以后续参数参数长度为 `04`。 实际的实现借鉴了官方给出的代码。这中间的过程因为我个人太菜,波折很多,不堪回首,略过了。 值得注意的是,官方的代码对于外部 uC (host) 收 BLUENRG-2N (controller) 发的情况,是由 BLUENRG-2N 拉高 IRQ 发起 STM32 的外部中断,然后等待 CS 拉低之后开始接收事务。但这里最后需要移植到 zephyr_polling 软件包中,而那边为了节省资源占用采用的是轮询方式,所以这里的 SPI 也要采用轮询的方式。 考虑采用的方案就是外部 uC 轮询拉高 CS,进入等待(超时则拉低 CS 然后返回),若 IRQ 拉高则发送接收的 header (0x0B), 根据缓冲区大小判断 BLUENRG-2N 是否有待传数据。这样做的话,接收行为的时序会与手册中给出的不相同,但实测是可用的。 >记录: BLUENRG-2N 会时不时向 host 的发送类似 `04:ff:03:01:00:04` 的包,是一个VS事件包,猜测是类似心跳包的事件。开发过程中给我带来了不小的麻烦(特别当时我对VS厂商包还没了解),我等着收`04:0e:04:01:03:0c:00`啊,来一堆这个影响判断。 >发送 header 之后得到的缓冲区大小因为是 LSB 需要注意取大小值的位运算方式。 >需要特别注意 SPI 通信对信号时序的要求。一定要注意 CS 和 IRQ 两个信号线的检测和控制,必须要加入等待机制和超时机制,包括传输前的等待 IRQ 拉起,传输后的等待 IRQ 拉低。 最后测试发送 reset 能收到正确的成功响应,完成了 HAL 库下的实现。 ## RTT 下的 SPI 通信实现 RTT 下的 SPI 通信实现首先是搭建 RTT 环境,了解运行机制等一系列工作,这里略过。 在 RTT 中 SPI 设备的使用有很详尽的[文档介绍](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/device/spi/spi?id=spi-%e7%ae%80%e4%bb%8b),按照文档将 HAL 库的 PIN、SPI 实现替换即可,包括两个 GPIO 引脚的配置,SPI 设备的挂载、配置。其中 GPIO 引脚的配置要注意平台通用性,不要用 stm32 特有的定义方式;SPI 注意按实际修改工程中 board 目录下的 SPI 引脚。 >这里的教训就是看文档要仔细。一开始做的时候看到有个`rt_spi_send_then_recv()`(嗯,收发是吧),就直接用了。这导致代码移植到 RT Studio 工程里的时候不能正常使用。而更致命的是当时手里没有逻辑分析仪,找问题也不方便,浪费了很多时间找原因。直到之后买了逻辑分析仪才发现这个函数是收一次完成之后再发送一次,应该使用的是双工的`rt_spi_transfer()`。 RT-thread 下的 SPI 通信实现也波折不少。最后的 [SPI 代码](https://github.com/bobwenstudy/RTT_PACKAGE_zephyr_polling/blob/main/platform/rtthread/rtthread_driver_spi.c)。 > 再记录一下:买的这个逻辑分析仪是个便宜货,信号引脚的电平和阻抗特性不太理想,接上去时不时让读到的传输数据变成乱的,并导致芯片运行出现异常,需要把硬件整个断电重启才能正常。这一开始是带来了困惑(这发的啥啊)。在发现这个东西的问题之后,是只能每使用一次,就断电重启 ,凑合着用。 之后芯片的事件包 ![2023-09-23-17-12-20.png](https://oss-club.rt-thread.org/uploads/20230923/f7ba7d10c294ad25963bbd34834ed1e2.png.webp) 返回的 `04:0f:04:01:01:03:0c`,查询[Core Spec v5.3](https://www.bluetooth.com/specifications/specs/core-specification-5-3/)之后,判断应该是逻辑分析仪导致芯片出错了。 ![2023-09-23-17-16-10.png](https://oss-club.rt-thread.org/uploads/20230923/a2be66a87228ebddd75738c1479c6b0f.png.webp) ![2023-09-23-17-14-16.png](https://oss-club.rt-thread.org/uploads/20230923/a561fbc5753a0619b9907e18f075a7bf.png.webp) ## 芯片宕机问题与修复 SPI 通信实现之后,还需要将其移植到 [zephyr_polling](https://github.com/bobwenstudy/zephyr_polling)中,这里又是一系列的对项目代码的阅读、实践和debug,中间还包括 BlueNRG-2N 芯片启动流程的实现 ,这里略过。 但最后收尾的时候,还出现了 SPI 收发导致的[芯片宕机问题](https://club.rt-thread.org/ask/article/c32ccbd9a4584ce2.html)。
0
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
paradox
这家伙很懒,什么也没写!
文章
7
回答
1
被采纳
0
关注TA
发私信
相关文章
1
BBB的SPI驱动
2
求个SPI上挂两个或多个设备的使用例子
3
SPI设备有个bug
4
spi flash 的fatfs使用一段时间后读写文件出现故障
5
SPI驱动
6
请教rt_spi_configure函数理解
7
SPI FLASH挂载的问题
8
SPI-FLASH 文件系统 SPIFFS
9
求助一个完整的 spi flash 驱动
10
关于同时使用文件系统与SPI FLASH的问题
推荐文章
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
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
I2C_IIC
ESP8266
UART
WIZnet_W5500
ota在线升级
PWM
cubemx
flash
freemodbus
BSP
packages_软件包
潘多拉开发板_Pandora
定时器
ADC
flashDB
GD32
socket
编译报错
中断
Debug
rt_mq_消息队列_msg_queue
SFUD
msh
keil_MDK
ulog
C++_cpp
MicroPython
本月问答贡献
xusiwei1236
8
个答案
2
次被采纳
踩姑娘的小蘑菇
1
个答案
2
次被采纳
用户名由3_15位
7
个答案
1
次被采纳
bernard
4
个答案
1
次被采纳
RTT_逍遥
3
个答案
1
次被采纳
本月文章贡献
聚散无由
2
篇文章
15
次点赞
catcatbing
2
篇文章
5
次点赞
Wade
2
篇文章
4
次点赞
Ghost_Girls
1
篇文章
6
次点赞
YZRD
1
篇文章
2
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部