600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > SMT32F407+FreeRTOS+LWIP+LAN8720使用Cube MX情况下无法实现网线热插拔

SMT32F407+FreeRTOS+LWIP+LAN8720使用Cube MX情况下无法实现网线热插拔

时间:2021-03-02 09:18:19

相关推荐

SMT32F407+FreeRTOS+LWIP+LAN8720使用Cube MX情况下无法实现网线热插拔

项目场景:

STM32F407+LAN8720使用Cube MX HAL库生成工程;

问题描述

使用Cube MX生成STM32F407+Free RTOS + LAN8720工程,在可以ping通后打开了LWIP->Key Options->LWIP_NETIF_LINK_CALLBACK选项,希望可以实现自动连接状态检测,发现在不插网线上电后,无法初始化完成,无法ping通,只有插着网线上电才可以;而插着网线上电后,在插拔2次之后发生卡死;

看了网上其他解决方法,多为旧版SDK在初始化阶段如果没有插入网线则会超时卡死,和新版SDK问题不同;

原因分析:

经过查阅源码发现了在LWIP初始化阶段会检测是否有网线连接,如果有连接则执行netif_set_up相关代码,如下:

文件路径: LWIP\Target\ethernetif.c....../*** @brief In this function, the hardware should be initialized.* Called from ethernetif_init().** @param netif the already initialized lwip network interface structure* for this ethernetif*/static void low_level_init(struct netif *netif){....../* Get MAC Config MAC */HAL_ETH_GetMACConfig(&heth, &MACConf);MACConf.DuplexMode = duplex;MACConf.Speed = speed;HAL_ETH_SetMACConfig(&heth, &MACConf);HAL_ETH_Start_IT(&heth);netif_set_up(netif);netif_set_link_up(netif);......

在增加了LWIP_NETIF_LINK_CALLBACK选项后,会在lwip.c中,增加ethernet_link_thread线程,用来监控网线是否插拔

文件路径:LWIP\App\lwip.c/*** LwIP initialization function*/void MX_LWIP_Init(void){....../* Set the link callback function, this function is called on change of link status*/netif_set_link_callback(&gnetif, ethernet_link_status_updated);/* Create the Ethernet link handler thread *//* USER CODE BEGIN H7_OS_THREAD_NEW_CMSIS_RTOS_V2 */memset(&attributes, 0x0, sizeof(osThreadAttr_t));attributes.name = "EthLink";attributes.stack_size = INTERFACE_THREAD_STACK_SIZE;attributes.priority = osPriorityBelowNormal;osThreadNew(ethernet_link_thread, &gnetif, &attributes);......}

但是在检测到插入网线后,进行的netif_set_up相关代码中,却和low_level_init中不同,没有使用中断方式,如下:

文件路径: LWIP\Target\ethernetif.c/*** @brief Check the ETH link state then update ETH driver and netif link accordingly.* @retval None*/void ethernet_link_thread(void* argument){......if(linkchanged){/* Get MAC Config MAC */HAL_ETH_GetMACConfig(&heth, &MACConf);MACConf.DuplexMode = duplex;MACConf.Speed = speed;HAL_ETH_SetMACConfig(&heth, &MACConf);HAL_ETH_Start(&heth);// 此处没有使用 HAL_ETH_Start_IT(&heth);netif_set_up(netif);netif_set_link_up(netif);}......

尝试修改了此处代码为如下,问题解决;

HAL_ETH_Start_IT(&heth);

解决方案:

将ethernet_link_thread线程中,检测到网线连接后的处理函数修改为中断模式,如下:

文件路径:LWIP\Target\ethernetif.c/*** @brief Check the ETH link state then update ETH driver and netif link accordingly.* @retval None*/void ethernet_link_thread(void* argument){ETH_MACConfigTypeDef MACConf = {0};int32_t PHYLinkState = 0;uint32_t linkchanged = 0U, speed = 0U, duplex = 0U;struct netif *netif = (struct netif *) argument;/* USER CODE BEGIN ETH link init *//* USER CODE END ETH link init */for(;;){PHYLinkState = LAN8742_GetLinkState(&LAN8742);if(netif_is_link_up(netif) && (PHYLinkState <= LAN8742_STATUS_LINK_DOWN)){HAL_ETH_Stop_IT(&heth);netif_set_down(netif);netif_set_link_down(netif);}else if(!netif_is_link_up(netif) && (PHYLinkState > LAN8742_STATUS_LINK_DOWN)){switch (PHYLinkState){case LAN8742_STATUS_100MBITS_FULLDUPLEX:duplex = ETH_FULLDUPLEX_MODE;speed = ETH_SPEED_100M;linkchanged = 1;break;case LAN8742_STATUS_100MBITS_HALFDUPLEX:duplex = ETH_HALFDUPLEX_MODE;speed = ETH_SPEED_100M;linkchanged = 1;break;case LAN8742_STATUS_10MBITS_FULLDUPLEX:duplex = ETH_FULLDUPLEX_MODE;speed = ETH_SPEED_10M;linkchanged = 1;break;case LAN8742_STATUS_10MBITS_HALFDUPLEX:duplex = ETH_HALFDUPLEX_MODE;speed = ETH_SPEED_10M;linkchanged = 1;break;default:break;}if(linkchanged){/* Get MAC Config MAC */HAL_ETH_GetMACConfig(&heth, &MACConf);MACConf.DuplexMode = duplex;MACConf.Speed = speed;HAL_ETH_SetMACConfig(&heth, &MACConf);HAL_ETH_Start_IT(&heth);// <<<<<<<<<<<<< 此处netif_set_up(netif);netif_set_link_up(netif);}}/* USER CODE BEGIN ETH link Thread core code for User BSP *//* USER CODE END ETH link Thread core code for User BSP */osDelay(100);}}

问题得以解决。

回顾:

在新版Cube MX SDK中,LWIP已经可以实现了网线热插拔,只需打开LWIP_NETIF_LINK_CALLBACK选项即可生成相关代码;会开辟一个线程每隔100ms检测一次连接状态,在检测到插拔后会自动调用netif_set_up和netif_set_down,不需要特殊处理,并且会自动触发APP/lwip.c中相关的回调函数;只是这里调用的函数需要修改一下,可能是没有处理到这部分代码的生成。只需修改此处问题可以解决,增加回调函数打印,串口调试输出如下图。

/*** @brief Notify the User about the network interface config status* @param netif: the network interface* @retval None*/static void ethernet_link_status_updated(struct netif *netif){if (netif_is_up(netif)){/* USER CODE BEGIN 5 */printf("netif_is_up...\r\n");/* USER CODE END 5 */}else /* netif is down */{/* USER CODE BEGIN 6 */printf("netif_is_down...\r\n");/* USER CODE END 6 */}}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。