ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

3DR Radio固件定制:SiK源码编译与烧录实战指南

3DR Radio固件定制:SiK源码编译与烧录实战指南 简介面向无线通信与嵌入式开发者的3DR Radio固件源码包围绕Si1000、C8051F930和SI4432三颗芯片提供完整的433MHz低功耗数字传输电台实现。压缩包共82个文件含24个C头文件、18个C源文件、12个Python脚本、9个C#工程文件并附Makefile与hex固件整体约230KB目录分层清晰便于对照阅读与重新编译。已有1058人学习/下载。源码开放了射频前端配置、数据包封装与解封装、错误检测与纠正机制以及待机与工作模式下的功耗优化策略开发者可自由查看和修改协议参数也可将其中无线通信框架移植到其他Si1000或SI4432相关项目中。对想深入理解无线数传底层原理的初学者、或从事嵌入式低功耗通信开发的技术人员这套开源固件都能提供扎实的实战参考与二次开发基础。 拆开一块 3DR Radio 模块主板上那枚不起眼的 Si1000 芯片才是真正的主角。它把 8051 内核、射频收发前端和 Flash 全部封进一颗芯片里而你从网上拉下来的 3DR Radio 固件源码就是跑在这颗芯片上的整套裸机程序。很多人把 3DR Radio 当成一个用就完事的遥测外设插上线、配对、飞。但只要你愿意打开固件源码会发现这块模块的很多东西——默认波特率、发射功率、空中速率、信道中心频率、LED 指示逻辑——全部可以由你自己改。这篇就把我从源码阅读到编译烧录的完整过程整理出来给想折腾这套固件的朋友一条能走通的路。1. 固件源码到底值不值得啃先搞清楚 3DR Radio 是什么1.1 模块拆开后的物理真相3DR Radio 这个名字最早来自 3D Robotics 推出的开源遥测无线电模块最常用的版本是 433MHz 和 915MHz 两种。它做的是地面站和飞控之间的透明串口桥接你在地面站上看到的 MAVLink 数据流本质上就是这个模块把飞控 UART 收到的数据打包、发射另一端的模块接收后再从 UART 吐出来。模块的核心不是普通的射频收发芯片而是 Silicon Labs 的 Si1000 系列 SoC。这颗芯片很有意思它内部集成了一个 8051 内核C8051F930和一颗完整射频收发前端不需要外接 MCU。这套硬件方案决定了固件的形态它是一份跑在 8051 内核上的大而全的裸机程序没有操作系统没有线程只有一个大循环在不断检查串口和射频中断。1.2 开源固件的真正价值3DR Radio 的固件项目叫 SiK全称是 Si1000 Kernel开源在 GitHub 的 ArduPilot 组织下。这是整套系统最有价值的资产。你不需要依赖原厂的升级工具不需要逆向二进制指令直接拉源码就能定位到每一处行为。从源码角度看它能改的东西大致分三类通信参数串口波特率、空中波特率、发射功率、信道频率、心跳超时协议行为MAVLink 透传策略、包重传机制、流控逻辑硬件指示LED 闪烁模式、按钮行为、串口调试输出这三类改动覆盖了绝大多数使用场景。比如你想让模块默认以 115200 波特率连接飞控不用每次上电都手动 AT 指令直接在源码里改默认值一劳永逸。2. 源码骨架拆解从目录结构到一条数据包的完整旅程2.1 目录结构先看 boards 再谈其他把 SiK 仓库拉下来之后第一步别急着读代码先看目录结构。仓库里最值得关注的是boards/文件夹里面按硬件版本划分了板级目录例如原厂的 3dr_radio_v1、v2、v3以及 Pixhawk 定制版本。每个板级目录下都有board.h、board.mk这类文件它们决定了固件编译时用哪些引脚定义、哪些射频配置。这里有个容易忽略的点同一套 SiK 源码编译出来的固件烧到不同硬件版本上行为可能完全不一样。原因就在boards/目录里不同板子有不同board.h。所以拿到源码后先确认自己手头的模块是哪个硬件版本再进到对应的板级目录去读文件这个顺序不能反。2.2 数据流从飞控串口到空中再到地面站读完目录结构下一步是理解一条数据包在固件内部是怎么流动的。SiK 的代码虽然文件不少但主线其实非常清楚飞控把 MAVLink 字节流从 UART 送进模块8051 的 UART 中断逐字节把数据收进缓冲区。主循环检测到缓冲区里有完整数据帧就交给内部的打包逻辑把数据帧按 SiK 自定义的无线包格式封装。封装后的包通过 Si1000 的 RF 部分做 GFSK 调制后从天线发出去。接收端模块收到射频包做完整性校验通过后把有效负载从 UART 吐给地面站。这个过程里固件还穿插做了两件容易被忽视的事ACK 重传和管理帧解析。SiK 的无线链路是有确认机制的发送方如果没收到接收方的 ACK会按重传策略重发这保证了 MavLink 数据在无线链路上的可靠性。管理帧则是 AT 指令的基础你在串口终端里输入ATI能返回固件版本走的就是管理通道。读源码的时候可以顺着数据流去搜函数UART接收处理、射频发射函数、ACK 超时处理。把这几个点找到整个固件的脉络就基本清楚了。3. 编译工具链搭建 SiK 固件的构建环境3.1 工具链选择与安装细节编译 SiK 是目前体验最复古的一环因为它的官方构建流程依赖 Silicon Labs 自家的 IDE 和 Keil C51 编译器。这套工具链主要跑在 Windows 上步骤如下安装 Silicon Laboratories IDE旧版 IDE当前官网可能不好找需要从历史下载链接或社区存档获取安装 Keil C51 编译器注意 SiK 源码对 C51 的版本有一定要求实测较新版本也能编译但个别文件可能有差异打开 SiK 仓库里的工程文件后缀通常是.uvproj或.wsp确认工程引用的板级目录是自己的硬件版本设置编译优化选项8051 内核的 Flash 空间有限一般要开启较高优化等级才能把固件塞进去这套环境放在现在来说确实有点古董但 SiK 本来就是为这颗 8051 SoC 写的绕不开。Linux 环境下也有人用 SDCC 交叉编译但对 Si1000 这种特定芯片SDCC 的支持不如 Keil C51 成熟生成的代码体积和稳定性都可能出问题。我的建议是别在工具链上折腾替代方案老老实实用官方 IDE 编译。3.2 board.h 里的关键参数清单编译之前务必打开自己板级目录下的board.h逐项过一遍。下表的参数是我在实际使用中确认过对行为影响最直接的几个。参数/宏名称作用我的实测备注SERIAL_BAUDUART 串口速率决定模块和飞控/地面站之间的波特率两边必须一致AIR_BAUD空中射频波特率空中速率受带宽限制过高会导致接收灵敏度下降TXPOWER射频发射功率受硬件限制普通模块不建议直接拉满RADIO_CHANNEL射频信道中心频率一般出厂已设好修改需要谨慎考虑频段合规问题MAVLINK 相关宏决定是否开启 MAVLink 特化处理非 MAVLink 透传场景可以关闭节省资源我强烈建议在动任何代码之前先把原厂固件用 AT 指令读一遍当前参数ATI记录下原始配置再对照board.h里的宏定义这样能快速定位哪些参数在源码里、哪些参数运行时才能改。3.3 编译后的产物编译成功后会生成 hex 文件这个 hex 文件就是最终要烧进模块的固件。在烧录之前可以对 hex 文件做一次简单的代码体积检查看占用了多少 Flash。SiK 原厂固件的体积通常很紧凑如果你加入的改动明显增大了代码体积得警惕编译优化等级是否被调低了。4. 第一次真正修改固件以改串口波特率和发射功率为例4.1 改串口波特率最直观的上手实验要说哪个改动最能建立成就感一定是改默认串口波特率。很多人的需求是让模块默认就跑 115200省得每次用 AT 指令改。源码中修改位置在board.h里的串口速率定义。类似下面的代码#define SERIAL_BAUD 57600 // 原厂默认值 // 改为 #define SERIAL_BAUD 115200 // 你的目标波特率改完编译、烧录模块上电后默认就是 115200。这里有一个我踩过的坑改完波特率之后如果模块连接的是飞控飞控对应的SERIALx_BAUD参数也必须改成 115200否则两端波特率不一致地面站会看到大量的掉包和校验失败。这不是模块的问题是两端没有对齐。4.2 调整发射功率与空中速率发射功率是另一个高频改动点。原厂固件默认功率设置通常比较保守源码里搜索TXPOWER或者直接定位到射频参数初始化段可以找到类似这样的代码// 射频功率寄存器配置 radio_set_txpower(20); // 20 dBm约 100 mW如果你用的是普通版本模块没有外置功放我建议不要把功率调得高于硬件规格。因为 Si1000 内部的功放能力有限盲目拉高功率会导致射频输出饱和、信号反而变差而且芯片发热明显上升。如果你的模块是带 PA/LNA 的高功率版本功率设置逻辑在源码里通常是另一条分支需要额外关注 PA 的偏置和开关时序。空中速率的调整逻辑类似。空中速率越高单包传输时间越短但同时接收灵敏度下降通信距离会缩短。拿 433MHz 模块来说空中速率设在 57600 和设在 19200实际拉距表现差距非常明显。如果你需要远距离数传把空中速率降下来收益远大于盲目加功率。5. 烧录、变砖与自救bootloader 是最后的救命稻草5.1 bootloader 的作用与进入方式SiK 固件分两部分出厂固化在芯片里的 bootloader 和用户通过 bootloader 写入的 app 固件。bootloader 的作用是接收来自串口的固件数据并写入 Flash这样就不用每次升级都动用 JTAG/编程器。进入 bootloader 的方式在 3DR Radio 模块上一般有两种按住模块上的按钮后上电部分硬件版本有小按钮在 UART 空闲时通过工具发送特定字节或把 BOOT 引脚拉低后上电不同的硬件版本细节不同。我在实际使用中最稳的办法是查阅自己模块对应的板级目录里board.h中对 bootloader 引脚的注释或者直接查看 bootloader 源码中串口接收处理的逻辑确认进入条件。5.2 用 sik_uploader.py 烧录的完整流程SiK 仓库的tools/目录下提供了sik_uploader.py脚本这是最常用的烧录工具。在 Linux 下用 USB-TTL 接好模块在模块上电瞬间按对应方式进入 bootloader之后执行类似下面的命令python sik_uploader.py /dev/ttyUSB0 path/to/firmware.hex脚本会先通过串口和 bootloader 握手然后以固定波特率把 hex 文件逐块写入 Flash。整个过程大概几十秒期间不能断开串口连接也不能断电。这个工具还有一个很有用的参数查看 bootloader 版本。不同版本的 bootloader 对 app 固件的兼容性有差异如果你遇到烧录成功但模块无法正常启动的情况先确认 bootloader 版本和固件版本是否配套。5.3 变砖案例复盘我和一块黑屏模块的半小时分享一次真实翻车经历。有次我想把波特率改成 115200但脑子一热同时把空中速率也调高了还顺手改了一个信道参数。烧录后模块完全没有反应串口终端打 AT 无回显LED 也不闪。第一反应是砖了。冷静下来后的排查路径是这样的。首先把模块重新上电尝试进入 bootloader。因为 bootloader 是独立于 app 的只要 bootloader 没被破坏就能强制进入。按住按钮上电排查脚本能识别到 bootloader说明芯片没死。然后我重新烧回原厂固件模块立刻恢复正常。这个案例的结论很简单折腾 app 固件不会把模块折腾砖因为 bootloader 才是最后的安全网。真正让模块报废的操作是烧录中途断电或者把 bootloader 区域擦掉。所以我的建议是无论怎么改固件务必保留原厂 hex 备份并且不要手滑烧录任何覆盖 bootloader 的镜像。6. 从源码到日常使用折腾完固件之后的几点提醒6.1 版本匹配是最大的隐性成本3DR Radio 的硬件版本、bootloader 版本、固件版本、地面站参数这四个东西是相互牵制的。只改其中一个另外三个不一定兼容。比如给旧版硬件刷新版固件射频前端寄存器配置可能对不上表现为信号强度异常或者通信距离变短。我只踩过一次旧硬件配新固件的坑模块能配对但丢包率高得离谱最后查下来是固件里默认的射频前导码长度和旧硬件的匹配度不好。所以刷固件之前一定记录当前模块的ATI信息包括固件版本、bootloader 版本。这样出现异常时能快速回退。6.2 备份原厂固件这件事别偷懒很多人刷完自定义固件才想起来原厂固件没备份回头网上找又不一定找得到对应版本的 hex。正确做法是拿到模块的第一时间先读一遍ATI然后从源码仓库或社区固件库下载对应版本的 hex 存好。这几十秒的功夫能在后面省下几小时的折腾时间。6.3 自定义固件最适合的三种场景根据自己的经验我总结三个真正值得改源码的场景固定串口速率批量部署数传模块时避免每台设备都手动 AT 配置编译时写死目标波特率定制 LED 指示逻辑通过 LED 状态判断模块是处在配对状态、传输状态还是 bootloader 模式户外调试时非常有用精简协议处理如果只传输特定类型的数据可以在固件层过滤掉不关心包降低有效带宽占用这三类改动在源码里都能找到明确的切入点。顺着数据流找 UART 接收处理、射频发送、管理帧处理这几个位置把断点附近的逻辑改掉即可。6.4 频率参数源码里的东西更得谨慎源码编译的灵活性带来一个隐蔽风险你可以在代码里把中心频率改到任何 Si1000 支持的频点。但实际使用中频率参数必须符合当地无线电管理规定而且模块的硬件天线匹配是针对出厂频段设计的随意改频不仅可能违法实际辐射效率和接收灵敏度也会劣化。我的个人原则是信道参数在编译后不再动只通过运行时 AT 指令选择已通过合规性考虑的信道。最后再分享一个小技巧如果刷了自定义固件后模块连接不稳定先用串口终端连上模块输入ATI确认固件版本和参数再用ATF恢复默认参数排除运行时参数被改乱的可能。很多时候问题不在固件代码而在参数被不明不白地改过。固件源码给了你绝对的掌控力但掌控之前先学会记录和回退。本文还有配套的精品资源点击获取
返回列表