• 正文
  • 相关推荐
申请入驻 产业图谱

BlueNRG-LP/LPS 2.4GHz 私有无线电驱动全解析:从基础通信到 OTA 升级

05/25 14:30
294
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

物联网设备开发中,蓝牙低功耗 (BLE) 已经成为主流的无线通信技术。但在某些特定场景下,开发者需要更灵活的无线电控制能力,摆脱标准蓝牙链路层的限制。意法半导体 (ST) 为其 BlueNRG-LP 和 BlueNRG-LPS 系列芯片提供了一套完整的 2.4GHz 无线电私有驱动程序,允许开发者直接控制无线电硬件,实现自定义的无线通信协议。本文将深入解读 UM2726 应用笔记,全面介绍这套私有驱动的工作原理、使用方法和高级功能。

资料获取:【应用笔记】UM2726 BlueNRG-LP、BlueNRG-LPS 2.4 GHz 无线电私有驱动程序

1. 私有无线电驱动概述

BlueNRG-LP 和 BlueNRG-LPS 是意法半导体推出的高性能蓝牙低功耗系统级芯片,集成了 2.4GHz 无线电收发器和 ARM Cortex-M4F 内核。标准的蓝牙协议栈虽然功能完善,但在一些对实时性、功耗或协议自定义要求较高的应用中显得不够灵活。

私有无线电底层驱动程序正是为了解决这个问题而设计的。它提供了对无线电硬件的直接访问权限,使开发者能够在不使用蓝牙链路层的情况下发送和接收数据包。通过这套驱动,开发者可以完全控制数据包的各种特征,包括传输间隔、通道频率、数据长度、前导码格式等,从而实现自定义的无线通信协议。

这套驱动具有几个显著的优势:

  • 高度的灵活性:可以根据应用需求定制通信协议
  • 低延迟:绕过了蓝牙链路层的处理,减少了通信延迟
  • 低功耗:支持自主睡眠管理,无需处理器干预
  • 硬件加速:数据包加密、CRC 校验等功能由硬件自动完成
  • 状态机支持:最多可以管理 8 种不同的无线电配置

值得注意的是,本文档中的所有内容同时适用于 BlueNRG-LP 和 BlueNRG-LPS 两种芯片,除非特别说明两者的区别。

2. 无线电操作与数据包格式

2.1 无线电操作原理

BlueNRG-LP/LPS 的无线电底层驱动接口不仅控制 2.4GHz 无线电模块,还与 32kHz 唤醒定时器、RAM 存储器和处理器紧密协作。RAM 用于存储无线电设置、当前状态、接收数据和待发送数据。

驱动程序采用状态机机制,最多可以管理 8 种不同的无线电配置。这种设计允许开发者在不同的通信模式之间快速切换,而无需重新配置所有参数。

无线电模块本身具有很强的自主性,许多功能不需要处理器干预即可完成,包括数据包加密、通信定时和睡眠管理。这大大降低了处理器的负载,有助于延长设备的电池寿命。

2.2 数据包格式

私有驱动使用统一的数据包格式,由六个字段组成:前导码 (Preamble)、网络 ID (NetworkID)、头部 (Header)、长度 (Length)、数据 (Data) 和 CRC 校验。

前导码默认长度为 1 字节,但可以通过RADIO_SetPreambleRep()函数设置重复次数。前导码的作用是帮助接收器同步到发送器的时钟信号

网络 ID 是一个 4 字节的地址字段,用于标识通信网络。接收设备只会接受网络 ID 与自身地址匹配的数据包。为了确保通信的可靠性,网络 ID 需要满足一些特定的规则:

  • 连续的 0 或 1 不超过 6 个
  • 4 个字节不能全部相等
  • 转换次数不超过 24 次
  • 最高有效 6 位中至少有 2 个转换

头部字段长度为 1 字节,可以接受任何值。它通常用于标识数据包的类型或状态。需要注意的是,头部字段不会被加密。

长度字段表示数据字段的字节数。对于 BlueNRG-LP/LPS,最大有效负载长度为 255 字节。如果启用了加密功能,则需要减去 4 字节用于 MIC (消息完整性校验) 字段。

数据字段包含实际的有效载荷,长度由长度字段决定。只有数据字段会被加密。

CRC 校验字段长度为 3 字节,用于检测数据包在传输过程中是否损坏。CRC 的计算和校验由硬件自动完成,开发者可以配置 CRC 的初始值,但在广播通道中初始值固定为 0x555555。

3. 驱动框架与 API 架构

3.1 驱动文件结构

无线电底层驱动由四个核心文件组成:

  • rf_driver_ll_radio.hrf_driver_ll_radio.c:实现了底层的 LL 层 API
  • rf_driver_hal_radio.hrf_driver_hal_radio.c:在 LL 层之上提供了更简单的 HAL 层 API

这种分层设计使开发者可以根据自己的需求选择合适的抽象级别。对于简单的应用,HAL 层 API 足够使用;对于需要更精细控制的应用,可以直接使用 LL 层 API。

3.2 核心 API 功能

LL 层 API 提供了丰富的功能,可以控制无线电的各个方面:

  • 无线电初始化
  • 加密功能配置
  • 物理层设置 (1Mbps、2Mbps、S=2、S=8)
  • 通信信道管理
  • 网络 ID 和 CRC 初始值设置
  • 发射功率等级调整
  • 接收数据包最大长度和超时时间设置
  • 测试模式 (定频发送 tone)

大多数 API 修改的是特定状态机的参数,但也有一些参数是全局性的,对所有状态机都有效。例如,RADIO_SetGlobalReceiveTimeout()函数设置的接收超时时间就是全局的。

3.3 ActionPacket 数据结构

驱动程序的核心是 ActionPacket 数据结构,它定义了一个完整的传输或接收操作。ActionPacket 包含输入字段和输出字段:输入字段用于配置动作,输出字段用于保存执行结果。
ActionPacket 的主要字段包括:

  • StateMachineNo:指定使用哪个状态机 (0-7)
  • ActionTag:位掩码,用于启用不同的无线电特性
  • WakeupTime:动作执行的时间,可以是相对时间或绝对时间
  • next_truenext_false:指向条件判断后的下一个 ActionPacket
  • condRoutine:条件回调函数,决定下一个要执行的 ActionPacket
  • dataRoutine:数据回调函数,用于处理发送或接收的数据
  • data:指向数据缓冲区的指针
  • status:动作执行的状态信息
  • rssi:接收信号强度指示 (仅 RX)
  • timestamp_receive:数据包接收时间戳 (仅 RX)

ActionTag 是一个非常重要的字段,它通过位掩码的方式控制无线电的各种特性。例如,第 1 位 (TXRX) 决定是发送还是接收动作,第 5 位 (RELATIVE) 决定 WakeupTime 是相对时间还是绝对时间,第 0 位 (PLL_TRIG) 决定是否启用射频校准。

4. 两种应用开发方法

4.1 HAL 层方法:简单易用

对于大多数简单的应用场景,HAL 层方法是最佳选择。HAL 层提供了四个主要的 API 函数,覆盖了最常见的通信需求:

  • 发送一个数据包
  • 发送一个数据包并等待 ACK
  • 等待接收一个数据包
  • 接收一个数据包并回应 ACK

使用 HAL 层方法时,开发者不需要直接操作 ActionPacket 结构,只需要提供一个用户回调函数来处理通信结果。回调函数在中断模式下调用,具有最高的优先级。

每个 HAL API 的第二个参数是相对时间 (以微秒为单位),表示从调用 API 的那一刻起到无线电活动开始的延迟。这个延迟必须足够长,否则无法对无线电计时器进行编程,函数会返回错误代码。

文档中提供了一个简单的发送示例:无线电被编程为每 10 毫秒发送一个包含 3 字节数据的数据包。代码非常简洁,只需要初始化系统、配置无线电、设置网络 ID 和发射功率,然后在主循环中调用HAL_RADIO_SendPacket()函数即可。

接收示例也同样简单:无线电每 9 毫秒进入接收状态,接收超时设置为 20 毫秒。在回调函数中,可以检查接收状态,获取接收到的数据、RSSI 和时间戳。

4.2 ActionPacket 方法:灵活强大

对于需要更复杂通信逻辑的应用,ActionPacket 方法提供了最大的灵活性。开发者可以声明多个 ActionPacket 结构,然后将它们链接在一起,形成一个完整的状态机。

使用 ActionPacket 方法的步骤如下:

  1. 声明 ActionPacket 结构
  2. 填充结构的各个字段,配置动作参数
  3. 调用RADIO_SetReservedArea()初始化 ActionPacket
  4. 调用RADIO_MakeActionPacketPending()开始执行动作

ActionPacket 方法的强大之处在于它的条件分支机制。每个 ActionPacket 都有一个condRoutine回调函数,它根据当前动作的结果返回 TRUE 或 FALSE。根据返回值,驱动程序会自动执行next_truenext_false指向的下一个 ActionPacket。

