你好,这边移植 TCP/IP 协议栈时,发现一个问题,在网线一直插入的情况下,通过 BMCR 重启自动协商后,功能异常。
手动启动协商后,ALPAR 以及 PHYSR 不能正确指示工作状态(通过对端网管交换机可以看到链路工作状态,但是与 ALPAR 以及 PHYSR 指示的状态不匹配),测试外置 PHY 没有该问题,请教该如何处理
注一:网线未插拔,手动启动协商状态异常
注二:手动启动协商时,如果手动插拔一下网线,ALPAR 及 PHYSR 正常,但再次手动启动协商时异常
注三:PHY 状态管理使用定期轮询方式,未使用 PHYLINK 中断
注四:现在我的解决方案是 HOOK 了 ETH_WritePHYRegister() 这个函数,当检测到 BMCR 写入自动协商命令时,强制关闭 10M PHY 时钟并等待一段时间以后,再次开启该时钟,也就是实际上不执行手动自动协商命令,短暂测试方案可行,不知道有没有隐患。
测试代码如图:
for ( ;; ) { printf ("PHY:\r\n"); uint16_t BMCR = ETH_ReadPHYRegister (1, 0x00); uint16_t BMSR = ETH_ReadPHYRegister (1, 0x01); uint16_t ALPAR = ETH_ReadPHYRegister (1, 0x05); uint16_t PHYSR = ETH_ReadPHYRegister (1, 0x10); uint16_t MDIX = ETH_ReadPHYRegister (1, 0x1E); printf (" BMCR: %04X\r\n", BMCR); printf (" BMSR: %04X\r\n", BMSR); printf ("ALPAR: %04X\r\n", ALPAR); printf ("PHYSR: %04X\r\n", PHYSR); printf (" MDIX: %04X\r\n", MDIX); vTaskDelay (1000); printf ("Restart Auto-Negotiation\r\n"); ETH_WritePHYRegister (1, 0x00, BMCR | 0x0200); vTaskDelay (5000); BMCR = ETH_ReadPHYRegister (1, 0x00); BMSR = ETH_ReadPHYRegister (1, 0x01); ALPAR = ETH_ReadPHYRegister (1, 0x05); PHYSR = ETH_ReadPHYRegister (1, 0x10); MDIX = ETH_ReadPHYRegister (1, 0x1E); printf (" BMCR: %04X\r\n", BMCR); printf (" BMSR: %04X\r\n", BMSR); printf ("ALPAR: %04X\r\n", ALPAR); printf ("PHYSR: %04X\r\n", PHYSR); printf (" MDIX: %04X\r\n", MDIX); }
测试结果如图
启动协商过程中插拔一次网线
启动协商过程中,保持网线一直有效连接