cancel
Showing results for 
Search instead for 
Did you mean: 

Looking for a exact place to put flag in the Lwip stack

Pyrodigy
Associate II

Dear forum, greetings.

I need a recommendation with my Lwip stack project.

First of all, I would mention that I have successfully installed lwip stack with freertos on h723 nucleo board and I can get ping.

My project scenario is;

There are multiple nodes on a network and each with a different fixed ip address. Each node in the network listen incoming packet requests from the PC. Whenever request packet income to the ip address matching node, then it will respond immediately. Unmatched ip address boards will stay Idle state.

My question is;

I just want to release separate semaphores or set user flags as soon as the data packet matching the ip address comes from the pc, and as soon as I send a reply back to the pc.

Where is the right place to put these flags or semaphores for this in the LWIP stack?

My main aim is to change or read the register of the PHY just before and just after the node with the matching ip address sends a response to the pc.

I tried to add these In the RX and TX callback functions in the ethernetif.c file but it didnt worked as expected. 

Protocols will be UDP, TCP or (ICMP) Ping.

Any recommendation appriciated.

8 REPLIES 8
ASEHST
ST Employee

Hello @Pyrodigy,

Could you please provide us with your implementation of the RX (ethernetif_input) and TX (low_level_output) callback functions? This will allow us to diagnose the issues more accurately and offer more targeted recommendations.

 

With Regards, 

If your question is answered, please close this topic by clicking "Accept as Solution".

@ASEHST Thank you for the response.
I am using project as exactly same with the link Github > STM32H7-LwIP-Examples /STM32H723_Nucleo_ETH

Here is the RX and TX Callbacks in the ethernetif.c file

 

/**
  * @brief  Ethernet Rx Transfer completed callback
  * @param  handlerEth: ETH handler
  * @retval None
  */
void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *handlerEth)
{
  osSemaphoreRelease(RxPktSemaphore);
//  osSemaphoreRelease(myBinarySem01Handle); // Scenario - 2 after complated the reception let the semaphore release
}
/**
  * @brief  Ethernet Tx Transfer completed callback
  * @param  handlerEth: ETH handler
  * @retval None
  */
void HAL_ETH_TxCpltCallback(ETH_HandleTypeDef *handlerEth)
{
  osSemaphoreRelease(TxPktSemaphore);
//  osSemaphoreRelease(myBinarySem02Handle); // Scenario - 2  after complated the transfer let the semaphore release
}

 

 ethernetif_input function;

 

void ethernetif_input(void* argument)
{
  struct pbuf *p = NULL;
  struct netif *netif = (struct netif *) argument;

  for( ;; )
  {
    if (osSemaphoreAcquire(RxPktSemaphore, TIME_WAITING_FOR_INPUT) == osOK)
    {
      do
      {
        p = low_level_input( netif );
        if (p != NULL)
        {
          if (netif->input( p, netif) != ERR_OK )
          {
            pbuf_free(p);
          }
        }
      } while(p!=NULL);
    }
  }
}

 

And ethernet output function;

 

static err_t low_level_output(struct netif *netif, struct pbuf *p)
{
  uint32_t i = 0U;
  struct pbuf *q = NULL;
  err_t errval = ERR_OK;
  ETH_BufferTypeDef Txbuffer[ETH_TX_DESC_CNT] = {0};

  memset(Txbuffer, 0 , ETH_TX_DESC_CNT*sizeof(ETH_BufferTypeDef));

  for(q = p; q != NULL; q = q->next)
  {
    if(i >= ETH_TX_DESC_CNT)
      return ERR_IF;

    Txbuffer[i].buffer = q->payload;
    Txbuffer[i].len = q->len;

    if(i>0)
    {
      Txbuffer[i-1].next = &Txbuffer[i];
    }

    if(q->next == NULL)
    {
      Txbuffer[i].next = NULL;
    }

    i++;
  }

  TxConfig.Length = p->tot_len;
  TxConfig.TxBuffer = Txbuffer;
  TxConfig.pData = p;

  pbuf_ref(p);

  do
  {
    if(HAL_ETH_Transmit_IT(&heth, &TxConfig) == HAL_OK)
    {
      errval = ERR_OK;
    }
    else
    {

      if(HAL_ETH_GetError(&heth) & HAL_ETH_ERROR_BUSY)
      {
        /* Wait for descriptors to become available */
        osSemaphoreAcquire(TxPktSemaphore, ETHIF_TX_TIMEOUT);
        HAL_ETH_ReleaseTxPacket(&heth);
        errval = ERR_BUF;
      }
      else
      {
        /* Other error */
        pbuf_free(p);
        errval =  ERR_IF;
      }
    }
  }while(errval == ERR_BUF);

  return errval;
}

 

Also I would like to share my tasks and semaphores in the the main.c file

 

//****************************************************************************
//****************************************************************************
void StartDefaultTask(void *argument)
{
  /* init code for LWIP */
  MX_LWIP_Init();
  /* USER CODE BEGIN 5 */
  LOCK_TCPIP_CORE();

	  const char* message = "Hello UDP message!\n\r";

	  osDelay(10);

	  ip_addr_t PC_IPADDR;
	  IP_ADDR4(&PC_IPADDR, 192, 168, 1, 1);

	  struct udp_pcb* my_udp = udp_new();
	  udp_connect(my_udp, &PC_IPADDR, 55151);
	  struct pbuf* udp_buffer = NULL;
	  UNLOCK_TCPIP_CORE();
	  /* Infinite loop */
	  for (;;) {
		osDelay(1000);
		/* !! PBUF_RAM is critical for correct operation !! */
		udp_buffer = pbuf_alloc(PBUF_TRANSPORT, strlen(message), PBUF_RAM);

		if (udp_buffer != NULL) {
		  memcpy(udp_buffer->payload, message, strlen(message));
//		  osSemaphoreRelease(myBinarySem01Handle); // Scenario - 1 Release semaphore just Before send message.
		  udp_send(my_udp, udp_buffer);
//		  osSemaphoreRelease(myBinarySem02Handle); // Scenario - 1 Release semaphore just After send message 
		  pbuf_free(udp_buffer);
		}
	  }
  /* USER CODE END 5 */
}

