2 FreeRTOS V9.0.0rc1 - 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
70 /* WinPCap includes. */
\r
72 #include "remote-ext.h"
\r
75 #include "net/uip.h"
\r
76 #include "net/uip_arp.h"
\r
77 #include "net/clock-arch.h"
\r
79 /* FreeRTOS includes. */
\r
80 #include "FreeRTOS.h"
\r
85 * Query the computer the simulation is being executed on to find the network
\r
86 * interfaces it has installed.
\r
88 static pcap_if_t * prvPrintAvailableNetworkInterfaces( void );
\r
91 * Open the network interface. The number of the interface to be opened is set
\r
92 * by the configNETWORK_INTERFACE_TO_USE constant in FreeRTOSConfig.h.
\r
94 static void prvOpenSelectedNetworkInterface( pcap_if_t *pxAllNetworkInterfaces );
\r
97 * Configure the capture filter to allow blocking reads, and to filter out
\r
98 * packets that are not of interest to this demo.
\r
100 static void prvConfigureCaptureBehaviour( void );
\r
102 pcap_t *pxOpenedInterfaceHandle = NULL;
\r
103 LARGE_INTEGER freq, sys_start_time;
\r
105 #define archNUM_BUFFERS 5
\r
106 #define archNUM_BUFFER_POINTERS ( archNUM_BUFFERS - 1 )
\r
108 static void prvInterruptSimulator( void *pvParameters );
\r
110 static unsigned char ucEthernetBuffer[ archNUM_BUFFERS ][ UIP_CONF_BUFFER_SIZE ];
\r
111 static unsigned char *pucEthernetBufferPointers[ archNUM_BUFFER_POINTERS ];
\r
113 static long lLengthOfDataInBuffer[ archNUM_BUFFER_POINTERS ] = { 0 };
\r
114 static unsigned char ucNextBufferToFill = 0U, ucNextBufferToProcess = 0U;
\r
116 unsigned char *uip_buf = NULL;
\r
117 char cErrorBuffer[PCAP_ERRBUF_SIZE];
\r
119 void vNetifTx( void )
\r
121 pcap_sendpacket( pxOpenedInterfaceHandle, uip_buf, uip_len );
\r
122 pcap_sendpacket( pxOpenedInterfaceHandle, uip_buf, uip_len );
\r
124 /*-----------------------------------------------------------*/
\r
126 UBaseType_t uxNetifRx( void )
\r
128 UBaseType_t xDataLen;
\r
129 unsigned char *pucTemp;
\r
131 /* Check there is really data available. */
\r
132 xDataLen = lLengthOfDataInBuffer[ ucNextBufferToProcess ];
\r
133 if( xDataLen != 0L )
\r
136 /* The buffer pointed to by uip_buf is going to change. Remember which
\r
137 buffer uip_buf is currently pointing to. */
\r
140 /* Point uip_buf at the next buffer that contains data. */
\r
141 uip_buf = pucEthernetBufferPointers[ ucNextBufferToProcess ];
\r
143 /* The buffer pointed to by
\r
144 pucEthernetBufferPointeres[ ucNextBufferToProcess ] is now in use by
\r
145 uip_buf, but the buffer uip_buf was pointing to on entry to this
\r
146 function is free. Set
\r
147 pucEthernetBufferPointeres[ ucNextBufferToProcess ] to the free
\r
149 pucEthernetBufferPointers[ ucNextBufferToProcess ] = pucTemp;
\r
150 lLengthOfDataInBuffer[ ucNextBufferToProcess ] = 0L;
\r
152 ucNextBufferToProcess++;
\r
153 if( ucNextBufferToProcess >= archNUM_BUFFER_POINTERS )
\r
155 ucNextBufferToProcess = 0L;
\r
161 /*-----------------------------------------------------------*/
\r
163 BaseType_t xNetifInit( void )
\r
166 pcap_if_t *pxAllNetworkInterfaces;
\r
168 /* Allocate a free buffer to each buffer pointer. */
\r
169 for( x = 0; x < sizeof( pucEthernetBufferPointers ) / sizeof( unsigned char * ); x++ )
\r
171 pucEthernetBufferPointers[ x ] = &( ucEthernetBuffer[ x ][ 0 ] );
\r
174 /* Start with uip_buf pointing to a buffer that is not referenced from the
\r
175 pucEthernetBufferPointers[] array. */
\r
176 uip_buf = &( ucEthernetBuffer[ archNUM_BUFFERS - 1 ][ 0 ] );
\r
178 /* Query the computer the simulation is being executed on to find the
\r
179 network interfaces it has installed. */
\r
180 pxAllNetworkInterfaces = prvPrintAvailableNetworkInterfaces();
\r
182 /* Open the network interface. The number of the interface to be opened is
\r
183 set by the configNETWORK_INTERFACE_TO_USE constant in FreeRTOSConfig.h.
\r
184 Calling this function will set the pxOpenedInterfaceHandle variable. If,
\r
185 after calling this function, pxOpenedInterfaceHandle is equal to NULL, then
\r
186 the interface could not be opened. */
\r
187 if( pxAllNetworkInterfaces != NULL )
\r
189 prvOpenSelectedNetworkInterface( pxAllNetworkInterfaces );
\r
195 /*-----------------------------------------------------------*/
\r
197 static pcap_if_t * prvPrintAvailableNetworkInterfaces( void )
\r
199 pcap_if_t * pxAllNetworkInterfaces = NULL, *xInterface;
\r
200 long lInterfaceNumber = 1;
\r
202 if( pcap_findalldevs_ex( PCAP_SRC_IF_STRING, NULL, &pxAllNetworkInterfaces, cErrorBuffer ) == -1 )
\r
204 printf( "\r\nCould not obtain a list of network interfaces\r\n%s\r\n", cErrorBuffer );
\r
205 pxAllNetworkInterfaces = NULL;
\r
208 if( pxAllNetworkInterfaces != NULL )
\r
210 /* Print out the list of network interfaces. The first in the list
\r
211 is interface '1', not interface '0'. */
\r
212 for( xInterface = pxAllNetworkInterfaces; xInterface != NULL; xInterface = xInterface->next )
\r
214 printf( "%d. %s", lInterfaceNumber, xInterface->name );
\r
216 if( xInterface->description != NULL )
\r
218 printf( " (%s)\r\n", xInterface->description );
\r
222 printf( " (No description available)\r\n") ;
\r
225 lInterfaceNumber++;
\r
229 if( lInterfaceNumber == 1 )
\r
231 /* The interface number was never incremented, so the above for() loop
\r
232 did not execute meaning no interfaces were found. */
\r
233 printf( " \r\nNo network interfaces were found.\r\n" );
\r
234 pxAllNetworkInterfaces = NULL;
\r
237 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
238 printf( "Attempting to open interface number %d.\r\n", configNETWORK_INTERFACE_TO_USE );
\r
240 if( ( configNETWORK_INTERFACE_TO_USE < 1L ) || ( configNETWORK_INTERFACE_TO_USE > lInterfaceNumber ) )
\r
242 printf("\r\nconfigNETWORK_INTERFACE_TO_USE is not in the valid range.\r\n" );
\r
244 if( pxAllNetworkInterfaces != NULL )
\r
246 /* Free the device list, as no devices are going to be opened. */
\r
247 pcap_freealldevs( pxAllNetworkInterfaces );
\r
248 pxAllNetworkInterfaces = NULL;
\r
252 return pxAllNetworkInterfaces;
\r
254 /*-----------------------------------------------------------*/
\r
256 static void prvOpenSelectedNetworkInterface( pcap_if_t *pxAllNetworkInterfaces )
\r
258 pcap_if_t *xInterface;
\r
261 /* Walk the list of devices until the selected device is located. */
\r
262 xInterface = pxAllNetworkInterfaces;
\r
263 for( x = 0L; x < ( configNETWORK_INTERFACE_TO_USE - 1L ); x++ )
\r
265 xInterface = xInterface->next;
\r
268 /* Open the selected interface. */
\r
269 pxOpenedInterfaceHandle = pcap_open( xInterface->name, /* The name of the selected interface. */
\r
270 UIP_CONF_BUFFER_SIZE, /* The size of the packet to capture. */
\r
271 PCAP_OPENFLAG_PROMISCUOUS, /* Open in promiscious mode as the MAC and
\r
272 IP address is going to be "simulated", and
\r
273 not be the real MAC and IP address. This allows
\r
274 trafic to the simulated IP address to be routed
\r
275 to uIP, and trafic to the real IP address to be
\r
276 routed to the Windows TCP/IP stack. */
\r
277 0xfffffffL, /* The read time out. This is going to block
\r
278 until data is available. */
\r
279 NULL, /* No authentication is required as this is
\r
280 not a remote capture session. */
\r
284 if ( pxOpenedInterfaceHandle == NULL )
\r
286 printf( "\r\n%s is not supported by WinPcap and cannot be opened\r\n", xInterface->name );
\r
290 /* Configure the capture filter to allow blocking reads, and to filter
\r
291 out packets that are not of interest to this demo. */
\r
292 prvConfigureCaptureBehaviour();
\r
295 /* The device list is no longer required. */
\r
296 pcap_freealldevs( pxAllNetworkInterfaces );
\r
298 /*-----------------------------------------------------------*/
\r
300 static void prvConfigureCaptureBehaviour( void )
\r
302 struct bpf_program xFilterCode;
\r
303 const long lMinBytesToCopy = 10L, lBlocking = 0L;
\r
304 unsigned long ulNetMask;
\r
306 /* Unblock a read as soon as anything is received. */
\r
307 pcap_setmintocopy( pxOpenedInterfaceHandle, lMinBytesToCopy );
\r
309 /* Allow blocking. */
\r
310 pcap_setnonblock( pxOpenedInterfaceHandle, lBlocking, cErrorBuffer );
\r
312 /* Set up a filter so only the packets of interest are passed to the uIP
\r
313 stack. cErrorBuffer is used for convenience to create the string. Don't
\r
314 confuse this with an error message. */
\r
315 sprintf( cErrorBuffer, "broadcast or multicast or host %d.%d.%d.%d", configIP_ADDR0, configIP_ADDR1, configIP_ADDR2, configIP_ADDR3 );
\r
317 ulNetMask = ( configNET_MASK3 << 24UL ) | ( configNET_MASK2 << 16UL ) | ( configNET_MASK1 << 8L ) | configNET_MASK0;
\r
319 if( pcap_compile(pxOpenedInterfaceHandle, &xFilterCode, cErrorBuffer, 1, ulNetMask ) < 0 )
\r
321 printf("\r\nThe packet filter string is invalid\r\n" );
\r
325 if( pcap_setfilter( pxOpenedInterfaceHandle, &xFilterCode ) < 0 )
\r
327 printf( "\r\nAn error occurred setting the packet filter.\r\n" );
\r
331 /* Create a task that simulates an interrupt in a real system. This will
\r
332 block waiting for packets, then send a message to the uIP task when data
\r
334 xTaskCreate( prvInterruptSimulator, "MAC_ISR", configMINIMAL_STACK_SIZE, NULL, ( configuIP_TASK_PRIORITY - 1 ), NULL );
\r
336 /*-----------------------------------------------------------*/
\r
338 static void prvInterruptSimulator( void *pvParameters )
\r
340 static struct pcap_pkthdr *pxHeader;
\r
341 const unsigned char *pucPacketData;
\r
342 extern xQueueHandle xEMACEventQueue;
\r
343 const unsigned long ulRxEvent = uipETHERNET_RX_EVENT;
\r
346 /* Just to kill the compiler warning. */
\r
347 ( void ) pvParameters;
\r
351 /* Get the next packet. */
\r
352 lResult = pcap_next_ex( pxOpenedInterfaceHandle, &pxHeader, &pucPacketData );
\r
355 /* Is the next buffer into which data should be placed free? */
\r
356 if( lLengthOfDataInBuffer[ ucNextBufferToFill ] == 0L )
\r
358 /* Copy the data from the captured packet into the buffer. */
\r
359 memcpy( pucEthernetBufferPointers[ ucNextBufferToFill ], pucPacketData, pxHeader->len );
\r
361 /* Note the amount of data that was copied. */
\r
362 lLengthOfDataInBuffer[ ucNextBufferToFill ] = pxHeader->len;
\r
364 /* Move onto the next buffer, wrapping around if necessary. */
\r
365 ucNextBufferToFill++;
\r
366 if( ucNextBufferToFill >= archNUM_BUFFER_POINTERS )
\r
368 ucNextBufferToFill = 0U;
\r
371 /* Data was received and stored. Send a message to the uIP task
\r
373 xQueueSendToBack( xEMACEventQueue, &ulRxEvent, portMAX_DELAY );
\r