[STM32F7] 未接网线先上电,再接网线也不工作

[复制链接]
102|28
万法归宗 发表于 2026-8-27 16:05 | 显示全部楼层 |阅读模式
我用 STM32CubeMX 生成了工程,板子上的以太网通信在网线预先插好的情况下可以正常工作。
但存在一个问题:只有在开机时网线已经接好,以太网才能正常工作。如果板子上电时没有插网线,以太网就无法正常工作,即便之后再插上网线也始终无法恢复。

为了解决这个问题,我在 LWIP 初始化完成后添加了如下函数:

netif_set_link_callback(&gnetif, ethernetif_update_config);

其中`ethernetif_update_config`函数是 CubeMX 自动生成的,作用是重启以太网自动协商。

void
ethernetif_update_config(
struct
netif *netif)
{
__IO uint32_t tickstart = 0;
uint32_t regvalue = 0;
if
(netif_is_link_up(netif))
{
/* Restart the auto-negotiation */
if
(heth.Init.AutoNegotiation != ETH_AUTONEGOTIATION_DISABLE)
{
/* Enable Auto-Negotiation */
HAL_ETH_WritePHYRegister(&heth, PHY_BCR, PHY_AUTONEGOTIATION);
/* Get tick */
tickstart = HAL_GetTick();
/* 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));
/* Read the result of the auto-negotiation */
HAL_ETH_ReadPHYRegister(&heth, PHY_SR, ®value);
/* Configure the MAC with the Duplex Mode fixed by the auto-negotiation process */
if
((regvalue & PHY_DUPLEX_STATUS) != (uint32_t)RESET)
{
/* Set Ethernet duplex mode to Full-duplex following the auto-negotiation */
heth.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
}
else
{
/* Set Ethernet duplex mode to Half-duplex following the auto-negotiation */
heth.Init.DuplexMode = ETH_MODE_HALFDUPLEX;
}
/* Configure the MAC with the speed fixed by the auto-negotiation process */
if
(regvalue & PHY_SPEED_STATUS)
{
/* Set Ethernet speed to 10M following the auto-negotiation */
heth.Init.Speed = ETH_SPEED_10M;
}
else
{
/* Set Ethernet speed to 100M following the auto-negotiation */
heth.Init.Speed = ETH_SPEED_100M;
}
}
else
/* AutoNegotiation Disable */
{
error :
/* Check parameters */
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)));
}
/* ETHERNET MAC Re-Configuration */
HAL_ETH_ConfigMAC(&heth, (ETH_MACInitTypeDef *) NULL);
/* Restart MAC interface */
HAL_ETH_Start(&heth);
}
else
{
/* Stop MAC interface */
HAL_ETH_Stop(&heth);
}
ethernetif_notify_conn_changed(netif);
}

我在插上网线后通过调用`netif_set_link_up(&gnetif)`手动触发该回调函数时,以太网依旧无法正常工作。有没有人知道在这种场景下该如何让以太网正常运行?

