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, &regvalue);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, &regvalue);/* 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);
不求甚解 就这样吧


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部