cancel
Showing results for 
Search instead for 
Did you mean: 

LWIP ethernet connection looses packages after cable replug; STM32H743ZI

TTata.2
Associate

Hi,

I am working on LWIP autogenerated form MxCube for stm32H743zi. I have used this bug fix that allowed me to obtain stable connections: https://community.st.com/s/question/0D50X0000C6eNNSSQ2/bug-fixes-stm32h7-ethernet. I use udp and tcp/ip connection. Everything works well unless cable is unpluged and pluged again. TCP connection looses stability and pinging looses about 15-30% of packets. After reset everything go ok again. Any ideas what could be the reason?

Thanks,

Tom

6 REPLIES 6
alister
Lead

>Everything works well unless cable is unpluged and pluged again.

Presumably the same network and without power-cycling any routers on it at the same time...

>I use udp and tcp/ip connection. Everything works well unless cable is unpluged and pluged again. TCP connection looses stability and pinging looses about 15-30% of packets

The fault description is too complicated.

Are the losses spanning the disconnection, or how long after reconnecting does the test start?

What PHY?

How is lwIP notified of link-state-change?

What does the lwIP link status callback (if used) do?

What is the ingress packet rate?

How many receive descriptors? How many receive buffers? What size receive buffer?

Determine a simple method to reproduce the fault, using just TCP, or just UDP or just ICMP, remove any other traffic, describe the observations carefully.

alister
Lead

Are tx and rx buffers allocated from different places?

Is TCP always transmitting? Could TCP be exhausting tx buffers, and with it needing retries and ACKs to those plus new transmits the available tx buffers never recover and that's starving UDP and ICMP too? Suggest remove TCP and re-test to determine if the problem is with the TCP or not.

From where are tx and rx buffers allocated and what are their dimensions?

Instrument available buffers and re-test to learn if the fault is with rx or tx buffers.

TTata.2
Associate

Thank you Alister for your fast reply.

So here is update:

i am using LAN8742;

I use tcp_echo_server example from STM32Cube_FW_H7_V1.8.0 modified for my needs.

Everything is working perfect before repluging cable. I use static ip address. Ethernet link thread is properly notified about link state change:

void ethernet_link_thread(void const * argument)
{
  ETH_MACConfigTypeDef MACConf;
  int32_t PHYLinkState;
  uint32_t linkchanged = 0, speed = 0, duplex =0;
 
  struct netif *netif = (struct netif *) argument;
/* USER CODE BEGIN ETH link init */
 
/* USER CODE END ETH link init */
 
  for(;;)
  {
  PHYLinkState = LAN8742_GetLinkState(&LAN8742);
 
  if(netif_is_link_up(netif) && (PHYLinkState <= LAN8742_STATUS_LINK_DOWN))
  {
    HAL_ETH_Stop_IT(&heth);
    netif_set_down(netif);
    netif_set_link_down(netif);
  }
  else if(!netif_is_link_up(netif) && (PHYLinkState > LAN8742_STATUS_LINK_DOWN))
  {
    switch (PHYLinkState)
    {
    case LAN8742_STATUS_100MBITS_FULLDUPLEX:
      duplex = ETH_FULLDUPLEX_MODE;
      speed = ETH_SPEED_100M;
      linkchanged = 1;
      break;
    case LAN8742_STATUS_100MBITS_HALFDUPLEX:
      duplex = ETH_HALFDUPLEX_MODE;
      speed = ETH_SPEED_100M;
      linkchanged = 1;
      break;
    case LAN8742_STATUS_10MBITS_FULLDUPLEX:
      duplex = ETH_FULLDUPLEX_MODE;
      speed = ETH_SPEED_10M;
      linkchanged = 1;
      break;
    case LAN8742_STATUS_10MBITS_HALFDUPLEX:
      duplex = ETH_HALFDUPLEX_MODE;
      speed = ETH_SPEED_10M;
      linkchanged = 1;
      break;
    default:
      break;
    }
 
    if(linkchanged)
    {
      /* Get MAC Config MAC */
      HAL_ETH_GetMACConfig(&heth, &MACConf);
      MACConf.DuplexMode = duplex;
      MACConf.Speed = speed;
      HAL_ETH_SetMACConfig(&heth, &MACConf);
      HAL_ETH_Start_IT(&heth);
      netif_set_up(netif);
      netif_set_link_up(netif);
    }
  }
 
/* USER CODE BEGIN ETH link Thread core code for User BSP */
 
/* USER CODE END ETH link Thread core code for User BSP */
 
    osDelay(100);
  }
}

But I figured out that if I comment

   HAL_ETH_Stop_IT(&heth);

   netif_set_down(netif);

   netif_set_link_down(netif);

and

   HAL_ETH_GetMACConfig(&heth, &MACConf);

   MACConf.DuplexMode = duplex;

   MACConf.Speed = speed;

   HAL_ETH_SetMACConfig(&heth, &MACConf);

   HAL_ETH_Start_IT(&heth);

   netif_set_up(netif);

   netif_set_link_up(netif);

than everything works fine even after I replug cable.

I have tested UDP, it works in both conditions. RX and TX window for tcp are OK. Is there anything I am missing I should reinit after netif_link_up() to ensure tcp stack is stable?

Thank you

It's the link that's changing, not the interface. So call netif_set_up after creating the netif and don't call netif_set_down.

Calling HAL_ETH_Stop_IT when the link goes down doesn't help anything. LwIP won't stop trying to transmit. UDP is connectionless and TCP will retry. Just call HAL_ETH_Start_IT when you start and leave it up, else you will deplete your tx buffers.

Check LAN8742_GetLinkState's result is sensible. If you're connected a switch, it won't be half-duplex.

Piranha
Chief II

There is a simple rule - everything from HAL/Cube is a broken bloatware. Even this single function has a bunch of critical problems:

  1. The lwIP multithreading requirements are ignored - netif_***() are called without core locking.
  2. The HAL_***() and LAN8742_***() functions are not thread safe, but are called from two threads - ethernetif_input() and ethernet_link_thread().
  3. CubeMX generates wrong PHY register and bit values for LAN8742.

All of that is described here:

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

> So call netif_set_up after creating the netif and don't call netif_set_down.

This code in the examples maybe is to copy the behavior of Windows. Several interfaces can have the same MAC address, but only one can be on.

If there's only one interface, this is pointless.