当前位置: 首页 > news >正文

LWIP 热插拔调试 -- 不同品牌路由器引起的问题

要完成热插拔,需要在MX_LWIP_Process中加入一个热插拔的处理函数,如下

ethernetif_set_link

void MX_LWIP_Process(void)
{
/* USER CODE BEGIN 4_1 */ 
/* USER CODE END 4_1 */
  ethernetif_input(&gnetif);
  
/* USER CODE BEGIN 4_2 */
/* USER CODE END 4_2 */  
  /* Handle timeouts */
  sys_check_timeouts();

/* USER CODE BEGIN 4_3 */
  ethernetif_set_link(&gnetif);  
/* USER CODE END 4_3 */
}

这个函数的源码内容很简单

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);
    
    regvalue &= PHY_LINKED_STATUS;
    
    /* Check whether the netif link down and the PHY link is up */
    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);
    }
  }
}

这里,HAL_ETH_ReadPHYRegister(&heth, PHY_BSR, &regvalue); 反复读取当前PHY寄存器中的状态参数。我用的是LAN8720,PHY_BSR=1,具体对应LAN8720手册中第4.2.2 BASIC STATUS REGISTER这一节。然后测试第3位(PHY_LINKED_STATUS位),如果为1 ,表明已经建立物理连接,直接连上。如果为0,则通过netif_set_link_down来清除各个设置参数。

无论是netif_set_link_up还是netif_set_link_down,其中都调用了一个函数,

NETIF_LINK_CALLBACK(netif);

这个回调函数是我们在LWIP_MX_Init中设置的,也就是ethernetif_update_config,该函数由cubemx自动生成,用户无需修改,

/* Set the link callback function, this function is called on change of link status*/
  netif_set_link_callback(&gnetif, ethernetif_update_config);

在ethernetif_update_config中,最后会调用ethernetif_notify_conn_changed这个函数,这个函数是提供给用户的,用户可以根据需求修改,空着不用也没关系。比如我的改成了这样,

void ethernetif_notify_conn_changed(struct netif *netif)
{
	ip_addr_t ipaddr;
	ip_addr_t netmask;
	ip_addr_t gw;
	
	if(netif_is_link_up(netif))
	{
		print_msg("The network cable is now connected \n");
    
		if(cfg_init_param &	CFG_BIT_STATICIP){
			/* IP addresses initialization without DHCP (IPv4) */
			IP4_ADDR(&ipaddr, IP_ADDRESS[0], IP_ADDRESS[1], IP_ADDRESS[2], IP_ADDRESS[3]);
			IP4_ADDR(&netmask, NETMASK_ADDRESS[0], NETMASK_ADDRESS[1] , NETMASK_ADDRESS[2], NETMASK_ADDRESS[3]);
			IP4_ADDR(&gw, GATEWAY_ADDRESS[0], GATEWAY_ADDRESS[1], GATEWAY_ADDRESS[2], GATEWAY_ADDRESS[3]);
			
			netif_set_addr(netif, &ipaddr , &netmask, &gw);
			print_msg("Static IP address: %s\n", ip4addr_ntoa((const ip4_addr_t *)&netif->ip_addr));
		}
		else {
			DHCP_state = DHCP_START;  // Update DHCP state machine
		}		
		
		print_msg("Sate: line link detected...\n");			
	} 
	else
	{
		if(0==(cfg_init_param &	CFG_BIT_STATICIP)) { //#ifdef USE_DHCP
			DHCP_state = DHCP_LINK_DOWN;             // Update DHCP state machine
		}                                            //#endif USE_DHCP    
	
		print_msg ("The network cable is not connected.");
		main_flag &= ~((uint16_t)(EMF_TCP_HWLINKED | EMF_TCP_LISTENBIND | EMF_TCP_CLIENTCONNECTED));
	}
}

基本上都是一些自定义的参数或报告输出,就是说连上后要用DHCP还是静态IP之类的。

好,这些都很好理解。

问题出在 ethernetif_set_link这个函数。我使用华为的路由器WS5200,其一是热插拔根本无法连接上;RESET重启后,多数情况下,启动时都会首先进入netif_set_link_up,几个循环之后,马上进入netif_set_link_down。

