GD32 使用DP83848 移植 LWIP 网线热插入网络不通的解决办法

问题描述 GD32 单片机网线正常插入状态下,启动程序,网络正常。如果GD32 单片机在未接网线的状态下,启动程序后,再将网线插入网口后&#xf

问题描述

  GD32 单片机网线正常插入状态下,启动程序,网络正常。如果GD32 单片机在未接网线的状态下,启动程序后,再将网线插入网口后,IP地址ping不通,网络模块无法正常使用。

解决办法

可参考:
https://blog.csdn/xukao5671927/article/details/77765464

异常现象: 
 
 1、网线不插入的情况下先给设备上电,之后再插入网线无法ping通;(如果上电前网线插入,网络正常); 
 
 2、网络已经正常的情况下,电脑PC端修改传输模式(比如从原来的100M全双工修改为10M全双工)导致网络不通; 
 
 
 
 
 原因分析: 
 
 1、针对第一种异常情况,是由于上电时网线未插入,导致ETH初始化部分未能成功完成,之后即使再插入网线,程序中没有再次进行初始化的逻辑补充,从而导致网络异常; 
 
 2、针对第二种情况,情况是上电时完成了ETH的初始化并与PC协商成功,此时网络正常。但当PC端修改传输模式后,程序中未能执行再次协商与MAC的初始化工作,导致网络异常; 
 
 
 
 
 解决方法: 
 
 首先,要明确上述问题的关键点所在,所有的异常均是网线的拔插导致(PC端修改连接传输方式时也相当于网线的拔掉重插),因此主程序中必须要有对当前网络连接与断开的检测或者利用PHY芯片的中断引脚; 
 
 其次,无论利用轮询或是PHY中断配置引脚,根本的原理都是一样的,就是感知到网络的连接与断开。

摘抄的代码如下:

//lan8720.c
u8 LAN8720_Get_Link() {
	u8 status;
	
	status = ((ETH_ReadPHYRegister(LAN8720_PHY_ADDRESS, PHY_BSR) & PHY_Linked_Status) >> 2);

	return status;
}

//server.c
void server_init()
{
	int i = 0;
	u8 status;

	if(!last_status) {
		LAN8720_Init();
	}

	status = LAN8720_Get_Link();

	if(status == 1) {
		//网络初始化,这里省略千万行代码
		......

		server_start();
	}
		
	last_status = 0;
}

void server_start()
{
	ETH_MACAddressConfig(ETH_MAC_Address0, mjipdev.mac);        //向STM32F4的MAC地址寄存器中写入MAC地址
	ETH_DMATxDescChainInit(DMATxDscrTab, Tx_Buff, ETH_TXBUFNB);
	ETH_DMARxDescChainInit(DMARxDscrTab, Rx_Buff, ETH_RXBUFNB);

	ETH_Start(); //开启MAC和DMA
}

void server_online_chk() {
	u8 status = LAN8720_Get_Link();

	if(status == 0x01 && last_status == 0x00) {
		server_init();
	}
	else if(status == 0x00 && last_status == 0x01) {
		ETH_Stop();
	}

	last_status = status;
}

或者
参考:
https://www.stmcu/module/forum/forum.php?mod=viewthread&tid=627564

在主循环中加入网络状态检测,比如:
if(Check_Link_Status())
	NVIC_SystemReset();//系统重启

在lwip.c中加个函数Check_Link_Status(void),如:
static uint32_t Link_Reg = 0;
uint8_t Check_Link_Status(void)
 {
          uint32_t    i = 0;

           HAL_ETH_ReadPHYRegister(&heth, PHY_SR, &i);

             i = i & PHY_LINK_STATUS;

             if(i != Link_Reg)//网口连接状态发生改变
                        return 1;//system reset
            else
             {
                        Link_Reg = i;
                        return 0;
             }       
 }

参考以上代码:

最终修改如下:

static uint32_t Link_Reg = PHY_LINKED_STATUS;
static uint8_t Check_Link_Status(void)
{
    uint16_t    i = 0;
    enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_SR, &i);
    i = i & PHY_LINKED_STATUS;

    if(i != Link_Reg)//网口连接状态发生改变
    {
        return 1;
    }
    else
    {
        Link_Reg = i;
        return 0;
    }
    
    
}

参考:
https://www.stmcu/module/forum/forum.php?mod=viewthread&tid=627564

https://blog.csdn/pingxiaozhao/article/details/125459956

https://blog.csdn/yekui006/article/details/120296041

https://club.rt-thread/ask/article/c8e511b2a1210586.html

https://club.rt-thread/ask/question/5c50e6b2787f4ba7.html

https://blog.csdn/qq_36553707/article/details/134423712

https://blog.csdn/xukao5671927/article/details/77765464

发布者:admin,转转请注明出处:http://www.yc00.com/web/1754983605a5224019.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信