Artix7 Microblaze下调试SDK官方lwIP RAW Mode TCP Server Application例程(详细说明)

Vivado 2019.1

FPGA: Artix7 XC7A100T
DDR3: MT41K256M16TW-107
PHY: RTL8211F(商业级)

为加快进入application,设置如下:
1.禁用autodetect, phy_link_speed设为100Mbps(此时autonegotiation被禁止,大大加快进入程序)
2.禁用dhcp, 使用默认IP地址设置(不用等待dhcp配置,加快速度)

先对SDK作简单的调整:
1.关闭保存自动编译

2.显示行数
 

 

Vivado新建lwip例程所必须的工程,BD如下:

1. AXI 1G/2.5G Ethernet Subsystem

 只需要设置首页,其他默认

2. AXI Direct Memory Access (此IP在自动连线时软件会自动添加!)

 3.Concat (一共5个中断通过AXI Interrupt Controller接入Microblaze,一定要全部接入MB中,否则例程不能正常工作)

 4.AXI Interrupt Controller

 

 

 5. AXI Timer (Timer为例程提供节拍)

由AXI 1G/2.5G Ethernet Subsystem IP 引出的引脚连接到RTL8211F芯片

 管脚分配约束如下:

#RGMII
set_property IOSTANDARD LVCMOS33 [get_ports reset_rtl_0]
set_property PACKAGE_PIN E21 [get_ports reset_rtl_0]

