Client/Server TCPIP communication - intermessage delay <22ms ERROR

Hi there,
I have a board with 2 ethernet peripherals.
I already enstablish the communication between these two peripherals embedding a client/server communication using FreeRTOS+TCP IP.

Below you can find the code snippet, just to give context:

//SERVER]
..
..

        	for( ;; )
        	{
	            xReceivedBytes = FreeRTOS_recv(xConnectedSocket, (void*)(&rx_eth_msg), sizeof(rx_eth_msg), 0 );
	            if( xReceivedBytes > 0 )
	            {
	            	tx_eth_msg = compute_client_request(rx_eth_msg);
	                encode_and_send_ETH_payload( tx_eth_msg, local_client_socket);
	                }
	            }
	           vTaskDelay(pdMS_TO_TICKS(6)); // small delay
	    	}

//CLIENT
..
..

    for (;;)
    {
    	encode_and_send_ETH_payload( msg_list[msg_id],  local_server_socket);
    	msg_id++;
    	if(msg_id>7) {msg_id = 0;}
    	vTaskDelay(pdMS_TO_TICKS(22)); // 1msg every 22 ms 
    }

In this example I send one ETH message every 22ms.

My communication works well, but, if I decide to lower the Client delay time,
I.E.:

( vTaskDelay (pdMS_TO_TICKS (21)))

something happens and my nodes do not talk anymore.

Is there a freeRTOS variable or setting you suggest to tweak in order to solve my issue?
I really wish to send/receive messages at a faster rate :smiley:

what does pdMS_TO_TICKS(22) evaluate to on your platform? I suspect 2 which means that if you make it lower than 20, you will get into the range where the task may typically not delay at all and thus starve your other tasks.

Can you explain or show the function encode_and_send_ETH_payload()?

Do you messages pas from 1 peripheral to the other and back? Are they connected by a LAN/switch?

What about the socket RCV/SND maximum waiting times?

I recommend checking every return value. Show them and take the proper action.

if ( ( iReturn < 0 ) &&
     ( iReturn != -pdFREERTOS_ERRNO_EAGAIN ) &&
     ( iReturn != -pdFREERTOS_ERRNO_EINTR ) )
{
    /* A fatal error occurred, like a disconnection. */
    return -1;
}

Actually, pdMS TO TICKS is 22:

For context:

This funciton just wraps the FreeRTOS send:

    void encode_and_send_ETH_payload(RCP_msg_t message, Socket_t xSocket){
    uint8_t xSentBytes;
    // Serialize the msg
     size_t messageSize = sizeof(message.msg_header) + sizeof(message.opt_header) + 
     sizeof(message.payload)/sizeof(message.payload[0]) + sizeof(message.footer_Checksum);
     uint8_t *buffer = (uint8_t *)malloc(messageSize);
     memcpy(buffer, &message, sizeof(message));
     FreeRTOS_send(xSocket, buffer, messageSize, 0);
     free(buffer);
    }

There are no switches in the system. Just 2 eth phy thransceivers enstablishing a communication.

Regarding rcv/snd timeouts, I set sockopts to 5seconds each when configuring socket options(both for client and server):

	static const TickType_t acpt_tout =  pdMS_TO_TICKS(5000); // 5 sec
	static const TickType_t rcv_tout =  pdMS_TO_TICKS(5000); // 5 sec
..

          FreeRTOS_setsockopt(local_server_socket, 0, FREERTOS_SO_RCVTIMEO, &rcv_tout, sizeof(rcv_tout));
          FreeRTOS_setsockopt(local_server_socket, 0, FREERTOS_SO_SNDTIMEO, &snd_tout, sizeof(snd_tout));

..

          FreeRTOS_setsockopt( xListeningSocket, 0, FREERTOS_SO_RCVTIMEO, &rcv_tout, sizeof(rcv_tout));
          FreeRTOS_setsockopt( xListeningSocket, 0, FREERTOS_SO_SNDTIMEO, &acpt_tout, sizeof(acpt_tout));

Would it be possible Simone, that you show a lot more from the testing program? You can take away any secrets or private code, I’d like to see all code related to +TCP.
Also I’d like to know which task is doing what? Or better: which tasks owns which sockets?
What platform are you using? Where did you get the driver?
Are you using a recent copy of the +TCP library?

But please start checking all return values. When you don’t, you might miss important information.

About +TCP and delays: normally a call to recv() might block if no packet is yet available. The function send() will normally return immediately, unless there is a queue of outgoing data.

Sure,
I didn’t attach all the code because I thought it was’t necessary.
I can achieve communication and it’s robust, I repeat.
But Server isn’t able to receive consecutive Client sends at a 21ms rate. (22ms works fine)

//MAIN

    void vApplicationIdleHook(void) {}

    int main(void)
    {
        uint8_t error;
	BOARD_init();
	error = startTCP_looped_communication();
	if (!error)
	{	vTaskStartScheduler();	}
	else	{	}
	for( ;; )	{	}
	return 0;
    }

//high level task

    uint32_t startTCP_looped_communication(void)
    {
      int32_t ret = pdPASS;
      if (ret == pdPASS)
      {	  /* Create server main task */
    	  ret = xTaskCreate(server_conn_Task, "server_conn_Task", REMOTE_SERVER_MAIN_TASK_STACK_SIZE, NULL, REMOTE_SERVER_MAIN_TASK_PRIORITY, &server_TaskHandler);
      }
      if (ret == pdPASS)
      {	  /* Create clientmain task */
	  ret = xTaskCreate(client_conn_Task, "client_conn_Task", REMOTE_SERVER_MAIN_TASK_STACK_SIZE, NULL, REMOTE_SERVER_MAIN_TASK_PRIORITY, &client_TaskHandler);
    	}
      return (ret == pdPASS) ? 0 : 1;
    }

//Client TASK

     portTASK_FUNCTION(client_conn_Task, pvParam)
     {    (void)pvParam;
     uint8_t ret;
     static const TickType_t tout =  pdMS_TO_TICKS(5000);
    Socket_t local_server_socket;
    const char *pcInterfaceName = "eth1"; 
    struct freertos_sockaddr xServerAddress, xClientAddress;
    BaseType_t xSentBytes;
    RCP_msg_t tx_msg;
    local_server_socket = FreeRTOS_socket(FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP);
    configASSERT(local_server_socket != FREERTOS_INVALID_SOCKET);
    FreeRTOS_setsockopt(local_server_socket, 0, FREERTOS_SO_BINDTODEVICE, pcInterfaceName, strlen(pcInterfaceName));
    FreeRTOS_setsockopt(local_server_socket, 0, FREERTOS_SO_RCVTIMEO, &tout , sizeof(tout ));
    FreeRTOS_setsockopt(local_server_socket, 0, FREERTOS_SO_SNDTIMEO, &tout , sizeof(tout ));
    xClientAddress.sin_family = FREERTOS_AF_INET;
    xClientAddress.sin_port = FreeRTOS_htons(ETH_PORT);
    xClientAddress.sin_addr = FreeRTOS_inet_addr("192.168.1.2");
    xServerAddress.sin_family = FREERTOS_AF_INET;
    xServerAddress.sin_port = FreeRTOS_htons(ETH_PORT);
    xServerAddress.sin_addr = FreeRTOS_inet_addr("192.168.1.1"); 

    vTaskDelay(pdMS_TO_TICKS(1000)); 
    do {
        ret = FreeRTOS_connect(local_server_socket, &xServerAddress, sizeof(xServerAddress));
        vTaskDelay(pdMS_TO_TICKS(750)); 
    } while (ret < 0);
    for (;;)
    {
    	encode_and_send_ETH_payload( msg_list[msg_id],  local_server_socket);
    	msg_id++;
    	if(msg_id>7) {msg_id = 0;}
    	vTaskDelay(pdMS_TO_TICKS(22)); 
      }
     }

