本例子使用zynq7000系列的ps带的两个mac,一个通过mio引出,一个通过emio引出。如下图:
由于lwip通常不使用双网口,有部分需要注意修改。有以下注意事项:
1 增加宏定义 vivado自带的问题,生成的时候少宏定义。
xxx_bsp/ps7_cortexa9_0/include/xparameters.h 增加宏定义:
#define XPAR_GMII2RGMIICON_0N_ETH1_ADDR 5
xxx_bsp/ps7_cortexa9_0/libsrc/lwip202_v1_2/src/contrib/ports/xilinx/netif/xemacpsif_physpeed.c 增加宏定义
#define XPAR_GMII2RGMIICON_0N_ETH1_ADDR 6
此数据5应与ip核设置为相同
2 路由相关设置
使能路由,并且由于双网口可能处于相同网段需要进行适度修改。
2.1 使能lwip的路由功能
xxx_bsp/ps7_cortexa9_0/libsrc/lwip202_v1_2/src/contrib/ports/Xilinx/include/lwipopts.h
#define IP_FORWARD 1 使能路由
2.2 增加路由功能宏定义
xxx_bsp/ps7_cortexa9_0/libsrc/lwip202_v1_2/src/lwip-2.0.2/src/include/lwip/ip4.h
#define LWIP_HOOK_IP4_ROUTE_SRC
2.3 修改路由相关函数
xxx_bsp/ps7_cortexa9_0/libsrc/lwip202_v1_2/src/lwip202_v1_2/src/include/lwip/netif.h 增加如下:
代码语言:javascript复制#if LWIP_SINGLE_NETIF
#define NETIF_FOREACH(netif) if (((netif) = netif_default) != NULL)
#else /* LWIP_SINGLE_NETIF */
/** The list of network interfaces. */
extern struct netif *netif_list;
#define NETIF_FOREACH(netif) for ((netif) = netif_list; (netif) != NULL; (netif) = (netif)->next)
#endif /* LWIP_SINGLE_NETIF */
xxx_bsp/ps7_cortexa9_0/libsrc/lwip202_v1_2/src/lwip-2.0.2/src/core/ipv4/ip4.c
修改ip4_route_src如下:
代码语言:javascript复制//struct netif *
//ip4_route_src(const ip4_addr_t *dest, const ip4_addr_t *src)
//{
// if (src != NULL) {
// /* when src==NULL, the hook is called from ip4_route(dest) */
// struct netif *netif = LWIP_HOOK_IP4_ROUTE_SRC(dest, src);
// if (netif != NULL) {
// return netif;
// }
// }
// return ip4_route(dest);
//}
struct netif *
ip4_route_src(const ip4_addr_t *dest,const ip4_addr_t *src)
{
#if !LWIP_SINGLE_NETIF
struct netif *netif;
//LWIP_ASSERT_CORE_LOCKED();
#if LWIP_MULTICAST_TX_OPTIONS
/* Use administratively selected interface for multicast by default */
if (ip4_addr_ismulticast(dest) && ip4_default_multicast_netif) {
return ip4_default_multicast_netif;
}
#endif /* LWIP_MULTICAST_TX_OPTIONS */
/* bug #54569: in case LWIP_SINGLE_NETIF=1 and LWIP_DEBUGF() disabled, the following loop is optimized away */
LWIP_UNUSED_ARG(dest);
/* iterate through netifs */
NETIF_FOREACH(netif) {
/* is the netif up, does it have a link and a valid address? */
if (netif_is_up(netif) && netif_is_link_up(netif) && !ip4_addr_isany_val(*netif_ip4_addr(netif))) {
/* network mask matches? */
// if (ip4_addr_netcmp(dest, netif_ip4_addr(netif), netif_ip4_netmask(netif))) {
if (ip4_addr_cmp(src, netif_ip4_addr(netif))) {
/* return netif on which to forward IP packet */
return netif;
}
/* gateway matches on a non broadcast interface? (i.e. peer in a point to point interface) */
if (((netif->flags & NETIF_FLAG_BROADCAST) == 0) && ip4_addr_cmp(dest, netif_ip4_gw(netif))) {
/* return netif on which to forward IP packet */
return netif;
}
}
}
#if LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF
/* loopif is disabled, looopback traffic is passed through any netif */
if (ip4_addr_isloopback(dest)) {
/* don't check for link on loopback traffic */
if (netif_default != NULL && netif_is_up(netif_default)) {
return netif_default;
}
/* default netif is not up, just use any netif for loopback traffic */
NETIF_FOREACH(netif) {
if (netif_is_up(netif)) {
return netif;
}
}
return NULL;
}
#endif /* LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF */
#ifdef LWIP_HOOK_IP4_ROUTE_SRC
netif = LWIP_HOOK_IP4_ROUTE_SRC(NULL, dest);
if (netif != NULL) {
return netif;
}
#elif defined(LWIP_HOOK_IP4_ROUTE)
netif = LWIP_HOOK_IP4_ROUTE(dest);
if (netif != NULL) {
return netif;
}
#endif
#endif /* !LWIP_SINGLE_NETIF */
if ((netif_default == NULL) || !netif_is_up(netif_default) || !netif_is_link_up(netif_default) ||
ip4_addr_isany_val(*netif_ip4_addr(netif_default)) || ip4_addr_isloopback(dest)) {
/* No matching netif found and default netif is not usable.
If this is not good enough for you, use LWIP_HOOK_IP4_ROUTE() */
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip4_route: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"n",
ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest)));
IP_STATS_INC(ip.rterr);
MIB2_STATS_INC(mib2.ipoutnoroutes);
return NULL;
}
return netif_default;
}
3 热插拔相关
原来的检测都是针对单网口的,需要适度修改
3.1 修改连接状态检测
xxx_bsp/ps7_cortexa9_0/libsrc/lwip202_v1_2/src/contrib/ports/Xilinx/netif/xadapter.c 截取PHY连接状态
代码语言:text复制void eth_link_detect(struct netif *netif)
{
u32_t link_speed, phy_link_status;
struct xemac_s *xemac = (struct xemac_s *)(netif->state);
#if defined(XLWIP_CONFIG_INCLUDE_GEM)
xemacpsif_s *xemacs = (xemacpsif_s *)(xemac->state);
XEmacPs *xemacp = &xemacs->emacps;
#elif defined(XLWIP_CONFIG_INCLUDE_AXI_ETHERNET)
xaxiemacif_s *xemacs = (xaxiemacif_s *)(xemac->state);
XAxiEthernet *xemacp = &xemacs->axi_ethernet;
#elif defined(XLWIP_CONFIG_INCLUDE_EMACLITE)
xemacliteif_s *xemacs = (xemacliteif_s *)(xemac->state);
XEmacLite *xemacp = xemacs->instance;
#endif
if(netif == xxx_netif){
if ((xemacp->IsReady != (u32)XIL_COMPONENT_IS_READY) ||
(eth_link_status == ETH_LINK_UNDEFINED))
return;
phy_link_status = phy_link_detect(xemacp, phyaddrforemac);
net0_link_state = phy_link_status;
if ((eth_link_status == ETH_LINK_UP) && (!phy_link_status))
eth_link_status = ETH_LINK_DOWN;
switch (eth_link_status) {
case ETH_LINK_UNDEFINED:
case ETH_LINK_UP:
return;
case ETH_LINK_DOWN:
netif_set_link_down(netif);
eth_link_status = ETH_LINK_NEGOTIATING;
xil_printf("Ethernet Link downrn");
netif->dhcp_bind_state = 0;
break;
case ETH_LINK_NEGOTIATING:
if (phy_link_status &&
phy_autoneg_status(xemacp, phyaddrforemac)) {
/* Initiate Phy setup to get link speed */
#if defined(XLWIP_CONFIG_INCLUDE_GEM)
link_speed = phy_setup_emacps(xemacp,
phyaddrforemac);
XEmacPs_SetOperatingSpeed(xemacp, link_speed);
#elif defined(XLWIP_CONFIG_INCLUDE_AXI_ETHERNET)
link_speed = phy_setup_axiemac(xemacp);
XAxiEthernet_SetOperatingSpeed(xemacp,
link_speed);
#endif
netif_set_link_up(netif);
eth_link_status = ETH_LINK_UP;
xil_printf("Ethernet Link uprn");
}
break;
}
// xil_printf("net0_link_state %drn",net0_link_state);
}
if(netif == xxx_netif1){
if ((xemacp->IsReady != (u32)XIL_COMPONENT_IS_READY) ||
(eth_link_status1 == ETH_LINK_UNDEFINED))
return;
phy_link_status = phy_link_detect(xemacp, phyaddrforemac);
net1_link_state = phy_link_status;
if ((eth_link_status1 == ETH_LINK_UP) && (!phy_link_status))
eth_link_status1 = ETH_LINK_DOWN;
switch (eth_link_status1) {
case ETH_LINK_UNDEFINED:
case ETH_LINK_UP:
return;
case ETH_LINK_DOWN:
netif_set_link_down(netif);
eth_link_status1 = ETH_LINK_NEGOTIATING;
xil_printf("Ethernet1 Link downrn");
netif->dhcp_bind_state = 0;
break;
case ETH_LINK_NEGOTIATING:
if (phy_link_status &&
phy_autoneg_status(xemacp, phyaddrforemac)) {
/* Initiate Phy setup to get link speed */
#if defined(XLWIP_CONFIG_INCLUDE_GEM)
link_speed = phy_setup_emacps(xemacp,
phyaddrforemac);
XEmacPs_SetOperatingSpeed(xemacp, link_speed);
#elif defined(XLWIP_CONFIG_INCLUDE_AXI_ETHERNET)
link_speed = phy_setup_axiemac(xemacp);
XAxiEthernet_SetOperatingSpeed(xemacp,
link_speed);
#endif
netif_set_link_up(netif);
eth_link_status1 = ETH_LINK_UP;
xil_printf("Ethernet1 Link uprn");
}
break;
}
}
3.2 修改初始化时候的连接状态
区分不同网口:
void init_emacps(xemacpsif_s *xemacps, struct netif *netif)修改:
代码语言:text复制 if(netif == xxx_netif){
if (link_speed == XST_FAILURE) {
eth_link_status = ETH_LINK_DOWN;
xil_printf("Assert due to phy setup failure nr",__func__);
} else {
eth_link_status = ETH_LINK_UP;
}
}
if(netif == xxx_netif1){
if (link_speed == XST_FAILURE) {
eth_link_status1 = ETH_LINK_DOWN;
xil_printf("Assert due to phy setup failure nr",__func__);
} else {
eth_link_status1 = ETH_LINK_UP;
}
}
增加另一个网口的状态判断。
3.3 增加新的网口检测
xxx/src/platform_zynq.c 中的定时检测
代码语言:javascript复制 if (DetectEthLinkStatus == ETH_LINK_DETECT_INTERVAL) {
eth_link_detect(xxx_netif);
eth_link_detect(xxx_netif1);
DetectEthLinkStatus = 0;
}
增加一个网口的状态检测。
4 修改长帧可能遇到的问题
不同设备定义的MUT含义可能不一样,将长度适当放开。
xxx_bsp/ps7_cortexa9_0/libsrc/lwip202_v1_2/src/contrib/ports/xilinx/netif/xemacpsif_dma.c 修改:
代码语言:javascript复制#ifdef ZYNQMP_USE_JUMBO
max_fr_size = MAX_FRAME_SIZE_JUMBO - 18;
max_fr_size = MAX_FRAME_SIZE_JUMBO - 4;//仅是减去crc的4个字节
#else
max_fr_size = XEMACPS_MAX_FRAME_SIZE - 18;
max_fr_size = XEMACPS_MAX_FRAME_SIZE - 4;//仅是减去crc的4个字节
#endif
增加最大长度