当前位置: 首页 > news >正文

【从零开始】手写BLE协议栈(1-1)NRF 52 RADIO 相关机制

NRF 52 RADIO 相关机制

一、前言

这篇文章只有一个核心问题:一包数据是怎么从 RAM 飞到空气中的?

我们将以 00_phy_raw_tx 这个例程为主线,逐步拆解 nRF52 芯片的无线发送过程。在这个过程中你会遇到一些陌生的名词——外设寄存器、TASK、EVENT、SHORTS、PLL、GFSK、CRC……每遇到一个新概念,我们都会先停下来把它解释清楚,再继续往下看代码。

阅读本文不需要任何 Nordic 或射频的基础,只需要你会读 C 代码。

二、外设寄存器:用内存地址控制硬件

在我们正式开始之前,需要先搞清楚一件事:如何用 C 代码控制硬件电路

在普通的程序里,写一个变量 x = 1 只是把数字存到 RAM 里,对外界没有任何影响。但 nRF52 芯片里有一类特殊的内存地址,它们并不对应 RAM,而是直接连接到芯片内部的硬件电路。往这些地址写数据,就等于在操作硬件开关。这类地址就叫做外设寄存器(Peripheral Register)

nRF52 芯片内部有很多个"外设"模块——无线电、时钟、定时器、GPIO……每个外设都有自己的一组寄存器,分布在固定的内存地址段。Zephyr 提供了一个指针 NRF_RADIO,它直接指向 RADIO 外设的寄存器块起始地址。因此,写 NRF_RADIO->TASKS_TXEN = 1 就是往那个特定的硬件地址写入 1,触发无线电电路启动的物理动作。

特别需要注意的是:往外设寄存器写入 1 和往普通变量写入 1 在逻辑上完全不同。 前者触发的是一个不可逆的硬件事件,而非简单的数据存储。


三、TASK / EVENT:nRF 外设的统一编程模型

理解了寄存器是什么,我们来看 nRF 系列芯片的一个核心设计理念。

nRF 的所有外设都遵循同一套"命令与应答"模式,叫做 TASK / EVENT 模型。它的规则非常简单:

TASK(任务) 是你向硬件发出的命令。往某个 TASK 寄存器写 1,就等于按下一个按钮,命令外设执行对应的动作。写入后硬件立刻执行,寄存器本身没有持久意义。

EVENT(事件) 是硬件向你发出的通知。当外设完成某个动作或达到某个状态时,它会把对应的 EVENT 寄存器自动置 1,通知软件"某件事发生了"。

有一个非常重要的特性:EVENT 寄存器是"粘性"的(sticky)。硬件把它置 1 之后,它会一直保持 1,不会自动变回 0。即使硬件已经完成了那个动作、进入了下一个状态,EVENT 仍然保持 1。这意味着:软件必须手动向 EVENT 寄存器写 0 来清除它,否则下次读到的还是上次的残留 1,会造成误判。

用一张表格来总结:

类型 方向 操作 特点
TASK 软件 → 硬件 1 触发动作 写完即生效,无需清除
EVENT 硬件 → 软件 1 表示发生 粘性,必须手动写 0 清除

这套 TASK / EVENT 模型贯穿 nRF52 的全部外设设计。理解了这两个概念,就掌握了整个 nRF 外设编程的基础。


四、RADIO 状态机:射频电路不是一个简单的开关

有了 TASK / EVENT 的基础,我们来看 RADIO 外设本身。

射频发送电路并不是"按下去就发"这么简单。在发出任何数据之前,芯片内部的 PLL(锁相环)需要先"预热"——它要把 16 MHz 的参考时钟倍频到 2.4 GHz 的载波频率,这个过程需要约 40 微秒让频率稳定下来。只有频率锁定之后,真正的发送才能开始。

因此,RADIO 外设在内部维护了一个状态机,一次完整的发送要按顺序经历以下几个状态:
![[image-2.png]]

DISABLED│  ← TASKS_TXEN(软件命令:开始预热)↓
TXRU   (TX Ramp-Up,PLL 预热阶段,约 40 µs)│  ← EVENT_READY(硬件通知:PLL 锁相完成,可以发送了)↓
TXIDLE (等待发送指令,PLL 保持锁定)│  ← TASKS_START(软件命令:开始发射)↓
TX     (正在发射比特流:前导码 → 接入地址 → PDU → CRC)│  ← EVENT_END(硬件通知:最后一个 bit 发完了)↓
TXIDLE (返回等待状态,射频电路仍然开着!)│  ← TASKS_DISABLE(软件命令:关闭射频)↓
DISABLED (射频完全关闭,功耗降至最低)│  ← EVENT_DISABLED(硬件通知:已彻底关闭)

这里有一个容易踩坑的细节:发送完毕后,RADIO 会回到 TXIDLE 状态,而不是自动关闭。在 TXIDLE 状态下,PLL 和射频电路仍然耗电。如果应用程序不主动发送 TASKS_DISABLE,射频就会一直开着白白耗电。


五、用 TASK / EVENT 手动驱动一次发送

