MCU stops if ethernet cable is not plugged in on startup

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

MCU stops if ethernet cable is not plugged in on startup

1,687 Views
Garry_Hoberg
Contributor II

Hello.

When I start the MCU and the ethernet cable is not plugged in, the MCU hangs outputting "PHY Auto-negotiation failed. Please check the cable connection and link partner setting." roughly every 10 seconds.

I'm running FreeRTOS and lwip on an LPC54628, both from SDK 2.9.0. I use a LAN8720a, so I have components/phylan8720a/fsl_phy.c from the SDK added to my project.

The stall is in a thread that initialises ethernet (UDP works fine when the cable is plugged in on MCU startup).

Threading is started when calling netifapi_netif_add(), but the threading is stopped again because LOCK_TCPIP_CORE() is executed by tcpip_api_call() along the way.

Further down the call stack (attached) in ethernetif_phy_init() you have the loop that causes the 10 seconds delay which is enclosed in another loop that repeats 0x1ffff times.

10 seconds of delay would be okay, but 10*0x1ffff means 364 hours delay. - Definitely not what I want.The device needs to be responsive to other interfaces, not to ethernet only.

I have tried to use PHY_GetLinkStatus() before netifapi_netif_add() to prevent this hangup but I just get a HardFault. I assume this is due to MDIO/PHY not being fully initialised before the netifapi_netif_add() call.

So: How can I check if the cable is plugged in before calling netifapi_netif_add()?

Thank you.

Garry

0 Kudos
5 Replies

1,650 Views
Garry_Hoberg
Contributor II

Content moved to proper position in thread.

0 Kudos

1,659 Views
Alice_Yang
NXP TechSupport
NXP TechSupport

Hello Garry_Hober,

How about first check the lwip_examples under SDK?

0 Kudos

1,642 Views
Garry_Hoberg
Contributor II

Hello Alice_Yang.

Thank you for this hint. I based the Ethernet initialisation on those. And as I wrote, UDP does work with the cable plugged in on startup.

I tested the current lpcxpresso54628_lwip_dhcp_bm example anyway. (Yes, I do know that's bare-metal and I'm using an RTOS. I had the RTOS examples running on my hardware before. Using the BM example is just to show that the Problem it is not with the RTOS at all.)
With the ethernet cable plugged in on startup the dhcp requests, checks, binds and prints the IP/NW info as intended. With the cable pulled on startup, it is the same behaviour as described in my initial post. - Which is not too surprising as the call to LOCK_TCPIP_CORE() under FreeRTOS prevents thread swapping and makes the system work very similar to bare metal until UNLOCK_TCPIP_CORE() gets called.

It's also the same behavior I observed (but didn't pay much attention to) in 2018 with both the NXP LPC56418 Board (OM13094) and the LPC56428 one (OM13098), obviously with the then current SDK 2.5 or 2.6 and MCUXpresso at about 10.2.

So, how to prevent the startup stall when the ethernet connection is physically not available?

Garry

0 Kudos

1,633 Views
Garry_Hoberg
Contributor II

A working solution seems to be to modify ethernetif_phy_init() in enet_ethernetif.c so that after each failed auto negotiation/link poll thread-swapping is re-enabled, the thread pauses for 100 ms and then stops thread-swapping again for the next attempt (I only added five lines marked by comments below):

 

...
    while ((initWaitCount < ENET_ATONEGOTIATION_TIMEOUT) && (!(link && autonego)))
    {
        status = PHY_Init(ethernetifConfig->phyHandle, &phyConfig);

        if (kStatus_Success != status)
        {
            LWIP_ASSERT("\r\nCannot initialize PHY.\r\n", 0);
        }

        /* Wait for auto-negotiation success and link up */
        autoWaitCount = ENET_ATONEGOTIATION_TIMEOUT;
        do
        {
            PHY_GetAutoNegotiationStatus(ethernetifConfig->phyHandle, &autonego);
            PHY_GetLinkStatus(ethernetifConfig->phyHandle, &link);
            if (autonego && link)
            {
                break;
            }
// start of added code
#if !NO_SYS
            UNLOCK_TCPIP_CORE();
            vTaskDelay(100);
            LOCK_TCPIP_CORE();
#endif
// end of added code
        } while (--autoWaitCount);
        if (!autonego)
        {
            PRINTF("PHY Auto-negotiation failed. Please check the cable connection and link partner setting.\r\n");
        }

        initWaitCount++;
    }
...

 

This problem has been in the SDK for years and means you can't blink some progress LED or do anything else if the ethernet cable is unplugged on startup. - You can't even give any hint to check the cable if you're not debugging anyway. - So I would kindly suggest NXP to integrate this or something to this effect in their SDK code. (enet_ethernetif.c is copyrighted by NXP.)
To get an output every 10 seconds again, I also changed the definition of ENET_ATONEGOTIATION_TIMEOUT to 99 (decimal) in enet_ethernetif.h (same copyright).
If NXP decides to add those changes, they might also want to change the macro name ENET_ATONEGOTIATION_TIMEOUT to ENET_AUTONEGOTIATION_TIMEOUT (typo).

In case of threads starting before ethernet init() is done, one might just set a global boolean flag in the program when ethernet initialisation is finished, so other threads can tell.

0 Kudos

1,621 Views
Alice_Yang
NXP TechSupport
NXP TechSupport

Hello Garry_Hoberg,

Thanks very much for your sharing, I will check and submit your suggestion to SDK development team, thanks again.

 

Best Regards,

Alice

0 Kudos