1. 问题背景:为什么需要定制LWIP库
在实际的Zynq项目开发中,我遇到过这样一个棘手的问题:使用Vivado 2017.4版本搭建了一个通过GTX高速串行接口驱动SFP光模块的系统,硬件设计看起来完美无缺,但软件端就是无法建立网络连接。经过深入排查,发现问题出在Xilinx SDK自带的LWIP协议栈上。
这个问题的根源有两个方面。首先是Vivado 2017.4版本的一个新bug:在早期版本中,当你在PL部分使用1G/2.5G Ethernet PCS/PMA或SGMII IP核时,Vivado会自动在生成的xparameters.h头文件中添加相关的宏定义。这些宏定义包括XPAR_GIGE_PCS_PMA_1000BASEX_CORE_PRESENT和XPAR_PCSPMA_1000BASEX_PHYADDR(对于1000BASEX模式),或者是XPAR_GIGE_PCS_PMA_SGMII_CORE_PRESENT和XPAR_PCSPMA_SGMII_PHYADDR(对于SGMII模式)。
这些宏定义在LWIP库的底层驱动代码中被用作编译选项,特别是在xemacpsif_physpeed.c和xemacpsif_hw.c这两个文件中。它们决定了MDIO接口如何配置外部PHY器件。由于1000BASEX PHY、SGMII PHY和普通PHY芯片的寄存器定义和配置方式存在显著差异,这些宏定义对于正确配置1G/2.5G Ethernet PCS/PMA或SGMII IP核至关重要。
然而在2017.4版本中,这些宏定义不再自动生成,导致LWIP库无法正确配置这些IP核。第二个问题是LWIP底层驱动自身的设计缺陷:只要在PL部分使用了这些IP核,LWIP就会强制使用特定的MDIO配置策略,即使你同时使用了与PS直接连接的RGMII接口PHY芯片,也会导致这些PHY无法被正常检测和配置。
2. 解决方案总览:定制化LWIP库的修改策略
面对上述问题,我采取的解决方案是对LWIP库进行深度定制。这个方案的核心思想是通过修改LWIP库的配置文件和底层驱动代码,手动添加缺失的宏定义,并解决MDIO接口配置的限制问题。
具体来说,我需要完成以下几个关键修改:首先修改LWIP库的元数据文件(.mld和.tcl文件),在BSP设置中添加自定义的配置选项;然后在底层驱动代码中调整条件编译的逻辑,使得MDIO接口的配置策略更加灵活;最后确保这些修改能够正确生成所需的宏定义,并适应不同的工作模式(1000BASEX或SGMII)。
这个方案的优点在于它不需要修改硬件设计,完全通过软件层面的调整解决问题。而且修改后的LWIP库保持了向后兼容性,既支持传统的RGMII接口PHY芯片,也支持通过GTX连接的SFP光模块。在实际项目中,这种灵活性非常重要,因为不同的应用场景可能需要不同的网络接口方案。
从实现难度来看,这个方案需要开发者对LWIP协议栈有一定的了解,特别是对Xilinx的移植版本的结构和配置机制要熟悉。但相对于重新设计硬件或等待官方修复,这个方案的实施周期和风险都更加可控。我在多个项目中采用了这个方案,都取得了良好的效果。
3. 详细实施步骤:修改LWIP库的具体操作
3.1 准备LWIP库副本
第一步是创建LWIP库的定制版本。找到Xilinx SDK安装目录下的LWIP库路径,通常是C:\Xilinx\SDK\2017.4\data\embeddedsw\ThirdParty\sw_services\lwip141_v2_0。将这个文件夹完整复制到你的工程目录下的sdk_repo\bsp文件夹中,并将副本重命名为lwip141_v2_05(版本号可以根据实际情况调整)。
这个步骤很重要,因为直接修改SDK自带的LWIP库会影响其他项目,而且升级SDK时修改可能会被覆盖。创建独立的副本可以确保修改的隔离性和可维护性。我建议为每个重要项目都维护一个独立的LWIP库副本,这样可以根据项目的具体需求进行定制化调整。
3.2 修改MLD文件添加配置选项
接下来修改lwip141_v2_05\data\lwip141.mld文件。这个文件定义了LWIP库在BSP配置中的选项界面。使用文本编辑器(如Notepad++)打开该文件,首先将版本号从OPTION VERSION = 2.0;修改为OPTION VERSION = 2.05;,这样可以确保BSP能够识别这是我们自定义的版本。
然后在该文件中添加新的配置类别和参数。需要添加的代码如下:
BEGIN CATEGORY pcs_pma_core_options
PARAM name = pcs_pma_core_options, desc = "Options setting the pcs pma core related parameters"
PARAM name = use_pcs_pma_core_on_zynq, desc = "Option if set to 1 ensures emacps is used as emio, and connect to pcs_pma_core in pl. Valid only for Zynq", type = bool, default = false;
PARAM name = use_1000basex, desc = "Option if set to 1 to ensures pcs_pma_core is using 1000basex mode", type = bool, default = false;
PARAM name = use_sgmii, desc = "Option if set to 1 to ensures pcs_pma_core is using sgmii mode", type = bool, default = false;
PARAM name = 1000basex_phy_address, desc = "Option to define the phy address corresponding to the set in pcs_pma_core in 1000basex mode", type = int, default = 0;
PARAM name = sgmii_phy_address, desc = "Option to define the phy address corresponding to the set in pcs_pma_core in sgmii mode", type = int, default = 0;
END CATEGORY
这段代码的作用是在BSP设置的LWIP参数窗口中增加一个名为pcs_pma_core_options的配置栏目,其中包含5个子选项:use_pcs_pma_core_on_zynq表示是否在PL端使用了1G/2.5G Ethernet PCS/PMA或SGMII IP核;use_1000basex和use_sgmii分别表示IP核的工作模式;1000basex_phy_address和sgmii_phy_address则分别对应两种模式下的PHY地址。
3.3 修改TCL文件生成宏定义
修改lwip141_v2_05\data\lwip141.tcl文件,这个文件负责根据BSP设置生成相应的宏定义。在文件中添加以下代码:
# PCS PMA CORE options
set use_pcs_pma_core_on_zynq [common::get_property CONFIG.use_pcs_pma_core_on_zynq $libhandle]
set use_1000basex [common::get_property CONFIG.use_1000basex $libhandle]
set use_sgmii [common::get_property CONFIG.use_sgmii $libhandle]
set 1000basex_phy_address [common::get_property CONFIG.1000basex_phy_address $libhandle]
set sgmii_phy_address [common::get_property CONFIG.sgmii_phy_address $libhandle]
if { $use_pcs_pma_core_on_zynq == true } {
puts $lwipopts_fd "#define USE_PCS_PMA_CORE 1"
}
if { $use_1000basex == true } {
puts $lwipopts_fd "#define XPAR_GIGE_PCS_PMA_1000BASEX_CORE_PRESENT 1"
puts $lwipopts_fd "#define XPAR_PCSPMA_1000BASEX_PHYADDR $1000basex_phy_address"
}
if { $use_sgmii == true } {
puts $lwipopts_fd "#define XPAR_GIGE_PCS_PMA_SGMII_CORE_PRESENT 1"
puts $lwipopts_fd "#define XPAR_PCSPMA_SGMII_PHYADDR $sgmii_phy_address"
}
puts $lwipopts_fd ""
这段代码的作用是根据BSP中的设置,在工程对应的lwipopts.h头文件中生成所需的宏定义。例如,如果你在BSP中设置了使用1000BASEX模式且PHY地址为6,那么就会生成#define XPAR_GIGE_PCS_PMA_1000BASEX_CORE_PRESENT 1和#define XPAR_PCSPMA_1000BASEX_PHYADDR 6这两个宏定义。这样就弥补了Vivado 2017.4版本中宏定义缺失的问题。
3.4 修改底层驱动代码解决配置限制
最后需要修改LWIP库的底层驱动代码,解决MDIO接口配置的限制问题。需要修改的文件是lwip141_v2_05\src\contrib\ports\xilinx\netif\xemacpsif_physpeed.c和xemacpsif_hw.c。
在这两个文件中,找到以下代码段:
#if XPAR_GIGE_PCS_PMA_1000BASEX_CORE_PRESENT == 1 || \
XPAR_GIGE_PCS_PMA_SGMII_CORE_PRESENT == 1
#define PCM_PMA_CORE_PRESENT
将其修改为:
#if USE_PCS_PMA_CORE == 1 && (XPAR_GIGE_PCS_PMA_1000BASEX_CORE_PRESENT == 1 || \
XPAR_GIGE_PCS_PMA_SGMII_CORE_PRESENT == 1)
#define PCM_PMA_CORE_PRESENT
这个修改的关键在于增加了USE_PCS_PMA_CORE == 1 &&这个条件。这样,只有当在BSP中明确设置了使用PCS/PMA核心时(即use_pcs_pma_core_on_zynq设为1),MDIO接口才会采用1G/2.5G Ethernet PCS/PMA或SGMII IP核的配置策略。如果这个选项设为0,LWIP库会使用标准的MDIO配置策略,从而不影响与PS直接连接的网口的正常使用。
这个修改解决了原始驱动中的设计缺陷,使得LWIP库能够同时支持传统的RGMII接口PHY和通过GTX连接的SFP光模块,大大提高了设计的灵活性。
4. 实际应用与测试:修改后的效果验证
完成上述修改后,需要在实际项目中验证修改的效果。首先在Vivado中创建或打开一个已有的项目,确保硬件设计包含了1G/2.5G Ethernet PCS/PMA或SGMII IP核,并且正确配置了GTX接口和SFP模块的连接。
导出硬件设计到SDK后,创建或修改BSP。在BSP的设置中,现在应该能看到新添加的pcs_pma_core_options配置栏目。根据实际硬件设计,正确设置这些选项:如果使用了PCS/PMA核心,将use_pcs_pma_core_on_zynq设为1;根据IP核的工作模式设置use_1000basex或use_sgmii;并正确设置PHY地址,这个地址必须与Vivado中IP核的配置完全一致。
然后创建一个LWIP示例工程,如echo server或http server,编译并下载到目标板中。通过串口终端观察程序输出,应该能看到PHY自动协商成功完成的消息,以及开发板的IP地址信息。如果使用1000BASEX模式,协商完成的消息可能会显示"autonegotiation complete"和"link speed for phy address 6: 1000"(假设PHY地址为6)。
在实际的网络通信测试中,可以使用网络调试工具(如ping或iperf)测试网络连接的稳定性和带宽。对于SFP光接口,特别注意检查光模块的发射和接收功率是否在正常范围内,这对于长期稳定运行至关重要。
我在多个项目中使用了这个修改方案,包括工业控制和通信设备,都取得了良好的效果。修改后的LWIP库不仅解决了Vivado 2017.4版本的兼容性问题,还提供了更灵活的配置选项,能够适应不同的网络接口需求。
5. 常见问题与调试技巧
在实际应用中,可能会遇到一些问题。一个常见的问题是PHY地址设置不正确。务必确保在BSP中设置的PHY地址与Vivado中IP核的配置完全一致,否则MDIO接口无法正确访问PHY寄存器。
另一个常见问题是时钟配置。1G/2.5G Ethernet PCS/PMA IP核需要正确的参考时钟,通常由PS提供一路200MHz的时钟。确保这个时钟的设置正确,并且在实际硬件中能够测量到稳定的时钟信号。
对于SFP光模块,需要注意不同型号的光模块可能有不同的特性。有些光模块需要额外的初始化序列或配置参数。如果遇到光模块无法正常工作的问題,可以尝试更换不同型号的光模块进行测试。
在调试MDIO接口时,可以通过在驱动代码中添加调试输出,打印MDIO读写操作的状态和结果。这有助于确定MDIO通信是否正常,以及PHY寄存器是否正确配置。
如果遇到网络连接不稳定或带宽不达标的问题,可以使用示波器或逻辑分析仪检查GTX接口的信号质量。确保GTX的发送和接收眼图符合规范要求,这是高速串行通信稳定性的基础。
最后,记得在修改LWIP库后,彻底清理和重新编译工程,包括BSP和应用程序。有时候旧的编译结果可能会影响新修改的效果,导致一些难以理解的问题。
180



被折叠的 条评论
为什么被折叠?



