黑金AX7Z100 FPGA开发板移植LWIP库(一)PS端

前言

LwIP是Light Weight (轻型)IP协议是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。AX7Z100开发板带有源码和教学视频,但不是AX7Z100开发板的,所以最初移植的时候遇到一些小问题困扰好长时间。因此笔者基于Vivado17.4整理比较详细的移植过程供后面参考。

一、Vivado 工程建立

1、新建一个空工程,名称为net_lwip_ps。
在这里插入图片描述
2、FPGA芯片选择xc7z100ffg900-2。
在这里插入图片描述

二、配置PS系统硬件

1、单击左侧导航栏的Create Block Design建立图形文件取名top,单击OK。
在这里插入图片描述
2、在图形文件中单击+号,在搜索栏输入zynq找到PS端的IP核
在这里插入图片描述
3、双击添加ARM核的IP。
在这里插入图片描述
4、双击IP核进入配置界面,因为PS端内嵌有两个以太网控制器不需要AXI总线扩展,所以勾选掉默认的AXI GP0接口
在这里插入图片描述
5、网络要通过串口测试,所以在Perioheral I/O Pins中开通串口
在这里插入图片描述
6、网络MAC的IP核Enet0需要开通
在这里插入图片描述
7、网络MACIP核Enet0控制外接PHY芯片的MDIO接口需要开通
在这里插入图片描述
8、以太网控制器采用RGMII工作方式,所以工作电压修改为:LVCMOS 1.8V
在这里插入图片描述
9、因为开发板DDR内存与默认不同,所以选择MT41J256M16 RE-125,单击OK退出。
在这里插入图片描述
10、单击自动连接生成引脚。
在这里插入图片描述
11、至此PS端开通网络的系统硬件配置完毕。但是直接编译原理图工程可能报错,所以通过Create HDL Wrapper将原理图工程转换为Verilog顶层工程
在这里插入图片描述

三、编译硬件生成bit文件

1、因为在引入PS端ZYNQ的ARM核过程中系统已经默认在工程文件夹下的/net_lwip_ps.srcs/sources_1/bd/top/ip/top_processing_system7_0_0/top_processing_system7_0_0.xdc文件中自动建立了管脚约束参数,其中包括网卡(Enet0)、串口(Uart0)和DDR的引脚约束,而且黑金开发板跟默认工程项目参数与其一致。所以TOP的项目约束文件可以省略,其它系统另行设置。因此直接编译生成bit文件(等待时间较长)
在这里插入图片描述
2、单击File菜单,导出bit文件的硬件信息给SDK应用。
在这里插入图片描述
3、导出对话框要勾选bit文件,单击OK。
在这里插入图片描述
至此,系统硬件部分bit文件编译导出完成,接下来将进入软件编程环节。

四、SDK程序设计

1、LwIP是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。在PS端跑裸机程序的时候因为没有操作系统所以要借助LwIP连接网络。SDK环境内嵌了LwIP的开发库保存在X:\Xilinx\SDK\2017.4\data\embeddedsw\ThirdParty\sw_services中(X为Vivado安装盘),Vivado17.4版本的SDK内嵌的是lwip141_v2_0。
在这里插入图片描述
2、但是在黑金的AX7Z100开发板中,以太网PHY芯片采用了MICREL公司的KSZ9031型号的芯片类型,与系统默认的PHY芯片不一致,所以SDK开发包中的LwIP库需要打补丁。打开lwip141_v2_0文件夹,进入lwip141_v2_0\src\contrib\ports\xilinx\netif文件夹找到xemacpsif_physpeed.c文件。
在这里插入图片描述
3、打开xemacpsif_physpeed.c文件在宏定义部分添加PHY芯片的ID信息。

#define PHY_DETECT_REG  						1
#define PHY_IDENTIFIER_1_REG					2
#define PHY_IDENTIFIER_2_REG					3
#define PHY_DETECT_MASK 					0x1808
#define PHY_MARVELL_IDENTIFIER				0x0141
#define PHY_TI_IDENTIFIER					0x2000
#define PHY_XILINX_PCS_PMA_ID1			0x0174
#define PHY_XILINX_PCS_PMA_ID2			0x0C00

// === Add by Yang ziheng ===//
#define MICREL_PHY_IDENTIFIER					0x22
#define MICREL_PHY_KSZ9031_MODEL				0x220
// === Add end ===//

