Skip to main content
Visitor II
November 4, 2016
Question

Initialize LWIP with Ethernet disconnected

  • November 4, 2016
  • 11 replies
  • 11709 views
Posted on November 04, 2016 at 14:45

Hello !

The board I am using for this topic is based on the ST

http://www.st.com/en/evaluation-tools/stm3220g-eval.html

hardware for the Ethernet part. I have generated a basic code with cubeMx (nice tool!) and Ethernet communication is working well on this board. The problem is that Ethernet is working only when Ethernet cable is connected at startup (especially when initialization function is run). If I start my board without cable, Ethernet is not working (ping test failed) and will never work even if I connect the cable. To solve this, I added the following function after LWIP initialization:

netif_set_link_callback(&gnetif, ethernetif_update_config);

The ''ethernetif_update_config'' function is generated by cubeMx (in ethernetif.c file) to restart auto-negotiation:

/**
* @brief Link callback function, this function is called on change of link status
* to update low level driver configuration.
* @param netif: The network interface
* @retval None
*/
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, ®value);
/* 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, ®value);
/* Configure the MAC with the Duplex Mode fixed by the auto-negotiation process */
if
((regvalue & PHY_DUPLEX_STATUS) != (uint32_t)RESET)
{
/* Set Ethernet duplex mode to Full-duplex following the auto-negotiation */
heth.Init.DuplexMode = ETH_MODE_FULLDUPLEX; 
}
else
{
/* Set Ethernet duplex mode to Half-duplex following the auto-negotiation */
heth.Init.DuplexMode = ETH_MODE_HALFDUPLEX; 
}
/* Configure the MAC with the speed fixed by the auto-negotiation process */
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);
}

Unfortunately, when I manually launch this callback by calling the ''netif_set_link_up(&gnetif)'' function after connecting the cable, Ethernet is still not working. Is anybody having an idea on how to make Ethernet working in this configuration? Thank you for your help #lwip-ethernet-disconnected
    This topic has been closed for replies.

    11 replies

    Visitor II
    September 13, 2022

    I take the feature of LWIP(static IP address) with freertos, and the same issue occurs.

    I used CubeMX to generate the lwip and freertos code for CubeIDE.

    And by dividing a function(lwip.c) into two functions, the issue is fixed for me now.

    In lwip.c, create three new functions(two created from MX_LWIP_Init)

    //in lwip.c, and used in freertos task
    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] = 254;
    /* 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);
     
     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);
     }
     
     /* 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 */
     Netif_LinkSemaphore = osSemaphoreNew(1, 1, NULL);
     
     link_arg.netif = &gnetif;
     link_arg.semaphore = Netif_LinkSemaphore;
     
     /* Create the Ethernet link handler thread */
    /* USER CODE BEGIN OS_THREAD_NEW_CMSIS_RTOS_V2 */
     memset(&attributes, 0x0, sizeof(osThreadAttr_t));
     attributes.name = "LinkThr";
     attributes.stack_size = INTERFACE_THREAD_STACK_SIZE;
     attributes.priority = osPriorityBelowNormal;
     osThreadNew(ethernetif_set_link, &link_arg, &attributes);
    /* USER CODE END OS_THREAD_NEW_CMSIS_RTOS_V2 */
    /* USER CODE BEGIN 3 */
    /* USER CODE END 3 */
    }
     
    //separate MX_LWIP_Init into two function, function 1 and function 2
    //located at the same file lwip.c
    //new function 1
    void NEW_LWIP_Init_Netif(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] = 254;
    	 /* 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);
    }
    //new function 2
    void NEW_LWIP_Init_Thread(void){
    	 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);
    	 }
    	 /* 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 */
    	 Netif_LinkSemaphore = osSemaphoreNew(1, 1, NULL);
     
    	 link_arg.netif = &gnetif;
    	 link_arg.semaphore = Netif_LinkSemaphore;
    	 /* Create the Ethernet link handler thread */
    	/* USER CODE BEGIN OS_THREAD_NEW_CMSIS_RTOS_V2 */
    	 memset(&attributes, 0x0, sizeof(osThreadAttr_t));
    	 attributes.name = "LinkThr";
    	 attributes.stack_size = INTERFACE_THREAD_STACK_SIZE;
    	 attributes.priority = osPriorityBelowNormal;
    	 osThreadNew(ethernetif_set_link, &link_arg, &attributes);
    }
    //and more, check the cable connection
    static uint32_t regvalue = 0;
    uint8_t NEW_LWIP_Link_Status(uint8_t mNetworkInit){
     /* 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 (mNetworkInit == 1){
     	if(!netif_is_link_up(&gnetif) && (regvalue))
     	{
     		printf("network cable link is connected\r\n");
     		netif_set_link_up(&gnetif);
     		return 1;
     	}
     }
     return 0;
    }

    and then in freertos.c, modify the default task of network initialization.

    //in freertos.c, the default task
    void StartDefaultTask(void *argument)
    {
     /* init code for LWIP */
     //MX_LWIP_Init(); //the original code of initializing network, marked
     /* USER CODE BEGIN StartDefaultTask */
     static uint8_t mNetworkInit = 1;
     NEW_LWIP_Init_Netif();
     
     /* Infinite loop */
     for(;;)
     { 
     //fix the issue of network cable not plugged at device booting up
    	if (NEW_LWIP_Link_Status(mNetworkInit)){
    		printf("Initialize Network Thread only once\r\n");
    		mNetworkInit = 0;
    		NEW_LWIP_Init_Thread();
    	}
     osDelay(10);
     }
     /* USER CODE END StartDefaultTask */
    }

    Visitor II
    February 16, 2024

    Hi C.Y.

    I am facing the issue of the Cable disconnection.

    1 - In your code, what is the declaration for link_arg ?

    2 - How do you use the Semaphore in ethernetif.c ? Can you share your modified code ?

     

    Thanks