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

LWIP热插拔功能实现

0 工具准备

1.lwip 1.4.1
2.RTOS(本文使用rt-thread)

1 使能连接变化回调功能

打开lwipopts.h,将宏定义LWIP_NETIF_LINK_CALLBACK的值设为1,如下:

#define LWIP_NETIF_LINK_CALLBACK        1

这个宏定义被使能后会将void ethernetif_update_config(struct netif *netif)函数加入工程中进行编译。这个函数的功能就是检查当前连接情况,进行不同的处理。
该函数如下:

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, &regvalue);/* 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, &regvalue);if ((regvalue & PHY_DUPLEX_STATUS) != (uint32_t)RESET){heth.Init.DuplexMode = ETH_MODE_FULLDUPLEX;}else{heth.Init.DuplexMode = ETH_MODE_HALFDUPLEX;}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);
}

2 完善连接状态变化回调函数

在ethernetif_update_config函数的最后有一个名为ethernetif_notify_conn_changed的函数需要用户自定义功能,由于我们这里使用的是固定IP,因此自定义的状态变化回调函数如下:

void ethernetif_notify_conn_changed(struct netif *netif)
{if(netif_is_link_up(netif)){printf("\r\nLan link up!\r\n");netif_set_up(netif);}else{printf("\r\nLan link down!\r\n");netif_set_down(netif);}
}

如果需要启用了DHCP功能,可以在发现网线插上后等待路由器分配IP。

3 绑定回调函数

前面我们已经编辑好了自定义的回调函数,接下来需要绑定回调函数,在我们的网线连接状态改变时执行回调函数。绑定回调函数只需要添加netif_set_link_callback(&gnetif, ethernetif_update_config)语句到LWIP初始化函数内即可。如下:

    netif_set_default(&gnetif);if (netif_is_link_up(&gnetif)){/* When the netif is fully configured this function must be called */netif_set_up(&gnetif);}else{/* When the netif link is down this function must be called */netif_set_down(&gnetif);}netif_set_link_callback(&gnetif, ethernetif_update_config);

4 轮询网口连接状态

前面我们已经完成了回调函数编写,同时绑定了回调函数。由于lwip 1.4.1原生没有轮询网口连接状态,因此这部分需要我们来编写。这里我们使用RTOS,将轮询网口连接状态的函数放到软件定时器内执行:

void lan_state_check(void)
{uint32_t regvalue = 0;HAL_ETH_ReadPHYRegister(&heth, PHY_BSR, &regvalue);if ((regvalue & PHY_LINKED_STATUS) == PHY_LINKED_STATUS){netif_set_flags(&gnetif, NETIF_FLAG_LINK_UP);if (netif_is_up(&gnetif) != 1){gnetif.link_callback(&gnetif);}}else{netif_clear_flags(&gnetif, NETIF_FLAG_LINK_UP);if (netif_is_up(&gnetif) != 0){gnetif.link_callback(&gnetif);}}
}

这个函数主要功能就是读取PHY的BSR寄存器查看连接状态,如果当前连接状态的物理状态和LWIP软件连接状态不一致则执行回调函数。
其中物理连接状态由软件定时器周期性设置,设置的bit为NETIF_FLAG_LINK_UP,软件连接状态由LWIP内核设置,设置的bit为NETIF_FLAG_UP。

5 优化启动速度

上电阶段有时网卡还未建立有效连接,ETH初始化函数会一直阻塞等待连接建立直至超时,默认的超时时间为5000ms,也就是说如果上电后网卡没有建立有效连接会一直阻塞等待5000ms,体验感非常差。为了解决这一问题,将以下2个宏定义修改成2000即可:

#define ETH_TIMEOUT_LINKED_STATE          2000U
#define ETH_TIMEOUT_AUTONEGO_COMPLETED    2000U

6 插拔测试

(1)上电后再插上网线,随后ping路由器
在这里插入图片描述
可以看到打印了“Lan link up!”,程序识别到了这一变化同时执行了回调函数,ping路由器正常。
(2)将网线拔下
在这里插入图片描述
可以看到打印了“Lan link down!”,程序识别到了这一变化同时执行了回调函数。
(3)反复执行(1)(2)查看是否正常。
在这里插入图片描述
反复执行也能保证稳定,测试结果正常。

7 总结

(1)LWIP实现热插拔的关键在于识别物理网口连接状态和软件连接状态是否一致,当二者不一致时则将软件连接状态设置为和物理网口连接状态一致。
(2)需要根据实际情况自定义回调函数。
(3)超时时间不要设置太短,实测2000ms有效。

相关文章:

LWIP热插拔功能实现

0 工具准备 1.lwip 1.4.1 2.RTOS(本文使用rt-thread)1 使能连接变化回调功能 打开lwipopts.h,将宏定义LWIP_NETIF_LINK_CALLBACK的值设为1,如下: #define LWIP_NETIF_LINK_CALLBACK 1这个宏定义被使能后会将…...