//****************************************************************************
//****************************************************************************

/* USER CODE END Header_StartTask01 */
void StartTask01(void *argument)
{
  /* USER CODE BEGIN StartTask01 */
  /* Infinite loop */
  for(;;)
  {
	osSemaphoreAcquire(myBinarySem01Handle, osWaitForever);
    /* Check */
	if( (PHY_REG_Globalvalue & LAN8742_CH_SELECT) == LAN8742_CH_SELECT){ 
		PHY_REG_Globalvalue &= ~ LAN8742_CH_SELECT;
		HAL_ETH_WritePHYRegister(&heth,PHY_ADDR,27); // write phy reg
	}
    osDelay(1);
  }
  /* USER CODE END StartTask01 */
}
//****************************************************************************
//****************************************************************************

/* USER CODE END Header_StartTask02 */
void StartTask02(void *argument)
{
  /* USER CODE BEGIN StartTask02 */
  /* Infinite loop */
  for(;;)
  {
	osSemaphoreAcquire(myBinarySem02Handle, osWaitForever);
	 /* Check */
	if((PHY_REG_Globalvalue & LAN8742_CH_SELECT) == 0){ 
		PHY_REG_Globalvalue |= LAN8742_CH_SELECT;
		HAL_ETH_WritePHYRegister(&heth,PHY_ADDR,27); // write phy
	}
    osDelay(1);
  }
  /* USER CODE END StartTask02 */
}

//****************************************************************************
//****************************************************************************

 


Edit:
In this example code above, i want to release these Semaphores as soon as valid data packet is received and as soon as it sends a response back to the server.  Therefore, direct them to the relevant tasks.
Valid data packed means only data packets which match with ip address only.
Thanks

ASEHST
ST Employee

Hello @Pyrodigy,

Please try to add checks in your RX and TX callbacks to ensure that the packets being processed match the node's IP address before releasing the semaphores. This will ensure that semaphores are only triggered for relevant packets, avoiding unexpected behaviors and improving resource management.

 

With Regards,

If your question is answered, please close this topic by clicking "Accept as Solution".

Hello, @ASEHST Thank you for your quickly response with valued information.
Could you please provide me further information abouth how to check ip address match the packets being proceed or complated packed into the RX Callback ?

I m thinking to use FreeRtos V.2 with Netconn Api.

Where the destination ip address stored in the incoming buffer ? Which function checks if the ip address matches ?

Is there any flag in the LWIP api to determine ip address matched while incoming packed or just received ?

Does RX Callback exactly means whole payload packed include ip address, received succesfully by the node even ip address match nor no-match ? 

If there is any Rtos with UDP and TCP example or project that i could able to asist  ?

Sorry for dummy questions but any help appriciated.

Best Regards.

 

 

 

ASEHST
ST Employee

Hello @Pyrodigy,

Without checking the IP address, semaphores may be released for packets that are not destined for the specific node. To avoid this, you can use the ip_hdr structure to manually check the destination IP address. Here's an example that might help

void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *handlerEth)
{
  struct pbuf *p = NULL;
  struct netif *netif = &gnetif; // Ensure that gnetif is properly defined

  // Call the original receive function
  p = low_level_input(netif);

  if (p != NULL)
  {
    struct ip_hdr *iphdr = (struct ip_hdr *)p->payload;
    if (iphdr->dest.addr == netif->ip_addr.addr)
    {
      osSemaphoreRelease(RxPktSemaphore);
    }
    pbuf_free(p);
  }
}

 

You can refer to the LwIP examples provided in the STM32CubeH7 package as a starting point: STM32CubeH7/Projects/NUCLEO-H723ZG/Applications/LwIP at master · STMicroelectronics/STM32CubeH7 (github.com)

 

With Regards,

If your question is answered, please close this topic by clicking "Accept as Solution".

I would like you thank you for your assist.
I ve added your code to my void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *handlerEth) function in the ethernetif.c file but i got errors after compiled. Where am i wrong ?
Thanks

 

ethernetif.c:207:34: error: 'gnetif' undeclared (first use in this function); did you mean 'netif'?
struct netif *netif = &gnetif; // Ensure that gnetif is properly defined

ethernetif.c:503:22: error: conflicting types for 'low_level_input'; have 'struct pbuf *(struct netif *)'
static struct pbuf * low_level_input(struct netif *netif)

 

 err1.PNG

and

err2ı.PNG

ASEHST
ST Employee

You are missing the declaration of gnetif. Please ensure that gnetif is properly declared as follows:

extern struct netif gnetif;

 

If your question is answered, please close this topic by clicking "Accept as Solution".

@ASEHSTThank you for your assist. Unfortunately this code didnt work. 

During the reception process (eg.ping)

osSemaphoreRelease(RxPktSemaphore)

never releases.
Best Regards

 

void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *handlerEth)
{
	  struct pbuf *p = NULL;
	  extern struct netif gnetif;
	  struct netif *netif = &gnetif; // Ensure that gnetif is properly defined

	  // Call the original receive function
	  p = low_level_input(netif);

	  if (p != NULL)
	  {
	    struct ip_hdr *iphdr = (struct ip_hdr *)p->payload;
	    if (iphdr->dest.addr == netif->ip_addr.addr)
	    {
	      osSemaphoreRelease(RxPktSemaphore);
	    }
	    pbuf_free(p);
	  }
}