STM32 LWIP 开机热插拔
STM32爬坑避雷日记
- 记录一次LWIP遇到的问题(STM32F407+DP83848)
- 问题
- 解决过程
- 结论
记录一次LWIP遇到的问题(STM32F407+DP83848)
问题
参考各路神仙实现LWIP热插拔,最后发现,只有开机插着网线可以实现热插拔,如果不插网线开机,会在“ethernetif_notify_conn_changed”函数反复打印断开连接和重新连接
void ethernetif_notify_conn_changed(struct netif *netif)
{/* NOTE : This is function could be implemented in user file when the callback is needed,*/if(netif_is_link_up(netif)){printf("netif_is_link_up\n");netif_set_up(netif);//udp_echoserver_init();}else{printf("netif_is_link_down\n");netif_set_down(netif);//UDP_RM();//Connect_Flag = 0;}}
解决过程
整理函数执行顺序
MX_LWIP_Process();
ethernetif_set_link(&gnetif);
netif_set_link_up(netif);/netif_set_link_down(netif);
NETIF_LINK_CALLBACK(netif);/ethernetif_update_config(netif);
ethernetif_notify_conn_changed(netif);
先看ethernetif_set_link函数,在图下所示的位置添加了打印
void ethernetif_set_link(struct netif *netif)
{uint32_t regvalue = 0;/* Ethernet Link every 200ms */if (HAL_GetTick() - EthernetLinkTimer >= 200){EthernetLinkTimer = HAL_GetTick();/* Read PHY_BSR*/HAL_ETH_ReadPHYRegister(&heth, PHY_BSR, ®value);printf("\n1:regvalue=%u\n",regvalue);//打印出来看看读出来啥regvalue &= PHY_LINKED_STATUS;/* Check whether the netif link down and the PHY link is up */printf("2:netif_is_link_up(netif) = %d\n",netif_is_link_up(netif));printf("3:regvalue = %d\n",regvalue);if(!netif_is_link_up(netif) && (regvalue)){/* network cable is connected */netif_set_link_up(netif);}else if(netif_is_link_up(netif) && (!regvalue)){/* network cable is disconnected */netif_set_link_down(netif);}}
}

不知道为啥 首测检测那个寄存器计算完后能读出来4 但是下次就读出来0了 显然不正常 但是还不知道为啥 但是这时候可以解释 为什么总是printf输出“netif_is_link_up”和 “netif_is_link_down”
接着看ethernetif_update_config函数
····/* Wait until the auto-negotiation will be completed */do{HAL_ETH_ReadPHYRegister(&heth, PHY_BSR, ®value);/* Check for the Timeout ( 1s ) */if((HAL_GetTick() - tickstart ) > 1000){/* In case of timeout */goto error;}} while (((regvalue & PHY_AUTONEGO_COMPLETE) != PHY_AUTONEGO_COMPLETE));
····else /* AutoNegotiation Disable */{error :/* Check parameters */printf("errorerrorerrorerrorerror\n");assert_param(IS_ETH_SPEED(heth.Init.Speed));assert_param(IS_ETH_DUPLEX_MODE(heth.Init.DuplexMode));/* Set MAC Speed and Duplex Mode to PHY */HAL_ETH_WritePHYRegister(&heth, PHY_BCR, ((uint16_t)(heth.Init.DuplexMode >> 3) |(uint16_t)(heth.Init.Speed >> 1)));}
····
这里也在读寄存器 然后一顿骚操作,打印一下看看 有没有错误

果不其然出错了,err和else都可以到达这里
if(heth.Init.AutoNegotiation != ETH_AUTONEGOTIATION_DISABLE)
显然是不成立的,debug看下,问题竟然没有了!那应该是时间出问题了,毕竟手动单步前进肯定没有程序快
修改成如下
if((HAL_GetTick() - tickstart ) > 2000)//1000->>>2000{/* In case of timeout */goto error;}
测试没出问题了,不再循环了

结论
猜测:程序中等待自动协商完成 超时时间为1秒钟 超时后跳过其他操作 导致再次读取PHY_BSR解析PHY_LINKED_STATUS时失败 所以再次进入netif_set_link_down(netif);
不求甚解 就这样吧
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
