2 FreeRTOS V8.2.0rc1 - Copyright (C) 2014 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 >>! NOTE: The modification to the GPL is included to allow you to !<<
\r
14 >>! distribute a combined work that includes FreeRTOS without being !<<
\r
15 >>! obliged to provide the source code for proprietary components !<<
\r
16 >>! outside of the FreeRTOS kernel. !<<
\r
18 FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
\r
19 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
\r
20 FOR A PARTICULAR PURPOSE. Full license text is available on the following
\r
21 link: http://www.freertos.org/a00114.html
\r
25 ***************************************************************************
\r
27 * Having a problem? Start by reading the FAQ "My application does *
\r
28 * not run, what could be wrong?". Have you defined configASSERT()? *
\r
30 * http://www.FreeRTOS.org/FAQHelp.html *
\r
32 ***************************************************************************
\r
34 ***************************************************************************
\r
36 * FreeRTOS provides completely free yet professionally developed, *
\r
37 * robust, strictly quality controlled, supported, and cross *
\r
38 * platform software that is more than just the market leader, it *
\r
39 * is the industry's de facto standard. *
\r
41 * Help yourself get started quickly while simultaneously helping *
\r
42 * to support the FreeRTOS project by purchasing a FreeRTOS *
\r
43 * tutorial book, reference manual, or both: *
\r
44 * http://www.FreeRTOS.org/Documentation *
\r
46 ***************************************************************************
\r
48 ***************************************************************************
\r
50 * Investing in training allows your team to be as productive as *
\r
51 * possible as early as possible, lowering your overall development *
\r
52 * cost, and enabling you to bring a more robust product to market *
\r
53 * earlier than would otherwise be possible. Richard Barry is both *
\r
54 * the architect and key author of FreeRTOS, and so also the world's *
\r
55 * leading authority on what is the world's most popular real time *
\r
56 * kernel for deeply embedded MCU designs. Obtaining your training *
\r
57 * from Richard ensures your team will gain directly from his in-depth *
\r
58 * product knowledge and years of usage experience. Contact Real Time *
\r
59 * Engineers Ltd to enquire about the FreeRTOS Masterclass, presented *
\r
60 * by Richard Barry: http://www.FreeRTOS.org/contact
\r
62 ***************************************************************************
\r
64 ***************************************************************************
\r
66 * You are receiving this top quality software for free. Please play *
\r
67 * fair and reciprocate by reporting any suspected issues and *
\r
68 * participating in the community forum: *
\r
69 * http://www.FreeRTOS.org/support *
\r
73 ***************************************************************************
\r
75 http://www.FreeRTOS.org - Documentation, books, training, latest versions,
\r
76 license and Real Time Engineers Ltd. contact details.
\r
78 http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
\r
79 including FreeRTOS+Trace - an indispensable productivity tool, a DOS
\r
80 compatible FAT file system, and our tiny thread aware UDP/IP stack.
\r
82 http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
\r
83 Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
\r
85 http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
\r
86 Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
\r
87 licenses offer ticketed support, indemnification and commercial middleware.
\r
89 http://www.SafeRTOS.com - High Integrity Systems also provide a safety
\r
90 engineered and independently SIL3 certified version for use in safety and
\r
91 mission critical applications that require provable dependability.
\r
96 /* WinPCap includes. */
\r
98 #include "remote-ext.h"
\r
100 /* uIP includes. */
\r
101 #include "net/uip.h"
\r
102 #include "net/uip_arp.h"
\r
103 #include "net/clock-arch.h"
\r
105 /* FreeRTOS includes. */
\r
106 #include "FreeRTOS.h"
\r
111 * Query the computer the simulation is being executed on to find the network
\r
112 * interfaces it has installed.
\r
114 static pcap_if_t * prvPrintAvailableNetworkInterfaces( void );
\r
117 * Open the network interface. The number of the interface to be opened is set
\r
118 * by the configNETWORK_INTERFACE_TO_USE constant in FreeRTOSConfig.h.
\r
120 static void prvOpenSelectedNetworkInterface( pcap_if_t *pxAllNetworkInterfaces );
\r
123 * Configure the capture filter to allow blocking reads, and to filter out
\r
124 * packets that are not of interest to this demo.
\r
126 static void prvConfigureCaptureBehaviour( void );
\r
128 pcap_t *pxOpenedInterfaceHandle = NULL;
\r
129 LARGE_INTEGER freq, sys_start_time;
\r
131 #define archNUM_BUFFERS 5
\r
132 #define archNUM_BUFFER_POINTERS ( archNUM_BUFFERS - 1 )
\r
134 static void prvInterruptSimulator( void *pvParameters );
\r
136 static unsigned char ucEthernetBuffer[ archNUM_BUFFERS ][ UIP_CONF_BUFFER_SIZE ];
\r
137 static unsigned char *pucEthernetBufferPointers[ archNUM_BUFFER_POINTERS ];
\r
139 static long lLengthOfDataInBuffer[ archNUM_BUFFER_POINTERS ] = { 0 };
\r
140 static unsigned char ucNextBufferToFill = 0U, ucNextBufferToProcess = 0U;
\r
142 unsigned char *uip_buf = NULL;
\r
143 char cErrorBuffer[PCAP_ERRBUF_SIZE];
\r
145 void vNetifTx( void )
\r
147 pcap_sendpacket( pxOpenedInterfaceHandle, uip_buf, uip_len );
\r
148 pcap_sendpacket( pxOpenedInterfaceHandle, uip_buf, uip_len );
\r
150 /*-----------------------------------------------------------*/
\r
152 UBaseType_t uxNetifRx( void )
\r
154 UBaseType_t xDataLen;
\r
155 unsigned char *pucTemp;
\r
157 /* Check there is really data available. */
\r
158 xDataLen = lLengthOfDataInBuffer[ ucNextBufferToProcess ];
\r
159 if( xDataLen != 0L )
\r
162 /* The buffer pointed to by uip_buf is going to change. Remember which
\r
163 buffer uip_buf is currently pointing to. */
\r
166 /* Point uip_buf at the next buffer that contains data. */
\r
167 uip_buf = pucEthernetBufferPointers[ ucNextBufferToProcess ];
\r
169 /* The buffer pointed to by
\r
170 pucEthernetBufferPointeres[ ucNextBufferToProcess ] is now in use by
\r
171 uip_buf, but the buffer uip_buf was pointing to on entry to this
\r
172 function is free. Set
\r
173 pucEthernetBufferPointeres[ ucNextBufferToProcess ] to the free
\r
175 pucEthernetBufferPointers[ ucNextBufferToProcess ] = pucTemp;
\r
176 lLengthOfDataInBuffer[ ucNextBufferToProcess ] = 0L;
\r
178 ucNextBufferToProcess++;
\r
179 if( ucNextBufferToProcess >= archNUM_BUFFER_POINTERS )
\r
181 ucNextBufferToProcess = 0L;
\r
187 /*-----------------------------------------------------------*/
\r
189 BaseType_t xNetifInit( void )
\r
192 pcap_if_t *pxAllNetworkInterfaces;
\r
194 /* Allocate a free buffer to each buffer pointer. */
\r
195 for( x = 0; x < sizeof( pucEthernetBufferPointers ) / sizeof( unsigned char * ); x++ )
\r
197 pucEthernetBufferPointers[ x ] = &( ucEthernetBuffer[ x ][ 0 ] );
\r
200 /* Start with uip_buf pointing to a buffer that is not referenced from the
\r
201 pucEthernetBufferPointers[] array. */
\r
202 uip_buf = &( ucEthernetBuffer[ archNUM_BUFFERS - 1 ][ 0 ] );
\r
204 /* Query the computer the simulation is being executed on to find the
\r
205 network interfaces it has installed. */
\r
206 pxAllNetworkInterfaces = prvPrintAvailableNetworkInterfaces();
\r
208 /* Open the network interface. The number of the interface to be opened is
\r
209 set by the configNETWORK_INTERFACE_TO_USE constant in FreeRTOSConfig.h.
\r
210 Calling this function will set the pxOpenedInterfaceHandle variable. If,
\r
211 after calling this function, pxOpenedInterfaceHandle is equal to NULL, then
\r
212 the interface could not be opened. */
\r
213 if( pxAllNetworkInterfaces != NULL )
\r
215 prvOpenSelectedNetworkInterface( pxAllNetworkInterfaces );
\r
221 /*-----------------------------------------------------------*/
\r
223 static pcap_if_t * prvPrintAvailableNetworkInterfaces( void )
\r
225 pcap_if_t * pxAllNetworkInterfaces = NULL, *xInterface;
\r
226 long lInterfaceNumber = 1;
\r
228 if( pcap_findalldevs_ex( PCAP_SRC_IF_STRING, NULL, &pxAllNetworkInterfaces, cErrorBuffer ) == -1 )
\r
230 printf( "\r\nCould not obtain a list of network interfaces\r\n%s\r\n", cErrorBuffer );
\r
231 pxAllNetworkInterfaces = NULL;
\r
234 if( pxAllNetworkInterfaces != NULL )
\r
236 /* Print out the list of network interfaces. The first in the list
\r
237 is interface '1', not interface '0'. */
\r
238 for( xInterface = pxAllNetworkInterfaces; xInterface != NULL; xInterface = xInterface->next )
\r
240 printf( "%d. %s", lInterfaceNumber, xInterface->name );
\r
242 if( xInterface->description != NULL )
\r
244 printf( " (%s)\r\n", xInterface->description );
\r
248 printf( " (No description available)\r\n") ;
\r
251 lInterfaceNumber++;
\r
255 if( lInterfaceNumber == 1 )
\r
257 /* The interface number was never incremented, so the above for() loop
\r
258 did not execute meaning no interfaces were found. */
\r
259 printf( " \r\nNo network interfaces were found.\r\n" );
\r
260 pxAllNetworkInterfaces = NULL;
\r
263 printf( "\r\nThe interface that will be opened is set by configNETWORK_INTERFACE_TO_USE which should be defined in FreeRTOSConfig.h\r\n" );
\r
264 printf( "Attempting to open interface number %d.\r\n", configNETWORK_INTERFACE_TO_USE );
\r
266 if( ( configNETWORK_INTERFACE_TO_USE < 1L ) || ( configNETWORK_INTERFACE_TO_USE > lInterfaceNumber ) )
\r
268 printf("\r\nconfigNETWORK_INTERFACE_TO_USE is not in the valid range.\r\n" );
\r
270 if( pxAllNetworkInterfaces != NULL )
\r
272 /* Free the device list, as no devices are going to be opened. */
\r
273 pcap_freealldevs( pxAllNetworkInterfaces );
\r
274 pxAllNetworkInterfaces = NULL;
\r
278 return pxAllNetworkInterfaces;
\r
280 /*-----------------------------------------------------------*/
\r
282 static void prvOpenSelectedNetworkInterface( pcap_if_t *pxAllNetworkInterfaces )
\r
284 pcap_if_t *xInterface;
\r
287 /* Walk the list of devices until the selected device is located. */
\r
288 xInterface = pxAllNetworkInterfaces;
\r
289 for( x = 0L; x < ( configNETWORK_INTERFACE_TO_USE - 1L ); x++ )
\r
291 xInterface = xInterface->next;
\r
294 /* Open the selected interface. */
\r
295 pxOpenedInterfaceHandle = pcap_open( xInterface->name, /* The name of the selected interface. */
\r
296 UIP_CONF_BUFFER_SIZE, /* The size of the packet to capture. */
\r
297 PCAP_OPENFLAG_PROMISCUOUS, /* Open in promiscious mode as the MAC and
\r
298 IP address is going to be "simulated", and
\r
299 not be the real MAC and IP address. This allows
\r
300 trafic to the simulated IP address to be routed
\r
301 to uIP, and trafic to the real IP address to be
\r
302 routed to the Windows TCP/IP stack. */
\r
303 0xfffffffL, /* The read time out. This is going to block
\r
304 until data is available. */
\r
305 NULL, /* No authentication is required as this is
\r
306 not a remote capture session. */
\r
310 if ( pxOpenedInterfaceHandle == NULL )
\r
312 printf( "\r\n%s is not supported by WinPcap and cannot be opened\r\n", xInterface->name );
\r
316 /* Configure the capture filter to allow blocking reads, and to filter
\r
317 out packets that are not of interest to this demo. */
\r
318 prvConfigureCaptureBehaviour();
\r
321 /* The device list is no longer required. */
\r
322 pcap_freealldevs( pxAllNetworkInterfaces );
\r
324 /*-----------------------------------------------------------*/
\r
326 static void prvConfigureCaptureBehaviour( void )
\r
328 struct bpf_program xFilterCode;
\r
329 const long lMinBytesToCopy = 10L, lBlocking = 0L;
\r
330 unsigned long ulNetMask;
\r
332 /* Unblock a read as soon as anything is received. */
\r
333 pcap_setmintocopy( pxOpenedInterfaceHandle, lMinBytesToCopy );
\r
335 /* Allow blocking. */
\r
336 pcap_setnonblock( pxOpenedInterfaceHandle, lBlocking, cErrorBuffer );
\r
338 /* Set up a filter so only the packets of interest are passed to the uIP
\r
339 stack. cErrorBuffer is used for convenience to create the string. Don't
\r
340 confuse this with an error message. */
\r
341 sprintf( cErrorBuffer, "broadcast or multicast or host %d.%d.%d.%d", configIP_ADDR0, configIP_ADDR1, configIP_ADDR2, configIP_ADDR3 );
\r
343 ulNetMask = ( configNET_MASK3 << 24UL ) | ( configNET_MASK2 << 16UL ) | ( configNET_MASK1 << 8L ) | configNET_MASK0;
\r
345 if( pcap_compile(pxOpenedInterfaceHandle, &xFilterCode, cErrorBuffer, 1, ulNetMask ) < 0 )
\r
347 printf("\r\nThe packet filter string is invalid\r\n" );
\r
351 if( pcap_setfilter( pxOpenedInterfaceHandle, &xFilterCode ) < 0 )
\r
353 printf( "\r\nAn error occurred setting the packet filter.\r\n" );
\r
357 /* Create a task that simulates an interrupt in a real system. This will
\r
358 block waiting for packets, then send a message to the uIP task when data
\r
360 xTaskCreate( prvInterruptSimulator, "MAC_ISR", configMINIMAL_STACK_SIZE, NULL, ( configuIP_TASK_PRIORITY - 1 ), NULL );
\r
362 /*-----------------------------------------------------------*/
\r
364 static void prvInterruptSimulator( void *pvParameters )
\r
366 static struct pcap_pkthdr *pxHeader;
\r
367 const unsigned char *pucPacketData;
\r
368 extern xQueueHandle xEMACEventQueue;
\r
369 const unsigned long ulRxEvent = uipETHERNET_RX_EVENT;
\r
372 /* Just to kill the compiler warning. */
\r
373 ( void ) pvParameters;
\r
377 /* Get the next packet. */
\r
378 lResult = pcap_next_ex( pxOpenedInterfaceHandle, &pxHeader, &pucPacketData );
\r
381 /* Is the next buffer into which data should be placed free? */
\r
382 if( lLengthOfDataInBuffer[ ucNextBufferToFill ] == 0L )
\r
384 /* Copy the data from the captured packet into the buffer. */
\r
385 memcpy( pucEthernetBufferPointers[ ucNextBufferToFill ], pucPacketData, pxHeader->len );
\r
387 /* Note the amount of data that was copied. */
\r
388 lLengthOfDataInBuffer[ ucNextBufferToFill ] = pxHeader->len;
\r
390 /* Move onto the next buffer, wrapping around if necessary. */
\r
391 ucNextBufferToFill++;
\r
392 if( ucNextBufferToFill >= archNUM_BUFFER_POINTERS )
\r
394 ucNextBufferToFill = 0U;
\r
397 /* Data was received and stored. Send a message to the uIP task
\r
399 xQueueSendToBack( xEMACEventQueue, &ulRxEvent, portMAX_DELAY );
\r