这种机制允许开发者实现非常复杂的通信协议,例如带重传机制的可靠传输、自动跳频TDMA 时分多址等。

需要注意的是,condRoutine函数对时间要求非常严格,必须在 45 微秒内完成。这是因为无线电控制器在执行下一个动作之前需要等待条件判断的结果。如果condRoutine执行时间过长,会导致无线电操作失败。

相比之下,dataRoutine函数的时间限制要宽松得多,它可以用来处理接收到的数据或准备下一个要发送的数据。

5. 私有协议 OTA 固件升级

除了基本的通信功能外,私有驱动还提供了完整的 OTA (空中下载) 固件升级解决方案。这对于物联网设备来说是一个非常重要的功能,允许开发者在设备部署后远程更新固件。

5.1 OTA 系统架构

OTA 系统由两个角色组成:服务器和客户端。

  • 服务器:负责通过无线方式向客户端发送二进制固件镜像
  • 客户端:作为复位管理器,决定运行用户应用程序还是 OTA 客户端应用程序

OTA 客户端应用程序非常小巧,占用的 Flash 空间不到 8KB。它被放置在 Flash 存储器的前 5 页 (10KB),用户应用程序从 0x2800 地址开始。

5.2 OTA 通信协议

OTA 通信基于私有无线电驱动实现,使用自定义的数据包格式。服务器和客户端通过一系列状态转换来完成固件升级过程。

服务器状态机包括 6 个状态:

  • CONNECTION:发送连接数据包,等待客户端响应
  • SIZE:发送固件镜像大小
  • START:等待客户端的启动请求
  • DATAREQ:接收客户端的数据请求
  • SENDATA:发送请求的数据包
  • COMPLETE:固件传输完成

客户端状态机包括 8 个状态:

  • CONNECTION:接收连接数据包,发送 ACK 响应
  • SIZE:接收固件镜像大小
  • START:发送启动请求
  • NOTSTART:如果固件大小超过 Flash 容量,发送不启动请求
  • DATAREQ:向服务器请求特定的数据包
  • SENDATA:接收数据包
  • FLASHDATA:将接收到的数据写入 Flash
  • COMPLETE:固件升级完成

为了确保传输的可靠性,OTA 协议实现了重传机制。如果在单个状态下的重试次数超过了配置的最大值,OTA 操作会中止并重新开始。

5.3 OTA 升级流程

完整的 OTA 固件升级流程如下:

  1. 服务器通过 UART 接口使用 YMODEM 协议从 PC 接收固件镜像
  2. 服务器开始发送连接数据包,寻找客户端
  3. 客户端接收到连接数据包后发送 ACK 响应,建立连接
  4. 服务器向客户端发送固件镜像大小
  5. 客户端检查固件大小是否适合自己的 Flash,如果适合则发送启动请求
  6. 客户端向服务器请求数据包
  7. 服务器发送请求的数据包
  8. 客户端接收数据包并写入 Flash
  9. 重复步骤 6-8,直到所有数据包传输完成
  10. 固件升级完成,客户端跳转到新的应用程序

5.4 集成 OTA 客户端功能

将 OTA 客户端功能集成到现有应用程序中非常简单,只需要三个步骤:

  1. 为 OTA 客户端保留 Flash 存储器的前 5 页,设置链接器符号MEMORY_FLASH_APP_OFFSET=0x2800
  2. 在项目中包含radio_ota.cradio_ota.h文件
  3. 定义一个触发器 (例如按钮按下),调用OTA_Jump_To_Reset_Manager()函数跳转到 OTA 客户端

BlueNRG-LP/LPS 的 2.4GHz 无线电私有驱动程序为开发者提供了一个强大而灵活的平台,用于实现自定义的无线通信协议。无论是简单的点对点通信,还是复杂的多设备网络,这套驱动都能满足需求。

HAL 层方法简单易用,适合快速开发简单的应用;ActionPacket 方法则提供了最大的灵活性,允许开发者实现复杂的通信逻辑。此外,内置的 OTA 固件升级功能大大简化了设备的维护和更新过程。

对于那些对标准蓝牙协议栈不满意,或者需要更精细控制无线电硬件的开发者来说,BlueNRG-LP/LPS 的私有无线电驱动程序无疑是一个非常有价值的工具。它结合了意法半导体在低功耗无线通信领域的技术积累,为物联网应用提供了一个高性能、低功耗的解决方案。

相关推荐