3、WiFi协议栈架构:OSI模型与WiFi分层、MAC层功能(CSMA/CA、帧结构)、PHY层功能(前导码、数据封装)

各位同学,今天我们来聊聊WiFi芯片的灵魂——协议栈架构。说实话,很多刚入行的工程师喜欢一上来就调电路、跑仿真,结果芯片做出来跟别人家设备连不上,回头才发现是协议栈理解不到位。我当年就吃过这个亏,所以今天把这部分掰开揉碎了讲清楚。

3.1 OSI模型与WiFi分层:别被七层吓到

OSI七层模型,你肯定背过。但做WiFi芯片,我们真正打交道的其实就三层:物理层(PHY)、数据链路层(MAC)、网络层(IP)。上面那些会话层、表示层,芯片里基本不碰。

我个人习惯把WiFi协议栈简化成下面这张图,你一看就明白:

WiFi协议栈简化分层模型 应用层(HTTP、FTP、视频流) 传输层(TCP/UDP) 网络层(IP) 数据链路层(MAC) CSMA/CA · 帧封装 · ACK重传 物理层(PHY) 前导码 · 编码调制 · OFDM 软件实现 固件+硬件 硬件加速 纯硬件

你看,MAC层和PHY层才是WiFi芯片的硬核所在。IP层以上,通常跑在CPU上,用软件搞定。但MAC和PHY,必须硬件加速,否则延迟受不了。

核心观点:WiFi芯片设计,本质上是把MAC和PHY的协议逻辑,用硬件电路高效实现。软件能跑的部分,尽量留给CPU。

3.2 MAC层功能:CSMA/CA与帧结构

MAC层,说白了就是管「谁先说话」的。无线信道是共享的,你不能想发就发,得讲规矩。这个规矩就是CSMA/CA——载波侦听多点接入/碰撞避免。

3.2.1 CSMA/CA:先听再说,不行就等

为什么WiFi不用CSMA/CD(碰撞检测)?因为无线环境里,你发信号的时候自己根本听不到别人在发——收发器不能同时工作。所以只能「避免碰撞」,而不是「检测碰撞」。

CSMA/CA的工作流程,我总结成四步:

  1. 侦听信道:发之前先听一下,信道忙不忙?
  2. 随机退避:如果信道空闲,等一个随机时间再发。这个随机时间很关键,防止多个设备同时抢发。
  3. 发送数据:退避结束,信道仍然空闲,就发送。
  4. 等待ACK:接收方收到数据后,必须回复ACK。如果没收到ACK,说明碰撞了,重传。

避坑指南:我曾经设计过一款IoT芯片,退避算法写得过于简单,随机窗口太小。结果在密集部署场景下,几十个设备同时退避结束,疯狂碰撞,吞吐量直接掉到零。后来把退避窗口调大,加了指数退避,问题才解决。

这里有个细节——RTS/CTS握手机制。当数据帧很长时,先发一个短的控制帧(RTS)探探路,对方回复CTS,再发长数据。这样即使碰撞,损失也小。我建议在芯片设计中,RTS/CTS做成可配置的,因为短报文场景下反而增加开销。

3.2.2 MAC帧结构:每一比特都有讲究

WiFi的MAC帧,结构比以太网复杂得多。来看一个典型的数据帧:

字段 长度(字节) 说明
帧控制 2 协议版本、类型、子类型、ToDS/FromDS等
持续时间/ID 2 NAV设置,用于虚拟载波侦听
地址1 6 接收地址(RA)
地址2 6 发送地址(TA)
地址3 6 BSSID或目标地址
序列控制 2 帧序号+分片号,用于去重和重组
地址4 6 仅WDS模式下使用
帧体 0~2312 实际数据载荷
FCS 4 CRC32校验

嗯,这里要注意——帧控制字段里的类型和子类型,决定了这个帧是管理帧、控制帧还是数据帧。芯片的MAC硬件必须能快速解析这个字段,决定后续处理流程。

我个人习惯在硬件设计里,把帧解析做成流水线。前8个字节(帧控制+持续时间)一收完,立刻判断帧类型,然后决定要不要继续收后面的地址字段。这样能省不少功耗。

3.3 PHY层功能:前导码与数据封装

PHY层,就是把MAC层丢过来的数据帧,变成能在天线上发射的无线电波。反过来,把收到的无线电波还原成数据帧。

3.3.1 前导码:让接收机找到节奏

你想想看,接收机一开始是「聋的」,不知道什么时候有信号来。前导码就是一段固定的、已知的波形,告诉接收机:「嘿,我要发数据了,准备好!」

WiFi的前导码分两部分:

  • L-STF(短训练序列):用于自动增益控制(AGC)、粗频率同步。说白了就是让接收机先把音量调好。
  • L-LTF(长训练序列):用于精细频率同步、信道估计。接收机通过它知道信道有多「脏」,然后做均衡补偿。

关键点:前导码的设计决定了接收机的灵敏度。我见过一些芯片为了省功耗,把前导码做短了,结果远距离场景下同步失败率飙升。前导码长度是协议规定的,别乱改。

3.3.2 数据封装:从比特到波形

MAC层送过来的数据,在PHY层要经过一系列处理才能发射。流程如下:

  1. 加扰:用伪随机序列对数据进行异或,避免长串的0或1导致直流偏移。
  2. 编码:常用卷积码或LDPC码,加入冗余信息,对抗信道噪声。
  3. 交织:把比特顺序打乱,防止突发错误连续破坏数据。
  4. 调制映射:BPSK、QPSK、16-QAM、64-QAM……把比特映射到复数星座点上。
  5. OFDM调制:IFFT变换,把频域信号变成时域信号。
  6. 加循环前缀:在OFDM符号前复制一段尾部,抵抗多径效应。

这一套流程,在芯片里全是硬件流水线。我当年做第一版PHY时,编码器和调制器之间的握手信号没处理好,导致数据断流,查了三天才找到问题。后来我养成了一个习惯——每个模块之间加一个FIFO,深度不用大,16级就够了,但能解决90%的流水线冲突。

警告:OFDM调制对时钟抖动非常敏感。如果你在芯片里用PLL产生的时钟做IFFT,务必保证相位噪声指标达标。我曾经因为PLL设计偷懒,导致EVM(误差矢量幅度)超标,整颗芯片的吞吐量直接腰斩。

3.4 小结:MAC和PHY的协同

MAC层和PHY层不是孤立的。MAC发一个帧,PHY得知道什么时候开始发前导码,什么时候发数据。反过来,PHY收到一个帧,得告诉MAC:「帧来了,校验对不对?」

我建议你在芯片架构设计时,把MAC和PHY之间的接口定义清楚。常用的做法是定义一个PHY-MAC接口总线,包含数据线、控制线、状态线。数据线传帧内容,控制线传「开始发送」「开始接收」等命令,状态线传「接收完成」「CRC错误」等反馈。

这个接口一旦定下来,后面MAC和PHY两个团队就可以并行开发了。我在多个项目中验证过,接口定义花一周时间,后面能省两个月。


公众号:蓝海资料掘金营,微信deep3321