android下的app性能测试应主要针对那些方面,如何开展?

如何开展安卓手机下的App性能测试,对于优秀的测试人员而言,除了要懂得性能测试的步骤流程外,还应该懂的性能测试的一些其他知识,比如性能测试指标、各指标的意义,常用的性能测试工具、如何查看结果分析等等知识。所以本…...

【深度学习】注意力机制(二)

本文介绍一些注意力机制的实现,包括EA/MHSA/SK/DA/EPSA。 【深度学习】注意力机制(一) 【深度学习】注意力机制(三) 目录 一、EA(External Attention) 二、Multi Head Self Attention 三、…...

学习黑马vue

项目分析 项目下载地址:vue-admin-template-master: 学习黑马vue 项目下载后没有环境可参考我的篇文章,算是比较详细:vue安装与配置-CSDN博客 安装这两个插件可格式化代码,vscode这个软件是免费的,官网:…...

gdb本地调试版本移植至ARM-Linux系统

移植ncurses库 本文使用的ncurses版本为ncurses-5.9.tar.gz 下载地址:https://ftp.gnu.org/gnu/ncurses/ncurses-5.9.tar.gz 1. 将ncurses压缩包拷贝至Linux主机或使用wget命令下载并解压 tar-zxvf ncurses-5.9.tar.gz 2. 解压后进入到ncurses-5.9目录…...

《Linux C编程实战》笔记:实现自己的ls命令

关键函数的功能及说明 1.void display_attribute(struct stat buf,char *name) 函数功能:打印文件名为name的文件信息,如 含义分别为:文件的类型和访问权限,文件的链接数,文件的所有者,文件所有者所属的组…...

Python个人代码随笔(观看无益,请跳过)

异常抛错:一般来说,在程序中,遇到异常时,会从这一层逐层往外抛错,一直抛到最外层,由最外层把错误显示在用户终端。 try:raise ValueError("A value error...") except ValueError:print("V…...

Unity中实现ShaderToy卡通火(总结篇)

文章目录 前言一、把卡通火修改为后处理效果1、在Shader属性面板定义属性接收帧缓存纹理2、在片元着色器对其纹理采样后,与卡通火相加输出请添加图片描述 二、我们自定义卡通火1、修改 _CUTOFF 使卡通火显示在屏幕两侧2、使火附近屏幕偏红色 前言 在之前的文章中&a…...

等保2.0的变化

1法律地位得到确认 《中华人民共和国网络安全法》第21条规定“国家实行网络安全等级保护制度”,要求“网络运营者应当按照网络安全等级保护制度要求,履行安全保护义务”;第31条规定“对于国家关键信息基础设施,在网络安全等级保护…...

漏洞复现-网神SecGate3600防火墙敏感信息泄露漏洞(附漏洞检测脚本)

免责声明 文章中涉及的漏洞均已修复,敏感信息均已做打码处理,文章仅做经验分享用途,切勿当真,未授权的攻击属于非法行为!文章中敏感信息均已做多层打马处理。传播、利用本文章所提供的信息而造成的任何直接或者间接的…...

ArkTS入门

代码结构分析 struct Index{ } 「自定义组件:可复用的UI单元」 xxx 「装饰器:用来装饰类结构、方法、变量」 Entry 标记当前组件是入口组件(该组件可被独立访问,通俗来讲:它自己就是一个页面)Component 用…...

JS中for循环之退出循环

我为大家介绍一下退出循环的两种方法 1.continue 退出本次循环&#xff0c;一般用于排除或者跳过某一个选项的时候&#xff0c;可以使用continue for(let i 0;i<5;i){if(i 3){continue}// 跳过了3console.log(i) //0 1 2 4}2.break 退出整个for循环&#xff0c;一般用于…...

《Global illumination with radiance regression functions》

总结一下最近看的这篇结合神经网络的全局光照论文。 论文的主要思想是利用了神经网络的非线性特性去拟合全局光照中的间接光照部分&#xff0c;采用了基础的2层MLP去训练&#xff0c;最终能实现一些点光源、glossy材质的光照渲染。为了更好的理解、其输入输出表示如下。 首先…...

华南理工C++试卷

诚信应考 , 考试作弊将带来严重后果&#xff01; 《C程序设计试卷》 注意事项&#xff1a;1. 考前请将密封线内填写清楚&#xff1b; 2. 所有答案请答在试卷的答案栏上&#xff1b; 3&#xff0e;考试形式&#xff1a;闭卷 4. 本试卷共 五 大题&#xff0c;满分100分&#xff…...

0001.WIN7(64位)安装ADS1.2出现L6218错误

用了十多年的笔记本电脑系统出现问题&#xff0c;硬件升级重装以后安装ADS1.2。在编译代码的时候出现L6218错误。如下&#xff1a; 图片是从网上找的&#xff0c;我编译出错的界面没有保留下来。 首先&#xff0c;代码本身没有任何问题 &#xff0c;代码在win7(32位)下编译没有…...

HBuilderX 配置 夜神模拟器 详细图文教程

在电脑端查看App的效果&#xff0c;不用真机调试&#xff0c;下载一个模拟器就可以了 --- Nox Player&#xff0c;夜神模拟器&#xff0c;是一款 Android 模拟器。他的使用非常安全&#xff0c;最重要的是完全免费。 一. 安装模拟器 官网地址&#xff1a; (yeshen.com) 二.配…...

10、神秘的“位移主题”

神秘的“位移主题” 1、什么是位移主题2、位移主题的消息格式3、位移主题是怎么被创建的4、什么地方会用到位移主题5、位移主题的删除机制 本章主题是&#xff1a;Kafka 中的内部主题&#xff08;Internal Topic&#xff09;__consumer_offsets。 __consumer_offsets 在 Kafka …...

【Linux】dump命令使用

dump命令 dump命令用于备份文件系统。使用dump命令可以检查ext2/3/4文件系统上的文件&#xff0c;并确定哪些文件需要备份。这些文件复制到指定的磁盘、磁带或其他存储介质保管。 语法 dump [选项] [目录|文件系统] bash: dump: 未找到命令... 安装dump yum -y install …...

使用 TensorFlow 创建生产级机器学习模型(基于数据流编程的符号数学系统)——学习笔记

资源出处&#xff1a;初学者的 TensorFlow 2.0 教程 | TensorFlow Core (google.cn) 前言 对于新框架的学习&#xff0c;阅读官方文档是一种非常有效的方法。官方文档通常提供了关于框架的详细信息、使用方法和示例代码&#xff0c;可以帮助你快速了解和掌握框架的使用。 如…...

vue实现悬浮窗拖动的自定义指令

首先在自己的项目根目录下建一个 src --> config --> drag.js 然后在main.js中全局引入 //鼠标拖动 import drag from /config/drag; Vue.use(drag); drag.js文件相关代码 import Vue from vue; //使用Vue.directive()定义一个全局指令 //1.参数一&#xff1a;指令的…...

Java 语言特性(面试系列2)

一、SQL 基础 1. 复杂查询 &#xff08;1&#xff09;连接查询&#xff08;JOIN&#xff09; 内连接&#xff08;INNER JOIN&#xff09;&#xff1a;返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...

脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)

