使用ZYNQ的PS外挂88E1111千兆网lwip调试不通(可以link up,ping不通,没数据通信),在网上搜索很多资料,没有太明确清晰的说法,因此记录一下调试过程,供有同样需求的参考。
前一篇介绍了88E1111的电路硬件配置及UDP客户端模板的应用程序分析和运行效果,TCP也类似,都可以直接使用SDK自动生成的模板,应用程序无需修改便可测试(我使用的平台是vivado2018.3)。
下面我们就一步一步找到最终的PHY驱动部分,以便TCP/UDP网络不通时进行适配修改。
如图为前一篇UDP客户端程序的main函数中网络接口初始化的位置:
进入xemac_add函数,最终执行的如下图,netif_add指定的初始化函数是xemacpsif_init。
进入xemacpsif_init函数,我们看到底层初始化函数实际上是low_level_init。
进入low_level_init函数,我们看到mac初始化函数是init_emacps。
进入init_emacps函数,我们看到PHY初始化函数是phy_setup_emacps。
进入phy_setup_emacps函数,我们看到PHY的LINKSPEED_AUTODETECT函数是get_IEEE_phy_speed。
进入get_IEEE_phy_speed函数,我们看到三个品牌的PHY各对应一个函数,我们使用的88E1111对应Marvell PHY。
进入get_Marvell_phy_speed函数,我们看到函数对PHY的寄存器读写操作来完成配置。查看88E1111手册可以看到RGMII模式有专门的章节描述PHY输入输出延时如图。
为了匹配通信时序,我们需要打开GTX_CLK和RX_CLK延时,延时修改在重置后才能生效,因此在get_Marvell_phy_speed函数如下位置(即软复位之前)添加IEEE_EXT_PHY_SPECIFIC_CONTROL_REG(即20寄存器)的bit7和bit1(即0x82)使能。
改写88E1111驱动后,重新运行程序,可以达到前一篇文章wireshark抓包软件的UDP客户端运行效果。
有的应用可能需要TCP示例,我们可以在SDK里新建一个TCP客户端如图:
TCP客户端的应用层程序跟UDP有所不同,但是网络接口硬件驱动是一模一样的,所以按照前面所述同样可以定位到TCP模板程序里88E1111的PHY驱动部分,在get_Marvell_phy_speed函数增加IEEE_EXT_PHY_SPECIFIC_CONTROL_REG的bit7和bit1(即0x82)使能后,网络可以正常ping通,并且TCP客户端连接发数。程序运行前需要打开一个TCP上位机服务器如图。
如下图是TCP客户端运行后三次握手建立连接和开始循环发送数据的wireshark抓包情况:
我们看到SDK自带模板TCP与UDP发送的数据稍有不同,对照程序一起来看一下,跟UDP一样在start_application函数中建立连接,并且对发送数据进行初始化,但TCP客户端的长度为TCP_SEND_BUFSIZE(宏定义为5*1460)如图,send_buf同样是在0x30-0x39循环变化。
跟踪TCP的发送函数transfer_data,实际在tcp_send_perf_traffic函数中发数如图,我们看到函数里直接将TCP_SEND_BUFSIZE长度的send_buf进行了tcp_write并且tcp_output,所以上位机收到的数据是直接从0x30开始的。
至此,参照我的调试过程,ZYNQ PS端+88E1111基于lwip协议栈的TCP/UDP客户端都可以正常网络通信了,为了方便大家有个基础的例子,我将完整的vivado和SDK工程上传在ZYNQ的PS外挂88E1111千兆网TCP/UDP客户端完整工程,包含TCP和UDP两个客户端,下载对应的程序即可。