lwip+freeRTOS 实现热插拔功能

1、lwip启用LWIP_NETIF_CALLBACK 宏,cubeMX会自动生成相关函数()。

 

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

 

回调函数在void ethernetif_update_config(struct netif *netif),其中主要完成通信协商之类的初始化。

最后调用__weak void ethernetif_notify_conn_changed(struct netif *netif),用户的代码在这里边实现。

比如,我是每当发现网卡出现插拔后,重新执行DHCP,动态获取IP,代码如下:

__weak void ethernetif_notify_conn_changed(struct netif *netif)
{/* NOTE : This is function could be implemented in user filewhen the callback is needed,*/int err;ipaddr.addr = 0;if (netif_is_link_up(&gnetif)){DEBUG("net link is up\r\n");DEBUG("starting dhcp...\n");err = dhcp_start(&gnetif);if (err == ERR_OK) {DEBUG("starting dhcp success!\n");} else {DEBUG("starting dhcp fail!\n");}int res = 0;do{res = ip_addr_cmp(&(gnetif.ip_addr),&ipaddr);if (res){osDelay(1000);DEBUG("wait dhcp...\r\n");}} while (res);DEBUG("dhcp get local ip :%d.%d.%d.%d\n\n",  \((gnetif.ip_addr.addr)&0x000000ff),       \(((gnetif.ip_addr.addr)&0x0000ff00)>>8),  \(((gnetif.ip_addr.addr)&0x00ff0000)>>16), \((gnetif.ip_addr.addr)&0xff000000)>>24);} else {DEBUG("net link is down\r\n");}
}

2、开机没接网线,无法初始化网卡,程序崩溃问题。

程序开机运行时如果由网线连接,那么正常初始化后按照上面的配置是可以实现热插拔的。但是,如果在初始化网卡之前没有连接网线,则程序会运行失败,甚至崩溃。

