Hello !
I am working on a TCP echo server using FreeRTOS+TCP on a STM32F4. I used example code to run my server but the program is stuck in FreeRTOS_recv() function.
I checked several things :
-
ARP is working, I can see with wireshark that the asking from my computer is well answered with my STM32.
-
Ping is working well too.
-
Connection on my server is working. when the client try to connect to my server, the connection is good and my code goes into FreeRTOS_recv.
-
The frame reception is working. When sending “test” with my client, my code breaks in prvTCPHandleState and the frame is processed.
-
Something is a bit weird. In FreeRTOS_TCP_IP.c in prvStoreRxData() function, my code does not enter in lTCPAddRxdata which seems to send the data to user part. the reason is that pxTCPWindow->ulUserDataLength is equal to 0.
/* Now lTCPAddRxdata() will move the rxHead pointer forward so data becomes available to the user immediately In case the low-water mark is reached, bLowWater will be set. */ if( ( xResult == 0 ) && ( pxTCPWindow->ulUserDataLength > 0UL ) ) { ( void ) lTCPAddRxdata( pxSocket, 0UL, NULL, pxTCPWindow->ulUserDataLength ); pxTCPWindow->ulUserDataLength = 0; }
Here is my main.cpp :
int main(void)
{
MainInit();
/* Initialise the RTOS’s TCP/IP stack. The tasks that use the network
are created in the vApplicationIPNetworkEventHook() hook function
below. The hook function is called when the network connects. */
FreeRTOS_IPInit( ucIPAddress,
ucNetMask,
ucGatewayAddress,
ucDNSServerAddress,
ucMACAddress );
// NVIC_SetPriorityGrouping( 0 ); // Demandé d'être mis a cette valeur dans port.c
NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 ); // Demandé d'etre mis a 4 dans https://www.freertos.org/RTOS-Cortex-M3-M4.html
/* Start the scheduler. */
vTaskStartScheduler();
// CANT GO HERE !
ASSERT(0);
return (0);
}
static void TcpServerTask( void *pvParameters )
{
printf("TcpServerTask created\n\r");
struct freertos_sockaddr xClient, xBindAddress;
Socket_t xListeningSocket, xConnectedSocket;
socklen_t xSize = sizeof( xClient );
static const TickType_t xReceiveTimeOut = portMAX_DELAY;
const BaseType_t xBacklog = 20;
#define BUFFER_SIZE 1500
static char cRxedData[ BUFFER_SIZE ];
BaseType_t lBytesReceived;
/* Attempt to open the socket. */
xListeningSocket = FreeRTOS_socket( FREERTOS_AF_INET,
FREERTOS_SOCK_STREAM, /* SOCK_STREAM for TCP. */
FREERTOS_IPPROTO_TCP );
/* Check the socket was created. */
ASSERT( xListeningSocket != FREERTOS_INVALID_SOCKET );
/* If FREERTOS_SO_RCVBUF or FREERTOS_SO_SNDBUF are to be used with
FreeRTOS_setsockopt() to change the buffer sizes from their default then do
it here!. (see the FreeRTOS_setsockopt() documentation. */
/* If ipconfigUSE_TCP_WIN is set to 1 and FREERTOS_SO_WIN_PROPERTIES is to
be used with FreeRTOS_setsockopt() to change the sliding window size from
its default then do it here! (see the FreeRTOS_setsockopt()
documentation. */
/* Set a time out so accept() will just wait for a connection. */
FreeRTOS_setsockopt( xListeningSocket,
0,
FREERTOS_SO_RCVTIMEO,
&xReceiveTimeOut,
sizeof( xReceiveTimeOut ) );
/* Set the listening port to 1337. */
xBindAddress.sin_port = ( uint16_t ) 1337;
xBindAddress.sin_port = FreeRTOS_htons( xBindAddress.sin_port );
/* Bind the socket to the port that the client RTOS task will send to. */
FreeRTOS_bind( xListeningSocket, &xBindAddress, sizeof( xBindAddress ) );
/* Set the socket into a listening state so it can accept connections.
The maximum number of simultaneous connections is limited to 20. */
FreeRTOS_listen( xListeningSocket, xBacklog );
for(;;)
{
/* Wait for incoming connections. */
xConnectedSocket = FreeRTOS_accept( xListeningSocket, &xClient, &xSize );
ASSERT( xConnectedSocket != FREERTOS_INVALID_SOCKET );
/* Receive another block of data into the cRxedData buffer. */
lBytesReceived = FreeRTOS_recv( xListeningSocket, &cRxedData, BUFFER_SIZE, 0 );
if( lBytesReceived > 0 )
{
BaseType_t xAlreadyTransmitted = 0, xBytesSent = 0;
size_t xLenToSend;
/* Data was received, process it here. */
/* Keep sending until the entire buffer has been sent. */
while( xAlreadyTransmitted < lBytesReceived )
{
/* How many bytes are left to send? */
xLenToSend = lBytesReceived - xAlreadyTransmitted;
xBytesSent = FreeRTOS_send( /* The socket being sent to. */
xListeningSocket,
/* The data being sent. */
&( cRxedData[ xAlreadyTransmitted ] ),
/* The remaining length of data to send. */
xLenToSend,
/* ulFlags. */
0 );
if( xBytesSent >= 0 )
{
/* Data was sent successfully. */
xAlreadyTransmitted += xBytesSent;
}
else
{
/* Error – break out of the loop for graceful socket close. */
break;
}
}
}
else if( lBytesReceived == 0 )
{
/* No data was received, but FreeRTOS_recv() did not return an error.
Timeout? */
}
else
{
/* Error (maybe the connected socket already shut down the socket?).
Attempt graceful shutdown. */
FreeRTOS_shutdown( xListeningSocket, FREERTOS_SHUT_RDWR );
break;
}
}
/* The RTOS task will get here if an error is received on a read. Ensure the
socket has shut down (indicated by FreeRTOS_recv() returning a FREERTOS_EINVAL
error before closing the socket). */
while( FreeRTOS_recv( xListeningSocket, cRxedData, lBytesReceived, 0 ) >= 0 )
{
/* Wait for shutdown to complete. If a receive block time is used then
this delay will not be necessary as FreeRTOS_recv() will place the RTOS task
into the Blocked state anyway. */
vTaskDelay( 250 );
/* Note – real applications should implement a timeout here, not just
loop forever. */
}
/* Shutdown is complete and the socket can be safely closed. */
FreeRTOS_closesocket( xListeningSocket );
/* Must not drop off the end of the RTOS task – delete the RTOS task. */
vTaskDelete( NULL );
}
So, it seems that FreeRTOS can not send the frame to the user part. but I don’t know why. Have you ever experienced this situation ?
Thank you.
fgu