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
76 /* Standard includes. */
\r
80 /* FreeRTOS includes. */
\r
81 #include "FreeRTOS.h"
\r
84 /* FreeRTOS+UDP includes. */
\r
85 #include "FreeRTOS_UDP_IP.h"
\r
86 #include "FreeRTOS_Sockets.h"
\r
88 #define simpTINY_DELAY ( ( TickType_t ) 2 )
\r
91 * Uses a socket to send data without using the zero copy option.
\r
92 * prvSimpleServerTask() will receive the data.
\r
94 static void prvSimpleClientTask( void *pvParameters );
\r
97 * Uses a socket to receive the data sent by the prvSimpleClientTask() task.
\r
98 * Does not use the zero copy option.
\r
100 static void prvSimpleServerTask( void *pvParameters );
\r
103 * Uses a socket to send data using the zero copy option.
\r
104 * prvSimpleZeroCopyServerTask() will receive the data.
\r
106 static void prvSimpleZeroCopyUDPClientTask( void *pvParameters );
\r
109 * Uses a socket to receive the data sent by the prvSimpleZeroCopyUDPClientTask()
\r
110 * task. Uses the zero copy option.
\r
112 static void prvSimpleZeroCopyServerTask( void *pvParameters );
\r
114 /*-----------------------------------------------------------*/
\r
116 void vStartSimpleUDPClientServerTasks( uint16_t usStackSize, uint32_t ulPort, UBaseType_t uxPriority )
\r
118 /* Create the client and server tasks that do not use the zero copy
\r
120 xTaskCreate( prvSimpleClientTask, "SimpCpyClnt", usStackSize, ( void * ) ulPort, uxPriority, NULL );
\r
121 xTaskCreate( prvSimpleServerTask, "SimpCpySrv", usStackSize, ( void * ) ulPort, uxPriority + 1, NULL );
\r
123 /* Create the client and server tasks that do use the zero copy interface. */
\r
124 xTaskCreate( prvSimpleZeroCopyUDPClientTask, "SimpZCpyClnt", usStackSize, ( void * ) ( ulPort + 1 ), uxPriority, NULL );
\r
125 xTaskCreate( prvSimpleZeroCopyServerTask, "SimpZCpySrv", usStackSize, ( void * ) ( ulPort + 1 ), uxPriority + 1, NULL );
\r
127 /*-----------------------------------------------------------*/
\r
129 static void prvSimpleClientTask( void *pvParameters )
\r
131 xSocket_t xClientSocket;
\r
132 struct freertos_sockaddr xDestinationAddress;
\r
133 char cString[ 50 ];
\r
134 BaseType_t lReturned;
\r
135 uint32_t ulCount = 0UL, ulIPAddress;
\r
136 const uint32_t ulLoopsPerSocket = 10UL;
\r
137 const TickType_t x150ms = 150UL / portTICK_RATE_MS;
\r
139 /* Remove compiler warning about unused parameters. */
\r
140 ( void ) pvParameters;
\r
142 /* It is assumed that this task is not created until the network is up,
\r
143 so the IP address can be obtained immediately. store the IP address being
\r
144 used in ulIPAddress. This is done so the socket can send to a different
\r
145 port on the same IP address. */
\r
146 FreeRTOS_GetAddressConfiguration( &ulIPAddress, NULL, NULL, NULL );
\r
148 /* This test sends to itself, so data sent from here is received by a server
\r
149 socket on the same IP address. Setup the freertos_sockaddr structure with
\r
150 this nodes IP address, and the port number being sent to. The strange
\r
151 casting is to try and remove compiler warnings on 32 bit machines. */
\r
152 xDestinationAddress.sin_addr = ulIPAddress;
\r
153 xDestinationAddress.sin_port = ( uint16_t ) ( ( uint32_t ) pvParameters ) & 0xffffUL;
\r
154 xDestinationAddress.sin_port = FreeRTOS_htons( xDestinationAddress.sin_port );
\r
158 /* Create the socket. */
\r
159 xClientSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
\r
160 configASSERT( xClientSocket != FREERTOS_INVALID_SOCKET );
\r
162 /* The count is used to differentiate between different messages sent to
\r
163 the server, and to break out of the do while loop below. */
\r
168 /* Create the string that is sent to the server. */
\r
169 sprintf( cString, "Server received (not zero copy): Message number %lu\r\n", ulCount );
\r
171 /* Send the string to the socket. ulFlags is set to 0, so the zero
\r
172 copy option is not selected. That means the data from cString[] is
\r
173 copied into a network buffer inside FreeRTOS_sendto(), and cString[]
\r
174 can be reused as soon as FreeRTOS_sendto() has returned. */
\r
175 lReturned = FreeRTOS_sendto( xClientSocket, ( void * ) cString, strlen( cString ), 0, &xDestinationAddress, sizeof( xDestinationAddress ) );
\r
179 } while( ( lReturned != FREERTOS_SOCKET_ERROR ) && ( ulCount < ulLoopsPerSocket ) );
\r
181 FreeRTOS_closesocket( xClientSocket );
\r
183 /* A short delay to prevent the messages printed by the server task
\r
184 scrolling off the screen too quickly, and to prevent reduce the network
\r
186 vTaskDelay( x150ms );
\r
189 /*-----------------------------------------------------------*/
\r
191 static void prvSimpleServerTask( void *pvParameters )
\r
194 char cReceivedString[ 60 ];
\r
195 struct freertos_sockaddr xClient, xBindAddress;
\r
196 uint32_t xClientLength = sizeof( xClient );
\r
197 xSocket_t xListeningSocket;
\r
199 /* Just to prevent compiler warnings. */
\r
200 ( void ) pvParameters;
\r
202 /* Attempt to open the socket. */
\r
203 xListeningSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
\r
204 configASSERT( xListeningSocket != FREERTOS_INVALID_SOCKET );
\r
206 /* This test receives data sent from a different port on the same IP
\r
207 address. Configure the freertos_sockaddr structure with the address being
\r
208 bound to. The strange casting is to try and remove compiler warnings on 32
\r
209 bit machines. Note that this task is only created after the network is up,
\r
210 so the IP address is valid here. */
\r
211 xBindAddress.sin_port = ( uint16_t ) ( ( uint32_t ) pvParameters ) & 0xffffUL;
\r
212 xBindAddress.sin_port = FreeRTOS_htons( xBindAddress.sin_port );
\r
214 /* Bind the socket to the port that the client task will send to. */
\r
215 FreeRTOS_bind( xListeningSocket, &xBindAddress, sizeof( xBindAddress ) );
\r
219 /* Zero out the receive array so there is NULL at the end of the string
\r
220 when it is printed out. */
\r
221 memset( cReceivedString, 0x00, sizeof( cReceivedString ) );
\r
223 /* Receive data on the socket. ulFlags is zero, so the zero copy option
\r
224 is not set and the received data is copied into the buffer pointed to by
\r
225 cReceivedString. By default the block time is portMAX_DELAY.
\r
226 xClientLength is not actually used by FreeRTOS_recvfrom(), but is set
\r
227 appropriately in case future versions do use it. */
\r
228 lBytes = FreeRTOS_recvfrom( xListeningSocket, cReceivedString, sizeof( cReceivedString ), 0, &xClient, &xClientLength );
\r
230 /* Print the received characters. */
\r
233 vOutputString( cReceivedString );
\r
237 configASSERT( lBytes == ( BaseType_t ) strlen( cReceivedString ) );
\r
240 /*-----------------------------------------------------------*/
\r
242 static void prvSimpleZeroCopyUDPClientTask( void *pvParameters )
\r
244 xSocket_t xClientSocket;
\r
245 uint8_t *pucUDPPayloadBuffer;
\r
246 struct freertos_sockaddr xDestinationAddress;
\r
247 BaseType_t lReturned;
\r
248 uint32_t ulCount = 0UL, ulIPAddress;
\r
249 const uint32_t ulLoopsPerSocket = 10UL;
\r
250 const char *pcStringToSend = "Server received (using zero copy): Message number ";
\r
251 const TickType_t x150ms = 150UL / portTICK_RATE_MS;
\r
252 /* 15 is added to ensure the number, \r\n and terminating zero fit. */
\r
253 const size_t xStringLength = strlen( pcStringToSend ) + 15;
\r
255 /* Remove compiler warning about unused parameters. */
\r
256 ( void ) pvParameters;
\r
258 /* It is assumed that this task is not created until the network is up,
\r
259 so the IP address can be obtained immediately. store the IP address being
\r
260 used in ulIPAddress. This is done so the socket can send to a different
\r
261 port on the same IP address. */
\r
262 FreeRTOS_GetAddressConfiguration( &ulIPAddress, NULL, NULL, NULL );
\r
264 /* This test sends to itself, so data sent from here is received by a server
\r
265 socket on the same IP address. Setup the freertos_sockaddr structure with
\r
266 this nodes IP address, and the port number being sent to. The strange
\r
267 casting is to try and remove compiler warnings on 32 bit machines. */
\r
268 xDestinationAddress.sin_addr = ulIPAddress;
\r
269 xDestinationAddress.sin_port = ( uint16_t ) ( ( uint32_t ) pvParameters ) & 0xffffUL;
\r
270 xDestinationAddress.sin_port = FreeRTOS_htons( xDestinationAddress.sin_port );
\r
274 /* Create the socket. */
\r
275 xClientSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
\r
276 configASSERT( xClientSocket != FREERTOS_INVALID_SOCKET );
\r
278 /* The count is used to differentiate between different messages sent to
\r
279 the server, and to break out of the do while loop below. */
\r
284 /* This task is going to send using the zero copy interface. The
\r
285 data being sent is therefore written directly into a buffer that is
\r
286 passed into, rather than copied into, the FreeRTOS_sendto()
\r
289 First obtain a buffer of adequate length from the IP stack into which
\r
290 the string will be written. Although a max delay is used, the actual
\r
291 delay will be capped to ipconfigMAX_SEND_BLOCK_TIME_TICKS, hence
\r
292 the do while loop is used to ensure a buffer is obtained. */
\r
295 } while( ( pucUDPPayloadBuffer = ( uint8_t * ) FreeRTOS_GetUDPPayloadBuffer( xStringLength, portMAX_DELAY ) ) == NULL );
\r
297 /* A buffer was successfully obtained. Create the string that is
\r
298 sent to the server. First the string is filled with zeros as this will
\r
299 effectively be the null terminator when the string is received at the other
\r
300 end. Note that the string is being written directly into the buffer
\r
301 obtained from the IP stack above. */
\r
302 memset( ( void * ) pucUDPPayloadBuffer, 0x00, xStringLength );
\r
303 sprintf( ( char * ) pucUDPPayloadBuffer, "%s%lu\r\n", pcStringToSend, ulCount );
\r
305 /* Pass the buffer into the send function. ulFlags has the
\r
306 FREERTOS_ZERO_COPY bit set so the IP stack will take control of the
\r
307 buffer rather than copy data out of the buffer. */
\r
308 lReturned = FreeRTOS_sendto( xClientSocket, /* The socket being sent to. */
\r
309 ( void * ) pucUDPPayloadBuffer, /* A pointer to the the data being sent. */
\r
310 strlen( ( const char * ) pucUDPPayloadBuffer ) + 1, /* The length of the data being sent - including the string's null terminator. */
\r
311 FREERTOS_ZERO_COPY, /* ulFlags with the FREERTOS_ZERO_COPY bit set. */
\r
312 &xDestinationAddress, /* Where the data is being sent. */
\r
313 sizeof( xDestinationAddress ) );
\r
315 if( lReturned == 0 )
\r
317 /* The send operation failed, so this task is still responsible
\r
318 for the buffer obtained from the IP stack. To ensure the buffer
\r
319 is not lost it must either be used again, or, as in this case,
\r
320 returned to the IP stack using FreeRTOS_ReleaseUDPPayloadBuffer().
\r
321 pucUDPPayloadBuffer can be safely re-used after this call. */
\r
322 FreeRTOS_ReleaseUDPPayloadBuffer( ( void * ) pucUDPPayloadBuffer );
\r
326 /* The send was successful so the IP stack is now managing the
\r
327 buffer pointed to by pucUDPPayloadBuffer, and the IP stack will
\r
328 return the buffer once it has been sent. pucUDPPayloadBuffer can
\r
329 be safely re-used. */
\r
334 } while( ( lReturned != FREERTOS_SOCKET_ERROR ) && ( ulCount < ulLoopsPerSocket ) );
\r
336 FreeRTOS_closesocket( xClientSocket );
\r
338 /* A short delay to prevent the messages scrolling off the screen too
\r
340 vTaskDelay( x150ms );
\r
343 /*-----------------------------------------------------------*/
\r
345 static void prvSimpleZeroCopyServerTask( void *pvParameters )
\r
348 uint8_t *pucUDPPayloadBuffer;
\r
349 struct freertos_sockaddr xClient, xBindAddress;
\r
350 uint32_t xClientLength = sizeof( xClient ), ulIPAddress;
\r
351 xSocket_t xListeningSocket;
\r
353 /* Just to prevent compiler warnings. */
\r
354 ( void ) pvParameters;
\r
356 /* Attempt to open the socket. */
\r
357 xListeningSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
\r
358 configASSERT( xListeningSocket != FREERTOS_INVALID_SOCKET );
\r
360 /* This test receives data sent from a different port on the same IP address.
\r
361 Obtain the nodes IP address. Configure the freertos_sockaddr structure with
\r
362 the address being bound to. The strange casting is to try and remove
\r
363 compiler warnings on 32 bit machines. Note that this task is only created
\r
364 after the network is up, so the IP address is valid here. */
\r
365 FreeRTOS_GetAddressConfiguration( &ulIPAddress, NULL, NULL, NULL );
\r
366 xBindAddress.sin_addr = ulIPAddress;
\r
367 xBindAddress.sin_port = ( uint16_t ) ( ( uint32_t ) pvParameters ) & 0xffffUL;
\r
368 xBindAddress.sin_port = FreeRTOS_htons( xBindAddress.sin_port );
\r
370 /* Bind the socket to the port that the client task will send to. */
\r
371 FreeRTOS_bind( xListeningSocket, &xBindAddress, sizeof( xBindAddress ) );
\r
375 /* Receive data on the socket. ulFlags has the zero copy bit set
\r
376 (FREERTOS_ZERO_COPY) indicating to the stack that a reference to the
\r
377 received data should be passed out to this task using the second
\r
378 parameter to the FreeRTOS_recvfrom() call. When this is done the
\r
379 IP stack is no longer responsible for releasing the buffer, and
\r
380 the task *must* return the buffer to the stack when it is no longer
\r
381 needed. By default the block time is portMAX_DELAY. */
\r
382 lBytes = FreeRTOS_recvfrom( xListeningSocket, ( void * ) &pucUDPPayloadBuffer, 0, FREERTOS_ZERO_COPY, &xClient, &xClientLength );
\r
384 /* It is expected to receive one more byte than the string length as
\r
385 the NULL terminator is also transmitted. */
\r
386 configASSERT( lBytes == ( ( BaseType_t ) strlen( ( const char * ) pucUDPPayloadBuffer ) + 1 ) );
\r
388 /* Print the received characters. */
\r
391 vOutputString( ( char * ) pucUDPPayloadBuffer );
\r
396 /* The buffer *must* be freed once it is no longer needed. */
\r
397 FreeRTOS_ReleaseUDPPayloadBuffer( pucUDPPayloadBuffer );
\r