现在,我们可以把 TASK / EVENT 模型和 RADIO 状态机结合起来,用最直接的轮询方式写出一次完整的发送过程。

在这段代码里,CPU 是"全程陪同"的。它要主动查询每一个 EVENT,确认发生后再发出下一个 TASK,就像一个人站在机器旁边,盯着指示灯,等一盏灯亮了再按下一个按钮:

// 假设 RADIO 已通过 radio_configure() 完成了所有参数配置NRF_RADIO->TASKS_TXEN = 1;       // 命令:开始 TX Ramp-Up(PLL 预热)while (NRF_RADIO->EVENTS_READY == 0) { }   // 等待 PLL 锁定
NRF_RADIO->EVENTS_READY = 0;              // 清除粘性 EVENT(必须!)NRF_RADIO->TASKS_START = 1;      // 命令:开始发射while (NRF_RADIO->EVENTS_END == 0) { }    // 等待所有 bit 发完
NRF_RADIO->EVENTS_END = 0;               // 清除粘性 EVENTNRF_RADIO->TASKS_DISABLE = 1;    // 命令:关闭射频while (NRF_RADIO->EVENTS_DISABLED == 0) { }  // 等待彻底关闭

这段代码完全正确,也很直观。但它有一个根本性的缺陷:CPU 要参与每一个状态转换,在等待 EVENT 的过程中反复读寄存器、空转。在某些时序严格的场景下(后文会讲到),这种 CPU 介入会带来无法接受的时延抖动。

这就引出了 SHORTS 机制。


六、SHORTS:把 EVENT 和 TASK 用导线直连

SHORTS(Shortcuts,快捷方式)是 nRF 芯片的一种硬件内部连线机制。它的思路非常直接:

既然 EVENT 发生后通常总要触发某个 TASK,为什么不直接在硬件里把它们接一根线呢?

SHORTS 就是这样一组可配置的"内部短路"。当你在 NRF_RADIO->SHORTS 寄存器中使能某一个 bit,就等于在芯片内部把对应的 EVENT 输出线和 TASK 输入线用金属导线直连起来。EVENT 一旦触发,对应的 TASK 会在不到一个时钟周期(约 15.6 纳秒 @ 64 MHz)内自动执行,完全不经过 CPU 和中断控制器。

你可以想象成继电器:SHORTS 是一个继电器开关,EVENT 的触发就是给线圈通电,接触点(TASK)瞬间闭合。整个过程是纯电气的,不需要有人在旁边操作。

NRF_RADIO->SHORTS 寄存器的每个 bit 代表一条可开启的"快捷路径":

Bit 宏定义 连接的 EVENT → TASK
0 RADIO_SHORTS_READY_START_Msk EVENT_READY → TASKS_START
1 RADIO_SHORTS_END_DISABLE_Msk EVENT_END → TASKS_DISABLE
2 RADIO_SHORTS_DISABLED_TXEN_Msk EVENT_DISABLED → TASKS_TXEN
3 RADIO_SHORTS_DISABLED_RXEN_Msk EVENT_DISABLED → TASKS_RXEN
5 RADIO_SHORTS_END_START_Msk EVENT_END → TASKS_START

00_phy_raw_tx 例程中,我们只使用了其中两条:

NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Msk |RADIO_SHORTS_END_DISABLE_Msk;

第一条的意思是:PLL 锁定完成(EVENT_READY)时,立刻自动开始发射(TASKS_START)。
第二条的意思是:数据发完(EVENT_END)时,立刻自动关闭射频(TASKS_DISABLE)。

有了这两条 SHORTS,整个发送流程就变成了这样:

软件写 NRF_RADIO->TASKS_TXEN = 1│↓  [TXRU,PLL 预热 ~40µs,硬件自动进行]││  EVENT_READY 触发│  ──[SHORTS 导线]──→ TASKS_START(自动!无需 CPU)↓[TX,正在发射,~240µs]││  EVENT_END 触发│  ──[SHORTS 导线]──→ TASKS_DISABLE(自动!无需 CPU)↓[DISABLED,射频关闭]││  EVENT_DISABLED 置 1↓
软件检查 radio_has_disabled() == true,得知完成

CPU 只做了两件事:最开始写一个寄存器,最后读一个标志。中间所有的状态转换全部由硬件自主完成,精确到纳秒,不受 CPU 负载、中断延迟的任何影响。

七、SHORTS 与 PPI 的关系

SHORTS 是外设内部的快捷路径,只能连接同一个外设内的 EVENT 和 TASK。如果需要让一个外设的 EVENT 触发另一个外设的 TASK,就要用到 PPI(Programmable Peripheral Interconnect,可编程外设互联)

PPI 是 nRF52 芯片级别的"事件总线",类似于一个可配置的交叉开关:你可以把任意外设的任意 EVENT 输出(EEP)连接到任意外设的任意 TASK 输入(TEP),实现跨外设的自动联动。

