自己怎么样做游戏网站,上海人才引进网站,网站怎么做图片搜索,软文街官网0 工具准备
1.lwip 1.4.1
2.RTOS#xff08;本文使用rt-thread#xff09;1 使能连接变化回调功能
打开lwipopts.h#xff0c;将宏定义LWIP_NETIF_LINK_CALLBACK的值设为1#xff0c;如下#xff1a;
#define LWIP_NETIF_LINK_CALLBACK 1这个宏定义被使能后会将…0 工具准备
1.lwip 1.4.1
2.RTOS本文使用rt-thread1 使能连接变化回调功能
打开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 2000U6 插拔测试
1上电后再插上网线随后ping路由器 可以看到打印了“Lan link up!”程序识别到了这一变化同时执行了回调函数ping路由器正常。 2将网线拔下 可以看到打印了“Lan link down!”程序识别到了这一变化同时执行了回调函数。 3反复执行12查看是否正常。 反复执行也能保证稳定测试结果正常。
7 总结
1LWIP实现热插拔的关键在于识别物理网口连接状态和软件连接状态是否一致当二者不一致时则将软件连接状态设置为和物理网口连接状态一致。 2需要根据实际情况自定义回调函数。 3超时时间不要设置太短实测2000ms有效。