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 * Creates two transmitting tasks and two receiving tasks. The transmitting
\r
72 * tasks send values that are received by the receiving tasks. One set of tasks
\r
73 * uses the standard API. The other set of tasks uses the zero copy API.
\r
75 * See the following web page for essential demo usage and configuration
\r
77 * http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/examples_FreeRTOS_simulator.html
\r
80 /* Standard includes. */
\r
84 /* FreeRTOS includes. */
\r
85 #include "FreeRTOS.h"
\r
88 /* FreeRTOS+TCP includes. */
\r
89 #include "FreeRTOS_IP.h"
\r
90 #include "FreeRTOS_Sockets.h"
\r
92 #define simpTINY_DELAY ( ( TickType_t ) 2 )
\r
95 * Uses a socket to send data without using the zero copy option.
\r
96 * prvSimpleServerTask() will receive the data.
\r
98 static void prvSimpleClientTask( void *pvParameters );
\r
101 * Uses a socket to receive the data sent by the prvSimpleClientTask() task.
\r
102 * Does not use the zero copy option.
\r
104 static void prvSimpleServerTask( void *pvParameters );
\r
107 * Uses a socket to send data using the zero copy option.
\r
108 * prvSimpleZeroCopyServerTask() will receive the data.
\r
110 static void prvSimpleZeroCopyUDPClientTask( void *pvParameters );
\r
113 * Uses a socket to receive the data sent by the prvSimpleZeroCopyUDPClientTask()
\r
114 * task. Uses the zero copy option.
\r
116 static void prvSimpleZeroCopyServerTask( void *pvParameters );
\r
118 /*-----------------------------------------------------------*/
\r
120 void vStartSimpleUDPClientServerTasks( uint16_t usStackSize, uint32_t ulPort, UBaseType_t uxPriority )
\r
122 /* Create the client and server tasks that do not use the zero copy
\r
124 xTaskCreate( prvSimpleClientTask, "SimpCpyClnt", usStackSize, ( void * ) ulPort, uxPriority, NULL );
\r
125 xTaskCreate( prvSimpleServerTask, "SimpCpySrv", usStackSize, ( void * ) ulPort, uxPriority + 1, NULL );
\r
127 /* Create the client and server tasks that do use the zero copy interface. */
\r
128 xTaskCreate( prvSimpleZeroCopyUDPClientTask, "SimpZCpyClnt", usStackSize, ( void * ) ( ulPort + 1 ), uxPriority, NULL );
\r
129 xTaskCreate( prvSimpleZeroCopyServerTask, "SimpZCpySrv", usStackSize, ( void * ) ( ulPort + 1 ), uxPriority + 1, NULL );
\r
131 /*-----------------------------------------------------------*/
\r
133 static void prvSimpleClientTask( void *pvParameters )
\r
135 Socket_t xClientSocket;
\r
136 struct freertos_sockaddr xDestinationAddress;
\r
137 uint8_t cString[ 50 ];
\r
138 BaseType_t lReturned;
\r
139 uint32_t ulCount = 0UL, ulIPAddress;
\r
140 const uint32_t ulLoopsPerSocket = 10UL;
\r
141 const TickType_t x150ms = 150UL / portTICK_PERIOD_MS;
\r
143 /* Remove compiler warning about unused parameters. */
\r
144 ( void ) pvParameters;
\r
146 /* It is assumed that this task is not created until the network is up,
\r
147 so the IP address can be obtained immediately. store the IP address being
\r
148 used in ulIPAddress. This is done so the socket can send to a different
\r
149 port on the same IP address. */
\r
150 FreeRTOS_GetAddressConfiguration( &ulIPAddress, NULL, NULL, NULL );
\r
152 /* This test sends to itself, so data sent from here is received by a server
\r
153 socket on the same IP address. Setup the freertos_sockaddr structure with
\r
154 this nodes IP address, and the port number being sent to. The strange
\r
155 casting is to try and remove compiler warnings on 32 bit machines. */
\r
156 xDestinationAddress.sin_addr = ulIPAddress;
\r
157 xDestinationAddress.sin_port = ( uint16_t ) ( ( uint32_t ) pvParameters ) & 0xffffUL;
\r
158 xDestinationAddress.sin_port = FreeRTOS_htons( xDestinationAddress.sin_port );
\r
162 /* Create the socket. */
\r
163 xClientSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
\r
164 configASSERT( xClientSocket != FREERTOS_INVALID_SOCKET );
\r
166 /* The count is used to differentiate between different messages sent to
\r
167 the server, and to break out of the do while loop below. */
\r
172 /* Create the string that is sent to the server. */
\r
173 sprintf( ( char * ) cString, "Server received (not zero copy): Message number %lu\r\n", ulCount );
\r
175 /* Send the string to the socket. ulFlags is set to 0, so the zero
\r
176 copy option is not selected. That means the data from cString[] is
\r
177 copied into a network buffer inside FreeRTOS_sendto(), and cString[]
\r
178 can be reused as soon as FreeRTOS_sendto() has returned. */
\r
179 lReturned = FreeRTOS_sendto( xClientSocket, ( void * ) cString, strlen( ( const char * ) cString ), 0, &xDestinationAddress, sizeof( xDestinationAddress ) );
\r
183 } while( ( lReturned != FREERTOS_SOCKET_ERROR ) && ( ulCount < ulLoopsPerSocket ) );
\r
185 FreeRTOS_closesocket( xClientSocket );
\r
187 /* A short delay to prevent the messages printed by the server task
\r
188 scrolling off the screen too quickly, and to prevent reduce the network
\r
190 vTaskDelay( x150ms );
\r
193 /*-----------------------------------------------------------*/
\r
195 static void prvSimpleServerTask( void *pvParameters )
\r
198 uint8_t cReceivedString[ 60 ];
\r
199 struct freertos_sockaddr xClient, xBindAddress;
\r
200 uint32_t xClientLength = sizeof( xClient );
\r
201 Socket_t xListeningSocket;
\r
203 /* Just to prevent compiler warnings. */
\r
204 ( void ) pvParameters;
\r
206 /* Attempt to open the socket. */
\r
207 xListeningSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
\r
208 configASSERT( xListeningSocket != FREERTOS_INVALID_SOCKET );
\r
210 /* This test receives data sent from a different port on the same IP
\r
211 address. Configure the freertos_sockaddr structure with the address being
\r
212 bound to. The strange casting is to try and remove compiler warnings on 32
\r
213 bit machines. Note that this task is only created after the network is up,
\r
214 so the IP address is valid here. */
\r
215 xBindAddress.sin_port = ( uint16_t ) ( ( uint32_t ) pvParameters ) & 0xffffUL;
\r
216 xBindAddress.sin_port = FreeRTOS_htons( xBindAddress.sin_port );
\r
218 /* Bind the socket to the port that the client task will send to. */
\r
219 FreeRTOS_bind( xListeningSocket, &xBindAddress, sizeof( xBindAddress ) );
\r
223 /* Zero out the receive array so there is NULL at the end of the string
\r
224 when it is printed out. */
\r
225 memset( cReceivedString, 0x00, sizeof( cReceivedString ) );
\r
227 /* Receive data on the socket. ulFlags is zero, so the zero copy option
\r
228 is not set and the received data is copied into the buffer pointed to by
\r
229 cReceivedString. By default the block time is
\r
230 ipconfigSOCK_DEFAULT_RECEIVE_BLOCK_TIME. xClientLength is not actually
\r
231 used by FreeRTOS_recvfrom(), but is set appropriately in case future
\r
232 versions do use it. */
\r
233 lBytes = FreeRTOS_recvfrom( xListeningSocket, cReceivedString, sizeof( cReceivedString ), 0, &xClient, &xClientLength );
\r
236 configASSERT( lBytes == ( BaseType_t ) strlen( ( const char * ) cReceivedString ) );
\r
239 /*-----------------------------------------------------------*/
\r
241 static void prvSimpleZeroCopyUDPClientTask( void *pvParameters )
\r
243 Socket_t xClientSocket;
\r
244 uint8_t *pucUDPPayloadBuffer;
\r
245 struct freertos_sockaddr xDestinationAddress;
\r
246 BaseType_t lReturned;
\r
247 uint32_t ulCount = 0UL, ulIPAddress;
\r
248 const uint32_t ulLoopsPerSocket = 10UL;
\r
249 const char *pcStringToSend = "Server received (using zero copy): Message number ";
\r
250 const TickType_t x150ms = 150UL / portTICK_PERIOD_MS;
\r
251 /* 15 is added to ensure the number, \r\n and terminating zero fit. */
\r
252 const size_t xStringLength = strlen( pcStringToSend ) + 15;
\r
254 /* Remove compiler warning about unused parameters. */
\r
255 ( void ) pvParameters;
\r
257 /* It is assumed that this task is not created until the network is up,
\r
258 so the IP address can be obtained immediately. store the IP address being
\r
259 used in ulIPAddress. This is done so the socket can send to a different
\r
260 port on the same IP address. */
\r
261 FreeRTOS_GetAddressConfiguration( &ulIPAddress, NULL, NULL, NULL );
\r
263 /* This test sends to itself, so data sent from here is received by a server
\r
264 socket on the same IP address. Setup the freertos_sockaddr structure with
\r
265 this nodes IP address, and the port number being sent to. The strange
\r
266 casting is to try and remove compiler warnings on 32 bit machines. */
\r
267 xDestinationAddress.sin_addr = ulIPAddress;
\r
268 xDestinationAddress.sin_port = ( uint16_t ) ( ( uint32_t ) pvParameters ) & 0xffffUL;
\r
269 xDestinationAddress.sin_port = FreeRTOS_htons( xDestinationAddress.sin_port );
\r
273 /* Create the socket. */
\r
274 xClientSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
\r
275 configASSERT( xClientSocket != FREERTOS_INVALID_SOCKET );
\r
277 /* The count is used to differentiate between different messages sent to
\r
278 the server, and to break out of the do while loop below. */
\r
283 /* This task is going to send using the zero copy interface. The
\r
284 data being sent is therefore written directly into a buffer that is
\r
285 passed into, rather than copied into, the FreeRTOS_sendto()
\r
288 First obtain a buffer of adequate length from the IP stack into which
\r
289 the string will be written. Although a max delay is used, the actual
\r
290 delay will be capped to ipconfigMAX_SEND_BLOCK_TIME_TICKS, hence
\r
291 the do while loop is used to ensure a buffer is obtained. */
\r
294 } while( ( pucUDPPayloadBuffer = ( uint8_t * ) FreeRTOS_GetUDPPayloadBuffer( xStringLength, portMAX_DELAY ) ) == NULL );
\r
296 /* A buffer was successfully obtained. Create the string that is
\r
297 sent to the server. First the string is filled with zeros as this will
\r
298 effectively be the null terminator when the string is received at the other
\r
299 end. Note that the string is being written directly into the buffer
\r
300 obtained from the IP stack above. */
\r
301 memset( ( void * ) pucUDPPayloadBuffer, 0x00, xStringLength );
\r
302 sprintf( ( char * ) pucUDPPayloadBuffer, "%s%lu\r\n", pcStringToSend, ulCount );
\r
304 /* Pass the buffer into the send function. ulFlags has the
\r
305 FREERTOS_ZERO_COPY bit set so the IP stack will take control of the
\r
306 buffer rather than copy data out of the buffer. */
\r
307 lReturned = FreeRTOS_sendto( xClientSocket, /* The socket being sent to. */
\r
308 ( void * ) pucUDPPayloadBuffer, /* A pointer to the the data being sent. */
\r
309 strlen( ( const char * ) pucUDPPayloadBuffer ) + 1, /* The length of the data being sent - including the string's null terminator. */
\r
310 FREERTOS_ZERO_COPY, /* ulFlags with the FREERTOS_ZERO_COPY bit set. */
\r
311 &xDestinationAddress, /* Where the data is being sent. */
\r
312 sizeof( xDestinationAddress ) );
\r
314 if( lReturned == 0 )
\r
316 /* The send operation failed, so this task is still responsible
\r
317 for the buffer obtained from the IP stack. To ensure the buffer
\r
318 is not lost it must either be used again, or, as in this case,
\r
319 returned to the IP stack using FreeRTOS_ReleaseUDPPayloadBuffer().
\r
320 pucUDPPayloadBuffer can be safely re-used after this call. */
\r
321 FreeRTOS_ReleaseUDPPayloadBuffer( ( void * ) pucUDPPayloadBuffer );
\r
325 /* The send was successful so the IP stack is now managing the
\r
326 buffer pointed to by pucUDPPayloadBuffer, and the IP stack will
\r
327 return the buffer once it has been sent. pucUDPPayloadBuffer can
\r
328 be safely re-used. */
\r
333 } while( ( lReturned != FREERTOS_SOCKET_ERROR ) && ( ulCount < ulLoopsPerSocket ) );
\r
335 FreeRTOS_closesocket( xClientSocket );
\r
337 /* A short delay to prevent the messages scrolling off the screen too
\r
339 vTaskDelay( x150ms );
\r
342 /*-----------------------------------------------------------*/
\r
344 static void prvSimpleZeroCopyServerTask( void *pvParameters )
\r
347 uint8_t *pucUDPPayloadBuffer;
\r
348 struct freertos_sockaddr xClient, xBindAddress;
\r
349 uint32_t xClientLength = sizeof( xClient ), ulIPAddress;
\r
350 Socket_t xListeningSocket;
\r
352 /* Just to prevent compiler warnings. */
\r
353 ( void ) pvParameters;
\r
355 /* Attempt to open the socket. */
\r
356 xListeningSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
\r
357 configASSERT( xListeningSocket != FREERTOS_INVALID_SOCKET );
\r
359 /* This test receives data sent from a different port on the same IP address.
\r
360 Obtain the nodes IP address. Configure the freertos_sockaddr structure with
\r
361 the address being bound to. The strange casting is to try and remove
\r
362 compiler warnings on 32 bit machines. Note that this task is only created
\r
363 after the network is up, so the IP address is valid here. */
\r
364 FreeRTOS_GetAddressConfiguration( &ulIPAddress, NULL, NULL, NULL );
\r
365 xBindAddress.sin_addr = ulIPAddress;
\r
366 xBindAddress.sin_port = ( uint16_t ) ( ( uint32_t ) pvParameters ) & 0xffffUL;
\r
367 xBindAddress.sin_port = FreeRTOS_htons( xBindAddress.sin_port );
\r
369 /* Bind the socket to the port that the client task will send to. */
\r
370 FreeRTOS_bind( xListeningSocket, &xBindAddress, sizeof( xBindAddress ) );
\r
374 /* Receive data on the socket. ulFlags has the zero copy bit set
\r
375 (FREERTOS_ZERO_COPY) indicating to the stack that a reference to the
\r
376 received data should be passed out to this task using the second
\r
377 parameter to the FreeRTOS_recvfrom() call. When this is done the
\r
378 IP stack is no longer responsible for releasing the buffer, and
\r
379 the task *must* return the buffer to the stack when it is no longer
\r
380 needed. By default the block time is portMAX_DELAY. */
\r
381 lBytes = FreeRTOS_recvfrom( xListeningSocket, ( void * ) &pucUDPPayloadBuffer, 0, FREERTOS_ZERO_COPY, &xClient, &xClientLength );
\r
383 /* Print the received characters. */
\r
386 /* It is expected to receive one more byte than the string length as
\r
387 the NULL terminator is also transmitted. */
\r
388 configASSERT( lBytes == ( ( BaseType_t ) strlen( ( const char * ) pucUDPPayloadBuffer ) + 1 ) );
\r
393 /* The buffer *must* be freed once it is no longer needed. */
\r
394 FreeRTOS_ReleaseUDPPayloadBuffer( pucUDPPayloadBuffer );
\r