3、WiFi协议栈架构:OSI模型与WiFi分层、MAC层功能(CSMA/CA、帧结构)、PHY层功能(前导码、数据封装)
各位同学,今天我们来聊聊WiFi芯片的灵魂——协议栈架构。说实话,很多刚入行的工程师喜欢一上来就调电路、跑仿真,结果芯片做出来跟别人家设备连不上,回头才发现是协议栈理解不到位。我当年就吃过这个亏,所以今天把这部分掰开揉碎了讲清楚。
3.1 OSI模型与WiFi分层:别被七层吓到
OSI七层模型,你肯定背过。但做WiFi芯片,我们真正打交道的其实就三层:物理层(PHY)、数据链路层(MAC)、网络层(IP)。上面那些会话层、表示层,芯片里基本不碰。
我个人习惯把WiFi协议栈简化成下面这张图,你一看就明白:
你看,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的工作流程,我总结成四步:
- 侦听信道:发之前先听一下,信道忙不忙?
- 随机退避:如果信道空闲,等一个随机时间再发。这个随机时间很关键,防止多个设备同时抢发。
- 发送数据:退避结束,信道仍然空闲,就发送。
- 等待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层要经过一系列处理才能发射。流程如下:
- 加扰:用伪随机序列对数据进行异或,避免长串的0或1导致直流偏移。
- 编码:常用卷积码或LDPC码,加入冗余信息,对抗信道噪声。
- 交织:把比特顺序打乱,防止突发错误连续破坏数据。
- 调制映射:BPSK、QPSK、16-QAM、64-QAM……把比特映射到复数星座点上。
- OFDM调制:IFFT变换,把频域信号变成时域信号。
- 加循环前缀:在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