#define XEMACPS_GMII2RGMII_SPEED1000_FD		0x140
#define XEMACPS_GMII2RGMII_SPEED100_FD		0x2100
#define XEMACPS_GMII2RGMII_SPEED10_FD		0x100
#define XEMACPS_GMII2RGMII_REG_NUM			0x10

4、在代码中搜索get_IEEE_phy_speed函数添加补丁代码。

static u32_t get_IEEE_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr)
{
	u16_t phy_identity;
	u32_t RetStatus;

	XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_IDENTIFIER_1_REG, &phy_identity);
	
	// === Add by Yang ziheng ===//
	if (phy_identity == MICREL_PHY_IDENTIFIER)
	{
		RetStatus = get_phy_speed_ksz9031(xemacpsp, phy_addr);
	} // === Add end ===//
	else if (phy_identity == PHY_TI_IDENTIFIER) 
	{
		RetStatus = get_TI_phy_speed(xemacpsp, phy_addr);
	}
	else 
	{
		RetStatus = get_Marvell_phy_speed(xemacpsp, phy_addr);
	}

	return RetStatus;
}

5、在文件中添加补丁代码中的KSZ9031型号芯片速度检测函数get_phy_speed_ksz9031

// === Add by Yang ziheng ===//
static u32_t get_phy_speed_ksz9031(XEmacPs* xemacpsp, u32_t phy_addr)
{
	u16_t temp;
	u16_t control;
	u16_t status;
	u16_t status_speed;
	u32_t timeout_counter = 0;
	u32_t temp_speed;
	u32_t phyregtemp;
	xil_printf("Start PHY autonegotiation \r\n");
	XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2);
	XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control);
	control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK;
	XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control);
	XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
	XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);
	control |= IEEE_ASYMMETRIC_PAUSE_MASK;
	control |= IEEE_PAUSE_MASK;
	control |= ADVERTISE_100;
	control |= ADVERTISE_10;
	XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);
	XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
		&control);
	control |= ADVERTISE_1000;
	XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
		control);
	XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
	XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,
		&control);
	control |= (7 << 12); /* max number of gigabit attempts */
	control |= (1 << 11); /* enable downshift */
	XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,
		control);
	XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
	control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;
	control |= IEEE_STAT_AUTONEGOTIATE_RESTART;
	XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
	XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
	control |= IEEE_CTRL_RESET_MASK;
	XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
	while (1) {
		XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
		if (control & IEEE_CTRL_RESET_MASK)
			continue;
		else
			break;
	}
	XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
	xil_printf("Waiting for PHY to complete autonegotiation.\r\n");
	while (!(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE)) {
		sleep(1);
		XEmacPs_PhyRead(xemacpsp, phy_addr,
			IEEE_COPPER_SPECIFIC_STATUS_REG_2, &temp);
		timeout_counter++;
		if (timeout_counter == 30) {
			xil_printf("Auto negotiation error \r\n");
			return;
		}
		XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
	}
	xil_printf("autonegotiation complete \r\n");
	XEmacPs_PhyRead(xemacpsp, phy_addr, 0x1f,
		&status_speed);
	if ((status_speed & 0x40) == 0x40)/* 1000Mbps */
		return 1000;
	else if ((status_speed & 0x20) == 0x20)/* 100Mbps */
		return 100;
	else if ((status_speed & 0x10) == 0x10)/* 10Mbps */
		return 10;
	else
		return 0;
	return XST_SUCCESS;
}
// === Add end ===//

6、单击File菜单SDK选项进入SDK开发环境,新建App工程取名main,单击下一步。
在这里插入图片描述
7、选择lwIP Echo Server后单击Finish。
在这里插入图片描述
8、工程文件建好后如下图
在这里插入图片描述

五、系统测试

1、在SDK开发环境中右击main工程文件,编译工程
在这里插入图片描述
2、在运行配置窗口勾选复位和FPGA编程选项,单击Run
在这里插入图片描述
3、在打开的UART0口的超级终端程序中显示网络信息(如显示不全,上面操作有误)
在这里插入图片描述
4、另打开超级终端程序,以telnet模式登录开发板,键盘输入字符会被回写显示,实验完毕。
在这里插入图片描述

  • 2
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

气血龙渊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值