set_property IOSTANDARD LVCMOS33 [get_ports {rgmii_rtl_0_rd[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {rgmii_rtl_0_rd[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {rgmii_rtl_0_rd[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {rgmii_rtl_0_rd[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports rgmii_rtl_0_rx_ctl]
set_property IOSTANDARD LVCMOS33 [get_ports rgmii_rtl_0_rxc]

set_property PACKAGE_PIN A19 [get_ports {rgmii_rtl_0_rd[3]}]
set_property PACKAGE_PIN A18 [get_ports {rgmii_rtl_0_rd[2]}]
set_property PACKAGE_PIN C20 [get_ports {rgmii_rtl_0_rd[1]}]
set_property PACKAGE_PIN D20 [get_ports {rgmii_rtl_0_rd[0]}]
set_property PACKAGE_PIN C22 [get_ports rgmii_rtl_0_rx_ctl]
set_property PACKAGE_PIN C18 [get_ports rgmii_rtl_0_rxc]

set_property IOSTANDARD LVCMOS33 [get_ports {rgmii_rtl_0_td[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {rgmii_rtl_0_td[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {rgmii_rtl_0_td[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {rgmii_rtl_0_td[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports rgmii_rtl_0_tx_ctl]
set_property IOSTANDARD LVCMOS33 [get_ports rgmii_rtl_0_txc]

set_property PACKAGE_PIN A21 [get_ports {rgmii_rtl_0_td[3]}]
set_property PACKAGE_PIN B21 [get_ports {rgmii_rtl_0_td[2]}]
set_property PACKAGE_PIN A20 [get_ports {rgmii_rtl_0_td[1]}]
set_property PACKAGE_PIN B20 [get_ports {rgmii_rtl_0_td[0]}]
set_property PACKAGE_PIN B22 [get_ports rgmii_rtl_0_tx_ctl]
set_property PACKAGE_PIN C19 [get_ports rgmii_rtl_0_txc]

set_property IOSTANDARD LVCMOS33 [get_ports mdio_rtl_0_mdc]
set_property IOSTANDARD LVCMOS33 [get_ports mdio_rtl_0_mdio_io]
set_property PACKAGE_PIN G21 [get_ports mdio_rtl_0_mdc]
set_property PACKAGE_PIN G22 [get_ports mdio_rtl_0_mdio_io]
 

BD完成后,Generate Bitstream, 然后File-Export-Export Hardware, File-Launch SDK.

进入SDK后,新建Application Project:

选择lwIP TCP Perf Server:

例程src目录下默认生产不同平台文件,我们可以将没有用的文件删除,最后如下:

 platform_mb.c 表示我们使用Microblaze平台

 lwiptcp_bsp: 例程的板级支持包。

我们先对支持包进行设置,右键lwiptcp_bsp

 黄色部分为需要修改的,即禁用dhcp,phy_link_speed = 100Mbps

 因为例程编译后很大,需要加载到DDR3中运行,此时需要设置,右键lwiptcp:

 确保例程代码在ddr中,Heap Size和Stack Size需设置大一些,不然最后程序有可能不断重启

 点击Generate代替之前的Linker Script

 保存,编译生成lwiptcp.elf

重点: 因为为了调试方便,我们指定了100Mbps 网口速度而非默认的autodetect, 所以SDK提供的例程我们不需要作修改即可用在RTL8211F芯片。 当phy_link_speed设置为Autodetect时,

此时我们需要修改lwip211_v1_0源码下的xaxiemacif_physpeed.c文件,添加RTL8211F的配置代码:

 代码如下:
1. 先添加定义,因为RTL8211F的idenifier ID固定为0x1c

 2. 找到unsigned get_IEEE_phy_speed(XAxiEthernet *xaxiemacp) 函数,添加RTL8211F配置代码, 代码实质工作就是配置8211的相关寄存器。最后这个函数返回autodetect后的Linkspeed. 当我们指定速度时,这个函数时跳过没有执行的。

unsigned get_IEEE_phy_speed(XAxiEthernet *xaxiemacp)
{
	u16 phy_identifier;
	u16 phy_model;
	u8 phytype;

	u16 control;
	u16 status;
	u16 status_speed;
	u32 temp_speed;
	u16 value;
	u32 timeout_counter = 0;


#ifdef XPAR_AXIETHERNET_0_BASEADDR
	u32 phy_addr = detect_phy(xaxiemacp);

	/* Get the PHY Identifier and Model number */
	XAxiEthernet_PhyRead(xaxiemacp, phy_addr, PHY_IDENTIFIER_1_REG, &phy_identifier);
	XAxiEthernet_PhyRead(xaxiemacp, phy_addr, PHY_IDENTIFIER_2_REG, &phy_model);

/* Depending upon what manufacturer PHY is connected, a different mask is
 * needed to determine the specific model number of the PHY. */
	if (phy_identifier == MARVEL_PHY_IDENTIFIER) {
		phy_model = phy_model & MARVEL_PHY_MODEL_NUM_MASK;

		if (phy_model == MARVEL_PHY_88E1116R_MODEL) {
			return get_phy_speed_88E1116R(xaxiemacp, phy_addr);
		} else if (phy_model == MARVEL_PHY_88E1111_MODEL) {
			return get_phy_speed_88E1111(xaxiemacp, phy_addr);
		}
	} else if (phy_identifier == TI_PHY_IDENTIFIER) {
		phy_model = phy_model & TI_PHY_DP83867_MODEL;
		phytype = XAxiEthernet_GetPhysicalInterface(xaxiemacp);

		if (phy_model == TI_PHY_DP83867_MODEL && phytype == XAE_PHY_TYPE_SGMII) {
			return get_phy_speed_TI_DP83867_SGMII(xaxiemacp, phy_addr);
		}

		if (phy_model == TI_PHY_DP83867_MODEL) {
			return get_phy_speed_TI_DP83867(xaxiemacp, phy_addr);
		}
	}
	else {
			if (phy_identifier==PHY_REALTEK_IDENTIFIER){

				xil_printf("Start PHY autonegotiation \r\n");

				/* 网线插拔检测 */
				XAxiEthernet_PhyRead(xaxiemacp, phy_addr, 1, &value); //BMSR register
				XAxiEthernet_PhyRead(xaxiemacp, phy_addr, 1, &value); //read twice
				if (value & 0x0004) xil_printf("Cable Linked\r\n");  //PHY_LINKED_STATUS

				XAxiEthernet_PhyRead(xaxiemacp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);
				 control |= IEEE_ASYMMETRIC_PAUSE_MASK;
				 control |= IEEE_PAUSE_MASK;
				 control |= ADVERTISE_100; //support 100Base FUll and Half
				 control |= ADVERTISE_10; //support 10Base FUll and Half
				XAxiEthernet_PhyWrite(xaxiemacp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);

				XAxiEthernet_PhyRead(xaxiemacp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,&control);
				control |= ADVERTISE_1000;
				XAxiEthernet_PhyWrite(xaxiemacp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,control);

				XAxiEthernet_PhyRead(xaxiemacp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
				control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;
				control |= IEEE_STAT_AUTONEGOTIATE_RESTART;
				XAxiEthernet_PhyWrite(xaxiemacp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);

				XAxiEthernet_PhyRead(xaxiemacp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
				control |= IEEE_CTRL_RESET_MASK;
				XAxiEthernet_PhyWrite(xaxiemacp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);

				while (1) {
					XAxiEthernet_PhyRead(xaxiemacp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
					if (control & IEEE_CTRL_RESET_MASK)
						continue;
					else
						break;
				}

				XAxiEthernet_PhyRead(xaxiemacp, 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);
					usleep(500000);
					timeout_counter++;
					if (timeout_counter == 30) {
						xil_printf("Auto negotiation error \r\n");
						return 0;
					}
					XAxiEthernet_PhyRead(xaxiemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
				}
				xil_printf("autonegotiation complete \r\n");

				XAxiEthernet_PhyRead(xaxiemacp, phy_addr,0x1A, &status_speed); /* Commercial RTL8211*/
				/*		 if (status_speed & 0x400) {  //link ok
						 temp_speed = status_speed & 0xc000;
						 if (temp_speed == 0x8000)
							 return 1000;
						 else if(temp_speed == 0x4000)
							 return 100;
						 else
							 return 10;	 */

				 if (status_speed & 0x04) {  //link ok
					 temp_speed = status_speed & 0x30;
					 if (temp_speed == 0x20)
						 return 1000;
					 else if(temp_speed == 0x10)
						 return 100;
					 else
						 return 10;

				 }


			 }
			return XST_SUCCESS;
//	else {
	    LWIP_DEBUGF(NETIF_DEBUG, ("XAxiEthernet get_IEEE_phy_speed: Detected PHY with unknown identifier/model.\r\n"));
	}
#endif
#ifdef PCM_PMA_CORE_PRESENT
	return get_phy_negotiated_speed(xaxiemacp, phy_addr);
#endif
}

返回link speed后,进入configure_IEEE_phy_speed(XAxiEthernet *xaxiemacp, unsigned speed)函数,我们在这个函数添加了配置8211 LED的代码:

    #define GREEN_LED 2 // 绿灯是LED2
    #define YELLOW_LED 1 // 黄灯是LED1


//配置网口LED灯状态
	XAxiEthernet_PhyWrite(xaxiemacp, phy_addr, 31, 0xd04);
    temp = 0x0b << (5 * GREEN_LED); // 绿灯表示连接状态
    temp |= 0x1b << (5 * YELLOW_LED); // 黄灯表示数据包收发状态
    XAxiEthernet_PhyWrite(xaxiemacp, phy_addr, 0x10, temp);

    temp = 1 << (YELLOW_LED + 1); // 绿灯不指示EEE节能状态, 插了网线后灯要常亮  // 但黄灯要指示EEE节能状态, 没有数据包时灯要熄灭

    XAxiEthernet_PhyWrite(xaxiemacp, phy_addr, 0x11, temp);
    XAxiEthernet_PhyWrite(xaxiemacp, phy_addr, 31, 0);
    // 插上网线后, 绿灯常亮; 拔掉网线后, 绿灯熄灭
    // 链路支持EEE节能: 有数据传输, 黄灯闪烁, 否则熄灭
    // 链路不支持EEE节能: 有数据传输, 黄灯闪烁, 否则常亮

回到之前最终生产了lwiptcp.elf,下面进行下载验证:

1. Xilinx - Program FPGA (作用1:将top_wrapper.bit 硬件流文件加载到FPGA中,并把bootloop.elf加载到BRAM用于引导后面的lwiptcp.elf。 所用2:并把两个文件合并生成一个download.bit文件,用于后面的程序固化到外部SPI FLASH中)

 

 

 2. 右键工程lwiptcp - Run as - Run Configurations

 

 点击Run后,SDK将lwiptcp.el加载到DDR3中并reset FPGA。(因为lwiptcp.elf编译后大小有30.28M,只能加载到DDR中,看之前设置)

 因为lwiptcp.elf太大,FPGA reset后需要等待十几秒才能运行。

iperf.exe windows默认没有,需要自己复制到c:\windows目录下(注意这里是第一版本的iperf, iperf3 不能用)

命令: iperf -c 192.168.31.55 -i 5 -t 30 -w 2M

实测100Mbps下,带宽只有16.7Mbps, 不知道什么原因。

  • 2
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Artix-7系列的FPGA中包含一个内置的XADC,可以用来进行一些精度不高的电压采集。 XADC是Xilinx ADC(模数转换器)的缩写,它是一种数字电路,用于将模拟信号转换为数字信号。在Artix-7 FPGA中,XADC可以用于测量和监测温度、电压和电流等模拟量。通过使用Xilinx提供的开发工具和IP核,可以轻松地配置和控制Artix-7的XADC来满足特定的应用需求。 请注意,Artix-7 FPGA的XADC适用于一些精度不高的电压采集任务,如果需要更高精度的模拟信号处理和采集,可能需要使用外部ADC模块或其他更高性能的FPGA系列。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Xilinx 7series XADC使用](https://blog.csdn.net/qq_43092637/article/details/126545872)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [FPGA学习笔记-1 FPGA原理与开发流程](https://blog.csdn.net/weixin_46258766/article/details/130012407)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值