zynq sdk使用官方freertos+lwip的socket编程。初始不插网线,一段时间后插入网线发现lwip初始化失败后没有继续进行热插拔检测并停止工作

使用官方的freertos+lwip的socket程序,一开始不接网线,程序打印如下信息

Start PHY autonegotiation 
Waiting for PHY to complete autonegotiation.

过一段时间后,程序继续打印如下信息

Auto negotiation error 
Phy setup error 
Assert due to phy setup failure 

然后插入网线,发现程序已无法进行TCP通信。
原因已查明,官方程序在检测热插拔一段时间后如果发现链路一直为断开状态,则lwip将退出主循环并报错。
所以只需要不断检测phy芯片的LINK寄存器,如果发现链路断开,则挂起lwip任务,如果发现链路通畅,此时继续lwip未竟任务即可。
查阅phy芯片手册,如下:
在这里插入图片描述
上图中寄存器地址1的第2个bit表示链路的连接情况,于是在lwip的xemacpsif.c 文件底层函数low_level_init()中做如下修改(第69-86行):

static err_t low_level_init(struct netif *netif)
{
	UINTPTR mac_address = (UINTPTR)(netif->state);
	struct xemac_s *xemac;
	xemacpsif_s *xemacpsif;
	u32 dmacrreg;

	s32_t status = XST_SUCCESS;

	NetIf = netif;
	xemacpsif = mem_malloc(sizeof *xemacpsif);
	if (xemacpsif == NULL) {
		LWIP_DEBUGF(NETIF_DEBUG, ("xemacpsif_init: out of memory\r\n"));
		return ERR_MEM;
	}

	xemac = mem_malloc(sizeof *xemac);
	if (xemac == NULL) {
		LWIP_DEBUGF(NETIF_DEBUG, ("xemacpsif_init: out of memory\r\n"));
		return ERR_MEM;
	}

	xemac->state = (void *)xemacpsif;
	xemac->topology_index = xtopology_find_index(mac_address);
	xemac->type = xemac_type_emacps;

	xemacpsif->send_q = NULL;
	xemacpsif->recv_q = pq_create_queue();
	if (!xemacpsif->recv_q)
		return ERR_MEM;

	/* maximum transfer unit */
#ifdef ZYNQMP_USE_JUMBO
	netif->mtu = XEMACPS_MTU_JUMBO - XEMACPS_HDR_SIZE;
#else
	netif->mtu = XEMACPS_MTU - XEMACPS_HDR_SIZE;
#endif

#if LWIP_IGMP
	netif->igmp_mac_filter = xemacpsif_mac_filter_update;
#endif

#if LWIP_IPV6 && LWIP_IPV6_MLD
 netif->mld_mac_filter = xemacpsif_mld6_mac_filter_update;
#endif

	netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP |
											NETIF_FLAG_LINK_UP;

#if LWIP_IPV6 && LWIP_IPV6_MLD
	netif->flags |= NETIF_FLAG_MLD6;
#endif

#if LWIP_IGMP
	netif->flags |= NETIF_FLAG_IGMP;
#endif

#if !NO_SYS
	sys_sem_new(&xemac->sem_rx_data_available, 0);
#endif
	/* obtain config of this emac */
	mac_config = (XEmacPs_Config *)xemacps_lookup_config((unsigned)(UINTPTR)netif->state);

	status = XEmacPs_CfgInitialize(&xemacpsif->emacps, mac_config,
						mac_config->BaseAddress);
	if (status != XST_SUCCESS) {
		xil_printf("In %s:EmacPs Configuration Failed....\r\n", __func__);
	}
	/*   ============== 从这里开始是增加的代码块,用于定时检测链路状态  ============== */
	while(1)
	{
	  unsigned short tmp;
	  //XEmacPs
	  XEmacPs_PhyRead(&xemacpsif->emacps, 1, 1, &tmp);
	  xil_printf("IEEE_STATUS_REG_OFFSET=%d\n",tmp);
	  if(tmp&(0X01<<2))
	  {
	    xil_printf("IEEE_STATUS_REG_OFFSET=%d\n",tmp);
	    break;
	  }
	  else
	  {
	    vTaskDelay(pdMS_TO_TICKS(2000));
	  }
	}
	/* ============== 增加的代码块到此为止 ==============  */
	/* initialize the mac */
	init_emacps(xemacpsif, netif);

	dmacrreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
														XEMACPS_DMACR_OFFSET);
	dmacrreg = dmacrreg | (0x00000010);
	XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
											XEMACPS_DMACR_OFFSET, dmacrreg);

#if defined(OS_IS_FREERTOS) && defined(__arm__) && !defined(ARMR5)
	/* Freertos tick is 10ms by default; set period to the same */
	xemac->xTimer = xTimerCreate("Timer", 10, pdTRUE, ( void * ) 1, vTimerCallback);
	if (xemac->xTimer == NULL) {
		xil_printf("In %s:Timer creation failed....\r\n", __func__);
	} else {
		if(xTimerStart(xemac->xTimer, 0) != pdPASS) {
			xil_printf("In %s:Timer start failed....\r\n", __func__);
		}
	}
#endif
	setup_isr(xemac);
	init_dma(xemac);
	start_emacps(xemacpsif);

	/* replace the state in netif (currently the emac baseaddress)
	 * with the mac instance pointer.
	 */
	netif->state = (void *)xemac;

	return ERR_OK;
}

编译后重新运行,该问题即可完全解决。

  • 5
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值