简介:openwifi 是一套基于软件定义无线电的完整开源 802.11/Wi-Fi 全栈设计,面向 FPGA、嵌入式 Linux 与无线通信开发者。方案将 mac80211 兼容驱动、AD9361 射频前端、DMA 与 FPGA 侧 OFDM/CSMA/CA 低 MAC 层打通,支持 802.11a/g/n、20 MHz 带宽、70 MHz 至 6 GHz 频率范围,并提供 STA/AP/Ad-hoc/监控模式、CSI 信道状态信息、IQ 捕获及可配置信道接入参数,适合学习基带信号处理、软硬件协同与 SDR 实现。资源包共 140 个文件,约 8.7 MB,以 C 源码、头文件、Shell/Makefile 构建脚本、设备树文件、Markdown 文档和图片为主,涵盖驱动、FPGA 工程、内核配置与运行验证素材,便于按模块查阅。源码在 PHY 与 MAC 分层、软硬件接口上提供了较完整的参考路径,能帮助读者观察从射频采样、OFDM 调制解调到 CSMA/CA 竞争接入、Linux 协议栈交互的整条数据通路。目前已有 3399 人学习下载,适合具备一定 Verilog、Zynq 或 Linux 驱动基础的开发者作为开源工程参考,可用于源码阅读与二次开发,结合代码与文档快速搭建实验环境,深入理解 Wi-Fi 基带到上位机的实现细节。
1. 为什么有人要把Wi-Fi基带芯片开源
做通信或者说做FPGA的朋友,应该都遇到过这种尴尬:想在实验室里研究一下真实的Wi-Fi信号,拿现成的路由器吧,黑盒子一个,里面怎么调制、怎么编码、怎么处理干扰完全看不到;想自己用FPGA搭一套吧,802.11的协议栈又厚又复杂,光OFDM调制和MAC层调度就够写几个月。
openwifi这个项目解决的正是这个问题。它是一个基于FPGA的、开源的IEEE 802.11物理层和MAC层实现,官方定位是软件无线电(SDR)平台。意味着你拿到的不是一段仿真代码,而是一套能跑在真实硬件上、能发出真实Wi-Fi信号、能被普通手机和电脑搜到并连接的开源基带芯片实现。
项目的主要载体是Xilinx Zynq系列SoC,配合ADI的AD9361射频前端,用Verilog实现PHY层和一部分MAC层逻辑,用ARM核运行Linux和上层协议栈。开源范围覆盖了硬件代码、FPGA工程、驱动、Linux补丁和上位机工具,基本可以看作一整套可复现的Wi-Fi基带芯片参考设计。
这个项目对三类人特别有价值。第一类是通信方向的研究生,想在真实信道上验证新的调制方式或MAC算法,openwifi提供了完整的实验平台;第二类是FPGA工程师,想了解OFDM收发通路的工程实现,openwifi的代码是很好的学习范本;第三类是做测试仪器或专用无线链路的人,需要一套可控的、可定制的基带方案,openwifi比从头写省太多事。
我自己折腾过一段时间,从源码阅读到上板实测,最大的感受是:这项目把“Wi-Fi基带芯片”从概念变成了可以摸到的东西,而且代码质量比很多商业IP还要清爽。
2. 整体架构与设计思路拆解
2.1 硬件平台为什么选Zynq加AD9361
openwifi的硬件方案非常明确:PS侧跑Linux,PL侧跑基带逻辑,AD9361负责射频收发。Zynq的ARM核和FPGA逻辑天然就在同一颗芯片里,ARM和PL之间通过AXI总线高速通信,这个架构对SDR来说几乎是最优解。
AD9361是一个收发一体的射频前端芯片,覆盖70MHz到6GHz频段,带宽最大56MHz,支持2x2 MIMO。对接下来就是掉进寄存器地狱,但openwifi做了完整的Linux驱动封装,你只需要通过标准的无线网卡接口去使用,FPGA和射频之间的IQ数据通路也被打磨得很顺。选这两个芯片组合,不是因为它们最便宜,而是因为生态成熟、参考资料多,踩坑成本低。
2.2 软硬件划分:PL做基带,PS跑协议栈
看openwifi的代码目录,最直观的感受是它把802.11协议切开了一条清晰的边界。PL侧实现的是PHY层和MAC下层的硬实时部分:帧检测、自动增益控制、OFDM调制解调、前向纠错编码、时间和频率同步、MAC帧的收发队列管理。这些功能有一个共性,就是延迟敏感、计算量大,放到软件里跑会浪费大量CPU周期,而且时序不好保证。
ARM侧跑的是真正“智能”的部分:Linux内核的mac80211子系统、cfg80211、hostapd等。以管理帧和信标帧为例,这些帧需要按协议定时发送,但频率不高,ARM侧完全可以处理。数据帧的payload也由ARM整理好之后,通过DMA送给PL,PL负责把MAC帧包装成802.11物理帧,调制后从天线发射出去。
这个划分的核心逻辑我总结为八个字:“定时器放硬件,决策放软件”。MAC层的退避算法、重传计数、速率选择都在软件里,方便修改和调试;但OFDM符号的生成和接收同步这些必须依靠硬件时钟的活,全部落到PL里。openwifi这样设计,既保证了信号质量,又保留了协议研究上的灵活性。
2.3 代码结构一览:从FPGA工程到Linux驱动
openwifi的FPGA工程基于Vivado,顶层把Xilinx的三款不同体量的Zynq(7020、7035、7045全部支持)都纳入了构建流程,你只需要根据自己板上芯片的型号做好引脚分配和约束,然后就能上板跑通。代码库里的顶层叫openofdm_rx和openofdm_tx,分别对应接收和发射通路,两者相对独立,中间由MAC模块衔接。
驱动部分比较有意思。openwifi在内核里实现了一个完整的无线网卡驱动,支持mac80211接口,这样你可以在Linux里直接用iw工具创建AP模式站点模式,甚至在两个板卡之间构建桥接网络。它还能通过FPGA的寄存器实时控制射频增益、信道带宽、调制阶数等参数,这是普通Wi-Fi网卡完全做不到的。整个链路从网卡驱动到mac80211到hostapd到TCP/IP,和商用Wi-Fi没有任何区别,但底层的基带实现是完全开放透明的。
3. 核心细节解析:基带芯片里的关键模块
3.1 OFDM收发通路:从比特到星座图再到空中信号
802.11的物理层核心是OFDM。openwifi对这部分处理得非常细致。发射侧,比特流入加扰器,做前向纠错编码,速率从6Mbps到54Mbps对应不同的编码率,然后交织、映射成QAM星座点,再经过IFFT变换到时域,加循环前缀,最后通过DAC和射频发射出去。接收侧是逆向流程,但多了两个发射侧没有的困难模块:时间同步和信道估计。
时间同步的目标是找到每个OFDM符号的起点。openwifi用前导序列做自相关运算,捕获到峰值之后锁定符号边界,然后做频率偏移估计和校正。信道估计则利用802.11帧头里的已知导频序列,算出一个复数均衡系数,去补偿无线信道的幅度衰落和相位旋转。在工程代码里,这些模块全部是流水线风格的Verilog,每一级处理的时钟周期数都被严格规划过,读起来很像教科书里的信号处理框图直接变成了硬件电路。
3.2 MAC层和数据收发流程
MAC模块是openwifi里连接PHY和软件协议栈的桥梁。负责的事情包括:把来自ARM的MPDU封装成PPDU,添加前导和头字段;在接收方向,检测到合法帧头之后启动接收流程,完成地址过滤后把payload递交给DMA。还有个关键模块是发送状态机,要处理ACK超时重传、CTS帧检测退避这类硬实时逻辑。
值得单独说的是MAC层和PHY层的接口时序。在802.11标准里,PHY向MAC提供TX/RX状态指示,MAC要在收到信道空闲指示之后才能发起发送。openwifi里专门有phy_rx_end、phy_tx_start等信号,通过一根简单的握手协议在两个模块间传递状态。时序上是分毫不差的,这一点在做基带设计时务必重视。
3.3 时序约束与多时钟域设计
做FPGA项目绕不开时序问题,openwifi在这一点上算是比较宽容的。整个PL设计主要在40MHz左右的时钟域下运行,OFDM符号周期4微秒,对应采样率20MHz,内部做半速率处理,器件主频不需要追求极限。但正因为主频不高,很多人误以为不用做约束,实际跑起来就会出问题,特别是IQ数据通路接口和请求响应握手信号之间,跨时钟域处理不好,数据就会串位。
openwifi在工程里已经给出了完整的XDC约束文件,包括主时钟定义、输入输出延迟和跨时钟域异步FIFO的约束。如果你要改动代码,比如调整FFT点数或者增加MIMO通道,建议先复制原约束,再根据实际路径更新虚拟时钟,不要一上来就删约束文件。我在6723的7561板上测试过,只要约束按原样保留,编译结果的时序余量是足够的。
3.4 射频前端接口与IQ数据通路
AD9361和FPGA之间的接口是LVDS差分对,数据速率取决于采样率。FPGA侧按照AD9361的数据格式去解包IP数据,要特别注意数据位宽和信道使能配置。如果想简化,也可以用AD9361的CMOS接口模式,牺牲数据速率换取接线的便利。
数据通路的另一端连着DMA,openwifi在PL里实现了高吞吐率的AXI DMA控制器,把IQ采样数据和以太网包数据分别映射到不同的内存区域。调试时可以通过读取DMA的状态寄存器查看是否有数据溢出,这在实际抓包中非常有用。
4. 实操过程与核心环节实现
4.1 开发环境搭建与代码获取
要跑通openwifi,第一步是准备环境。推荐用Vivado 2020以上版本,不只是因为综合工具本身,还因为较新版本对Zynq UltraScale+的支持更完善,而openwifi的老分支是基于传统Zynq的。内核侧,openwifi官方维护了一个基于Linux的fork版本,你需要拉下来编译出内核镜像和驱动模块,配合buildroot或者Yocto生成根文件系统。整个环境的搭建如果以前做过Zynq的Linux开发,两个小时能搞定,如果没做过可能要一个周末。
提示:先把Vivado工程编译通过,再碰Linux驱动。两者同时推进一旦出了问题,光定位是硬件还是软件问题就够折磨人的。
获取代码的方式很简单,从openwifi的官方仓库拉取即可,这是他们的代码是基于AGPL许可的,做学术研究和学习没有问题,但如果要做闭源商业用途需要格外注意授权条款。
4.2 Vivado工程编译与上板流程
打开openwifi软件包下的fpga目录,里面有分类好的工程脚本。运行vivado批处理,会生成一个完整的工程,接下来实际操作的几个关键点:
- 综合后先检查资源利用率。openwifi的接收通路包含一个FFT和大量乘加器,在7020上占用率大约在六到七成,如果遇到时序不收敛,优先检查是否有LUT堆积在关键路径上。
- 实现完成后生成bit文件,同时导出hdf硬件描述文件,供后续SDK或PetaLinux二次开发使用。
- 上板前用JTAG连接,先加载bit文件,再用XSCT工具初始化DDR和串口,确认PL侧的AXI接口能正确响应ARM的读写请求。这个步骤可以验证链路的基础状态,例如读版本寄存器、读PHY状态寄存器,返回值和预期一致再往下走。
我个人的习惯是先不烧Linux,只加载bit文件检查基带寄存器,确认时钟锁定和复位已释放后再启动系统,这样可以排除大量低级问题。
4.3 用板卡对板卡打通一条无线链路
整套环境跑通之后,最激动人心的操作是搭一个最小无线网络。准备两块板卡,一块配置成AP模式,另一块配置成站点模式,用iw命令修改信道为36(5.18GHz频段),把发射功率调到合理范围,启动hostapd建AP,站点刷动态IP去连接。
实际跑起来会发现,第一次不一定能ping通。针对常见情况,建议按照以下步骤排查:
- 检查两个节点是否都处于同一信道,且频宽一致(20MHz或40MHz),不同频宽会导致接收端看不到合法帧头。
- 查看PHY层的接收寄存器,里面有CRC错误计数和信号强度指示,如果CRC错误很高,说明物理链路底噪或增益配置有问题,试着调整射频增益。
- 确认MAC层的状态寄存器,如果发送后长时间没有收到ACK,大概率是因为接收端没有成功解出帧头,问题仍然在PHY层。
我在实测中用的是一块基于Zynq 7020的板子和一块基于Zynq 7045的板子,两者通过网线各自接到PC,AP模式下板子上跑iperf3服务,站点模式下PC端跑iperf3客户端,实测TCP吞吐在20MHz带宽下能跑到约27Mbps,看着不算高,但考虑到这是SDR平台,而且所有物理层参数全程都可见可调,这个结果已经非常有参考价值。
5. 常见问题与排查技巧实录
| 现象 | 可能原因 | 排查方法 |
|---|---|---|
| bit文件加载后PS时钟无输出 | 启动模式拨码错误或DDR初始化失败 | 检查Zynq的Boot Mode引脚,用XSCT确认PS端寄存器的值 |
| iw list看不到无线接口 | 驱动模块未加载或内核未编译mac80211 | dmesg查看是否有驱动报错,重新加载openwifi模块 |
| 扫描时能看到AP,但无法连接 | MAC层重传超时或加密方式不匹配 | 先关闭所有加密测试开放网络连接,确认链路稳定再启用WPA2 |
| ping通但TCP吞吐极低 | DMA缓冲区配置过小或CPU中断太频繁 | 调大NAPI权重参数,查看PL侧DMA统计寄存器确认是否有丢包计数增长 |
| 接收端CRC错误率偏高 | 射频增益不合适或采样偏差 | 动态调整AD9361的增益控制模式,观察IQ功率是否在合理范围 |
第一个值得单独说的是“扫描不到AP但另一块板能看到”的情况,十个里有八个是天线没接好,射频端口没接天线时,信号泄漏到接收通路也能制造假帧头,但包质量极差。先把天线接稳,再用频谱仪或者AD9361的捕获模式观察接收频谱,确认环境里确实有目标信号再往下排查。
第二个常见坑是Vivado版本切换导致的IP核升级问题。openwifi仓库里锁定了部分IP版本,用新版本打开时可能会提示升级IP核。建议遇到这类情况优先看升级后的IP是否影响接口定义,尤其是AXI DMA和AXIS数据宽度相关的内容,宁可手工重做IP封装也不要盲目点自动升级,否则容易引发接口不匹配的编译错误。
第三个建议是在驱动层调试时多关注FPGA的寄存器打印,openwifi驱动的源码里已经封装好了一组寄存器读写的工具接口,通过它可以把PHY层的实时状态导出来检查。这些寄存器能在不看示波器的前提下判断物理链路是否存在问题,比如接收信号强度指示值明显偏低但CRC正常,说明发送端功率设置过低;如果强度正常但CRC极高,说明频率偏移补偿没有收敛。这类判断用熟了,现场问题基本五分钟能定位个大概。
最后再分享两个小建议
我对openwifi最大的体会是:它不仅仅是代码开源,更是一个用工程标准写的“基带教科书”。建议拿到代码之后不要急着上板,先花一个晚上把openofdm_tx方向的代码从头读一遍,从加扰开始,一直到IFFT输出,每一级都对应着802.11标准中的一个子块。读懂这一条通路,你对OFDM的理解会从“公式会推”变成“电路会写”。
第二个建议是,如果条件允许,在板子上加一块ADC采集板,把AD9361的中频输出接到示波器或逻辑分析仪上,直接观察OFDM时域波形的包络变化。这个操作能让你非常直观地看到不同的调制阶数和频宽设置对波形的影响,比看任何教科书都管用。openwifi开放了这套测试接口,不改任何代码就能接出来调试。
openwifi目前还在持续更新,社区也在逐步补充对802.11ac等新特性的支持。对这个领域有兴趣的话,早一点入手,早一点跑通链路,后面的研究空间会比想象中大得多。
本文还有配套的精品资源,点击获取