]> git.sur5r.net Git - freertos/blob - FreeRTOS-Labs/Demo/FreeRTOS_Plus_TCP_and_FAT_Windows_Simulator/DemoTasks/TCPEchoClient_SingleTasks.c
Add the Labs projects provided in the V10.2.1_191129 zip file.
[freertos] / FreeRTOS-Labs / Demo / FreeRTOS_Plus_TCP_and_FAT_Windows_Simulator / DemoTasks / TCPEchoClient_SingleTasks.c
1 /*\r
2     FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.\r
3     All rights reserved\r
4 \r
5     VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
6 \r
7     This file is part of the FreeRTOS distribution.\r
8 \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
12 \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
19 \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
24 \r
25     ***************************************************************************\r
26      *                                                                       *\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
31      *                                                                       *\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
36      *                                                                       *\r
37     ***************************************************************************\r
38 \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
42 \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
46 \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
51 \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
55 \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
58 \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
62 \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
66 \r
67     1 tab == 4 spaces!\r
68 */\r
69 \r
70 /*\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
76  *\r
77  * See the following web page for essential demo usage and configuration\r
78  * details:\r
79  * http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/examples_FreeRTOS_simulator.html\r
80  */\r
81 \r
82 /* Standard includes. */\r
83 #include <stdint.h>\r
84 #include <stdio.h>\r
85 #include <stdlib.h>\r
86 \r
87 /* FreeRTOS includes. */\r
88 #include "FreeRTOS.h"\r
89 #include "task.h"\r
90 #include "queue.h"\r
91 \r
92 /* FreeRTOS+TCP includes. */\r
93 #include "FreeRTOS_IP.h"\r
94 #include "FreeRTOS_Sockets.h"\r
95 \r
96 /* Exclude the whole file if FreeRTOSIPConfig.h is configured to use UDP only. */\r
97 #if( ipconfigUSE_TCP == 1 )\r
98 \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
102 congested. */\r
103 #define echoLOOP_DELAY  ( ( TickType_t ) 150 / portTICK_PERIOD_MS )\r
104 \r
105 /* The echo server is assumed to be on port 7, which is the standard echo\r
106 protocol port. */\r
107 #define echoECHO_PORT   ( 7 )\r
108 \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
113 \r
114 /* The number of instances of the echo client task to create. */\r
115 #define echoNUM_ECHO_CLIENTS            ( 5 )\r
116 \r
117 /*-----------------------------------------------------------*/\r
118 \r
119 /*\r
120  * Uses a socket to send data to, then receive data from, the standard echo\r
121  * port number 7.\r
122  */\r
123 static void prvEchoClientTask( void *pvParameters );\r
124 \r
125 /*\r
126  * Creates a pseudo random sized buffer of data to send to the echo server.\r
127  */\r
128 static BaseType_t prvCreateTxData( char *ucBuffer, uint32_t ulBufferLength );\r
129 \r
130 /*-----------------------------------------------------------*/\r
131 \r
132 /* Rx and Tx time outs are used to ensure the sockets do not wait too long for\r
133 missing data. */\r
134 static const TickType_t xReceiveTimeOut = pdMS_TO_TICKS( 4000 );\r
135 static const TickType_t xSendTimeOut = pdMS_TO_TICKS( 2000 );\r
136 \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
141 \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
145 \r
146 /*-----------------------------------------------------------*/\r
147 \r
148 void vStartTCPEchoClientTasks_SingleTasks( uint16_t usTaskStackSize, UBaseType_t uxTaskPriority )\r
149 {\r
150 BaseType_t x;\r
151 \r
152         /* Create the echo client tasks. */\r
153         for( x = 0; x < echoNUM_ECHO_CLIENTS; x++ )\r
154         {\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
161         }\r
162 }\r
163 /*-----------------------------------------------------------*/\r
164 \r
165 static void prvEchoClientTask( void *pvParameters )\r
166 {\r
167 Socket_t xSocket;\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
177 \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
183 \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
188 \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
192 \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
201 \r
202         for( ;; )\r
203         {\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
207 \r
208                 /* Set a time out so a missing reply does not cause the task to block\r
209                 indefinitely. */\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
212 \r
213                 /* Set the window and buffer sizes. */\r
214                 FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_WIN_PROPERTIES, ( void * ) &xWinProps,     sizeof( xWinProps ) );\r
215 \r
216                 /* Connect to the echo server. */\r
217                 if( FreeRTOS_connect( xSocket, &xEchoServerAddress, sizeof( xEchoServerAddress ) ) == 0 )\r
218                 {\r
219                         ulConnections[ xInstance ]++;\r
220 \r
221                         /* Send a number of echo requests. */\r
222                         for( lLoopCount = 0; lLoopCount < lMaxLoopCount; lLoopCount++ )\r
223                         {\r
224                                 /* Create the string that is sent to the echo server. */\r
225                                 lStringLength = prvCreateTxData( pcTransmittedString, echoBUFFER_SIZES );\r
226 \r
227                                 /* Add in some unique text at the front of the string. */\r
228                                 sprintf( pcTransmittedString, "TxRx message number %u", ulTxCount );\r
229                                 ulTxCount++;\r
230 \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
236 \r
237                                 if( lTransmitted < 0 )\r
238                                 {\r
239                                         /* Error? */\r
240                                         break;\r
241                                 }\r
242 \r
243                                 /* Clear the buffer into which the echoed string will be\r
244                                 placed. */\r
245                                 memset( ( void * ) pcReceivedString, 0x00, echoBUFFER_SIZES );\r
246                                 xReceivedBytes = 0;\r
247 \r
248                                 /* Receive data echoed back to the socket. */\r
249                                 while( xReceivedBytes < lTransmitted )\r
250                                 {\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
255 \r
256                                         if( xReturned < 0 )\r
257                                         {\r
258                                                 /* Error occurred.  Latch it so it can be detected\r
259                                                 below. */\r
260                                                 xReceivedBytes = xReturned;\r
261                                                 break;\r
262                                         }\r
263                                         else if( xReturned == 0 )\r
264                                         {\r
265                                                 /* Timed out. */\r
266                                                 break;\r
267                                         }\r
268                                         else\r
269                                         {\r
270                                                 /* Keep a count of the bytes received so far. */\r
271                                                 xReceivedBytes += xReturned;\r
272                                         }\r
273                                 }\r
274 \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
279                                 {\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
283                                         {\r
284                                                 /* The echo reply was received without error. */\r
285                                                 ulTxRxCycles[ xInstance ]++;\r
286                                         }\r
287                                         else\r
288                                         {\r
289                                                 /* The received string did not match the transmitted\r
290                                                 string. */\r
291                                                 ulTxRxFailures[ xInstance ]++;\r
292                                                 break;\r
293                                         }\r
294                                 }\r
295                                 else if( xReceivedBytes < 0 )\r
296                                 {\r
297                                         /* FreeRTOS_recv() returned an error. */\r
298                                         break;\r
299                                 }\r
300                                 else\r
301                                 {\r
302                                         /* Timed out without receiving anything? */\r
303                                         break;\r
304                                 }\r
305                         }\r
306 \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
310 \r
311                         /* Expect FreeRTOS_recv() to return an error once the shutdown is\r
312                         complete. */\r
313                         xTimeOnEntering = xTaskGetTickCount();\r
314                         do\r
315                         {\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
319                                         0 );\r
320 \r
321                                 if( xReturned < 0 )\r
322                                 {\r
323                                         break;\r
324                                 }\r
325 \r
326                         } while( ( xTaskGetTickCount() - xTimeOnEntering ) < xReceiveTimeOut );\r
327                 }\r
328 \r
329                 /* Close this socket before looping back to create another. */\r
330                 FreeRTOS_closesocket( xSocket );\r
331 \r
332                 /* Pause for a short while to ensure the network is not too\r
333                 congested. */\r
334                 vTaskDelay( echoLOOP_DELAY );\r
335         }\r
336 }\r
337 /*-----------------------------------------------------------*/\r
338 \r
339 static BaseType_t prvCreateTxData( char *cBuffer, uint32_t ulBufferLength )\r
340 {\r
341 BaseType_t lCharactersToAdd, lCharacter;\r
342 char cChar = '0';\r
343 const BaseType_t lMinimumLength = 60;\r
344 \r
345         /* Randomise the number of characters that will be sent in the echo\r
346         request. */\r
347         do\r
348         {\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
351 \r
352         /* Fill the buffer. */\r
353         for( lCharacter = 0; lCharacter < lCharactersToAdd; lCharacter++ )\r
354         {\r
355                 cBuffer[ lCharacter ] = cChar;\r
356                 cChar++;\r
357 \r
358                 if( cChar > '~' )\r
359                 {\r
360                         cChar = '0';\r
361                 }\r
362         }\r
363 \r
364         return lCharactersToAdd;\r
365 }\r
366 /*-----------------------------------------------------------*/\r
367 \r
368 BaseType_t xAreSingleTaskTCPEchoClientsStillRunning( void )\r
369 {\r
370 static uint32_t ulLastEchoSocketCount[ echoNUM_ECHO_CLIENTS ] = { 0 }, ulLastConnections[ echoNUM_ECHO_CLIENTS ] = { 0 };\r
371 BaseType_t xReturn = pdPASS, x;\r
372 \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
376         {\r
377                 if( ulTxRxCycles[ x ] == ulLastEchoSocketCount[ x ] )\r
378                 {\r
379                         xReturn = pdFAIL;\r
380                 }\r
381                 else\r
382                 {\r
383                         ulLastEchoSocketCount[ x ] = ulTxRxCycles[ x ];\r
384                 }\r
385 \r
386                 if( ulConnections[ x ] == ulLastConnections[ x ] )\r
387                 {\r
388                         xReturn = pdFAIL;\r
389                 }\r
390                 else\r
391                 {\r
392                         ulConnections[ x ] = ulLastConnections[ x ];\r
393                 }\r
394         }\r
395 \r
396         return xReturn;\r
397 }\r
398 \r
399 #endif /* ipconfigUSE_TCP */\r
400 \r