說明:基於Microblaze+Lwip+perf建立測試工程驗證以太網通信
以太網接口:MII/RMII/GMII/RGMII/SGMII(本次主要使用MII/RMII接口)
-------------------------------------------------------------------------------------------------------------------------------------------------
第一部分:建立vivado工程
1、我們可以通過vivado自帶的官方example來生成一個microblaze的以太網參考設計:
這個設計時基於官方board的,我們可以選擇一個相近的板卡作爲參考,我們只需要網口部分,不需要的都不選,簡化設計:
參照這個設計,新建一個工程對應到自己的板卡,以及自己的以太網PHY
2、對於mii/gmii/rgmii接口ethernet subsystem ip核是很好支持的,sgmii接口複雜點,目前還我沒有找到正確的操作方法
注意microblaze默認高電平復位,但我們外部信號一般是低電平復位的(點到這個引腳,Ctrl+E在屬性裏面設置下):
以太網對內存有一定要求,我們儘可能把LBM設置大點:
LMB容量最大可以選擇4MBytes,在Address Editor更新後,重新生成block裏面會同步更新!
同時注意不要有懸空net沒有連接:
3、當你有多個Microblaze以及對應的Ethernet Subsytem時:當你只有一個 ETH核時,選第一個,把共享邏輯放在覈裏;當你有多個ETH核時,保留一個選第一個(共享邏輯放在覈裏),其它都選第二個(在設計裏共享),同時“把共享邏輯放在覈裏”作爲時鐘輸出將信號給到其它核
4、Ethernet ip需要license,可以在官網上自行申請:
https://www.xilinx.com/products/intellectual-property/ip-evaluation.html
copy license需要不同的名字否則會把原來的覆蓋,同時工程需要重新生成!
5、適配管腳,生成bit,以太網接口需要放到同一Bank
同時要注意clk引腳不能放在bank的boundary位置:
參考:https://www.xilinx.com/support/answers/67641.html
關於引腳信息請參考:ug575-ultrascale-pkg-pinout.pdf
http://www.xilinx.com/support/packagefiles/usapackages/usaall.zip
--------------------------------------------------------------------------------------------------------------
第二步:成功生成bit後需要進入SDK中進行後面的軟件生成及調試操作:
1、新建Tcp Appllication/選擇tcp perf server
2、雖然LBM已經設置到了最大,但編譯lwip還是會make error,我們需要配置下lwip的參數:
3、debug
備註:
-------------------------------------------------------------------------------------------------------------------------------------------------------
第三部分:適配自己的phy及網絡調試
1、以太網調試首先是要適配自己的phy,xilinx提供的參考例程只是適配了自己的官方板卡的phy,其它型號的phy需要自己適配:
以太網PHY的SMI接口屬於總線接口,類似於I2C,每個PHY都是有地址的,lwip不關心這個地址時多少,它會掃描查找31-1(0地址沒有查找)
SMI接口頻率設置:
unsigned int get_phy_speed_88E1514(XAxiEthernet *xaxiemacp, u32 phy_addr)
{
u16 phy_val;
u16 control;
u16 status;
u16 partner_capabilities;
u16 temp;
//mode select:sgmii reg20_18
XAxiEthernet_PhyWrite(xaxiemacp,phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 18);
XAxiEthernet_PhyRead(xaxiemacp, phy_addr, 20, &temp);
xil_printf("phy_addr:%d mode:%x \r\n",phy_addr,temp);
temp |= 0x0001;
temp &= 0xfff9;
XAxiEthernet_PhyWrite(xaxiemacp,phy_addr, 20, temp);
xil_printf("phy_addr:%d mode:%x \r\n",phy_addr,temp);
//reset phy
temp |= 0x8000;
XAxiEthernet_PhyWrite(xaxiemacp,phy_addr, 20, temp);
//will add:
//reg:0_1 sgmii negotiation
XAxiEthernet_PhyWrite(xaxiemacp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 1);
XAxiEthernet_PhyRead(xaxiemacp, phy_addr, 0, &temp);
xil_printf("phy_addr:%d auto negotiation:%x \r\n",phy_addr,temp);
temp |= 1<<12;//auto negotiation
temp |= 1<<9;//restart auto negotiation
XAxiEthernet_PhyWrite(xaxiemacp,phy_addr, 0, temp);
xil_printf("phy_addr:%d auto negotiation:%x \r\n",phy_addr,temp);
//reg:26_1 sgmii negotiation
XAxiEthernet_PhyWrite(xaxiemacp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 1);
XAxiEthernet_PhyRead(xaxiemacp, phy_addr, 26, &temp);
xil_printf("phy_addr:%d auto negotiation:%x \r\n",phy_addr,temp);
temp &= (~(1<<6));//auto negotiation
XAxiEthernet_PhyWrite(xaxiemacp,phy_addr, 26, temp);
xil_printf("phy_addr:%d auto negotiation:%x \r\n",phy_addr,temp);
//-----------------------------------------------------------------
xil_printf("Start PHY autonegotiation \r\n");
//reg:21_2(page)
XAxiEthernet_PhyWrite(xaxiemacp,phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2);
XAxiEthernet_PhyRead(xaxiemacp, phy_addr, IEEE_CONTROL_REG_MAC, &control);
control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK;
XAxiEthernet_PhyWrite(xaxiemacp, phy_addr, IEEE_CONTROL_REG_MAC, control);
XAxiEthernet_PhyWrite(xaxiemacp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
//reg:4_0(page)
XAxiEthernet_PhyRead(xaxiemacp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);
control |= IEEE_ASYMMETRIC_PAUSE_MASK;
control |= IEEE_PAUSE_MASK;
control |= ADVERTISE_100;
control |= ADVERTISE_10;
XAxiEthernet_PhyWrite(xaxiemacp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);
////reg:9_0(page) 1000 BASE-T FUll-Duplex/Half-Duplex Advertise
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);
//reg:16_0(page) Not for 88e1514
//XAxiEthernet_PhyWrite(xaxiemacp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
//XAxiEthernet_PhyRead(xaxiemacp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,&control);
//control |= (7 << 12); /* max number of gigabit atphy_valts */
//control |= (1 << 11); /* enable downshift */
//XAxiEthernet_PhyWrite(xaxiemacp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,control);
//reg:0_0(page)
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);
//reset the phy
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;
}
//
xil_printf("Waiting for PHY to complete autonegotiation.\r\n");
xil_printf("\r\n----------------------------------------\r\n");
//reg:1_0(page)
XAxiEthernet_PhyRead(xaxiemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {
xil_printf("IEEE_STATUS_REG:%x\r\n",status);
AxiEthernetUtilPhyDelay(1);
//reg:19_0(page)
XAxiEthernet_PhyRead(xaxiemacp, phy_addr, IEEE_COPPER_SPECIFIC_STATUS_REG_2,
&phy_val);
if (phy_val & IEEE_AUTONEG_ERROR_MASK) {
xil_printf("Auto negotiation error \r\n");
}
XAxiEthernet_PhyRead(xaxiemacp, phy_addr, IEEE_STATUS_REG_OFFSET,
&status);
}
xil_printf("IEEE_STATUS_REG:%x\r\n",status);
xil_printf("autonegotiation complete \r\n");
XAxiEthernet_PhyRead(xaxiemacp, phy_addr, IEEE_SPECIFIC_STATUS_REG,
&partner_capabilities);
if ( ((partner_capabilities >> 14) & 3) == 2)/* 1000Mbps */
return 1000;
else if ( ((partner_capabilities >> 14) & 3) == 1)/* 100Mbps */
return 100;
else /* 10Mbps */
return 10;
}
2、網絡報文
ila中抓取到的包:
同時我們也可以在代碼裏將報文通過串口打印出來分析:
在low_level_input/low_level_ouput函數中將buf數據打印數出來
3、PC端監控:單獨將PC和板卡通過一根網線連接,通過抓包軟件對PC端網卡進行抓包可以分析兩邊的通信數據,同時通過wifi連接網絡,這時PC端的有線網卡數據比較乾淨主要是和子卡之間的數據便於調試。
4、perf測試
當dhcp成功給我們的板卡分配一個ip後,便可以進行perf測試,該軟件有windows及linux兩個版本,也可以通過命令行操作: