2 FreeRTOS V8.1.1 - Copyright (C) 2014 Real Time Engineers Ltd.
\r
5 VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
\r
7 ***************************************************************************
\r
9 * FreeRTOS provides completely free yet professionally developed, *
\r
10 * robust, strictly quality controlled, supported, and cross *
\r
11 * platform software that has become a de facto standard. *
\r
13 * Help yourself get started quickly and support the FreeRTOS *
\r
14 * project by purchasing a FreeRTOS tutorial book, reference *
\r
15 * manual, or both from: http://www.FreeRTOS.org/Documentation *
\r
19 ***************************************************************************
\r
21 This file is part of the FreeRTOS distribution.
\r
23 FreeRTOS is free software; you can redistribute it and/or modify it under
\r
24 the terms of the GNU General Public License (version 2) as published by the
\r
25 Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
\r
27 >>! NOTE: The modification to the GPL is included to allow you to !<<
\r
28 >>! distribute a combined work that includes FreeRTOS without being !<<
\r
29 >>! obliged to provide the source code for proprietary components !<<
\r
30 >>! outside of the FreeRTOS kernel. !<<
\r
32 FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
\r
33 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
\r
34 FOR A PARTICULAR PURPOSE. Full license text is available from the following
\r
35 link: http://www.freertos.org/a00114.html
\r
39 ***************************************************************************
\r
41 * Having a problem? Start by reading the FAQ "My application does *
\r
42 * not run, what could be wrong?" *
\r
44 * http://www.FreeRTOS.org/FAQHelp.html *
\r
46 ***************************************************************************
\r
48 http://www.FreeRTOS.org - Documentation, books, training, latest versions,
\r
49 license and Real Time Engineers Ltd. contact details.
\r
51 http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
\r
52 including FreeRTOS+Trace - an indispensable productivity tool, a DOS
\r
53 compatible FAT file system, and our tiny thread aware UDP/IP stack.
\r
55 http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
\r
56 Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
\r
57 licenses offer ticketed support, indemnification and middleware.
\r
59 http://www.SafeRTOS.com - High Integrity Systems also provide a safety
\r
60 engineered and independently SIL3 certified version for use in safety and
\r
61 mission critical applications that require provable dependability.
\r
67 * Creates two transmitting tasks and two receiving tasks. The transmitting
\r
68 * tasks send values that are received by the receiving tasks. One set of tasks
\r
69 * uses the standard API. The other set of tasks uses the zero copy API.
\r
72 /* Standard includes. */
\r
76 /* FreeRTOS includes. */
\r
77 #include "FreeRTOS.h"
\r
80 /* FreeRTOS+UDP includes. */
\r
81 #include "FreeRTOS_UDP_IP.h"
\r
82 #include "FreeRTOS_Sockets.h"
\r
84 #define simpTINY_DELAY ( ( TickType_t ) 2 )
\r
87 * Uses a socket to send data without using the zero copy option.
\r
88 * prvSimpleServerTask() will receive the data.
\r
90 static void prvSimpleClientTask( void *pvParameters );
\r
93 * Uses a socket to receive the data sent by the prvSimpleClientTask() task.
\r
94 * Does not use the zero copy option.
\r
96 static void prvSimpleServerTask( void *pvParameters );
\r
99 * Uses a socket to send data using the zero copy option.
\r
100 * prvSimpleZeroCopyServerTask() will receive the data.
\r
102 static void prvSimpleZeroCopyUDPClientTask( void *pvParameters );
\r
105 * Uses a socket to receive the data sent by the prvSimpleZeroCopyUDPClientTask()
\r
106 * task. Uses the zero copy option.
\r
108 static void prvSimpleZeroCopyServerTask( void *pvParameters );
\r
110 /*-----------------------------------------------------------*/
\r
112 void vStartSimpleUDPClientServerTasks( uint16_t usStackSize, uint32_t ulPort, UBaseType_t uxPriority )
\r
114 /* Create the client and server tasks that do not use the zero copy
\r
116 xTaskCreate( prvSimpleClientTask, "SimpCpyClnt", usStackSize, ( void * ) ulPort, uxPriority, NULL );
\r
117 xTaskCreate( prvSimpleServerTask, "SimpCpySrv", usStackSize, ( void * ) ulPort, uxPriority + 1, NULL );
\r
119 /* Create the client and server tasks that do use the zero copy interface. */
\r
120 xTaskCreate( prvSimpleZeroCopyUDPClientTask, "SimpZCpyClnt", usStackSize, ( void * ) ( ulPort + 1 ), uxPriority, NULL );
\r
121 xTaskCreate( prvSimpleZeroCopyServerTask, "SimpZCpySrv", usStackSize, ( void * ) ( ulPort + 1 ), uxPriority + 1, NULL );
\r
123 /*-----------------------------------------------------------*/
\r
125 static void prvSimpleClientTask( void *pvParameters )
\r
127 xSocket_t xClientSocket;
\r
128 struct freertos_sockaddr xDestinationAddress;
\r
129 char cString[ 50 ];
\r
130 BaseType_t lReturned;
\r
131 uint32_t ulCount = 0UL, ulIPAddress;
\r
132 const uint32_t ulLoopsPerSocket = 10UL;
\r
133 const TickType_t x150ms = 150UL / portTICK_RATE_MS;
\r
135 /* Remove compiler warning about unused parameters. */
\r
136 ( void ) pvParameters;
\r
138 /* It is assumed that this task is not created until the network is up,
\r
139 so the IP address can be obtained immediately. store the IP address being
\r
140 used in ulIPAddress. This is done so the socket can send to a different
\r
141 port on the same IP address. */
\r
142 FreeRTOS_GetAddressConfiguration( &ulIPAddress, NULL, NULL, NULL );
\r
144 /* This test sends to itself, so data sent from here is received by a server
\r
145 socket on the same IP address. Setup the freertos_sockaddr structure with
\r
146 this nodes IP address, and the port number being sent to. The strange
\r
147 casting is to try and remove compiler warnings on 32 bit machines. */
\r
148 xDestinationAddress.sin_addr = ulIPAddress;
\r
149 xDestinationAddress.sin_port = ( uint16_t ) ( ( uint32_t ) pvParameters ) & 0xffffUL;
\r
150 xDestinationAddress.sin_port = FreeRTOS_htons( xDestinationAddress.sin_port );
\r
154 /* Create the socket. */
\r
155 xClientSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
\r
156 configASSERT( xClientSocket != FREERTOS_INVALID_SOCKET );
\r
158 /* The count is used to differentiate between different messages sent to
\r
159 the server, and to break out of the do while loop below. */
\r
164 /* Create the string that is sent to the server. */
\r
165 sprintf( cString, "Server received (not zero copy): Message number %lu\r\n", ulCount );
\r
167 /* Send the string to the socket. ulFlags is set to 0, so the zero
\r
168 copy option is not selected. That means the data from cString[] is
\r
169 copied into a network buffer inside FreeRTOS_sendto(), and cString[]
\r
170 can be reused as soon as FreeRTOS_sendto() has returned. */
\r
171 lReturned = FreeRTOS_sendto( xClientSocket, ( void * ) cString, strlen( cString ), 0, &xDestinationAddress, sizeof( xDestinationAddress ) );
\r
175 } while( ( lReturned != FREERTOS_SOCKET_ERROR ) && ( ulCount < ulLoopsPerSocket ) );
\r
177 FreeRTOS_closesocket( xClientSocket );
\r
179 /* A short delay to prevent the messages printed by the server task
\r
180 scrolling off the screen too quickly, and to prevent reduce the network
\r
182 vTaskDelay( x150ms );
\r
185 /*-----------------------------------------------------------*/
\r
187 static void prvSimpleServerTask( void *pvParameters )
\r
190 char cReceivedString[ 60 ];
\r
191 struct freertos_sockaddr xClient, xBindAddress;
\r
192 uint32_t xClientLength = sizeof( xClient );
\r
193 xSocket_t xListeningSocket;
\r
195 /* Just to prevent compiler warnings. */
\r
196 ( void ) pvParameters;
\r
198 /* Attempt to open the socket. */
\r
199 xListeningSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
\r
200 configASSERT( xListeningSocket != FREERTOS_INVALID_SOCKET );
\r
202 /* This test receives data sent from a different port on the same IP
\r
203 address. Configure the freertos_sockaddr structure with the address being
\r
204 bound to. The strange casting is to try and remove compiler warnings on 32
\r
205 bit machines. Note that this task is only created after the network is up,
\r
206 so the IP address is valid here. */
\r
207 xBindAddress.sin_port = ( uint16_t ) ( ( uint32_t ) pvParameters ) & 0xffffUL;
\r
208 xBindAddress.sin_port = FreeRTOS_htons( xBindAddress.sin_port );
\r
210 /* Bind the socket to the port that the client task will send to. */
\r
211 FreeRTOS_bind( xListeningSocket, &xBindAddress, sizeof( xBindAddress ) );
\r
215 /* Zero out the receive array so there is NULL at the end of the string
\r
216 when it is printed out. */
\r
217 memset( cReceivedString, 0x00, sizeof( cReceivedString ) );
\r
219 /* Receive data on the socket. ulFlags is zero, so the zero copy option
\r
220 is not set and the received data is copied into the buffer pointed to by
\r
221 cReceivedString. By default the block time is portMAX_DELAY.
\r
222 xClientLength is not actually used by FreeRTOS_recvfrom(), but is set
\r
223 appropriately in case future versions do use it. */
\r
224 lBytes = FreeRTOS_recvfrom( xListeningSocket, cReceivedString, sizeof( cReceivedString ), 0, &xClient, &xClientLength );
\r
226 /* Print the received characters. */
\r
229 vOutputString( cReceivedString );
\r
233 configASSERT( lBytes == ( BaseType_t ) strlen( cReceivedString ) );
\r
236 /*-----------------------------------------------------------*/
\r
238 static void prvSimpleZeroCopyUDPClientTask( void *pvParameters )
\r
240 xSocket_t xClientSocket;
\r
241 uint8_t *pucUDPPayloadBuffer;
\r
242 struct freertos_sockaddr xDestinationAddress;
\r
243 BaseType_t lReturned;
\r
244 uint32_t ulCount = 0UL, ulIPAddress;
\r
245 const uint32_t ulLoopsPerSocket = 10UL;
\r
246 const char *pcStringToSend = "Server received (using zero copy): Message number ";
\r
247 const TickType_t x150ms = 150UL / portTICK_RATE_MS;
\r
248 /* 15 is added to ensure the number, \r\n and terminating zero fit. */
\r
249 const size_t xStringLength = strlen( pcStringToSend ) + 15;
\r
251 /* Remove compiler warning about unused parameters. */
\r
252 ( void ) pvParameters;
\r
254 /* It is assumed that this task is not created until the network is up,
\r
255 so the IP address can be obtained immediately. store the IP address being
\r
256 used in ulIPAddress. This is done so the socket can send to a different
\r
257 port on the same IP address. */
\r
258 FreeRTOS_GetAddressConfiguration( &ulIPAddress, NULL, NULL, NULL );
\r
260 /* This test sends to itself, so data sent from here is received by a server
\r
261 socket on the same IP address. Setup the freertos_sockaddr structure with
\r
262 this nodes IP address, and the port number being sent to. The strange
\r
263 casting is to try and remove compiler warnings on 32 bit machines. */
\r
264 xDestinationAddress.sin_addr = ulIPAddress;
\r
265 xDestinationAddress.sin_port = ( uint16_t ) ( ( uint32_t ) pvParameters ) & 0xffffUL;
\r
266 xDestinationAddress.sin_port = FreeRTOS_htons( xDestinationAddress.sin_port );
\r
270 /* Create the socket. */
\r
271 xClientSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
\r
272 configASSERT( xClientSocket != FREERTOS_INVALID_SOCKET );
\r
274 /* The count is used to differentiate between different messages sent to
\r
275 the server, and to break out of the do while loop below. */
\r
280 /* This task is going to send using the zero copy interface. The
\r
281 data being sent is therefore written directly into a buffer that is
\r
282 passed into, rather than copied into, the FreeRTOS_sendto()
\r
285 First obtain a buffer of adequate length from the IP stack into which
\r
286 the string will be written. Although a max delay is used, the actual
\r
287 delay will be capped to ipconfigMAX_SEND_BLOCK_TIME_TICKS, hence
\r
288 the do while loop is used to ensure a buffer is obtained. */
\r
291 } while( ( pucUDPPayloadBuffer = ( uint8_t * ) FreeRTOS_GetUDPPayloadBuffer( xStringLength, portMAX_DELAY ) ) == NULL );
\r
293 /* A buffer was successfully obtained. Create the string that is
\r
294 sent to the server. First the string is filled with zeros as this will
\r
295 effectively be the null terminator when the string is received at the other
\r
296 end. Note that the string is being written directly into the buffer
\r
297 obtained from the IP stack above. */
\r
298 memset( ( void * ) pucUDPPayloadBuffer, 0x00, xStringLength );
\r
299 sprintf( ( char * ) pucUDPPayloadBuffer, "%s%lu\r\n", pcStringToSend, ulCount );
\r
301 /* Pass the buffer into the send function. ulFlags has the
\r
302 FREERTOS_ZERO_COPY bit set so the IP stack will take control of the
\r
303 buffer rather than copy data out of the buffer. */
\r
304 lReturned = FreeRTOS_sendto( xClientSocket, /* The socket being sent to. */
\r
305 ( void * ) pucUDPPayloadBuffer, /* A pointer to the the data being sent. */
\r
306 strlen( ( const char * ) pucUDPPayloadBuffer ) + 1, /* The length of the data being sent - including the string's null terminator. */
\r
307 FREERTOS_ZERO_COPY, /* ulFlags with the FREERTOS_ZERO_COPY bit set. */
\r
308 &xDestinationAddress, /* Where the data is being sent. */
\r
309 sizeof( xDestinationAddress ) );
\r
311 if( lReturned == 0 )
\r
313 /* The send operation failed, so this task is still responsible
\r
314 for the buffer obtained from the IP stack. To ensure the buffer
\r
315 is not lost it must either be used again, or, as in this case,
\r
316 returned to the IP stack using FreeRTOS_ReleaseUDPPayloadBuffer().
\r
317 pucUDPPayloadBuffer can be safely re-used after this call. */
\r
318 FreeRTOS_ReleaseUDPPayloadBuffer( ( void * ) pucUDPPayloadBuffer );
\r
322 /* The send was successful so the IP stack is now managing the
\r
323 buffer pointed to by pucUDPPayloadBuffer, and the IP stack will
\r
324 return the buffer once it has been sent. pucUDPPayloadBuffer can
\r
325 be safely re-used. */
\r
330 } while( ( lReturned != FREERTOS_SOCKET_ERROR ) && ( ulCount < ulLoopsPerSocket ) );
\r
332 FreeRTOS_closesocket( xClientSocket );
\r
334 /* A short delay to prevent the messages scrolling off the screen too
\r
336 vTaskDelay( x150ms );
\r
339 /*-----------------------------------------------------------*/
\r
341 static void prvSimpleZeroCopyServerTask( void *pvParameters )
\r
344 uint8_t *pucUDPPayloadBuffer;
\r
345 struct freertos_sockaddr xClient, xBindAddress;
\r
346 uint32_t xClientLength = sizeof( xClient ), ulIPAddress;
\r
347 xSocket_t xListeningSocket;
\r
349 /* Just to prevent compiler warnings. */
\r
350 ( void ) pvParameters;
\r
352 /* Attempt to open the socket. */
\r
353 xListeningSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
\r
354 configASSERT( xListeningSocket != FREERTOS_INVALID_SOCKET );
\r
356 /* This test receives data sent from a different port on the same IP address.
\r
357 Obtain the nodes IP address. Configure the freertos_sockaddr structure with
\r
358 the address being bound to. The strange casting is to try and remove
\r
359 compiler warnings on 32 bit machines. Note that this task is only created
\r
360 after the network is up, so the IP address is valid here. */
\r
361 FreeRTOS_GetAddressConfiguration( &ulIPAddress, NULL, NULL, NULL );
\r
362 xBindAddress.sin_addr = ulIPAddress;
\r
363 xBindAddress.sin_port = ( uint16_t ) ( ( uint32_t ) pvParameters ) & 0xffffUL;
\r
364 xBindAddress.sin_port = FreeRTOS_htons( xBindAddress.sin_port );
\r
366 /* Bind the socket to the port that the client task will send to. */
\r
367 FreeRTOS_bind( xListeningSocket, &xBindAddress, sizeof( xBindAddress ) );
\r
371 /* Receive data on the socket. ulFlags has the zero copy bit set
\r
372 (FREERTOS_ZERO_COPY) indicating to the stack that a reference to the
\r
373 received data should be passed out to this task using the second
\r
374 parameter to the FreeRTOS_recvfrom() call. When this is done the
\r
375 IP stack is no longer responsible for releasing the buffer, and
\r
376 the task *must* return the buffer to the stack when it is no longer
\r
377 needed. By default the block time is portMAX_DELAY. */
\r
378 lBytes = FreeRTOS_recvfrom( xListeningSocket, ( void * ) &pucUDPPayloadBuffer, 0, FREERTOS_ZERO_COPY, &xClient, &xClientLength );
\r
380 /* It is expected to receive one more byte than the string length as
\r
381 the NULL terminator is also transmitted. */
\r
382 configASSERT( lBytes == ( ( BaseType_t ) strlen( ( const char * ) pucUDPPayloadBuffer ) + 1 ) );
\r
384 /* Print the received characters. */
\r
387 vOutputString( ( char * ) pucUDPPayloadBuffer );
\r
392 /* The buffer *must* be freed once it is no longer needed. */
\r
393 FreeRTOS_ReleaseUDPPayloadBuffer( pucUDPPayloadBuffer );
\r