cancel
Showing results for 
Search instead for 
Did you mean: 

TCP Client outputs wrong data after couple of minutes

amirshn
Associate II

I have coded a TCP client on a ST32F746ZGT6 and i am receiving data from a TCP sever with a rate of 50hz and a packet size of 1460 bytes through ethernet. as part of my TCP client in tcp_client_handle function, i am extracting only 4 bytes of the receive packets and send it another device by Wi-Fi. Here is my code for the whole TCP client:

 

 

int counter = 0;
uint8_t data[100];

extern TIM_HandleTypeDef htim1;

/* create a struct to store data */
struct tcp_client_struct *esTx = 0;

struct tcp_pcb *pcbTx = 0;

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	char buf[100];

	/* Prepare the first message to send to the server */
	int len = sprintf (buf, "This is APM Computer %d\n", counter);

	if (counter !=0)
	{
		/* allocate pbuf */
		esTx->p = pbuf_alloc(PBUF_TRANSPORT, len , PBUF_POOL);


		/* copy data to pbuf */
		pbuf_take(esTx->p, (char*)buf, len);

		tcp_client_send(pcbTx, esTx);

		pbuf_free(esTx->p);
	}

}
/* IMPLEMENTATION FOR TCP CLIENT

1. Create TCP block.
2. connect to the server
3. start communicating
*/

void tcp_client_init(void)
{
	/* 1. create new tcp pcb */
	struct tcp_pcb *tpcb;

	tpcb = tcp_new();

	/* 2. Connect to the server (PDAS) */
	ip_addr_t destIPADDR;
	IP_ADDR4(&destIPADDR, 192, 168, 1, 254);// PDAS IP Address
	tcp_connect(tpcb, &destIPADDR, 49000, tcp_client_connected); // PDAS port number
}

/** This callback is called, when the client is connected to the server
 * Here we will initialise few other callbacks
 * and in the end, call the client handle function
  */
static err_t tcp_client_connected(void *arg, struct tcp_pcb *newpcb, err_t err)
{
  err_t ret_err;
  struct tcp_client_struct *es;

  LWIP_UNUSED_ARG(arg);
  LWIP_UNUSED_ARG(err);

  /* allocate structure es to maintain tcp connection information */
  es = (struct tcp_client_struct *)mem_malloc(sizeof(struct tcp_client_struct));
  if (es != NULL)
  {
    es->state = ES_CONNECTED;
    es->pcb = newpcb;
    es->retries = 0;
    es->p = NULL;

    /* pass newly allocated es structure as argument to newpcb */
    tcp_arg(newpcb, es);

    /* initialize lwip tcp_recv callback function for newpcb  */
    tcp_recv(newpcb, tcp_client_recv);

    ret_err = ERR_OK;
  }
  else
  {
    /*  close tcp connection */
    tcp_client_connection_close(newpcb, es);
    /* return memory error */
    ret_err = ERR_MEM;
  }
  return ret_err;
}


/** This callback is called, when the client receives some data from the server
 * if the data received is valid, we will handle the data in the client handle function
  */
static err_t tcp_client_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
{
  struct tcp_client_struct *es;
  err_t ret_err;

  LWIP_ASSERT("arg != NULL",arg != NULL);

  es = (struct tcp_client_struct *)arg;

  /* if we receive an empty tcp frame from server => close connection */
  if (p == NULL)
  {
    /* remote host closed connection */
    es->state = ES_CLOSING;
    if(es->p == NULL)
    {
       /* we're done sending, close connection */
       tcp_client_connection_close(tpcb, es);
    }
    ret_err = ERR_OK;
  }
  /* else : a non empty frame was received from server but for some reason err != ERR_OK */
  else if(err != ERR_OK)
  {
    /* free received pbuf*/
    if (p != NULL)
    {
      es->p = NULL;
      pbuf_free(p);
    }
    ret_err = err;
  }
  else if(es->state == ES_CONNECTED)
  {
   /* store reference to incoming pbuf (chain) */
	//load reduction on the receiver data handling func
	receive_reduc_counter++;
	if (receive_reduc_counter == 5){

    es->p = p;
    /* handle the received data */

    tcp_client_handle(tpcb, es);
	receive_reduc_counter = 0;
	}

    /* Acknowledge the received data */
    tcp_recved(tpcb, p->tot_len);

    pbuf_free(p);

    ret_err = ERR_OK;
  }
  else if(es->state == ES_CLOSING)
  {
    /* odd case, remote side closing twice, trash data */
    tcp_recved(tpcb, p->tot_len);
    es->p = NULL;
    pbuf_free(p);
    ret_err = ERR_OK;
  }
  else
  {
    /* unknown es->state, trash data  */
    tcp_recved(tpcb, p->tot_len);
    es->p = NULL;
    pbuf_free(p);
    ret_err = ERR_OK;
  }
  return ret_err;
}