一、数据处理与分析实战 &#xff08;一&#xff09;实时滤波与参数调整 基础滤波操作 60Hz 工频滤波&#xff1a;勾选界面右侧 “60Hz” 复选框&#xff0c;可有效抑制电网干扰&#xff08;适用于北美地区&#xff0c;欧洲用户可调整为 50Hz&#xff09;。 平滑处理&…...

3.3.1_1 检错编码(奇偶校验码)

从这节课开始&#xff0c;我们会探讨数据链路层的差错控制功能&#xff0c;差错控制功能的主要目标是要发现并且解决一个帧内部的位错误&#xff0c;我们需要使用特殊的编码技术去发现帧内部的位错误&#xff0c;当我们发现位错误之后&#xff0c;通常来说有两种解决方案。第一…...

可靠性+灵活性:电力载波技术在楼宇自控中的核心价值

可靠性灵活性&#xff1a;电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中&#xff0c;电力载波技术&#xff08;PLC&#xff09;凭借其独特的优势&#xff0c;正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据&#xff0c;无需额外布…...

FastAPI 教程:从入门到实践

FastAPI 是一个现代、快速&#xff08;高性能&#xff09;的 Web 框架&#xff0c;用于构建 API&#xff0c;支持 Python 3.6。它基于标准 Python 类型提示&#xff0c;易于学习且功能强大。以下是一个完整的 FastAPI 入门教程&#xff0c;涵盖从环境搭建到创建并运行一个简单的…...

聊聊 Pulsar:Producer 源码解析

一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台&#xff0c;以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中&#xff0c;Producer&#xff08;生产者&#xff09; 是连接客户端应用与消息队列的第一步。生产者…...

Golang dig框架与GraphQL的完美结合

将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用&#xff0c;可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器&#xff0c;能够帮助开发者更好地管理复杂的依赖关系&#xff0c;而 GraphQL 则是一种用于 API 的查询语言&#xff0c;能够提…...

【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)

升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点&#xff0c;但无自动故障转移能力&#xff0c;Master宕机后需人工切换&#xff0c;期间消息可能无法读取。Slave仅存储数据&#xff0c;无法主动升级为Master响应请求&#xff…...

浅谈不同二分算法的查找情况

二分算法原理比较简单&#xff0c;但是实际的算法模板却有很多&#xff0c;这一切都源于二分查找问题中的复杂情况和二分算法的边界处理&#xff0c;以下是博主对一些二分算法查找的情况分析。 需要说明的是&#xff0c;以下二分算法都是基于有序序列为升序有序的情况&#xf…...

基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解

JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用&#xff0c;结合SQLite数据库实现联系人管理功能&#xff0c;并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能&#xff0c;同时可以最小化到系统…...