2025-06-19 8:48 PM
Hi,
I have created an lwIP + FreeRTOS application using CubeIDE for my Nucleo 439 Board. The problem here is that the the init sequence generated by CubeIDE
LWIP/App/lwip.c function
MX_LWIP_Init()
it calls the following function without checking for the actual status of PHY (even when it is possible)
/* We must always bring the network interface up connection or not... */
netif_set_up(&gnetif);
So, even if I don't plug in my LAN cable to the RJ45 of Nucleo board, my network is marked as "UP", while actually its is "DOWN"
I don't understand the need for this. I have seen the the EthLink thread is already testing the status of the actual phy and calling the same function for us. So what is the need to call it in init sequence?
Ethernet Link State (Physical Ethernet Cable connection)
This thread manages the Link state of netif.
The thread's task function is defined in the file LWIP/Target/ethernetif.c
It runs in an infinite loop. With 100ms delay between loops.
In each iteration of the loop it gets the link state using PHY driver function LAN8742_GetLinkState()
The function is the part of BSP (Board Support Package) thus it is present inside the Driver\BSP\Components\lan8742.c
From its return value we can know if
This thread calls the following functions for us to keep the netif state in sync.
netif_set_up(netif); netif_set_link_up(netif); |
Solved! Go to Solution.
2025-06-20 2:58 AM
waiting until the cable is connected is the purpose of the link monitoring function you mention.
it polls until LAN8742_GetLinkState() returns link connected status. Then it calls netif_set_link_up().
It is all right to have netif_set_up() called before. The LwIP stack will process packets only when netif_set_link_up() is called.
If this doesn't work, then you need to investigate why the LAN8742 doesn't return proper status.
Are you sure everything is configured correctly ?
Is the board connected to an ethernet switch that use auto negotiation ?
2025-06-20 1:39 AM
Hi
In LwIP, the netif "up" and "down" status is kind of an "administrative" status. It means "LwIP can process the packets" (even if the hardware link is not ready).
What you are looking for is netif_set_link_up(). It is another flag ("link" flag) that indicates if the hardware network link is ready (physically connected).
So you can have a netif that is up (it is allowed to process packets) but with a link down (so no processing of packets until link is up).
Note that both flags don't mean 'please do the action'. They mean 'we have done the needed operations, now LwIP can handle the IP packets'.
see lwIP: Flags NETIF_FLAG_UP, NETIF_FLAG_LINK_UP
netif_is_up()
2025-06-20 1:43 AM
Then how can we wait until we have cable connected before trying to start communication? My code directly runs to socket connection and fails because of a broken link (cable not plugged)
2025-06-20 2:58 AM
waiting until the cable is connected is the purpose of the link monitoring function you mention.
it polls until LAN8742_GetLinkState() returns link connected status. Then it calls netif_set_link_up().
It is all right to have netif_set_up() called before. The LwIP stack will process packets only when netif_set_link_up() is called.
If this doesn't work, then you need to investigate why the LAN8742 doesn't return proper status.
Are you sure everything is configured correctly ?
Is the board connected to an ethernet switch that use auto negotiation ?
2025-06-20 6:59 AM
Thank you! Now every thing is clear to me. I have also written the logic for cable connection before I open and connect socket clients.
I have shared my code here
https://github.com/avinash-gupta-in/stm32f439-lwip-tcp-client
So the logic works like this.
in file LWIP/App/lwip.c [CubeMX generated]
I have edited (of-course in USER CODE Sections only)
to add a volatile variable is_net_up to convey the Link state to application code.
Then I have modified the link status change callback in the same file to update this variable
static void ethernet_link_status_updated(struct netif *netif)
{
if (netif_is_link_up(netif))
{
/* USER CODE BEGIN 5 */
is_net_up=1;
/* USER CODE END 5 */
}
else /* netif is down */
{
/* USER CODE BEGIN 6 */
is_net_up=0;
/* USER CODE END 6 */
}
}
And since callback is registered only after the call to
netif_add(&gnetif, &ipaddr, &netmask, &gw, NULL, ðernetif_init, &tcpip_input);
if cable is already connected at the time of boot then our callback is NOT called and the variable is_net_up is initialized to 0 by our code, it will be in an invalid state that is why I have modified the last lines of function void MX_LWIP_Init(void)
and checked the link state at boot time using the function (may be a PP marco only) netif_is_link_up(&gnetif)
and initialized the variable is_net_up properly.
again this code is added to USER code section only so as to avoid rewrite when code is generated again from CubeMX
/* USER CODE BEGIN 3 */
if(netif_is_link_up(&gnetif))
{
is_net_up=1;
}
/* USER CODE END 3 */
In my application code I wait for cable to be connected before I start any network transactions. Its a while loop that polls this variable that is is_net_up with one sec gaps between polls and as soon as it is set to 1, we break the loop and print that cable has been plugged. After that our code proceed to network IO.
void StartDefaultTask(void *argument)
{
/* init code for LWIP */
MX_LWIP_Init();
/* USER CODE BEGIN 5 */
printf("Simple TCP Client example for Nucleo 439 using lwIP stack\r\n ");
printf("---------------------------------------------------------\r\n ");
while(is_net_up==0)
{
printf("Waiting for Ethernet Cable plug in ... \r\n ");
osDelay(1000);
}
printf("GREAT! Cable plugged in !\r\n ");
...
...
...
}
Its the output of the program on Serial Terminal