根据我个人的测定,华为路由器设定了一个奇怪的规则:大约2分钟或几十秒之内,可能根据具体情况的不同(是什么情况无法判定),新断开的IP不允许重新连接。只要过一段时间后再试才能成功。

换了一个TPlinkWR842N测试,完全没有这些问题,不论热插拔还是重启,反复测试,都能很快实现连接。

因为这个问题太奇怪了,所以记录一下备忘记,到现在还不知道要怎么设置华为的路由器才能实现快速响应。

如果你的LWIP热插拔也存在同样的问题,那还得看一下是不是你的路由器的问题。

相关文章:

  • OpenCV的一个BUG: BMP读取后无法用imwrite成功保存PNG
  • 承接机器视觉项目到底应该选哪个解决方案?传统机器视觉 vs 人工智能
  • 安装OpenPCDet碰到的问题
  • Python3.8上安装vtk和mayavi踩坑: Building wheel for mayavi (setup.py) ...
  • ubuntu中如何显示或隐藏配置文件夹如.config
  • vscode没法选python解释器interpreter
  • 在windows10上安装运行ROS2
  • Ubuntu18.04 安装 ros2 foxy
  • VSCode常用操作
  • Ceres-Solver安装与简介
  • SLAM算法VINS-MONO安装运行介绍
  • Protobuf,gmock,gtest在windows10上的编译与安装
  • CMD闪退的问题及报错“点的大小应介于5和72之间”
  • 常用git 指令
  • 常用的anaconda(conda)命令
  • 「面试题」如何实现一个圣杯布局?
  • 11111111
  • axios 和 cookie 的那些事
  • CentOS 7 修改主机名
  • docker容器内的网络抓包
  • Vue全家桶实现一个Web App
  • 番外篇1:在Windows环境下安装JDK
  • 工作中总结前端开发流程--vue项目
  • 关于Flux,Vuex,Redux的思考
  • 湖南卫视:中国白领因网络偷菜成当代最寂寞的人?
  • 漫谈开发设计中的一些“原则”及“设计哲学”
  • 面试遇到的一些题
  • 设计模式(12)迭代器模式(讲解+应用)
  • 一起来学SpringBoot | 第三篇:SpringBoot日志配置
  • # 数据结构
  • #绘制圆心_R语言——绘制一个诚意满满的圆 祝你2021圆圆满满
  • (Redis使用系列) Springboot 在redis中使用BloomFilter布隆过滤器机制 六
  • (ZT)薛涌:谈贫说富
  • (超详细)2-YOLOV5改进-添加SimAM注意力机制
  • (二)什么是Vite——Vite 和 Webpack 区别(冷启动)
  • (附源码)计算机毕业设计SSM基于健身房管理系统
  • (免费领源码)Python#MySQL图书馆管理系统071718-计算机毕业设计项目选题推荐
  • (十二)springboot实战——SSE服务推送事件案例实现
  • (转)重识new
  • ***微信公众号支付+微信H5支付+微信扫码支付+小程序支付+APP微信支付解决方案总结...
  • .NET 6 Mysql Canal (CDC 增量同步,捕获变更数据) 案例版
  • .NET Core日志内容详解,详解不同日志级别的区别和有关日志记录的实用工具和第三方库详解与示例
  • .net 发送邮件
  • .NET中 MVC 工厂模式浅析
  • .Net中间语言BeforeFieldInit
  • @RequestBody的使用
  • @四年级家长,这条香港优才计划+华侨生联考捷径,一定要看!
  • [ IO.File ] FileSystemWatcher
  • [<事务专题>]
  • [20160902]rm -rf的惨案.txt
  • [AIGC codze] Kafka 的 rebalance 机制
  • [codevs1288] 埃及分数
  • [Delphi]一个功能完备的国密SM4类(TSM4)[20230329更新]
  • [IE编程] 打开/关闭IE8的光标浏览模式(Caret Browsing)
  • [Linux] LVS+Keepalived高可用集群部署