先给结论
官方驱动没有按照GD32F4XX手册要求,等待ENET_DMA_CTL第20bit清0后再写
synopsys_emac.c 文件,void EMAC_FlushTransmitFIFO(struct rt_synopsys_eth * ETHERNET_MAC)函数,增加一句判断即可解决。
/**
* Clears the ETHERNET transmit FIFO.
*/
void EMAC_FlushTransmitFIFO(struct rt_synopsys_eth * ETHERNET_MAC)
{
uint16_t timeout=0;
/* Set the Flush Transmit FIFO bit */
ETHERNET_MAC->OMR |= EMAC_DMAOMR_FTF;
while((ENET_DMA_CTL & EMAC_DMAOMR_FTF)&&(timeout< 1000))
{
timeout++;
}
// rt_kprintf("ENET_DMA_CTL :0x%x ,cnt:%d\n",ENET_DMA_CTL,cnt);
}
测试时发现将以太网强制设置成10M全双工,就不会出现偶尔ping不通这个问题,原因不详,欢迎交流讨论。
具体现象为
板子没有开启DHCP功能,固定ip、mac地址,电脑一直ping板子,反复上电(或者reboot),会偶发性出现电脑ping不通板子。ping通后,可以一直ping通下去,ping不通就一直ping不通。
排查记录
1.因为开发过程中遇到应用程序关闭网口设备的问题,怀疑应用程序导致问题,先注释掉可能影响的程序,增加udp pcb数量,增加线程堆栈大小,关断mqtt功能,注释掉其他可能会占用CPU组件的线程,发现还有有问题。
2.怀疑以太网初始化,设置的问题,因为需要在各个组件初始化完重新写入mac(具体为啥要这样见博文RT-Thread框架下,ENET初始化结束后,重新设置MAC方法_灵魂Maker的博客-CSDN博客),怀疑为这个问题导致,注释掉。还有问题。
3.因为phy芯片支持自协商,驱动默认开启,phy芯片和交换机自动协商成100M全双工模式,怀疑为自协商问题,先关断自协商,强行设置为100M full duplex,还有问题,设置为100M half duplex,有问题,10M full duplex,居然没问题了。
4.因为发现10M可以100M不可以,怀疑为硬件时序问题,重新测量RMII时序,虽然不是很完美的波形,但是对比手册给的建立保持均符合要求。尝试设置phy拓展的寄存器推相位。
8201F可以通过设置第7页,第16寄存器,调节时序
这里有个疑问,手册里写了该 寄存器的Rg_rmii_rx_offset 等,为一次性熔丝编程,但是注意事项又说 “RW/EFUS and RW/LI types will return to default values after a software reset (set Reg.0 Bit15 to 1).”,复位后恢复默认值,很奇怪
总而言之,相位调到完美还是不行,偶尔ping不同的问题依然出现。
5.硬件复位信号,软复位时间均调大,还是不行,问题依旧存在。裂开了
6.没办法,开始祭出绝招,一项一项对正常状态下和异常状态下所有enet相关的寄存器值,在眼都花了之后,,发现以太网 DMA 控制寄存器 (ENET_DMA_CTL)在异常状态下,第20bit一直是1,
查看手册,发现手册要求:在该位为’0’之前,不允许写 ENET_DMA_CTL 寄存器,
对比发现RTT对应驱动没有进行对应判断处理,添加等待清零程序,问题解决。