呼,终于写到网络通信这章了。从点灯、按键、串口一路走过来,到这一章,前面学的时序概念、状态机、FIFO、异步处理,全都得拿出来用一遍。很多朋友到这一步会慌:网络通信听起来太系统级了,又是MAC又是PHY,又是ARP又是CRC,怕自己搞不定。
实际上,FPGA上的网络通信,百分之八十的工作量在硬件初始化和数据通路打通上,剩下的才是协议处理。对入门阶段来说,你需要关心的核心就两个词:MAC和PHY。搞清楚它们之间的接口长什么样,再把数据从FPGA逻辑里搬到网口上,本章的任务就完成一大半了。
这篇是“从近似0基础开始FPGA开发”系列的第七篇,默认你已经会开Vivado工程、会写简单Verilog、看得懂时序图。这篇不跟你扯太深的应用层协议,目标是把FPGA和网线之间的这层窗户纸捅破,让你能在一两天内,从板子上电到用Wireshark看到自己FPGA发出来的以太网帧。
1. 网络通信到底在干什么:先把概念捋顺
1.1 拆掉“网络通信”这个吓人的壳
很多初学者一听到“FPGA网络通信”就脑补出一整套TCP/IP协议栈,觉得要写一堆复杂逻辑。其实在FPGA入门阶段,你要做的根本不是实现完整的网络协议栈,而是先把“比特流从一个设备搬到另一个设备”这件事做通。
打个比方。你要寄一封信,其实分两层:第一层是把信纸写出来,第二层是把信纸装进信封、写上地址、丢进邮筒。对应到FPGA网络通信里,你的逻辑代码是“写信的人”,MAC层负责“装信封、写地址、贴条码”,PHY芯片就是“邮筒和邮递员”,把信封变成网线上的电信号送出去。
所以,FPGA上的网络通信,核心就两部分:一个是MAC控制器,负责组帧、拆帧、校验;一个是PHY芯片,负责把MAC传来的并行数据和网线上的串行模拟信号互相转换。MAC层通常在FPGA内部实现,可以用IP核,也可以自己写;PHY是板子上的独立芯片,FPGA通过RGMII、GMII这类接口跟它相连。
这篇文章我默认你用的是最常见方案:FPGA + 板载千兆PHY芯片 + RJ45网口,FPGA内部例化一个三速以太网MAC核,外部通过RGMII接PHY。这套组合是市面上绝大多数开发板、核心板、通信板卡的标配,也是你以后出去做项目最常遇到的架构。
1.2 以太网帧长什么样:你要处理的数据格式
不管你后面想传图像、传AD数据、传自定义协议,最终到线上都得包成以太网帧(Ethernet Frame)。这个帧的格式是IEEE 802.3定义的,入门阶段你只要记住几个关键段就行。
| 字段 | 长度 | 作用 |
|---|---|---|
| 前导码 Preamble | 7字节 | 同步时钟,内容固定为0x55 |
| 帧起始定界符 SFD | 1字节 | 标志帧的开始,固定为0xD5 |
| 目的MAC地址 | 6字节 | 发给谁 |
| 源MAC地址 | 6字节 | 我是谁 |
| 长度/类型 | 2字节 | 小于1500表示长度,大于1536表示协议类型,如0x0800是IP包 |
| 数据 Payload | 46~1500字节 | 真正要传的内容,不够46字节要填充 |
| 帧校验 FCS | 4字节 | CRC32校验,覆盖目的MAC到数据末尾 |
这里有两个新手容易踩的坑。
第一,前导码和SFD不算在帧长度里,但它们确实在线上传输。用Wireshark抓包时,抓包软件通常把前导码和SFD直接隐藏了,你看到的帧是从目的MAC开始的。
第二,以太网帧最小64字节,最大1518字节(不放VLAN标签的情况下)。如果你要发一个只有10字节的数据,必须在数据区补到46字节,否则整个帧不够64字节,很多PHY和交换机直接就不认了。反之,数据超过1500字节就必须拆帧,这就是IP层MTU的由来。FPGA如果做UDP大包发送,经常要处理分包逻辑,这一条后面会反复遇到。
1.3 数据从FPGA到网线,要经历哪几步
我画一条完整通路给你看,这样后面所有配置和调试你都有坐标参考。
FPGA内部用户逻辑 —> MAC IP核(组帧/解帧/CRC) —> RGMII接口 —> PHY芯片(编码/并串转换) —> 网络变压器 —> RJ45 —> 网线 —> 电脑/交换机
- 发送方向:你写一个发送模块,把用户数据通过AXI-Stream接口塞给MAC核,MAC核自动添加前导码、目的MAC、源MAC、长度和CRC,最后转成RGMII时序送给PHY。
- 接收方向:PHY从网线上收下模拟信号,转成RGMII数字时序,MAC核解析并对齐字节,去掉前导码和SFD,输出一帧完整的数据,你再在逻辑里判断目的MAC是不是自己,是就收下,不是就丢掉。
数据链路层的事基本就这些。至于ARP、ICMP、UDP、TCP这些,属于网络层和传输层,这章先不碰。你把MAC层跑通,后续往上加协议就是模块叠加问题,难度完全不同。
2. 板载PHY芯片和RGMII接口:硬件准备不能再想当然
2.1 先到原理图里认识你的PHY芯片
FPGA开发板上PHY芯片一般都在RJ45网口附近,丝印上能直接看到型号,最常见的有瑞昱RTL8211系列、Microchip的KSZ9031、裕太微的YT8531,老一点的有Marvell的88E1111。不同PHY寄存器定义略有差异,但功能结构大同小异。
拿到一块新板子,第一件事不是写代码,而是去原理图里找这几个信号:
- PHY的复位引脚:接了FPGA的哪个GPIO,还是直接拉了上电复位,还是接到了别的复位芯片。
- PHY的MDIO/MDC引脚:这是配置PHY的“管理总线”,通常直接连到FPGA的普通IO。
- PHY的RGMII信号组:TX_CLK、TX_CTL、TXD[3:0]、RX_CLK、RX_CTL、RXD[3:0],看看有没有中间加电平转换芯片。
- PHY的时钟来源:有些板子PHY自带25MHz晶振,有些是FPGA给时钟,甚至有些设计用125MHz差分时钟,这个直接决定你初始化的时序。
为什么让你先看原理图?因为PHY芯片的启动配置,除了你后面用MDIO写的寄存器,还涉及其硬件引脚上下拉。比如PHY地址通常通过引脚上的上下拉电阻设定,常见的PHY地址是0x00、0x01、0x04,个别板子拉到0x1F。如果后面MDIO读写没反应,大概率就是PHY地址搞错了。
提示:所有PHY芯片的电源域和引脚电平都要确认清楚。现在很多板子FPGA是1.8V、2.5V、3.3V混合IO,PHY的RGMII接口通常是2.5V或3.3V,如果FPGA的Bank电压不一致,轻则通信异常,重则烧芯片。上电拿万用表量一下,比写代码省心得多。
2.2 RGMII信号怎么理解:把它当成带方向的串口
RGMII的全称是Reduced Gigabit Media Independent Interface,相比老一代GMII,数据线从8根减到4根,速率提高一倍。你可以粗暴地理解为:这是一组在时钟上下沿都能采数据的并行接口,比UART复杂一点,但本质还是“时钟+控制+数据”的同步接口。
RGMII的信号就五组:
| 信号 | 方向 | 作用 |
|---|---|---|
| TX_CLK | FPGA到PHY | 发送时钟,1000M时为125MHz |
| TX_CTL | FPGA到PHY | 发送控制,上升沿为TX_EN,下降沿为TX_ER |
| TXD[3:0] | FPGA到PHY | 发送数据,上升沿发低4位,下降沿发高4位 |
| RX_CLK | PHY到FPGA | 接收时钟,由PHY恢复输出 |
| RX_CTL | PHY到FPGA | 接收控制,上升沿为RX_DV,下降沿为RX_ER |
| RXD[3:0] | PHY到FPGA | 接收数据,上升沿收低4位,下降沿收高4位 |
千兆模式下,TX_CLK和RX_CLK都是125MHz,每个时钟沿传4bit,一个时钟周期传8bit,正好是1Gbps。百兆模式下时钟变成25MHz,十兆是2.5MHz。
这里要注意的是,发送方向时钟由FPGA输出给PHY,接收方向时钟由PHY恢复出来送给FPGA。所以你在做时序约束时,TX引脚要约束output delay,RX引脚要约束input delay。不过用IP核的话,IP内部已经做了大量处理,你只需要在XDC里约束好RGMII引脚位置和时钟,然后用set_input_delay/set_output_delay粗略约束一下就行。
2.3 MDIO管理接口:PHY芯片的“遥控器”
MDIO(Management Data Input/Output)是IEEE 802.3定义的管理总线,作用就是让FPGA能读写PHY芯片内部的寄存器。你可以理解成PHY芯片背后有个控制面板,但面板上的旋钮都在寄存器里,你要通过MDIO去拧。
MDIO总共就两根线:MDC(管理时钟)和MDIO(管理数据)。MDC由FPGA提供,频率不能太快,一般建议2.5MHz,稳妥一点1MHz都行,很多PHY对太高的MDC时钟不敏感。
MDIO的时序是标准帧格式,写操作和读操作略有区别:
- 写操作:32位前导码(全1) + 起始码01 + 操作码01 + PHY地址5bit + 寄存器地址5bit + 2bit的TA(写为10)+ 16bit数据
- 读操作:前面一样,操作码换成10,TA变成高阻,PHY回数据
手动用Verilog写MDIO控制器并不难,但多数时候可以直接用Vivado的VIO(虚拟IO)配合ILA来在线读写,甚至只在调试阶段用ILA发寄存器的值到MDIO模块。我自己习惯的做法是先写一个简单的MDIO驱动模块,用状态机实现读写,然后通过VIO给命令,这样不需要反复编译。
注意:MDIO读操作在TA阶段,MDIO线是双向的,需要从FPGA输出切到高阻输入。如果写Verilog时把INOUT方向搞错,读出来永远是0xFFFF或者0x0000。遇到这种情况,先用逻辑分析仪抓MDIO线上的波形,看TA阶段是不是真的拉了高阻。
3. 用IP核搭数据通路:三速以太网MAC使用要点
3.1 为什么别一上来就手写MAC控制器
我在很多群里看到新手问“能不能自己写一个MAC控制器”?能,当然能,但前提是你对时序、CRC、状态机、跨时钟域都有足够的把控力。手写MAC控制器的工作量比写一个UART大一个数量级,而且写完还要做大量仿真验证,不是一个“从近似0基础开始”的系列应该走的路。
用IP核不是丢人,恰恰是工程上的正确选择。Xilinx Vivado自带一个三速以太网MAC核,叫Tri-Mode Ethernet MAC,简称TEMAC。它的作用是在你不需要了解RGMII和CRC细节的情况下,把收发数据变成干净的AXI4-Stream接口。Intel/AMD平台的FPGA也有对应的三速以太网IP,高云、安路这些国产FPGA基本都是类似思路。
TEMAC内部已经包含了RGMII接口转换、收发FIFO、CRC校验/生成、流量控制、MDIO控制等模块。你要做的就三件事:正确配置IP核、把收发接口连到自己的逻辑、约束好引脚和时序。这也是为什么工作三五年的人做FPGA网络通信,第一步也都是例化IP,只有特殊需求比如超高吞吐、超低延迟的定制协议,才考虑完全手写。
3.2 Vivado里例化TEMAC的关键配置项
在Vivado的IP Catalog里搜索Tri-Mode Ethernet MAC,双击打开配置界面。不同版本界面略有差异,但核心配置项没变。
我按自己的使用习惯给你过一遍:
- Physical Interface选择RGMII。如果你板子PHY是GMII接口,选GMII,但绝大多数开发板是RGMII。
- Speed Default设置为1 Gbps。如果你的设计需要支持多种速率自动协商,那就让PHY自协商之后通过寄存器读取当前速率,再动态切换MAC侧的速率,这个对新手稍复杂,可以先固定千兆。
- Shared Logic选项:如果只有一个MAC核,直接选Include shared logic in core,省事,时钟和复位都由IP内部管理。如果是复杂系统多个以太网口,再考虑Exclude shared logic,自己统一管理。
- AXI4-Stream接口选项要勾上,这样MAC对外的收发就是标准的tvalid/tready/tdata/tkeep/tlast握手信号,方便你写自己的逻辑。
- 收发FIFO深度一般默认即可,默认通常是16KB,至少能撑住几个大帧的突发。数据量大、突发密集的场景,可以把发送FIFO调大到32KB。
此外,IP核里还有一个重要的寄存器接口。TEMAC有独立的配置寄存器,需要通过AXI4-Lite口去写。这个AXI4-Lite口可以在配置时选择单独的接口,也可以让IP核内部自动配置,但多数情况下需要你通过一个AXI4-Lite接口模块来配置MAC的收发使能、速度、回环模式等。Vivado官方示例里提供了一个简单的主机接口,你可以参考。
如果不想写AXI4-Lite主机逻辑,也可以用VIO去读写,但这样不太优雅。我建议第一次跑通时直接用VIO控制,功能验证通过后再用代码实现配置流程,能省很多时间。
3.3 收发逻辑怎么跟MAC核对接
配置完TEMAC,你在Block Design或直接例化Verilog时会发现,MAC对外暴露了三个主要接口:AXI4-Lite配置口、AXI4-Stream发送口、AXI4-Stream接收口。
用户逻辑这边,需要干三件事。
接收方向:MAC核会把收到的有效帧通过接收AXI4-Stream接口吐出来,tvalid表示有数据,tdata是数据,tlast表示帧结束。你需要自己判断MAC地址是否匹配。不过TEMAC也提供地址过滤功能,可以通过配置寄存器设置,入学阶段更建议在用户逻辑里判断,灵活,便于加自己的过滤规则。
发送方向:你准备好一帧数据,先把tvalid拉高,数据按字节往tdata上放,直到最后一拍拉tlast,然后再看tready是否准备好。简单来说,就是标准的AXI-Stream主从握手,唯一要记得的是发送前必须组好整个帧,至少64字节,不够就填充0。
讲一个我见过的典型错误:有些新手直接用一个寄存器或开关控制发送,把tvalid一直拉高,然后数据一直往tdata送,结果MAC反复发同一个帧。正确做法是先在缓存里把整个帧准备好,再通过状态机启动一次发送,tvalid只在数据有效期间拉高,tlast在最后一拍拉高后立刻释放,等tready一起握手,才算发完一帧。
接收方向还有个细节:MAC核默认会检查CRC,坏帧会直接丢弃,这没问题。但如果你在调试阶段想看到原始帧,可以在配置里关闭CRC检查,收什么都往上送,方便分析问题,等后面跑协议时再打开。
3.4 时序约束和引脚约束不要到最后才补
很多FPGA例化IP一个顶俩,但忘了写XDC,综合能过,上板后网口就是不通。RGMII这类高速接口,引脚位置错一个、约束少一条,根本起不来。
引脚约束还好说,照着原理图把TXD[3:0]、TX_CTL、TX_CLK、RXD[3:0]、RX_CTL、RX_CLK、MDC、MDIO这些信号的位置填进去就行。麻烦在时序约束。
常规做法是:
- 对RX_CLK,用
create_clock创建输入时钟约束,频率125MHz。 - 对RXD、RX_CTL,用
set_input_delay约束,大致范围在1ns到3ns之间。 - 对TX_CLK,如果是MAC输出给PHY的时钟,通常由IP内部生成,不需要额外约束太多;但TXD和TX_CTL需要
set_output_delay,一般设2ns左右。
具体数值要根据PHY手册的时序参数来算,但入门阶段先用这些经验值就能跑通。如果后面上到非常高的频率或者遇到时序收敛问题,再回头细调。
提示:RGB类RGB类,先确认你在XDC里用的时钟名和IP核实际生成的时钟名是否一致,否则约束不生效。用
report_clock_interaction和report_timing_summary看是否有时钟没约束上,这一步很多人忽略。
4. 上板调试五步走:从点灯到Wireshark看到包
4.1 第一步:先让PHY的link灯亮起来
配置完和布局完,上板第一件事不是写一堆收发逻辑,而是看板子上的网口link灯亮不亮。link灯一般有两个,一个表示链路通,一个表示速率。插上网线到交换机或者电脑,如果link灯不亮,后面所有调试都是空谈。
link不亮的排查顺序是固定的:PHY有没有复位、PHY有没有时钟、PHY电源对不对、网络变压器和后级电路有没有焊错。没有时钟就查晶振,复位被拉死就查复位芯片,电源有误就查LDO,大概率是硬件问题,不是FPGA逻辑问题。
如果link灯亮了且速率灯显示千兆,说明PHY的物理层通路已经起来了,FPGA即使不发一帧数据,链路也是正常协商好的。这时候再进行下一步。
4.2 第二步:通过MDIO读PHY寄存器确认能通信
PHY的link状态、速度模式、回环模式、中断状态,全都可以通过寄存器读出来。用你写的MDIO驱动,先读一下PHY的ID寄存器,比如RTL8211的寄存器2和3会回读出芯片ID,你必须能读到一个非0xFFFF的值,才说明MDIO通路正常。
读通之后,再读PHY的Basic Status寄存器(寄存器1),看bit2是不是1,表示链路已建立。如果不能读到寄存器,检查MDIO时序有没有问题,MDC是不是太快,PHY地址对不对。这一步通过VIO加ILA来在线操作特别高效,不用改代码重新编译。
4.3 第三步:MAC回环打通内部通路
外环链路通了、MDIO也能读了,接下来就是验证FPGA内部通路。TEMAC有寄存器可以配置MAC回环(Loopback),你可以把发送的数据直接从内部绕回接收侧,逻辑里自己收自己发的帧。这个测试能快速验证MAC核配置、AXI-Stream接口、FIFO是否工作正常。
具体操作是在IP核配置后,通过AXI4-Lite写寄存器,把内部回环使能打开,然后用户逻辑开始发送数据,接收侧理应能收到一模一样的帧。用ILA挂在接收AXI-Stream接口上,看到tvalid/tdata/tlast正常变化,就说明内部通路一点问题没有。
4.4 第四步:电脑直连并抓包分析
内部通了,把回环关掉,网线直连电脑,再用Wireshark抓包。这时候会看到两种结果。
第一种:电脑在发ARP广播包,目的MAC是FF:FF:FF:FF:FF:FF,源MAC是电脑自己。FPGA如果还没支持ARP协议,通常不会回包,但你能在Wireshark里看到请求帧,说明接收方向是通的。
第二种:你让FPGA定期发送一个自定义广播帧,目的MAC设成FF:FF:FF:FF:FF:FF,电脑端Wireshark就能看到FPGA发出来的这个帧。能收到,发送方向就通了。
这时候再检查三个重要项目:帧长度对不对、CRC是否正确、源目的MAC是不是填反了。Wireshark对坏CRC帧会直接标注“Malformed”或“bad FCS”,一目了然。
4.5 第五步:用稳定性和收发统计验证
项目做到“能收到包”只是第一步,完整交付还要做稳定性和性能测试。比如写一个收发统计模块,在逻辑里统计收了多少帧、丢了多少帧、CRC错帧多少、发送完成了多少。跑个10分钟、1小时,看看数据是否稳定。
电脑侧用ping测试更直观,但ping需要IP和ARP协议,这章先不展开。如果你只是想测试MAC层的收发完整性,可以在FPGA内部生成已知模式的循环帧,电脑端Wireshark过滤规则统计,看有没有丢帧。
到这一步,一个FPGA的以太网通信通路就算真正打通了,你可以在这个基础上加ARP协议、UDP协议、自定义数据协议,都是后面的事了。
5. 常见问题排查与避坑清单
5.1 PHY link灯不亮,但硬件看着都正常
先查PHY的复位时序。PHY芯片上电后一般需要等待一个稳定时延再释放复位,有些开发板把PHY复位接到FPGA的IO上,但FPGA配置期间IO默认是什么状态、配置完成后是什么状态,都不能拍脑袋。具体做法是上电后用信号量测一下PHY的复位引脚电平,如果是低,PHY一直处于复位,肯定不工作。
第二查PHY的时钟。很多PHY自带晶振,但有些设计是从FPGA送时钟过来的。如果FPGA还没配置成功,时钟没起来,PHY就没法工作。
第三查网线。这种反直觉的检查其实很常见,尤其会议室网线牵错交叉线的案例数不胜数。现在的PHY基本都支持MDI-X自动翻转,但有些老设备不行,换一条直通线或换个交换机端口试试。
5.2 MDIO读写无响应,读ID出来全是0xFFFF
这个问题的90%原因是PHY地址不对。开发板原理图里PHY地址一般有明确标注,比如RTL8211引脚LED2_PHY_AD2、LED1_PHY_AD1、LED0_PHY_AD0,上拉为1下拉为0,组合起来就是PHY地址。没有原理图就挨个试0x00到0x1F,总能读到。
第二个原因是MDC时钟频率太高。有些PHY手册写最高25MHz,但实际布局布线不好时,走线噪声一大,高频率下就是读写失败。把MDC降到2.5MHz甚至1MHz,问题基本消失。
第三个原因是你MDIO的TA阶段方向切换没做好,写Verilog时inout信号在读操作时要先拉高阻抗,不然PHY回的数据根本传不回来。用ILA抓波形,一看就明白。
5.3 能收到ARP广播,但发出去的数据抓不到
接收通了但发送不通,排查重点在发送方向。
先看发送AXI-Stream握手:tvalid拉高后tready有没有拉高,两拍相与才能完成一次数据传输。如果tready一直低,可能是发送FIFO满了,或者是MAC核没处于发送使能状态,回去查MAC配置寄存器有没有使能发送路径。
再看TX_CTL和TXD的时序。RGMII是双沿采样,如果用错了IDDR/ODDR的沿,就会出现数据错位。IP核内部一般没有这个问题,但你自己扩展逻辑时要注意。
最后,确认发送帧有没有满足最小帧长。发一个只有几个字节的数据不填充,PHY根本不会把它当成有效帧发出去,Wireshark自然收不到。数据区补到46字节以上再试。
5.4 收到的帧长度一直不对,或者CRC错误
帧长度不对,十有八九是你对“帧长度”理解错了。以太网帧长度指的是从目的MAC开始到数据结束的长度,不包含前导码和SFD,FCS也是后加的。如果用Wireshark看,它会自动把前导码隐藏,显示长度一般等于目的MAC起始到FCS结束,也就是64到1518字节。
CRC错常发生在自己写MAC的场景,此时往往是自己组RPGRAM,CRC算法或初始值写错。用IP核时出现CRC错,问题多半在PHY配置,比如PHY工作在MII模式而MAC工作在RGMII模式,速率不匹配就会产生错误帧。
注意:如果电脑网卡显示连接速率只有百兆,而FPGA MAC配置的是千兆,链路层速率不一致时,收上来的帧就会出现大量CRC错误。先让两边速率模式对齐,再排查逻辑问题。
5.5 收发单包正常,高负载就丢帧
单个包跑得好好的,大量数据进来就丢,这是典型的FIFO深度和背压问题。
MAC核内部FIFO如果不够大,接收方向上,上一帧还没被用户逻辑取走,下一帧就来了,丢帧。解决方法是调大FIFO深度,或者在用户逻辑侧用DMA方式持续搬运,而不是一帧一帧地停等。
发送方向也有类似的坑。如果你的用户逻辑在写发送FIFO时,等整个帧写完了才允许下一次发送,那么连续快速发包时会导致发送FIFO没清空。正确做法是让发送状态机在上一次tlast发送完成后,尽快启动下一帧,中间只保留必要的帧间隔。
我在实际项目中遇到过一个问题:单独用testbench仿真空转什么都对,一上板拉高速率就丢包,最后查出来是时钟域没有处理好。接收方向MAC核输出的时钟和用户逻辑时钟不在同一个域,直接用跨时钟域的办法搬运数据,丢帧自然缓解。
经验速查:网络通信调试这张表足够
| 现象 | 排查方向 |
|---|---|
| link灯不亮 | PHY复位、时钟、电源、网线/网络变压器 |
| MDIO无响应 | PHY地址、MDC频率、inout方向 |
| 能link但收不到帧 | RGMII引脚约束、RX_CTL极性、速率模式是否匹配 |
| 收到坏CRC帧 | PHY速率配置、MAC回环配置、数据线位序 |
| 单包正常高负载丢帧 | FIFO深度、发送背压、跨时钟域处理 |
| 电脑网卡识别异常 | PHY自动协商配置、RJ45引脚极性 |
最后再补充一个实战经验:做FPGA网络通信,不要把IP核和PHY绑定得太死。同一套RGMII接口逻辑,换不同型号PHY芯片时,寄存器和配置流程会变,但MAC核和RGMII时序基本不变。我才开始学习时,一直用一套板子和固定的PHY,后来换了一个完全不同型号的PHY,才发现真正值钱的是对RGMII和MAC层协议的理解,那才是搬不走的东西。后面如果你想在自己设计的板子上跑网络通信,先把这个基本功练扎实,你会少走很多弯路。