ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Zynq实战:MII转GMII与EMIO UART0配置详解

Zynq实战:MII转GMII与EMIO UART0配置详解 1. 项目概述与整体设计思路1.1 核心需求解析Zynq开发中MII转GMII的配置和EMIO UART0的配置属于典型的“FPGA逻辑PL与ARM处理器PS协同”问题。我在实际调试中遇到这个需求往往是因为板上PHY芯片的接口模式和PS端默认的MIO管脚分配对不上或者是串口数量不够用、管脚被占用需要把UART从MIO挪到EMIO上。先说清楚这两个东西到底解决什么问题MII转GMIIZynq的GEMGigabit Ethernet MAC控制器本身支持多种接口模式其中RGMII是板上最常用的MII是百兆模式GMII是千兆模式。MII和GMII在数据位宽、时钟频率、管脚数量上完全不同如果PHY芯片只支持GMII接口而控制器配置成了MII或者反过来网络就会彻底不通。所以“MII转GMII”本质上不是硬件上做协议转换而是在Vivado里把GEM的接口模式配置正确同时把PHY芯片的工作模式也匹配上两边对齐了链路才能起来。EMIO UART0Zynq的PS端UART控制器默认可以走MIO管脚也可以走EMIO管脚。MIO管脚是PS端专用引脚数量有限BGA封装一般是54个而EMIO是PS连接到PL的接口数量更多64个可以灵活约束到FPGA的任意IO上。当MIO资源被其他外设挤占或者是板卡设计时把串口接到了PL侧引脚上就必须把UART0从MIO切到EMIO然后在XDC文件中做管脚约束。这个需求的典型应用场景包括自研板卡的串口调试口设计、以太网PHY芯片选型后的接口适配、以及需要同时跑多路串口或以太网的自定义硬件平台。1.2 方案选型的逻辑推演为什么要把这两个配置放在一起讨论因为它们在Zynq开发流程里属于同一层级的操作——都是在Vivado里的Zynq PS配置界面Zynq Block Design中完成的而且都涉及PS-PL接口的打通。我在多个项目里实测下来最稳妥的做法是在Vivado Block Design中添加Zynq PS核双击打开配置界面在PS-PL Configuration页面中把UART0的接口从MIO改为EMIO在I/O Configuration页面中把GEM的接口模式从RGMII切换为MII或GMII生成比特流后在XDC中额外约束EMIO的管脚位置这个方案的优点是完全绕开了硬件改板纯逻辑层面就能解决问题。缺点是EMIO的信号路径经过PL内部路由会引入额外的时延和时序约束要求对高速接口如GMII的125MHz时钟来说走线约束要格外小心。对比一下其他方案有人会倾向于直接用MIO管脚但MIO数量有限且不可灵活布局也有人会在PL侧用IP核重新实现一个UART控制器如AXI UART Lite但这样会占用额外的LUT资源而且和PS端的中断、DMA机制对接更麻烦。所以在资源足够、需要PS原生外设功能的场景下改成EMIO是最合理的。这里有个容易踩的坑MII转GMII并不是在PS配置界面里勾选一下就完事的。GEM的接口模式由两个地方共同决定PS内部的GEM配置以及外部PHY芯片的接口模式。如果PHY芯片是MII接口而GEM配成GMII数据完全对不上协议层再怎么调都没用。所以先确认PHY芯片型号和支持的接口模式再动手配置。1.3 适用人群与前置知识这篇配置笔记适合以下三类人阅读正在用Zynq做板卡开发的硬件工程师遇到了网络不通、串口无输出的问题想把PS端外设映射到PL管脚上的FPGA逻辑工程师从纯软件转过来做Zynq SoC开发的朋友需要理解PS-PL接口的基本概念需要具备的前置知识不多但有几个基础概念必须先弄清楚MIO和EMIO的区别这在后面的章节详细说明、Zynq PS端外设控制器的基本结构、以及Vivado Block Design的基本操作流程。如果你对这些概念不太熟悉建议先走一遍Vivado的Hello World例程再回来看这篇配置笔记。2. MIO与EMIO的核心差异与选择依据2.1 MIO和EMIO到底是什么很多刚接触Zynq的人会对MIO和EMIO这两个缩写一头雾水。简单说MIOMultiplexed I/O是PS端专用的多功能引脚直接连接到PS的SoC内部不经过PL所以访问延时低、时序简单EMIOExtended Multiplexed I/O则是PS外设控制器和PL之间的桥接接口信号从PS侧出去后要先经过PL内部路由再约束到PL的IOB上。拿UART0举例当配置为MIO模式时串口的TX、RX两条线直接接到芯片的MIO引脚上软件直接操作PS寄存器就能收发数据完全不涉及FPGA逻辑。当配置为EMIO模式时UART0的TX、RX信号会出现在PL侧的接口列表里你需要手动在Block Design中创建端口并将其约束到FPGA的物理引脚上然后综合、实现、生成比特流。MIO和EMIO的关键区别我用一张表列出来对比项MIOEMIO信号路径PS内部直连引脚经过PL内部路由后再到引脚引脚数量54个BGA封装具体看型号64个可自由分配到PL IO灵活度固定位置不可自由布局可约束到任意PL引脚访问延时低无需时序约束中需要XDC约束占用FPGA资源不占用占用少量LUT和布线资源典型场景调试串口、SDIO、USB等MIO被占满或需要灵活布局从这张表能看出来MIO适合“固定管脚、要求低延时”的场景EMIO适合“管脚灵活、不受PS约束”的场景。在实际板卡设计中很多硬件工程师为了布局方便会把串口、以太网等接口放到PL侧这时就必须用EMIO。2.2 为什么以太网接口更需要谨慎选择以太网接口比串口复杂得多。MII接口需要14根信号线GMII需要24根信号线RGMII只要12根但时序要求更高。如果你在配置时把MII转成GMII不仅数据线数量翻倍时钟频率也从25MHzMII的TX/RX时钟提升到125MHzGMII的GTXCLK/RXCLK。这里有一个工程上的现实问题MIO引脚的数量和位置是固定的你很难在MIO上找到足够多、且走线合理的引脚来布GMII接口。所以GMII接口通常必须通过EMIO来引出这就意味着以太网信号要经过PL内部布线在125MHz时钟下时序收敛会成为一个大问题。我在做第一个千兆以太网项目时就遇到过GMII信号经过PL后时序不收敛的情况。后排查下来问题出在XDC中的管脚约束太随意没有对GTXCLK做专门的时钟约束导致综合工具无法正确推断时钟路径。后来在XDC中显式创建了GTXCLK的生成时钟约束问题才解决。2.3 MIO与EMIO的选型决策树在实际项目中怎么快速决定用MIO还是EMIO我总结了一个简单的决策流程先查芯片封装确认MIO引脚数量和现有占用情况看外设接口是否需要高速信号以太网、USB、SDIO等如果高速接口数量多优先考虑走EMIO看板卡布局如果PHY芯片、串口芯片的位置离PL引脚近走EMIO可以缩短走线长度如果MIO资源充足且外设对延时敏感如调试串口、实时控制信号优先走MIO如果MIO资源紧张或者外设信号需要连接到PL内部逻辑比如UART数据要做协议解析走EMIO这个决策树的本质是平衡“性能、灵活度、开发复杂度”三者的关系。MIO是性能最好但最不灵活的方案EMIO是灵活但需要更多开发工作的方案。实操心得如果是调试用的串口我建议优先用MIO因为调试串口对管脚位置不敏感而且MIO模式不需要任何FPGA逻辑参与出了问题时排查路径更短。只有当MIO确实被占满时才考虑EMIO方案。3. MII转GMII的配置实操全流程3.1 配置前的硬件与工程准备动手配置之前先把准备工作做足免得做到一半才发现环境不对。首先是确认PHY芯片型号。不同的PHY芯片支持的接口模式不同有些只支持RGMII有些是GMII/MII可配置的。常见的有Marvell 88E1512支持RGMII/SGMII、Realtek RTL8211E支持RGMII、TI DP83867支持RGMII/SGMII等。如果你用的是GMII接口的PHY还需要确认PHY芯片的接口模式配置引脚如RX_DV、TX_EN等是否正确设置。其次是确认Vivado版本。Zynq的Block Design配置界面在不同版本中略有差异但核心选项位置基本一致。我的测试环境是Vivado 2023.1配置路径在Zynq PS的I/O Configuration页面中。最后是确认参考时钟。GMII接口的GEM控制器需要125MHz的参考时钟这个时钟通常由PS的时钟输出或外部晶振提供。在配置界面里你需要确认GEM的时钟源选择正确否则即使接口模式对了也没有时钟信号。我做项目时习惯先画一张硬件接口映射表把PHY芯片的信号名和Zynq的引脚信号一一对应起来然后检查是否存在信号反转、差分对匹配等问题。这个习惯帮我避免了很多低级错误。3.2 在Vivado Block Design中配置GEM接口下面进入核心配置环节。我以Vivado 2023.1为例详细说明操作步骤。第一步创建或打开一个包含Zynq PS核的Block Design。在Diagram窗口中双击Zynq PS核打开Re-customize IP对话框。第二步在左侧导航栏选择I/O Configuration展开Ethernet选项。你会看到GEM控制器的配置项不同的Zynq型号在这里的选项名称略有不同。比如Zynq-7000系列通常显示为Gigabit Ethernet ControllerZynq UltraScale系列则是GEM。第三步在Ethernet接口下将接口模式从默认的RGMII切换为GMII或MII。注意这里的选择不是随便选的必须和PHY芯片的实际接口模式完全一致。如果你的PHY支持MII和GMII双模式通过PHY芯片的配置引脚来选择。此时GEM侧的配置必须和PHY的物理配置一致。第四步确认GMII接口信号出现在Block Design中。切换模式后你会看到GEM的接口信号从12根左右的RGMII信号变为24根左右的GMII信号。这些信号包括GTXCLK、GTXEN、GTXD[7:0]、RXDV、RXCLK、RXD[7:0]、RXER、TXER、MDIO、MDC等。第五步为GEM接口创建外部端口。在GMII接口的信号上右键选择Make External创建对应的端口供后续XDC约束使用。这里有一个非常重要的细节GMII的GTXCLK和RXCLK是不同方向的时钟信号。GTXCLK是GEM发送数据时提供给PHY的时钟频率125MHz千兆模式或25MHz百兆模式RXCLK是PHY接收数据时提供给GEM的时钟由PHY根据收到的数据流恢复频率同样是125MHz或25MHz但来源不同。这两根时钟在XDC中需要分别约束且RXCLK是外部异步时钟处理不好会导致时序问题。3.3 GMII接口的XDC约束详解配置完Block Design后生成HDL、综合、布局布线然后就需要写XDC约束了。GMII接口的XDC约束是很容易被忽略但极其关键的环节。首先是管脚位置约束。你在Block Design中创建的GMII外部端口需要一一映射到FPGA的物理引脚上。引脚位置通常由PCB布线决定所以这一步是照抄板卡的原理图。比如# GMII TX接口 set_property PACKAGE_PIN AB12 [get_ports gmii_txd[0]] set_property PACKAGE_PIN AB11 [get_ports gmii_txd[1]] # ... 其他信号其次是电平标准约束。GMII接口的IO电平通常为1.8V或2.5V取决于PHY芯片的IO电源域电压。Zynq的PL侧IO支持多种电平标准需要根据PHY芯片的供电电压来设置。如果电平不匹配轻则信号质量差、偶尔丢包重则烧毁PHY芯片。最后是时钟约束。GMII接口的时序约束是整个工程中最容易出问题的部分。GTXCLK是GEM输出给PHY的时钟如果你在外部端口上把它当作普通信号处理综合工具无法正确分析这条路径的时序。正确做法是为GTXCLK创建一个生成时钟约束并将其设为发送数据的参考时钟# 假设GTXCLK连接到了某个MMCM的输出或者是直接的外部时钟 create_generated_clock -name gem_gtxclk -source [get_pins mmcm/CLKOUT0] -divide_by 1 [get_ports gtclk_out]RXCLK的约束更特殊。它是PHY输出的异步时钟和PS端的系统时钟没有任何相位关系。对于跨时钟域的RX数据GEM内部会做同步处理但XDC中必须把这个时钟定义为异步时钟否则时序分析会报告大量violation# 将RXCLK定义为输入时钟 create_clock -name gem_rxclk -period 8.000 [get_ports rxclk] # 设置异步时钟域 set_clock_groups -asynchronous -group [get_clocks -include_generated_clocks gem_rxclk] -group [get_clocks -include_generated_clocks gem_gtxclk]实操心得第一次做GMII接口时我因为没有约束RXCLK导致综合报告里出现几百条时序violation看着吓人。后来我把RXCLK和GTXCLK设置为异步时钟域后violation瞬间清零。要知道GMII的RXCLK和GTXCLK虽然都叫125MHz但它们是不同晶振/不同PHY恢复出来的时钟频率可能有几十ppm的偏差必须按异步处理。3.4 验证GMII接口是否配置成功配置完成后怎么验证接口是否真的通了我一般分三步做第一步检查phy链路状态。在FSBLFirst Stage Boot Loader阶段或Linux内核启动时观察GEM的链接状态寄存器GEM_NWCTRL、GEM_NWSR的link up位。如果链路没起来寄存器值不对说明物理层有问题可能是接口模式不匹配、XDC约束错误或PHY芯片配置不对。第二步检查MAC层通信。在U-Boot中使用ping指令测试网络连通性。U-Boot中的网络驱动会完成GEM的初始化如果U-Boot下能ping通说明MAC层和PHY层的配置基本正确。第三步跑吞吐率测试。在Linux下使用iperf3测试网络吞吐。如果协商出来是千兆模式实测吞吐应该能达到900Mbps以上考虑到协议开销如果只有百兆模式吞吐在90Mbps左右。通过这个数据可以反向确认GEM和PHY协商的速率是否符合预期。有时候U-Boot下ping不通但Linux下能通这是因为Linux下的PHY驱动会重新做PHY初始化覆盖了U-Boot的配置。所以最终验证以Linux下的ethtool信息为准。我遇到过PHY芯片的接口模式引脚被上下拉电阻配置错导致PHY工作在RGMII模式但GEM配置为GMII的诡异情况U-Boot直接死机Linux却启动且自动协商到了百兆模式。这种问题不通过ethtool查看实际协商速率根本发现不了。3.5 百兆与千兆模式下的信号时序差异配置MII和GMII时还有一个容易忽略的问题百兆模式和千兆模式的时序完全相同但频率不同。MII模式TX_CLK和RX_CLK都是25MHz数据线4位TXD[3:0]、RXD[3:0]一个时钟周期传输一个4位数据组成一个字节需要两个时钟周期。GMII模式GTX_CLK和RX_CLK都是125MHz数据线8位TXD[7:0]、RXD[7:0]一个时钟周期传输一个8位数据。RGMII模式TXC和RXC都是125MHz千兆或25MHz百兆数据线4位DDR模式下上下沿各传输一次一个时钟周期传输一个字节。看到没有RGMII和GMII在千兆模式下虽然都是125MHz、8位有效数据但物理线上的信号数量和边沿触发方式完全不同。RGMII只有4根数据线用DDR双沿传输GMII是8根数据线单沿传输。如果你把GEM配置为GMII但PHY工作在RGMII模式那么在GEM看来TXD[3:0]这4根线上有数据RXD[7:4]则完全没信号而且没有有效的TXC/RXC时钟对齐关系最终表现就是链路起不来或者协商到最低速率。这种低级错误在我见过的项目里出现过不止一次。所以配置前一定要打开原理图确认PHY芯片的接口模式配置引脚比如一些PHY芯片的MODE[2:0]引脚在高电平还是低电平以此判断PHY实际工作在什么模式然后让GEM的配置跟着走。4. EMIO UART0的配置实操全流程4.1 Block Design中启用EMIO UART0以太网搞定了我们来看第二半场——把UART0从MIO切换到EMIO。打开Zynq PS的配置界面在Peripheral IO Pins标签页里展开UART选项。你会看到UART0和UART1两个控制器每个控制器都可以选择使用MIO引脚或EMIO引脚。默认情况下UART0和UART1都挂在MIO上。要切换到EMIO只需要把UART0对应的MIO引脚配置取消勾选然后在下面的EMIO部分勾选UART0接口。这个操作的直观效果是Block Design中会出现uart0_tx和uart0_rx两个外部端口有些版本可能显示为UART0_TX和UART0_RX大小写因版本而异。这里有一个设计上的技巧如果你不想取消MIO的UART0而是希望MIO和EMIO同时使用UART0这种操作是不被支持的。每个UART控制器只能选择MIO或EMIO之一不能同时使用。如果需要两路串口就应该用UART0走EMIO、UART1走MIO或者反过来。配置完成后生成Block Design并创建HDL Wrapper。此时你会发现在顶层模块中多出了两个端口uart0_rx和uart0_tx。这两个端口就是UART0信号经过PL内部路由后从PS端引出的接口。4.2 UART0 EMIO的XDC管脚约束和GMII接口一样EMIO UART0也需要管脚约束。在XDC文件中将uart0_tx和uart0_rx信号约束到FPGA的PL引脚上set_property PACKAGE_PIN L20 [get_ports uart0_tx] set_property IOSTANDARD LVCMOS18 [get_ports uart0_tx] set_property PACKAGE_PIN M20 [get_ports uart0_rx] set_property IOSTANDARD LVCMOS18 [get_ports uart0_rx]注意几个细节方向千万别搞错。uart0_tx是PS输出到外部设备的信号pin约束为输出或inoutuart0_rx是外部设备发给PS的信号pin约束为输入。如果方向和板卡上串口芯片的走线接反了串口无论如何都不会有输出。电平标准必须匹配。如果外部串口芯片是1.8V供电就设LVCMOS18如果是3.3V就设LVCMOS33。Zynq PL侧的IO bank电压决定了支持的电平标准所以约束前先查一下所在bank的VCCO电压。强制使用错误的IOSTANDARD轻则信号乱码重则损坏器件。如果板卡上有上拉或下拉电阻要注意默认电平状态是否符合UART空闲电平要求。UART的TX和RX在空闲状态下都是高电平逻辑1如果外部硬件把RX拉低了会导致检测到起始位接收到垃圾数据。这个问题很难查因为软件层面看不出任何异常。4.3 串口收发验证与常见现象分析约束完成后重新综合、实现、生成比特流然后就可以进行实机验证了。第一步连接串口线。将USB转串口模块的TX连接到Zynq的uart0_rx引脚USB转串口模块的RX连接到Zynq的uart0_tx引脚。注意是交叉连接我见过不少人把TX接TX、RX接RX结果数据全发到了自己身上串口当然没有输出。第二步在终端软件如MobaXterm、SecureCRT、PuTTY中新建串口会话设置波特率、数据位、停止位等参数。Zynq UART默认配置通常是115200、8N1但有些BSP会把默认波特率改成9600或57600需要看启动打印信息。第三步上电启动观察串口输出。如果一切正常你会看到BootROM的启动信息、FSBL的打印信息以及U-Boot的启动日志。如果串口没有输出不要慌按下面的排查顺序来检查XDC中的管脚方向对不对用万用表测量TX引脚的电压空闲状态应该是高电平检查终端软件的波特率设置用示波器查看TX引脚是否有信号跳变我遇到过一个比较刁钻的问题在Vivado里配置了EMIO UART0XDC约束也做了但比特流下载后串口依然无输出。后来发现是Block Design中的EMIO端口没有勾选Enable选项导致信号根本没有连接到PL。在Vivado的某些版本中你需要在PS的配置界面的EMIO页面手动勾选UART0的使能选项否则即使端口出现在接口列表里也不会有实际信号。还有一个常见问题是UART的波特率在EMIO模式下比MIO模式下更容易出错。原因是EMIO路径经过PL内部布线增加了信号延时和抖动。如果板上有两个串口同时工作相互之间的干扰可能导致误码。此时可以尝试降低波特率或者检查PCB的串口走线是否远离高速信号线。4.4 EMIO UART0的中断与DMA配置如果你的软件方案中串口数据量大需要以中断或DMA方式接收数据那么还需要在PS端配置相应的中断控制器。Zynq的UART控制器支持两种数据接收方式轮询和中断。在EMIO模式下中断机制和MIO模式完全一样都是通过UART控制器的中断寄存器触发的区别只在于物理信号路径。所以从软件角度看EMIO UART0和MIO UART0对驱动完全透明驱动不需要做任何修改。但如果你在PL侧使用了AXI UART Lite那就完全不是一回事了。AXI UART Lite是一个独立的IP核有自己的寄存器接口和中断线它的中断信号通过AXI Interconnect连接到PS的中断控制器GIC的PL端中断输入IRQ_F2P。在这种架构下软件的驱动模型就完全不同了不能在Linux下直接使用/dev/ttyPS0设备节点而需要为AXI UART Lite编写专门的驱动或者使用uartlite驱动。所以EMIO UART0的价值就在于它让你在保持PS原生UART驱动不变的前提下获得管脚布局的灵活性。软件工作量几乎为零。4.5 硬件设计中的管脚选择建议最后聊聊EMIO UART0在硬件设计时的管脚选择。理论上EMIO可以连接到PL侧任意一个user IO引脚上。但实际项目中有几个原则需要遵守第一优先选择靠近目标连接器、走线短的引脚。UART信号虽然只有9.6Kbps到4Mbps的速率不是高频信号但走线过长仍然会引入串扰和衰减在高速波特率下会造成误码。第二避免选择靠近时钟引脚、差分对的引脚。这些引脚附近的电容耦合效应可能影响UART信号的噪声容限。第三避免选择已分配给DDR、PCIe、MIPI等高速接口的引脚。这些引脚通常有特殊的电平标准和阻抗要求强行用作UART可能违反bank的电气规范。第四管脚约束时考虑bank电压。如果选中的PL引脚所在bank的VCCO是1.8V而外部串口芯片工作在3.3V电平那么就需要添加电平转换电路否则无法通信。我在自研板卡时一般会预留一组专门的UART测试引脚通常4~6个包含TX、RX、RTS、CTS全部放在一个比较偏的位置方便后期调试和飞线。这些引脚在原理图上就预留好EMIO的路径后期软件配置时只需要在XDC中修改管脚约束即可。5. 常见问题与排查技巧实录5.1 网络不通的逐步排查法MII转GMII配置完成后网络不通是最常见的问题。我把自己实战中的排查顺序整理成了下面的速查表照着做可以省下大量时间排查步骤操作内容确认方法1确认PHY芯片接口模式查看原理图中PHY的MODE引脚配置确认是MII、GMII还是RGMII2确认GEM配置和PHY一致在Vivado中查看GEM接口模式和PHY的模式必须相同3确认XDC管脚约束检查GMII所有信号的PACKAGE_PIN是否和原理图一致4确认电平标准检查IOSTANDARD是否和PHY的IO电源电压匹配5确认时钟约束检查GTXCLK、RXCLK是否正确约束时钟域是否分组6确认PHY复位检查PHY的复位引脚是否被正确释放有些PHY需要几百毫秒的复位时间7检查U-Boot下的link状态在U-Boot中运行mdio read命令读取PHY寄存器确认link状态位8检查Linux下的协商速率在Linux中运行ethtool eth0确认速率、双工模式这里面有个小细节很多人不知道PHY芯片的复位不仅仅是一个GPIO控制问题还牵扯到PHY的配置加载时序。很多PHY芯片在复位释放后需要从配置引脚或EEPROM中加载工作模式配置这个过程需要几个毫秒到几十毫秒。如果GEM在PHY还没有完成配置时就开始初始化可能会读到错误的PHY ID或协商失败。SoC启动时的初始化顺序寄存器配置不要急着做。5.2 时序收敛问题的实战解法GMII接口经过PL内部路由后时序收敛是最大的难点。我个人的经验是如果在综合报告中出现大量的GMII时序violation先别急着调整XDC的约束而是先检查以下三个地方。第一检查GTXCLK的约束方式。GMII的GTXCLK是GEM的输出时钟它的约束方式直接决定了发送数据的时序分析边界。如果你没有为GTXCLK创建生成时钟工具会把它当作普通数据信号处理导致无法正确分析。这个我在前面已经详细说过不再重复。第二检查GMII数据信号与GTXCLK的相位关系。在GMII模式中发送数据信号GTXD[7:0]和GTXEN以GTXCLK为参考在时钟上升沿稳定。如果PCB走线长度不一致或者PL内部路由长度差异大可能导致数据信号在时钟沿附近变化造成时序violation。解决方法是调整XDC中的set_output_delay约束给数据信号和时钟之间留出足够的建立时间窗口。第三考虑降低GMII的工作频率。如果你在测试中发现GMII链路不稳定、时序收敛困难而且你的实际业务对带宽要求不高可以把GEM配置为百兆模式MII这样时钟频率降到25MHz时序收敛压力大幅减小。我有一次在原型调试阶段就是用这个方法快速把网络调通后面再做性能优化。5.3 串口乱码与无输出的根因分析串口问题虽然比以太网简单但排查起来有时候更头疼因为串口输出“没有”和“乱码”是两种不同的根因方向。串口完全无输出的排查XDC管脚约束错误TX、RX方向接错或者引脚位置不对EMIO端口在Block Design中未使能波特率不匹配软件设置的波特率和实际硬件收到的波特率不一致启动流程问题FSBL或U-Boot中串口初始化失败串口乱码的排查波特率漂移如果板上晶振精度差波特率可能出现偏差导致乱码电平标准不匹配1.8V和3.3V混用可能导致信号幅度不足地线不稳串口通信对地线比较敏感如果USB转串口模块和Zynq板卡的地有压差容易乱码中断冲突如果系统中有其他外设抢占CPU资源UART接收缓冲区溢出导致数据丢失和乱码针对乱码问题我有个小技巧把USB转串口模块用一根短线独立接地不要通过电脑的USB地线间接共地。很多廉价USB转串口模块的隔离不好电脑地线上有噪声会直接影响串口信号质量。5.4 软硬件协同调试的建议顺序最后分享一个我自己总结的软硬件协同调试顺序。Zynq开发最怕的是软硬件边界不清出了问题不知道是硬件问题还是软件问题。我的做法是第一步先验证硬件通路。用纯逻辑的方法测试PL引脚是否正常工作。比如把UART的TX引脚设置为普通GPIO输出手动拉高拉低用示波器或万用表测量引脚电压变化。如果引脚电压能跟随GPIO的变化说明PL引脚到连接器的物理通路是好的。第二步验证PS配置。在裸机工程中只初始化UART0和GEM不加载操作系统。裸机环境排查问题最简单因为整个系统可控不需要考虑操作系统调度、驱动框架等干扰因素。第三步验证Linux下行为。如果裸机下功能正常但Linux下不正常问题大概率出在设备树配置或驱动上。此时检查设备树中的UART节点和以太网节点确认正确的compatible字符串、时钟资源、中断号等。这个顺序的本质是先隔离物理层问题再隔离逻辑层问题最后才处理软件层问题。每前进一步都确保前面的环节都是正常的这样排查效率最高。实操心得在Zynq开发中设备树device tree中EMIO UART0的配置特别容易出错。因为设备树里并不需要显式指定“EMIO”这个模式它只需要指定使用的UART控制器编号如serial0指向UART0而UART0走MIO还是EMIO是完全由硬件比特流决定的。所以如果比特流中配置了EMIO UART0但设备树中alias没设置好Linux内核可能默认使用UART1做控制台导致你看到串口0没有输出。这个细节我吃了不少亏。6. 经验总结与踩坑备忘6.1 一定要记住的五个关键点在完成MII转GMII和EMIO UART0的配置后我总结了五个最关键的经验希望你能少走弯路第一先确认PHY芯片接口模式再配置GEM这是所有网络调试的前提。接口模式不匹配后面的工作全是白费。第二GMII的RXCLK必须按异步时钟处理。这不仅是工具规范问题更是数据正确性的根基。把RXCLK和GTXCLK设置为异步时钟域可以减少大量无意义的时序violation也符合真实硬件的行为。第三EMIO UART0的XDC中方向约束比位置约束更容易出错。TX是输出、RX是输入这个看起来简单但在实际项目中因为命名不规范有人把uart0_tx命名为uart0_tx_from_ps经常搞混。第四设备树中的alias配置直接影响Linux控制台输出。UART0走EMIO后设备树中必须确保stdout-path指向正确的serial节点否则Linux启动时控制台可能默默换到了别的串口上。第五调试过程中多用示波器和万用表不要一上来就怀疑软件。Zynq的调试串口信号用逻辑分析仪抓一下能省去大量猜谜时间。6.2 值得后续扩展的优化方向这次配置解决了基础通信问题但真正要提升系统稳定性和性能还有几个方向值得深入管脚约束的时序优化GMII的125MHz信号经过PL内部布线时如果布局工具自动选的路由距离过长可以手动在XDC中添加区域约束把GEM的IO逻辑限制在特定bank。Linux驱动的性能调优如果网络吞吐不达标可以检查Linux内核中GEM驱动的tx-ring-size和rx-ring-size参数适当调大可以提升高吞吐场景下的性能。多路串口的扩展方案如果一个UART不够用可以考虑UART0走EMIO、UART1走MIO实现双串口调试。如果还不够才考虑用AXI UART Lite来增加更多串口通道。6.3 最终实操建议根据我实际调试Zynq十年左右的经验最后给几条最实在的建议做板卡设计时把调试串口和以太网的信号预留到容易测量的位置尽量留出测试点。真到调试的时候这些测试点能救命。每次修改Block Design配置后保存前都检查一下生成的外部端口数量和信号名防止漏掉某个信号导致综合报错。遇到问题时保留完整的综合日志和时序报告。很多玄学问题在经过多次综合后都能从报告中找到线索。在团队协作中把XDC约束文件和Block Design配置的变更记录保持同步。我们曾经因为同事改了XDC但忘记更新Block Design导致版本不一致浪费了一整天的调试时间。个人在实际操作中还有一个体会很多Zynq外设配置问题根因都不在配置本身而在配置之外的细节。比如PHY的复位时序、电源的上电顺序、时钟芯片的锁定时间这些硬件层面的因素往往比软件配置更影响系统的稳定性。做嵌入式开发软硬结合的能力很重要能心平气和地把信号测量、寄存器读取、日志分析这些基本功做扎实比会背一百个配置项更有价值。希望这篇配置笔记能帮你少踩几个坑。
返回列表