特性 SHORTS PPI
连接范围 同一外设内部 任意两个外设之间
配置方式 单个寄存器的 bit 通道寄存器(EEP/TEP 寄存器对)
典型用途 RADIO 状态机内部跳转 RADIO 触发 TIMER,TIMER 触发 RADIO
延迟 < 1 个时钟周期 1~2 个时钟周期

在完整的 BLE Controller 实现中,SHORTS、PPI 和 TIMER 三者配合构成时序控制的核心架构:TIMER 精确计量 T_IFS,超时后通过 PPI 触发 RADIO 的 TASKS_DISABLE;RADIO 通过 PPI 触发 TIMER 的 CAPTURE,记录收到接入地址的精确时刻。三者各司其职,全程不依赖 CPU。


八、总结

通过 00_phy_raw_tx 例程,我们从寄存器层面完整走了一遍"数据从 RAM 到空气"的全流程:

概念 核心要点
外设寄存器 特定内存地址直接控制硬件电路,写入即触发动作
TASK / EVENT TASK = 向硬件发命令;EVENT = 硬件发来通知,粘性,要手动清除
RADIO 状态机 DISABLED → TXRU → TXIDLE → TX → TXIDLE → DISABLED,每步都需要 TASK 驱动
HFXO 射频工作的时钟前提,RC 振荡器精度不足,必须用外部晶振
SHORTS 在外设内部将 EVENT 输出与 TASK 输入硬件直连,纳秒级响应,不经过 CPU
包格式引擎 PCNF0/PCNF1 定义 DMA 读取格式,Preamble、AA、CRC 全部硬件自动生成
数据白化 LFSR 消除长串连续 0/1,保证接收方时钟恢复正常工作

参考资料:

  • nRF52832 Product Specification v1.6 — Chapter 6.20 RADIO
  • Bluetooth Core Specification 5.3 — Vol 6, Part B(LE Air Interface)
  • Zephyr RTOS BLE Controller 源码:subsys/bluetooth/controller/
http://www.jsqmd.com/news/544155/

相关文章:

  • 2026年推荐侧按轻触开关口碑排行榜,韩荣电子靠谱吗 - 工业品牌热点
  • GitHub Desktop 中文本地化工具:让 Git 操作更简单的全流程指南
  • 说说美团品牌通,它能为深圳企业带来什么效果,靠谱吗 - 工业品网
  • React Router终极性能优化指南:5个技巧大幅减少包大小和提升加载速度
  • 双叶家具联系方式查询指南:如何在大同地区通过正规渠道联系品牌服务商并了解选购注意事项 - 品牌推荐
  • 20|反幻觉策略:引用、可执行验证、拒答与降级
  • HP-Socket开源项目赞助合作提案回复模板:如何专业地接受与拒绝赞助请求
  • 2026年绍兴适合男性的西点培训选购攻略,老牌品牌排名 - 工业设备
  • 告别官网下载慢!MSP430开发环境(CCS+MSPWare)国内镜像与离线包快速部署攻略
  • 双叶家具联系方式查询:关于实木家具选购与大同地区门店服务的几点通用指南 - 品牌推荐
  • 2026年河南geo优化公司Top10,正规资质厂家口碑如何 - 工业推荐榜
  • 终极设计模式指南:如何通过容器调度优化提升系统性能
  • MiniSat:高效SAT求解器的技术解析与实践指南
  • springboot框架教师科研项目管理系统可视化
  • Linux RTC子系统深度实战:基于RK3568的闹钟功能实现与稳定性优化
  • LFM2.5-1.2B-Thinking-GGUF惊艳效果:32K上下文内跨10页PDF核心信息定位
  • 梳理2026年玻璃刀定制厂家,口碑不错的玻璃刀资深厂商推荐 - mypinpai
  • Odoo时间跟踪终极指南:10个技巧提升员工生产力300%
  • Java大厂面试实录:电商高并发场景下的Spring Boot+Redis+Kafka技术栈深度解析
  • 新手蓝队入门:用D盾和日志分析,手把手复现知攻善防Web靶场应急响应
  • 2025年-2026年空调计费厂家十大品牌推荐:基于动态分析模型的客观对比与实用排行 - 品牌推荐
  • OpenClaw语音交互:ollama-QwQ-32B模型接入Whisper实现全语音控制
  • OpenClaw异常处理:QwQ-32B任务中断的自动恢复方案
  • MVC / MVVM 在web前端开发中怎么理解(Vue 3 是“最接近 MVVM 思想”的前端框架之一)
  • 一键部署LiuJuan风格生成器:Xinference服务搭建完整指南
  • 终极解决方案:超纯水系统终极选购指南:甄别高品质、高性能、好信誉的制造商与供应商 - 品牌推荐大师
  • OpenClaw代码审查:Qwen3-VL:30B分析GitHub PR截图提改进建议
  • 2026年太原高考复读学校深度盘点:选对适合自己的,提分才顺利 - 华Sir1
  • 结构仿真全流程服务 - 品牌2026
  • 寻找“最大的ComfyUI平台”:看StableDiffusion如何跨越硬件鸿沟走向云端 - 资讯焦点