Skip to main content
March 5, 2020
Question

Ethernet does not work if uC starts with the cable disconnected

  • March 5, 2020
  • 9 replies
  • 7341 views

When starting uC (or performing a reset) with the cable connected to the router, ping.exe receives a response normally. If the cable is removed, ping.exe does not receive a response, but after reconnecting, ping.exe receives a response.

The problem is that if the cable is disconnected, and the uC is initialized, then ping.exe does not receive a response, obviously due to the disconnected cable. But after connecting the cable, ping.exe still doesn't get a response.

I tried to force the execution of MX_LWIP_Init () but it didn't work, even if the Ethernet is already responding to ping.exe, it will stop responding if I call MX_LWIP_Init () again.

I noticed that MX_LWIP_Init () has a long timeout, 5000ms, but even so, I can't get it to work without restarting uC.

Note: DHCP: off. External PHY: LAN8720. uC: STM32F407VG.

I tested a code made with Arduino IDE, and it happens the same way it happens in STM32CubeIDE.

How to reset the Ethernet, without having to restart the uC?

    This topic has been closed for replies.

    9 replies

    Super User
    March 5, 2020

    Do you use an existing example from the ST library (which are by the way created not in Cube or Cube IDE),

    or you generate from scratch in Cube new code with LwIP?

    If the latter - please, do study the LwIP examples. Even for different/newer STM32 families. There are examples how to deal with reconnect.

    Do NOT call MX_LWIP_Init () again.

    -- pa

    March 6, 2020

    They were created with STM32CubeMX or STM32CubeIDE, which alias use the same base.

    This artifice of using other tools to generate examples, in my view, is not a good sign, since users will use the available tools, and preferably they are free, which means that the examples need to be done with the same tool, even that are just identical copies.

    About the reconnection, would you know how to say a search term, a key word, or a subroutine name to be searched?

    Graduate II
    March 6, 2020

    So, you've made a thousand topics with million images with "something doesn't work", but haven't found and read my report?

    Post edited to adhere to community guidelines.

    https://community.st.com/s/question/0D50X0000BOtfhnSQB/how-to-make-ethernet-and-lwip-working-on-stm32

    March 6, 2020

    Well, I was already thinking about using ESP32 instead of STM32, I'll see if ESP works better with Ethernet.

    Thank you.​

    Super User
    March 6, 2020

    > About the reconnection, would you know how to say a search term, a key word, or a subroutine name to be searched?

    Detection of link state changes.

    See here for example (in 'H7 library, but should be similar for F4).

    Note that the PHY is responsible for link up/down detection. If you have a different PHY, need to adapt. There can be more states than in the LAN8742 example: auto-negotiation in progress, etc,

    Regards,

    -- pa

    March 6, 2020

    Since MX_LWIP_Init () cannot be called again, I added a flag that prevents the first call until the cable has been connected, it seems to have worked well.

    Before testing the PHY status, it was necessary to initialize it.

    lwip.c

    /* USER CODE BEGIN 0 */
    #define ETH_UsrLog(...) do { \
    		printf(__VA_ARGS__); \
    		printf("\n"); \
    } while (0)
     
    uint8_t eth_is_initialized = 0;

    void MX_LWIP_Init(void)
    {
    	if(eth_is_initialized != 0) return;
     
    	ethernetif_init(&gnetif);
     
    	uint32_t phyreg = 0;
     
    	if(HAL_ETH_ReadPHYRegister(&heth, PHY_BSR, &phyreg) != HAL_OK)
    	{
    		ETH_UsrLog("HAL_ETH_ReadPHYRegister: error");
    	}
     
    	if((phyreg & PHY_LINKED_STATUS) != PHY_LINKED_STATUS) return;
     
    	/* IP addresses initialization */
    	IP_ADDRESS[0] = 192;
    	IP_ADDRESS[1] = 168;
    	IP_ADDRESS[2] = 1;
    	IP_ADDRESS[3] = 111;
    	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] = 1;
    	GATEWAY_ADDRESS[3] = 1;
     
    	/* Initilialize the LwIP stack without RTOS */
    	lwip_init();
     
    	/* 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) without RTOS */
    	netif_add(&gnetif, &ipaddr, &netmask, &gw, NULL, &ethernetif_init, &ethernet_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);
    	}
     
    	/* USER CODE BEGIN 3 */
    	eth_is_initialized = 1;
     
    	//tcp_echoserver_init();
    	/* USER CODE END 3 */
    }
    void MX_LWIP_Process(void)
    {
    /* USER CODE BEGIN 4_1 */
    	if(eth_is_initialized == 0) return;

    main.c

    while (1)
    	{
    		/* USER CODE END WHILE */
     
    		/* USER CODE BEGIN 3 */
    		MX_LWIP_Process();
     
    		MX_LWIP_Init();

    ST Employee
    March 11, 2020

    As per Arduino is concerned, it works like a charm with the setup below.

    Board: NUCLEO_F429ZI which embed PHY: LAN8742

    Sketch: WebServer.ino (provided with https://github.com/stm32duino/STM32Ethernet library)

    see details https://github.com/stm32duino/STM32Ethernet/issues/42

    March 11, 2020

    Please test again, the wait time I'm using is 10 seconds or more. The LwIP startup has a long timeout, 5 seconds if I'm not mistaken.

    Super User
    March 11, 2020

    > The LwIP startup has a long timeout, 5 seconds if I'm not mistaken.

    ??? Perhaps only if DHCP is enabled, and it does several retries before failing.

    @rtek1000

    >  I added a flag that prevents the first call until the cable has been connected

    In your code above the initialization still may occur several times.

    Line 5: ethernetif_init called

    Line 14: if the link is not detected, it returns and next time ethernetif_init called again.

    -- pa

    March 11, 2020

    I added a output in milliseconds, it seems that for both (fixed) Static IP and DHCP the waiting time is the same.

    UsrLog("%lu", HAL_GetTick());

    Static IP (cable disconnected):

    14:52:38.676: 0
    14:52:43.926: 5272

    Static IP (cable connected):

    15:05:56.909: 0
    15:05:58.553: 1569

    DHCP (cable disconnected):

    14:55:37.284: 0
     
    14:55:42.534: Assertion "netif is not up, old style port?" failed at line 744 in ../Middlewares/Third_Party/LwIP/src/core/ipv4/dhcp.c
     
    14:55:42.534: 5284

    DHCP (cable connected):

    14:56:45.753: 0
     
    14:56:47.394: 1658

    March 14, 2020

    I managed to test the LAN8720 with the ESP32 chip, the performance seems to be similar to the STM32, in relation to data transfer.

    But this problem of disconnected cable when booting does not seem to occur with ESP32.

    (Unfortunately another type of problem also occurred, it seems that with ESP32 the LAN8720 is not being reset during the initialization of ESP32, but that is another story, for another manufacturer to resolve. [P.S.: (Solved) https://github.com/espressif/arduino-esp32/issues/3817])

    ESP32 source code: https://github.com/espressif/arduino-esp32/blob/master/libraries/WiFi/examples/ETH_LAN8720/ETH_LAN8720.ino

    Explorer II
    April 1, 2021

    However the above solution works, the real problem is that `netif_set_up(&gnetif)` is never called when the cable is connected after the initialization routine is executed. It took me a day because I was to stubborn to accept this as a solution since hot-plugging afterwards works find. It's easily overlooked because the function names of netif_set_up and netif_set_link_up look near identical...

    To my knowledge it's perfectly fine to call `netif_set_up(&gnetif)` when there is no network link because the link management is done via the function `netif_set_link_up(&gnetif)`. It's very easy to overlook because the functions look identical. The problem is thus also fixed by changing in the function `MX_LWIP_Init`:

    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);
     }

    to

    /* We must always bring the network interface up connection or not... */
     netif_set_up(&gnetif);

    This avoid extra management of tracking if this is the first time that the cable is connected. LwIP is perfectly capable of managing that by itself, as long as netif_set_link_up and netif_set_link_down are properly used. And that they do as long as you call:

    // check the link status
    	ethernetif_set_link(&gnetif);

    in `MX_LWIP_Process`

    Graduate II
    April 2, 2021

    You are completely right. Although it was already reported by me and others here, I added more details and a link to this topic to my Ethernet/lwIP issue list.

    Visitor II
    January 7, 2025
    Hi,
    
    Thank you all, thanks to you I was able to find the solution to my problem which was the same.
    
    I used the functions in my main.c:
    
    -ethernetif_input(&gnetif);
    
    -sys_check_timeouts();
    
    But in the latest version there is in MX_LWIP_Process(), the additional function:
    
    Ethernet_Link_Periodic_Handle(&gnetif) which fixes this problem by monitoring the cable connection.
    
    
    If anyone ever comes across this very useful page like me ;).