STM32CubeMX + LWIP 框架的网线热插拔处理

笔记

同事以前的工程,有个bug : 网线掉了之后,再也访问不到了,插上也没用, 只能重启设备。
但是那个工程用的F1/F4的固件库.

现在用STM32CubeMX6.3.0 + ETH + LWIP的HAL库框架代码,可以很方便做这个处理。
可以应对网线在启动前被拔掉,启动后拔掉又插上的情况。不管啥时候插上网线,都能正常进行网络操作。

首先ETH要配置好,试验已经做好了(test STM32F407 ETH RMII)

在LWIP配置时,将网络接口选项(Network interfaces Options)中的3个状态指示回调都勾上。
STM32CubeMX + LWIP 框架的网线热插拔处理_第1张图片
用CubeMX生成框架后,修改ethernetif_set_link(),加入2句网卡上线和网卡下线调用就可以了。

/**
  * @brief  This function sets the netif link status.
  * @param  netif: the network interface
  * @retval None
  */
void ethernetif_set_link(void const *argument)

{
     
  uint32_t regvalue = 0;
  struct link_str *link_arg = (struct link_str *)argument;

  for(;;)
  {
     
    /* Read PHY_BSR*/
    HAL_ETH_ReadPHYRegister(&heth, PHY_BSR, &regvalue);

    regvalue &= PHY_LINKED_STATUS;

    /* Check whether the netif link down and the PHY link is up */
    if(!netif_is_link_up(link_arg->netif) && (regvalue))
    {
     
      /* network cable is connected */
      netif_set_link_up(link_arg->netif);

      // 加入下面一句调用
      netif_set_up(link_arg->netif); // 热插拔上线时, 加入netif_set_up(), 才可以继续ping通
    }
    else if(netif_is_link_up(link_arg->netif) && (!regvalue))
    {
     
      /* network cable is dis-connected */
      netif_set_link_down(link_arg->netif);
      
      // 加入下面一句调用
      netif_set_down(link_arg->netif); // 热插拔下线时, 要调用一下netif_set_down()
    }

    /* Suspend thread for 200 ms */
    osDelay(200);
  }
}

为啥加这2句呢?
因为ethernetif_set_link()只是网络接口的状态变化指示,原有的框架代码,只是标记了网卡是否插上或被拔掉。这里肯定要加一句是网卡生效或失效的代码,那该填啥代码呢?框架工程中总能找到线索吧?e.g. 网卡初始化或LWIP初始化的地方找找。
我在 MX_LWIP_Init() 中找到了疑似代码,试试,好使,就这样。

void MX_LWIP_Init(void)
{
     
  /* IP addresses initialization */
  IP_ADDRESS[0] = 192;
  IP_ADDRESS[1] = 168;
  IP_ADDRESS[2] = 0;
  IP_ADDRESS[3] = 100;
  NETMASK_ADDRESS[0] = 255;
  NETMASK_ADDRESS[1] = 255;
  NETMASK_ADDRESS[2] = 255;
  NETMASK_ADDRESS[3] = 0;
  GATEWAY_ADDRESS[0] = 192;
  GATEWAY_ADDRESS[1] = 168;
  GATEWAY_ADDRESS[2] = 0;
  GATEWAY_ADDRESS[3] = 1;

/* USER CODE BEGIN IP_ADDRESSES */
/* USER CODE END IP_ADDRESSES */

  /* Initilialize the LwIP stack with RTOS */
  tcpip_init( NULL, NULL );

  /* IP addresses initialization without DHCP (IPv4) */
  IP4_ADDR(&ipaddr, IP_ADDRESS[0], IP_ADDRESS[1], IP_ADDRESS[2], IP_ADDRESS[3]);
  IP4_ADDR(&netmask, NETMASK_ADDRESS[0], NETMASK_ADDRESS[1] , NETMASK_ADDRESS[2], NETMASK_ADDRESS[3]);
  IP4_ADDR(&gw, GATEWAY_ADDRESS[0], GATEWAY_ADDRESS[1], GATEWAY_ADDRESS[2], GATEWAY_ADDRESS[3]);

  /* add the network interface (IPv4/IPv6) with RTOS */
  netif_add(&gnetif, &ipaddr, &netmask, &gw, NULL, &ethernetif_init, &tcpip_input);

  /* Registers the default network interface */
  netif_set_default(&gnetif);

  // ST的框架代码在网络上线或掉线时, 就是调用了netif_set_up()/netif_set_down()
  if (netif_is_link_up(&gnetif))
  {
     
    /* When the netif is fully configured this function must be called */
    // ST的大神们注释写的很清楚,网络上线时,必须调用netif_set_up()
    netif_set_up(&gnetif);
  }
  else
  {
     
    /* When the netif link is down this function must be called */
    // ST的大神们注释写的很清楚,网络下(掉)线时,必须调用netif_set_down()
    netif_set_down(&gnetif);
  }

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

  /* create a binary semaphore used for informing ethernetif of frame reception */
  osSemaphoreDef(Netif_SEM);
  Netif_LinkSemaphore = osSemaphoreCreate(osSemaphore(Netif_SEM) , 1 );

  link_arg.netif = &gnetif;
  link_arg.semaphore = Netif_LinkSemaphore;
  /* Create the Ethernet link handler thread */
/* USER CODE BEGIN OS_THREAD_DEF_CREATE_CMSIS_RTOS_V1 */
  osThreadDef(LinkThr, ethernetif_set_link, osPriorityBelowNormal, 0, configMINIMAL_STACK_SIZE * 2);
  osThreadCreate (osThread(LinkThr), &link_arg);
/* USER CODE END OS_THREAD_DEF_CREATE_CMSIS_RTOS_V1 */

/* USER CODE BEGIN 3 */

/* USER CODE END 3 */
}

你可能感兴趣的:(#,ST,下位机,LWIP,stm32,HAL,LWIP)