ZYNQ 裸机lwip 双网口注意事项

2024-03-06 14:09:14 浏览数 (2)

本例子使用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

增加最大长度

0 人点赞