网卡初始化,调用HAL库的 hal_eth_init_status = HAL_ETH_Init(&heth); 进一步可以发现该函数中由以下内容:

  if((heth->Init).AutoNegotiation != ETH_AUTONEGOTIATION_DISABLE){/* Get tick */tickstart = HAL_GetTick();/* We wait for linked status */do{HAL_ETH_ReadPHYRegister(heth, PHY_BSR, &phyreg);/* Check for the Timeout */if((HAL_GetTick() - tickstart ) > ETH_TIMEOUT_LINKED_STATE){/* In case of write timeout */err = ETH_ERROR;/* Config MAC and DMA */ETH_MACDMAConfig(heth, err);heth->State= HAL_ETH_STATE_READY;/* Process Unlocked */__HAL_UNLOCK(heth);return HAL_TIMEOUT;}} while (((phyreg & PHY_LINKED_STATUS) != PHY_LINKED_STATUS));

该部分描述的是如果启用了速率自协商,那么会一直判断读取PHY芯片的BSR寄存器当前是否由连接,否则等待直到超时。超时时间是ETH_TIMEOUT_LINKED_STATE,也即5s。程序一直卡在这里,如果启用了操作系统,那么这个任务将阻塞其他的任务,导致报错。

解决方案是在网卡初始化和LWIP初始化之前,检查是否由网线连接,读PHY_BSR寄存器,然后判断即可。当然,需要先初始化网卡的基本接口,保证寄存器能够读取。

等待网络连接的接口如下:


int waitNetLink(uint32_t timeout_s)
{ETH_HandleTypeDef heth;heth.Instance = ETH;heth.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE;heth.Init.PhyAddress = LAN8720_PHY_ADDRESS;heth.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII;HAL_ETH_MspInit(&heth);osDelay(PHY_RESET_DELAY);uint32_t checkCnt = 0;if((heth.Init).AutoNegotiation != ETH_AUTONEGOTIATION_DISABLE) {uint32_t tickstart = HAL_GetTick();uint32_t phyreg = 0U;do {HAL_ETH_ReadPHYRegister(&heth, PHY_BSR, &phyreg);osDelay(1000);if (0 == (checkCnt++ % 3)) {DEBUG("wait net link, timeout %u s, now %u s...\r\n", timeout_s, checkCnt);}if (checkCnt >= timeout_s - 1) {if (((phyreg & PHY_LINKED_STATUS) != PHY_LINKED_STATUS)) {HAL_ETH_MspDeInit(&heth);return -1;}}} while (((phyreg & PHY_LINKED_STATUS) != PHY_LINKED_STATUS));}HAL_ETH_MspDeInit(&heth);if (checkCnt <= timeout_s - 1) { return 0; }else { return 1; }
}

使用方法:

/* USER CODE END Header_lwIPAppTaskFunc */
void lwIPAppTaskFunc(void *argument)
{/* USER CODE BEGIN lwIPAppTaskFunc */DEBUG("lwip app task started\r\n");/* init code for LWIP */int link_res = waitNetLink(osWaitForever);if (0 != link_res){DEBUG("wait net link timeout\r\n");} else {/*! lwip init */MX_LWIP_Init();/*! creat socket client */int creat_res = creat_tcp_client(&client_id,SOCKET_SERVER_ADDR,SOCKET_SERVER_PORT);if (creat_res != 0) {DEBUG("creat_tcp_client error: res = %d\r\n", creat_res);} else {DEBUG("creat_tcp_client success\r\n");}}/* Infinite loop */for(;;){osDelay(1);}/* USER CODE END lwIPAppTaskFunc */
}

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/404806.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

iOS设计模式 - 享元

iOS设计模式 - 享元 原理图 说明 享元模式使用共享物件&#xff0c;用来尽可能减少内存使用量以及分享资讯给尽可能多的相似物件&#xff1b;它适合用于只是因重复而导致使用无法令人接受的大量内存的大量物件。通常物件中的部分状态是可以分享。常见做法是把它们放在外部数据结…

带箭头的菜单列表

<title>带箭头的菜单列表</title><style>body{background-color:#999;}#menu{font-size:16px;width:140px;margin:0 auto;border:solid 1px #ccc;}#menu a,#menu a:visited{text-decoration:none;text-align:center;color:#c00;display:block;padding:4px;ba…

gcc编译选项-Os的用法

From: http://hi.baidu.com/caosicong/item/e61fa700581980d11ff0469c **********************gcc/egcs 的主要选项********* gcc 命令的常用选项 选项 解释 -ansi 只支持 ANSI 标准的 C 语法。这一选项将禁止 GNU C 的某些特色&#xff0c; 例如 asm 或 typeof 关键词。…

ASP.NET和PHP全面对比

谁是速度之王&#xff1f; 刚刚在9月编程语言排行榜上取得历史性突破的PHP在Web开发领域最到的对手可能就是基于微软.NET技术的ASP.NET。近日&#xff0c;微软的 Joe Stagner在博客上发表了一系列文章比较了PHP和ASP.NET性能方面的文章&#xff0c;引起了来自双方程序员的大量回…

40个漂亮的单页网站设计案例(上篇)

有很多人喜欢单页网站&#xff0c;这种网站只有一个页面&#xff0c;设计都很精美&#xff0c;通过锚记进行平滑的导航。不过&#xff0c;并不是每个网站都适合做成单页&#xff0c;一般都是内容比较少而且将来内容也不怎么增加的情况才适合这样做。如果你打算做一个这样的网站…

jsoncpp之初体验

参考文章 http://blog.csdn.net/JoeBlackzqq/article/details/9043315 , 我将里面的代码做在了一个工程亲自体验了下。 1. 下载jsoncpp源码&#xff0c; 地址: http://nchc.dl.sourceforge.net/project/jsoncpp/jsoncpp/0.5.0/jsoncpp-src-0.5.0.tar.gz 2. 编译json&#xff0…

让Windwos Server 2008 R2 SP1的FTP真正能访问

今天把FTP配置好后&#xff0c;在本机上匿名访问没有问题了&#xff0c;以为万事大吉&#xff0c;于是把需要的文件放入后&#xff0c;到另一台机子上去试试&#xff0c;结果发现出现下面的画面。访问不通&#xff01;什么原因&#xff1f;于是把防火墙完全关闭了&#xff0c;发…

几款用于电能质量测量的芯片

1、ATT7022B ATT7022B 是专用的智能电表计量芯片&#xff0c;ATT7022B 包含六路二阶 sigma-delta ADC、电能质量参数数字信号处理等电路。ATT7022B 可以测量系统的电压、电流、频率、有功功率、无功功率、有功能量、无功能量等参数。ATT7022B 通过 SPI 通信接口进行数据通信。…

深入浅出UML类图

From: http://www.uml.org.cn/oobject/201211231.asp 在UML 2.0的13种图形中&#xff0c;类图是使用频率最高的UML图之一。Martin Fowler在其著作《UML Distilled: A Brief Guide to the Standard Object Modeling Language, Third Edition》&#xff08;《UML精粹&#xff1a;…

TI基于MSP430F67641的电能表技术方案

1、三相四线硬件架构 1.1 阻容降压供电 1.2 电压输入 1.3 电流输入 2、RMS有效值计算 3、计量参数算法 3.1 有功和无功 3.2 视在功率 3.3 三相总功率 3.4 电能 3.5 频率 3.6 功率因数

comsol 多物理场仿真流程-以开关柜为例

1、主要方法 在SolidWorks中对于开关柜的内部与外部结构进行建模&#xff0c;生成能够导入软件计算的3D模型。将SolidWorks中的模型导入comsol软件中&#xff0c;设置参数进行多物理场耦合仿真。 1、具体步骤 删除高压开关柜中对其内部电磁环境无较大影响的结构&#xff0c;如…

2.UiSelector API 详细介绍

一、UiSelector类介绍 //通过各种属性与节点关系定位组件简单实例&#xff1a;public void testDemo2() throws UiObjectNotFoundException{UiSelector l new UiSelector().text("相机");//搜索条件UiObject objectnew UiObject(l);//一句搜索条件找到对象object.cli…

断路器操作机构分合闸线圈电流特征曲线特点

1、特征量描述 高压断路器操作机构线圈电流波形可以反映分合闸电磁铁本身及所控制的锁闩或阀门以及与之相连的开关操动机构、辅助触点在操作过程中的工作情况。操作机构分合闸过程的工作原理相同&#xff0c;其线圈电流波形也类似。以下是典型的特征电流曲线示意图&#xff1a…

几种仪表放大器电路总结

一般模拟信号在进入A/D采样前&#xff0c;需要先进行信号调理&#xff0c;模拟信号放大部分需要着重设计。放大电路采用仪表放大器&#xff0c;其能有效抵抗共模干扰且具有很高的输入电阻&#xff0c;有效提高信噪比。 以下总结常用的仪表模拟放大电路设计。 1、单运放仪表放…

IEEE1459功率理论计算方法

0、ADC采集5通道电压&#xff08;ABCN地&#xff09;&#xff0c;4通道电流采用每周波1024点同步采样 1、计算各相&#xff08;Ua、Ub、Uc&#xff09;、线电压&#xff08;Uab、Uac、Ubc&#xff09;&#xff0c;相电流&#xff08;Ia、Ib、Ic&#xff09; 2、计算各相电压、…

使用Visio 2000逆向工程将代码转换为UML图表

From: http://www.sudu.cn/info/html/website/20080508/307109.html 摘要&#xff1a;Microsoft Visio 2000 Professional Edition 和 Enterprise Edition 包含通过逆向工程将 Microsoft Visual C、Microsoft Visual Basic 和 Microsoft Visual J 代码转换为统一建模语言 (UM…

POJ1177 Picture 线段树+离散化+扫描线

求最终的覆盖图形周长&#xff0c;写这种代码应该短而精确&#xff0c;差的比较远 /* Problem: 1177 User: 96655 Memory: 348K Time: 32MS Language: C Result: Accepted */ #include<iostream> #include<stdio.h> #include<stdlib.h>…

DA模拟量控制外接600V高压直流源-设计分析

一、STM32 12位AD DA线性度测试 配置STM32 DA为12bit输出&#xff0c;AD为12bit检测&#xff0c;测试AD和DA的线性度与误差。DAC从0到2.49V步进1mV。ErrorDAC 为标准值减去 ADC的测量值。 板子的Vref2.5V&#xff0c;ADC和DAC的极限为2.5V&#xff0c;测试时直接用杜邦线连接…

使用 rose 将 c++代码转换为 uml 类图

From: http://www.cppblog.com/prayer/archive/2009/12/24/103954.html 阅读本文章&#xff0c;你需要对 uml 有简单的了解&#xff0c;懂得以下术语&#xff1a; 类图( class diagram ) 即 c 中的 class 。 聚合( Aggregation ) 即我们c中的引用。表现为 class 头文件中的…