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;它适合用于只是因重复而导致使用无法令人接受的大量内存的大量物件。通常物件中的部分状态是可以分享。常见做法是把它们放在外部数据结…

C# 视频监控系列(11):H264播放器——封装API[HikPlayM4.dll]

前言 当你认真的写完客户端和服务器端的时候可能不需要再继续往下看关于播放器的代码和说明&#xff0c;因为你已经掌握了如何转换VC代码的技巧了&#xff0c;加上GOOGLE再来完成这个播放器应该算小菜了。但是作为我的系列&#xff0c;我还是有必要认真的将这部分写完才算完整&…

[react] React16废弃了哪些生命周期?为什么?

[react] React16废弃了哪些生命周期&#xff1f;为什么&#xff1f; React16废弃的生命周期有3个will&#xff1a; componentWillMount componentWillReceiveProps componentWillUpdate 废弃的原因&#xff0c;是在React16的Fiber架构中&#xff0c;调和过程会多次执行will周…

lwip+freeRTOS 故障容错 客户端主动发起连接

1、简单的需求 STM32终端为tcp客户端&#xff0c;主动向TCP服务器发起连接&#xff0c;然后进行通信。 流程&#xff1a;STM32网卡初始化-----lwIP初始化--------DHCP-------------creat socket Client-------send-------recv 2、实际情况 &#xff08;1&#xff09;如何处…

JS正则表达式大全【转】

正则表达式中的特殊字符 字符 含意 \ 做为转意&#xff0c;即通常在"\"后面的字符不按原来意义解释&#xff0c;如/b/匹配字符"b"&#xff0c;当b前面加了反斜杆后/\b/&#xff0c;转意为匹配一个单词的边界。 -或- 对正则表达式功能字符的还原&#xff0c…

C++回调函数用法

From: http://blog.csdn.net/wubin1124/article/details/4386269 一回调函数 我们经常在C设计时通过使用回调函数可以使有些应用&#xff08;如定时器事件回调处理、用回调函数记录某操作进度等&#xff09;变得非常方便和符合逻辑&#xff0c;那么它的内在机制如何呢&#x…

[react] 举例说明什么是高阶组件(HOC)的属性代理

[react] 举例说明什么是高阶组件(HOC)的属性代理 function HOC(WrappedComponent) {return class HOC extends Component {render() {const newProps { type: HOC };return <div><WrappedComponent {...this.props} {...newProps} /></div>}} }hoc class O…

树莓派使用STEP8:使能串口调试

1、打开SD卡根目录"config.txt"文件&#xff0c;文末增加dtoverlaypi3-miniuart-bt并且保存 &#xff1b; 2、修改根目录"cmdline.txt"&#xff0c;清空原内容&#xff0c;增加 dwc_otg.lpm_enable0 consoletty1 consoleserial0,115200 root/dev/mmcblk0p…

【C++模板】特化与偏特化 template [partial] specialization

1 template specialization 模板特化 一般情况下类模板定义如下&#xff1a; template<class Window, class Controller> class Widget {... 泛化实现代码 ... };特化是指把类模板中指定的class T变成具体的类型&#xff1a;class Widget<ModalDialog, MyController&g…

正则表达式匹配中文字符串的文章URL

http://www.cnblogs.com/yitian/archive/2008/11/14/1333569.html转载于:https://www.cnblogs.com/llcdbk/p/4932172.html

[react] React中你有使用过getDefaultProps吗?它有什么作用?

[react] React中你有使用过getDefaultProps吗&#xff1f;它有什么作用&#xff1f; createReactClass 参数对象内的一个方法&#xff0c;用于初始化组件属性 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放弃很容易&#xff0c; 但坚持一定很酷。欢迎大家一起讨论 主…

GCC优化选项:一般的文档里不容易找到的-Os

From: http://hi.baidu.com/ah__fu/item/9287dd5227227c908d12ed50 在研究编译驱动的makefile的时候&#xff0c;发现GCC的命令行里面有一个-Os的优化选项。 遍查GCC文档&#xff0c;发现了-O0, -O1, -O2, -O3&#xff0c;就是没有发现-Os。 祭出GOOGLE大法搜了一下…

带箭头的菜单列表

<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…

电网交流采样

电能表计量、谐波分析等待应用场景需要用到交流采样&#xff0c;相应地当采集的信号是变换平缓的直流信号时叫直流采样。 1、采样方法 一般交流采样有三种方式&#xff1a;同步采样法、非同步采样法、准同步采样法。 2、频谱泄露问题 当交流信号经采样、AD转换后进行数字处…

[react] React中getInitialState方法的作用是什么

[react] React中getInitialState方法的作用是什么 使用es5创建组件caerteClass getInitialState&#xff08;初始化state&#xff09; 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放弃很容易&#xff0c; 但坚持一定很酷。欢迎大家一起讨论 主目录 与歌谣一起通关前…

Android--发送短信,并且通知发送方

1、发送短信涉及到权限&#xff0c;我们需要把权限加上 2、当我们发送短信时&#xff0c;不管发送是否成功&#xff0c;接收方是否接收到&#xff0c;系统都会发送广播 3、这时我们注册广播去接收一下就可以了 4、布局文件很简单&#xff0c;里面就两个EditText和一个button 下…

gcc编译选项-Os的用法

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

Sharepoint2007个人网站不能同步域信息的处理方法

如果在AD上改变的帐户的信息&#xff0c;比如邮箱地址&#xff0c;可能sharepoint不能自动更新。 sharepoint管理中心&#xff0d;共享服务管理&#xff0d;sharedServices1&#xff0d;用户配置文件和属性 在些处可导入&#xff0c;编辑帐户信息。 当然也可以直接开始完全导入…

相干采样要求

引自&#xff1a;使用AD7779 24位同步采样Σ-Δ型ADC实现电能质量测量的相干采样 http://www.chinaaet.com/tech/solution/3000020192 0、相干采样要求 要使电能计量和电能质量设备的谐波数据和计量参数获得要求的精度&#xff0c;应确保ADC采样速率和电力线频率之间的相干性…

[react] 在React中组件和元素有什么区别?

[react] 在React中组件和元素有什么区别&#xff1f; 组件首字母大写 组件是由元素构成的。元素数据结构是普通对象&#xff0c;而组件数据结构是类或纯函数 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放弃很容易&#xff0c; 但坚持一定很酷。欢迎大家一起讨论 主…