2 FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
\r
5 VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
\r
7 This file is part of the FreeRTOS distribution.
\r
9 FreeRTOS is free software; you can redistribute it and/or modify it under
\r
10 the terms of the GNU General Public License (version 2) as published by the
\r
11 Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
\r
13 ***************************************************************************
\r
14 >>! NOTE: The modification to the GPL is included to allow you to !<<
\r
15 >>! distribute a combined work that includes FreeRTOS without being !<<
\r
16 >>! obliged to provide the source code for proprietary components !<<
\r
17 >>! outside of the FreeRTOS kernel. !<<
\r
18 ***************************************************************************
\r
20 FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
\r
21 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
\r
22 FOR A PARTICULAR PURPOSE. Full license text is available on the following
\r
23 link: http://www.freertos.org/a00114.html
\r
25 ***************************************************************************
\r
27 * FreeRTOS provides completely free yet professionally developed, *
\r
28 * robust, strictly quality controlled, supported, and cross *
\r
29 * platform software that is more than just the market leader, it *
\r
30 * is the industry's de facto standard. *
\r
32 * Help yourself get started quickly while simultaneously helping *
\r
33 * to support the FreeRTOS project by purchasing a FreeRTOS *
\r
34 * tutorial book, reference manual, or both: *
\r
35 * http://www.FreeRTOS.org/Documentation *
\r
37 ***************************************************************************
\r
39 http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
\r
40 the FAQ page "My application does not run, what could be wrong?". Have you
\r
41 defined configASSERT()?
\r
43 http://www.FreeRTOS.org/support - In return for receiving this top quality
\r
44 embedded software for free we request you assist our global community by
\r
45 participating in the support forum.
\r
47 http://www.FreeRTOS.org/training - Investing in training allows your team to
\r
48 be as productive as possible as early as possible. Now you can receive
\r
49 FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
\r
50 Ltd, and the world's leading authority on the world's leading RTOS.
\r
52 http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
\r
53 including FreeRTOS+Trace - an indispensable productivity tool, a DOS
\r
54 compatible FAT file system, and our tiny thread aware UDP/IP stack.
\r
56 http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
\r
57 Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
\r
59 http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
\r
60 Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
\r
61 licenses offer ticketed support, indemnification and commercial middleware.
\r
63 http://www.SafeRTOS.com - High Integrity Systems also provide a safety
\r
64 engineered and independently SIL3 certified version for use in safety and
\r
65 mission critical applications that require provable dependability.
\r
71 * A set of tasks are created that send TCP echo requests to the standard echo
\r
72 * port (port 7) on the IP address set by the configECHO_SERVER_ADDR0 to
\r
73 * configECHO_SERVER_ADDR3 constants, then wait for and verify the reply
\r
74 * (another demo is avilable that demonstrates the reception being performed in
\r
75 * a task other than that from with the request was made).
\r
77 * See the following web page for essential demo usage and configuration
\r
79 * http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/examples_FreeRTOS_simulator.html
\r
82 /* Standard includes. */
\r
87 /* FreeRTOS includes. */
\r
88 #include "FreeRTOS.h"
\r
92 /* FreeRTOS+TCP includes. */
\r
93 #include "FreeRTOS_IP.h"
\r
94 #include "FreeRTOS_Sockets.h"
\r
96 /* Exclude the whole file if FreeRTOSIPConfig.h is configured to use UDP only. */
\r
97 #if( ipconfigUSE_TCP == 1 )
\r
99 /* The echo tasks create a socket, send out a number of echo requests, listen
\r
100 for the echo reply, then close the socket again before starting over. This
\r
101 delay is used between each iteration to ensure the network does not get too
\r
103 #define echoLOOP_DELAY ( ( TickType_t ) 150 / portTICK_PERIOD_MS )
\r
105 /* The echo server is assumed to be on port 7, which is the standard echo
\r
107 #define echoECHO_PORT ( 7 )
\r
109 /* The size of the buffers is a multiple of the MSS - the length of the data
\r
110 sent is a pseudo random size between 20 and echoBUFFER_SIZES. */
\r
111 #define echoBUFFER_SIZE_MULTIPLIER ( 3 )
\r
112 #define echoBUFFER_SIZES ( ipconfigTCP_MSS * echoBUFFER_SIZE_MULTIPLIER )
\r
114 /* The number of instances of the echo client task to create. */
\r
115 #define echoNUM_ECHO_CLIENTS ( 5 )
\r
117 /*-----------------------------------------------------------*/
\r
120 * Uses a socket to send data to, then receive data from, the standard echo
\r
123 static void prvEchoClientTask( void *pvParameters );
\r
126 * Creates a pseudo random sized buffer of data to send to the echo server.
\r
128 static BaseType_t prvCreateTxData( char *ucBuffer, uint32_t ulBufferLength );
\r
130 /*-----------------------------------------------------------*/
\r
132 /* Rx and Tx time outs are used to ensure the sockets do not wait too long for
\r
134 static const TickType_t xReceiveTimeOut = pdMS_TO_TICKS( 4000 );
\r
135 static const TickType_t xSendTimeOut = pdMS_TO_TICKS( 2000 );
\r
137 /* Counters for each created task - for inspection only. */
\r
138 static uint32_t ulTxRxCycles[ echoNUM_ECHO_CLIENTS ] = { 0 },
\r
139 ulTxRxFailures[ echoNUM_ECHO_CLIENTS ] = { 0 },
\r
140 ulConnections[ echoNUM_ECHO_CLIENTS ] = { 0 };
\r
142 /* Rx and Tx buffers for each created task. */
\r
143 static char cTxBuffers[ echoNUM_ECHO_CLIENTS ][ echoBUFFER_SIZES ],
\r
144 cRxBuffers[ echoNUM_ECHO_CLIENTS ][ echoBUFFER_SIZES ];
\r
146 /*-----------------------------------------------------------*/
\r
148 void vStartTCPEchoClientTasks_SingleTasks( uint16_t usTaskStackSize, UBaseType_t uxTaskPriority )
\r
152 /* Create the echo client tasks. */
\r
153 for( x = 0; x < echoNUM_ECHO_CLIENTS; x++ )
\r
155 xTaskCreate( prvEchoClientTask, /* The function that implements the task. */
\r
156 "Echo0", /* Just a text name for the task to aid debugging. */
\r
157 usTaskStackSize, /* The stack size is defined in FreeRTOSIPConfig.h. */
\r
158 ( void * ) x, /* The task parameter, not used in this case. */
\r
159 uxTaskPriority, /* The priority assigned to the task is defined in FreeRTOSConfig.h. */
\r
160 NULL ); /* The task handle is not used. */
\r
163 /*-----------------------------------------------------------*/
\r
165 static void prvEchoClientTask( void *pvParameters )
\r
168 struct freertos_sockaddr xEchoServerAddress;
\r
169 int32_t lLoopCount = 0UL;
\r
170 const int32_t lMaxLoopCount = 1;
\r
171 volatile uint32_t ulTxCount = 0UL;
\r
172 BaseType_t xReceivedBytes, xReturned, xInstance;
\r
173 BaseType_t lTransmitted, lStringLength;
\r
174 char *pcTransmittedString, *pcReceivedString;
\r
175 WinProperties_t xWinProps;
\r
176 TickType_t xTimeOnEntering;
\r
178 /* Fill in the buffer and window sizes that will be used by the socket. */
\r
179 xWinProps.lTxBufSize = 6 * ipconfigTCP_MSS;
\r
180 xWinProps.lTxWinSize = 3;
\r
181 xWinProps.lRxBufSize = 6 * ipconfigTCP_MSS;
\r
182 xWinProps.lRxWinSize = 3;
\r
184 /* This task can be created a number of times. Each instance is numbered
\r
185 to enable each instance to use a different Rx and Tx buffer. The number is
\r
186 passed in as the task's parameter. */
\r
187 xInstance = ( BaseType_t ) pvParameters;
\r
189 /* Point to the buffers to be used by this instance of this task. */
\r
190 pcTransmittedString = &( cTxBuffers[ xInstance ][ 0 ] );
\r
191 pcReceivedString = &( cRxBuffers[ xInstance ][ 0 ] );
\r
193 /* Echo requests are sent to the echo server. The address of the echo
\r
194 server is configured by the constants configECHO_SERVER_ADDR0 to
\r
195 configECHO_SERVER_ADDR3 in FreeRTOSConfig.h. */
\r
196 xEchoServerAddress.sin_port = FreeRTOS_htons( echoECHO_PORT );
\r
197 xEchoServerAddress.sin_addr = FreeRTOS_inet_addr_quick( configECHO_SERVER_ADDR0,
\r
198 configECHO_SERVER_ADDR1,
\r
199 configECHO_SERVER_ADDR2,
\r
200 configECHO_SERVER_ADDR3 );
\r
204 /* Create a TCP socket. */
\r
205 xSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP );
\r
206 configASSERT( xSocket != FREERTOS_INVALID_SOCKET );
\r
208 /* Set a time out so a missing reply does not cause the task to block
\r
210 FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVTIMEO, &xReceiveTimeOut, sizeof( xReceiveTimeOut ) );
\r
211 FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_SNDTIMEO, &xSendTimeOut, sizeof( xSendTimeOut ) );
\r
213 /* Set the window and buffer sizes. */
\r
214 FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_WIN_PROPERTIES, ( void * ) &xWinProps, sizeof( xWinProps ) );
\r
216 /* Connect to the echo server. */
\r
217 if( FreeRTOS_connect( xSocket, &xEchoServerAddress, sizeof( xEchoServerAddress ) ) == 0 )
\r
219 ulConnections[ xInstance ]++;
\r
221 /* Send a number of echo requests. */
\r
222 for( lLoopCount = 0; lLoopCount < lMaxLoopCount; lLoopCount++ )
\r
224 /* Create the string that is sent to the echo server. */
\r
225 lStringLength = prvCreateTxData( pcTransmittedString, echoBUFFER_SIZES );
\r
227 /* Add in some unique text at the front of the string. */
\r
228 sprintf( pcTransmittedString, "TxRx message number %u", ulTxCount );
\r
231 /* Send the string to the socket. */
\r
232 lTransmitted = FreeRTOS_send( xSocket, /* The socket being sent to. */
\r
233 ( void * ) pcTransmittedString, /* The data being sent. */
\r
234 lStringLength, /* The length of the data being sent. */
\r
235 0 ); /* No flags. */
\r
237 if( lTransmitted < 0 )
\r
243 /* Clear the buffer into which the echoed string will be
\r
245 memset( ( void * ) pcReceivedString, 0x00, echoBUFFER_SIZES );
\r
246 xReceivedBytes = 0;
\r
248 /* Receive data echoed back to the socket. */
\r
249 while( xReceivedBytes < lTransmitted )
\r
251 xReturned = FreeRTOS_recv( xSocket, /* The socket being received from. */
\r
252 &( pcReceivedString[ xReceivedBytes ] ),/* The buffer into which the received data will be written. */
\r
253 lStringLength - xReceivedBytes, /* The size of the buffer provided to receive the data. */
\r
254 0 ); /* No flags. */
\r
256 if( xReturned < 0 )
\r
258 /* Error occurred. Latch it so it can be detected
\r
260 xReceivedBytes = xReturned;
\r
263 else if( xReturned == 0 )
\r
270 /* Keep a count of the bytes received so far. */
\r
271 xReceivedBytes += xReturned;
\r
275 /* If an error occurred it will be latched in xReceivedBytes,
\r
276 otherwise xReceived bytes will be just that - the number of
\r
277 bytes received from the echo server. */
\r
278 if( xReceivedBytes > 0 )
\r
280 /* Compare the transmitted string to the received string. */
\r
281 configASSERT( strncmp( pcReceivedString, pcTransmittedString, lTransmitted ) == 0 );
\r
282 if( strncmp( pcReceivedString, pcTransmittedString, lTransmitted ) == 0 )
\r
284 /* The echo reply was received without error. */
\r
285 ulTxRxCycles[ xInstance ]++;
\r
289 /* The received string did not match the transmitted
\r
291 ulTxRxFailures[ xInstance ]++;
\r
295 else if( xReceivedBytes < 0 )
\r
297 /* FreeRTOS_recv() returned an error. */
\r
302 /* Timed out without receiving anything? */
\r
307 /* Finished using the connected socket, initiate a graceful close:
\r
308 FIN, FIN+ACK, ACK. */
\r
309 FreeRTOS_shutdown( xSocket, FREERTOS_SHUT_RDWR );
\r
311 /* Expect FreeRTOS_recv() to return an error once the shutdown is
\r
313 xTimeOnEntering = xTaskGetTickCount();
\r
316 xReturned = FreeRTOS_recv( xSocket, /* The socket being received from. */
\r
317 &( pcReceivedString[ 0 ] ), /* The buffer into which the received data will be written. */
\r
318 echoBUFFER_SIZES, /* The size of the buffer provided to receive the data. */
\r
321 if( xReturned < 0 )
\r
326 } while( ( xTaskGetTickCount() - xTimeOnEntering ) < xReceiveTimeOut );
\r
329 /* Close this socket before looping back to create another. */
\r
330 FreeRTOS_closesocket( xSocket );
\r
332 /* Pause for a short while to ensure the network is not too
\r
334 vTaskDelay( echoLOOP_DELAY );
\r
337 /*-----------------------------------------------------------*/
\r
339 static BaseType_t prvCreateTxData( char *cBuffer, uint32_t ulBufferLength )
\r
341 BaseType_t lCharactersToAdd, lCharacter;
\r
343 const BaseType_t lMinimumLength = 60;
\r
345 /* Randomise the number of characters that will be sent in the echo
\r
349 lCharactersToAdd = ipconfigRAND32() % ( ulBufferLength - 20UL );
\r
350 } while ( ( lCharactersToAdd == 0 ) || ( lCharactersToAdd < lMinimumLength ) ); /* Must be at least enough to add the unique text to the start of the string later. */
\r
352 /* Fill the buffer. */
\r
353 for( lCharacter = 0; lCharacter < lCharactersToAdd; lCharacter++ )
\r
355 cBuffer[ lCharacter ] = cChar;
\r
364 return lCharactersToAdd;
\r
366 /*-----------------------------------------------------------*/
\r
368 BaseType_t xAreSingleTaskTCPEchoClientsStillRunning( void )
\r
370 static uint32_t ulLastEchoSocketCount[ echoNUM_ECHO_CLIENTS ] = { 0 }, ulLastConnections[ echoNUM_ECHO_CLIENTS ] = { 0 };
\r
371 BaseType_t xReturn = pdPASS, x;
\r
373 /* Return fail is the number of cycles does not increment between
\r
374 consecutive calls. */
\r
375 for( x = 0; x < echoNUM_ECHO_CLIENTS; x++ )
\r
377 if( ulTxRxCycles[ x ] == ulLastEchoSocketCount[ x ] )
\r
383 ulLastEchoSocketCount[ x ] = ulTxRxCycles[ x ];
\r
386 if( ulConnections[ x ] == ulLastConnections[ x ] )
\r
392 ulConnections[ x ] = ulLastConnections[ x ];
\r
399 #endif /* ipconfigUSE_TCP */
\r