/** This callback is called, when the server acknowledges the data sent by the client
 * If there is no more data left to sent, we will simply close the connection
  */
static err_t tcp_client_sent(void *arg, struct tcp_pcb *tpcb, u16_t len)
{
  struct tcp_client_struct *es;

  LWIP_UNUSED_ARG(len);

  es = (struct tcp_client_struct *)arg;
  es->retries = 0;

  if(es->p != NULL)
  {
	// tcp_sent has already been initialized in the beginning.
    /* still got pbufs to send */

  }
  else
  {
    /* if no more data to send and client closed connection*/
    if(es->state == ES_CLOSING)
      tcp_client_connection_close(tpcb, es);
  }
  return ERR_OK;
}

/** A function to send the data to the server
  */
static void tcp_client_send(struct tcp_pcb *tpcb, struct tcp_client_struct *es)
{
  struct pbuf *ptr;
  err_t wr_err = ERR_OK;

  while ((wr_err == ERR_OK) &&
         (es->p != NULL) &&
         (es->p->len <= tcp_sndbuf(tpcb)))
  {

    /* get pointer on pbuf from es structure */
    ptr = es->p;

    /* enqueue data for transmission */
    wr_err = tcp_write(tpcb, ptr->payload, ptr->len, 1);

    if (wr_err == ERR_OK)
    {
      u16_t plen;
      u8_t freed;

      plen = ptr->len;

      /* continue with next pbuf in chain (if any) */
      es->p = ptr->next;

      if(es->p != NULL)
      {
        /* increment reference count for es->p */
        pbuf_ref(es->p);
      }

     /* chop first pbuf from chain */
      do
      {
        /* try hard to free pbuf */
        freed = pbuf_free(ptr);
      }
      while(freed == 0);
     /* we can read more data now */
//     tcp_recved(tpcb, plen);
   }
   else if(wr_err == ERR_MEM)
   {
      /* we are low on memory, try later / harder, defer to poll */
     es->p = ptr;
   }
  }
}


static void tcp_client_connection_close(struct tcp_pcb *tpcb, struct tcp_client_struct *es)
{

  /* remove all callbacks */
  tcp_arg(tpcb, NULL);
  tcp_sent(tpcb, NULL);
  tcp_recv(tpcb, NULL);
  tcp_err(tpcb, NULL);
  tcp_poll(tpcb, NULL, 0);

  /* delete es structure */
  if (es != NULL)
  {
    mem_free(es);
  }

  /* close tcp connection */
  tcp_close(tpcb);
}

/* Handle the incoming TCP Data */

static void tcp_client_handle (struct tcp_pcb *tpcb, struct tcp_client_struct *es)
{

    if (es->p->len == 1460) {
    memcpy(ch7, es->p->payload + 1124, 4);

	fch7 = charBufferToFloat(ch7);
#ifdef DEBUG
	if (fch7 < 2){
////	for (int i = 0; i < 12; i++)
////	{
////	    trace_printf("%02X", ch7[i]);
////	    trace_printf(":");
////	}
////	printf("\n");
    trace_printf("%f\n",fch7);
	}
#endif
    sprintf(buf_PDAS, "PDAS_data,%f",fch7);
    err = WIFI_Send(buf_PDAS);

    }
	counter++;
}

float charBufferToFloat(char buffer[4]) {
    // Create an instance of the union
    union IntFloatUnion converter;

    // Combine the bytes into the intValue part of the union
    // Assuming buffer is in little endian order
    converter.intValue = (uint8_t)buffer[0] |
                         ((uint8_t)buffer[1] <<  |
                         ((uint8_t)buffer[2] << 16) |
                         ((uint8_t)buffer[3] << 24);

    // Return the float value
    return converter.floatValue;
}

 

 

Everything work fine for couple of minutes ( up to 25 minutes), however it outputs zero for the rest of the packets. It worth mentioning that if i print the extracted values in the receive handle function, it output zero after almost 5 seconds, so probably its the question of load handling on the MCU. (I have attached my LWIP configuration for TCP connection.)

Any help or advice would be highly appreciated.

 

Amir

1 REPLY 1
ASEHST
ST Employee

Hello @amirshn 

It seems there's a discrepancy in your TCP_MSS setting. The standard MTU for Ethernet networks is 1500 bytes, leading to a TCP_MSS of 1460 bytes once you account for the IP and TCP headers. Your current TCP_MSS value is set for an MTU that exceeds the Ethernet standard (1750 bytes).

Could you please verify your network's MTU and adjust the TCP_MSS as needed to prevent unnecessary packet fragmentation?

 

With Regards,

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