//SERVER task

	portTASK_FUNCTION(server_conn_Task, pvParam ) {
	(void)pvParam;
	Socket_t xListeningSocket, xConnectedSocket, local_client_socket;
	struct freertos_sockaddr xBindAddress, connected_client_sockadd;
    socklen_t connected_client_size = sizeof(connected_client_sockadd);
	static const TickType_t tout =  pdMS_TO_TICKS(5000); 
	const char *pcInterfaceName = "eth0"; //test8650 // eth0=8670
    RCP_msg_t rx_eth_msg, tx_eth_msg;
    BaseType_t xReceivedBytes, xSentBytes;
	xListeningSocket = FreeRTOS_socket(FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP);
	if (xListeningSocket != FREERTOS_INVALID_SOCKET)
	{
		FreeRTOS_setsockopt( xListeningSocket, 0, FREERTOS_SO_RCVTIMEO, &tout , sizeof(tout ));
		FreeRTOS_setsockopt( xListeningSocket, 0, FREERTOS_SO_SNDTIMEO, &tout , sizeof(tout ));
		FreeRTOS_setsockopt( xListeningSocket, 0, FREERTOS_SO_BINDTODEVICE, pcInterfaceName, strlen(pcInterfaceName));
		xBindAddress.sin_family = FREERTOS_AF_INET;
		xBindAddress.sin_port = FreeRTOS_htons( ETH_PORT );
		xBindAddress.sin_addr = FreeRTOS_inet_addr("192.168.1.1");
		FreeRTOS_bind( xListeningSocket, &xBindAddress, sizeof( xBindAddress ) ); //bind to 5555
		FreeRTOS_listen( xListeningSocket, xBacklog );
        xConnectedSocket = FreeRTOS_accept( xListeningSocket, &connected_client_sockadd, &connected_client_size );
        if (xConnectedSocket != 0x0)
        {
      	local_client_socket = FreeRTOS_socket(FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP);
         if(local_client_socket != 0x0){
           FreeRTOS_setsockopt(local_client_socket, 0, FREERTOS_SO_BINDTODEVICE, pcInterfaceName, strlen(pcInterfaceName));
           FreeRTOS_setsockopt(local_client_socket, 0, FREERTOS_SO_RCVTIMEO, &tout , sizeof(tout ));
           FreeRTOS_setsockopt(local_client_socket, 0, FREERTOS_SO_SNDTIMEO, &tout , sizeof(tout ));
        	for( ;; )
        	{
	            xReceivedBytes = FreeRTOS_recv(xConnectedSocket, (void*)(&rx_eth_msg), sizeof(rx_eth_msg), 0 );
	            if( xReceivedBytes > 0 )
	            {
	            	tx_eth_msg = compute_client_request(rx_eth_msg);
	                //send response
	                encode_and_send_ETH_payload( tx_eth_msg, local_client_socket);
	                }
	            }
	           vTaskDelay(pdMS_TO_TICKS(6)); // small delay
    }}}}

I’m quite sure there is some freeRTOS configuration parameter which is “bottlenecking” my application. :smiling_face_with_tear:

The following code looks wrong to me:

    xConnectedSocket = FreeRTOS_accept( xListeningSocket, &connected_client_sockadd, &connected_client_size );
    if( xConnectedSocket != 0x0 )
    {
  	    local_client_socket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP );
        if(local_client_socket != 0x0)
        {
            FreeRTOS_setsockopt(local_client_socket, 0, FREERTOS_SO_BINDTODEVICE, pcInterfaceName, strlen(pcInterfaceName));
            FreeRTOS_setsockopt(local_client_socket, 0, FREERTOS_SO_RCVTIMEO, &tout , sizeof(tout ));
            FreeRTOS_setsockopt(local_client_socket, 0, FREERTOS_SO_SNDTIMEO, &tout , sizeof(tout ));
            for( ;; )
            {
                xReceivedBytes = FreeRTOS_recv(xConnectedSocket, (void*)(&rx_eth_msg), sizeof(rx_eth_msg), 0 );
                if( xReceivedBytes > 0 )
                {
                    tx_eth_msg = compute_client_request(rx_eth_msg);
                    //send response
                    encode_and_send_ETH_payload( tx_eth_msg, local_client_socket);
                }
            }
            vTaskDelay(pdMS_TO_TICKS(6)); // small delay
        }
    }

Why do you need local_client_socket? Should it not be just the following:

    xConnectedSocket = FreeRTOS_accept( xListeningSocket, &connected_client_sockadd, &connected_client_size );
    if( xConnectedSocket != 0x0 )
    {
        for( ;; )
        {
            xReceivedBytes = FreeRTOS_recv(xConnectedSocket, (void*)(&rx_eth_msg), sizeof(rx_eth_msg), 0 );
            if( xReceivedBytes > 0 )
            {
                tx_eth_msg = compute_client_request(rx_eth_msg);
                //send response
                encode_and_send_ETH_payload( tx_eth_msg, xConnectedSocket);
            }
        }
        vTaskDelay(pdMS_TO_TICKS(6)); // small delay
    }

@aggarg wrote:

Why do you need local_client_socket? Should it not be just the following

I understand that neither.

You are trying to communicate through local_client_socket, but that socket is not yet connected, either through accept() or through connect().

Where did you find the socket option FREERTOS_SO_BINDTODEVICE? Google can not help me with it.

It looks like you have implemented a loop: a socket is listening on one interface, and it receives a connection from the other interface.

You are using malloc() without testing the result. Two questions: are you sure it is safe to call malloc(): normally I use pvPortMalloc(size_t size), after having chosen one out of:

    portable\MemMang\heap_1.c
    ...
    portable\MemMang\heap_5.c

Normally I use heap_5.c.

-    if( xConnectedSocket != 0x0 )
+    if( xConnectedSocket != NULL )

because in FreeRTOS+TCP a socket is a pointer, not a number.