zynq sdk使用官方freertos+lwip的socket编程。初始不插网线,一段时间后插入网线发现lwip初始化失败后没有继续进行热插拔检测并停止工作
使用官方的freertos+lwip的socket程序,一开始不接网线,程序打印如下信息Start PHY autonegotiationWaiting for PHY to complete autonegotiation.过一段时间后,程序继续打印如下信息Auto negotiation errorPhy setup errorAssert due to phy setup failure然后
·
使用官方的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;
}
编译后重新运行,该问题即可完全解决。
点击阅读全文
更多推荐
活动日历
查看更多
直播时间 2025-02-26 16:00:00


直播时间 2025-01-08 16:30:00


直播时间 2024-12-11 16:30:00


直播时间 2024-11-27 16:30:00


直播时间 2024-11-21 16:30:00


所有评论(0)