磨砂 发表于 2026-9-10 17:35 | 显示全部楼层
仅靠netif_set_link_callback注册的回调函数,并不能完全覆盖“运行中重新插网线”的全场景恢复逻辑
晓伍 发表于 2026-9-10 19:22 | 显示全部楼层
netif_set_link_callback注册的回调,仅当PHY的链路状态实际变化且LWIP框架主动触发时才会执行
八层楼 发表于 2026-9-10 21:07 | 显示全部楼层
你需要先确认PHY芯片是否真的检测到“网线插入”,并产生可被MCU感知的状态变化
观海 发表于 2026-9-11 08:16 | 显示全部楼层
STM32的HAL库以太网驱动默认没有开启PHY链路状态变化的硬件中断,也未实现自动回调的机制
guanjiaer 发表于 2026-9-11 10:01 | 显示全部楼层
当链路刚恢复时,PHY可能还在执行自动协商,此时直接调用netif_set_link_up,实际链路并未真正稳定
heimaojingzhang 发表于 2026-9-11 11:53 | 显示全部楼层
启用HAL库的PHY链路状态中断,实现主动通知
keaibukelian 发表于 2026-9-11 13:46 | 显示全部楼层
如果你的硬件设计中,PHY没有中断引脚连接到MCU的EXTI,或者你不想配置中断,轮询检测是最简单且有效的替代方案——定期检测PHY的LINK状态,发现链路恢复后自动触发恢复流程
paotangsan 发表于 2026-9-11 15:42 | 显示全部楼层
不同PHY芯片的寄存器地址和位定义可能不同
renzheshengui 发表于 2026-9-11 17:31 | 显示全部楼层
在恢复流程中,重新配置MAC时,速率和双工模式必须和PHY的自动协商结果完全一致,否则即使链路恢复,也无法正常收发数据
wowu 发表于 2026-9-11 19:06 | 显示全部楼层
开启PHY链路状态中断,结合完整的恢复函数,从底层硬件状态感知到协议栈同步,形成闭环,既能保证响应速度,又不占用CPU资源
又见江南雨 发表于 2026-9-10 15:33 | 显示全部楼层
这个问题的核心在于LWIP的网络接口有两个状态:链路状态和管理状态。链路状态由PHY芯片检测网线是否插入,管理状态由软件控制协议栈是否启用接口。上电时没有网线,管理状态被设为down,之后即使链路恢复,管理状态也没有被重新设为up
在海边聆听 发表于 2026-9-10 16:45 | 显示全部楼层
CubeMX自动生成的ethernetif_update_config函数只处理了链路状态的变化和PHY重新协商,但没有同步更新LWIP的管理状态。这就是为什么手动调用netif_set_link_up()仍然无法恢复网络的原因
才没有脸红 发表于 2026-9-10 19:10 | 显示全部楼层
解决方法是在ethernetif_update_config函数中添加两行代码:当链路up时调用netif_set_up(netif),当链路down时调用netif_set_down(netif)。这两行代码是CubeMX默认生成代码中缺失的关键部分
故里说长安 发表于 2026-9-10 20:20 | 显示全部楼层
你手动调用netif_set_link_up()之所以无效,是因为这个函数只设置了LINK_UP标志位,但没有设置NETIF_FLAG_UP标志位。LWIP在发送数据前会检查这两个标志,任何一个不满足都会拒绝发送
没有太阳的晴天 发表于 2026-9-10 21:35 | 显示全部楼层
在CubeMX的LWIP配置界面中,需要确保勾选了LWIP_NETIF_LINK_CALLBACK和LWIP_NETIF_STATUS_CALLBACK这两个选项。如果只勾选了其中一个,回调机制就不完整,状态同步会出问题
海滨消消 发表于 2026-9-10 22:56 | 显示全部楼层
上电时没有网线的情况下,MX_LWIP_Init()函数执行时会检测到链路down,然后调用netif_set_down()将管理状态也设为down。之后PHY检测到网线插入并触发回调时,回调函数只恢复了链路状态,管理状态仍然是down
甜心puppy 发表于 2026-9-11 10:36 | 显示全部楼层
这是一个CubeMX代码生成器的已知问题,默认生成的代码没有完整处理热插拔场景。ST官方社区有多位开发者报告过类似问题,解决方法都是手动在回调中添加管理状态同步代码
等凌晨日出 发表于 2026-9-11 11:58 | 显示全部楼层
ethernetif_notify_conn_changed函数是CubeMX提供的用户回调接口,你可以在这个函数中实现DHCP重新获取IP的逻辑。当网线插入后,除了恢复接口状态,还需要重新启动DHCP来获取IP地址
茉璃夏 发表于 2026-9-11 12:40 | 显示全部楼层
如果使用静态IP配置,问题会简单一些,只需要恢复接口的管理状态即可。但如果使用DHCP,网线插入后还需要确保DHCP客户端重新启动,否则设备可能一直使用旧的或无效的IP地址
您需要登录后才可以回帖 登录 | 注册

本版积分规则

65

主题

586

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部
0