cancel
Showing results for 
Search instead for 
Did you mean: 

TCP Client outputs wrong data after couple of minutes

amirshn
Associate III

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; }
View more

 

 

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".