2 FreeRTOS V7.5.0 - Copyright (C) 2013 Real Time Engineers Ltd.
\r
4 VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
\r
6 ***************************************************************************
\r
8 * FreeRTOS provides completely free yet professionally developed, *
\r
9 * robust, strictly quality controlled, supported, and cross *
\r
10 * platform software that has become a de facto standard. *
\r
12 * Help yourself get started quickly and support the FreeRTOS *
\r
13 * project by purchasing a FreeRTOS tutorial book, reference *
\r
14 * manual, or both from: http://www.FreeRTOS.org/Documentation *
\r
18 ***************************************************************************
\r
20 This file is part of the FreeRTOS distribution.
\r
22 FreeRTOS is free software; you can redistribute it and/or modify it under
\r
23 the terms of the GNU General Public License (version 2) as published by the
\r
24 Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
\r
26 >>! NOTE: The modification to the GPL is included to allow you to distribute
\r
27 >>! a combined work that includes FreeRTOS without being obliged to provide
\r
28 >>! the source code for proprietary components outside of the FreeRTOS
\r
31 FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
\r
32 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
\r
33 FOR A PARTICULAR PURPOSE. Full license text is available from the following
\r
34 link: http://www.freertos.org/a00114.html
\r
38 ***************************************************************************
\r
40 * Having a problem? Start by reading the FAQ "My application does *
\r
41 * not run, what could be wrong?" *
\r
43 * http://www.FreeRTOS.org/FAQHelp.html *
\r
45 ***************************************************************************
\r
47 http://www.FreeRTOS.org - Documentation, books, training, latest versions,
\r
48 license and Real Time Engineers Ltd. contact details.
\r
50 http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
\r
51 including FreeRTOS+Trace - an indispensable productivity tool, a DOS
\r
52 compatible FAT file system, and our tiny thread aware UDP/IP stack.
\r
54 http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
\r
55 Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
\r
56 licenses offer ticketed support, indemnification and middleware.
\r
58 http://www.SafeRTOS.com - High Integrity Systems also provide a safety
\r
59 engineered and independently SIL3 certified version for use in safety and
\r
60 mission critical applications that require provable dependability.
\r
65 /* WinPCap includes. */
\r
67 #include "remote-ext.h"
\r
70 #include "net/uip.h"
\r
71 #include "net/uip_arp.h"
\r
72 #include "net/clock-arch.h"
\r
74 /* FreeRTOS includes. */
\r
75 #include "FreeRTOS.h"
\r
80 * Query the computer the simulation is being executed on to find the network
\r
81 * interfaces it has installed.
\r
83 static pcap_if_t * prvPrintAvailableNetworkInterfaces( void );
\r
86 * Open the network interface. The number of the interface to be opened is set
\r
87 * by the configNETWORK_INTERFACE_TO_USE constant in FreeRTOSConfig.h.
\r
89 static void prvOpenSelectedNetworkInterface( pcap_if_t *pxAllNetworkInterfaces );
\r
92 * Configure the capture filter to allow blocking reads, and to filter out
\r
93 * packets that are not of interest to this demo.
\r
95 static void prvConfigureCaptureBehaviour( void );
\r
97 pcap_t *pxOpenedInterfaceHandle = NULL;
\r
98 LARGE_INTEGER freq, sys_start_time;
\r
100 #define archNUM_BUFFERS 5
\r
101 #define archNUM_BUFFER_POINTERS ( archNUM_BUFFERS - 1 )
\r
103 static void prvInterruptSimulator( void *pvParameters );
\r
105 static unsigned char ucEthernetBuffer[ archNUM_BUFFERS ][ UIP_CONF_BUFFER_SIZE ];
\r
106 static unsigned char *pucEthernetBufferPointers[ archNUM_BUFFER_POINTERS ];
\r
108 static long lLengthOfDataInBuffer[ archNUM_BUFFER_POINTERS ] = { 0 };
\r
109 static unsigned char ucNextBufferToFill = 0U, ucNextBufferToProcess = 0U;
\r
111 unsigned char *uip_buf = NULL;
\r
112 char cErrorBuffer[PCAP_ERRBUF_SIZE];
\r
114 void vNetifTx( void )
\r
116 pcap_sendpacket( pxOpenedInterfaceHandle, uip_buf, uip_len );
\r
117 pcap_sendpacket( pxOpenedInterfaceHandle, uip_buf, uip_len );
\r
119 /*-----------------------------------------------------------*/
\r
121 unsigned portBASE_TYPE uxNetifRx( void )
\r
123 unsigned portBASE_TYPE xDataLen;
\r
124 unsigned char *pucTemp;
\r
126 /* Check there is really data available. */
\r
127 xDataLen = lLengthOfDataInBuffer[ ucNextBufferToProcess ];
\r
128 if( xDataLen != 0L )
\r
131 /* The buffer pointed to by uip_buf is going to change. Remember which
\r
132 buffer uip_buf is currently pointing to. */
\r
135 /* Point uip_buf at the next buffer that contains data. */
\r
136 uip_buf = pucEthernetBufferPointers[ ucNextBufferToProcess ];
\r
138 /* The buffer pointed to by
\r
139 pucEthernetBufferPointeres[ ucNextBufferToProcess ] is now in use by
\r
140 uip_buf, but the buffer uip_buf was pointing to on entry to this
\r
141 function is free. Set
\r
142 pucEthernetBufferPointeres[ ucNextBufferToProcess ] to the free
\r
144 pucEthernetBufferPointers[ ucNextBufferToProcess ] = pucTemp;
\r
145 lLengthOfDataInBuffer[ ucNextBufferToProcess ] = 0L;
\r
147 ucNextBufferToProcess++;
\r
148 if( ucNextBufferToProcess >= archNUM_BUFFER_POINTERS )
\r
150 ucNextBufferToProcess = 0L;
\r
156 /*-----------------------------------------------------------*/
\r
158 portBASE_TYPE xNetifInit( void )
\r
161 pcap_if_t *pxAllNetworkInterfaces;
\r
163 /* Allocate a free buffer to each buffer pointer. */
\r
164 for( x = 0; x < sizeof( pucEthernetBufferPointers ) / sizeof( unsigned char * ); x++ )
\r
166 pucEthernetBufferPointers[ x ] = &( ucEthernetBuffer[ x ][ 0 ] );
\r
169 /* Start with uip_buf pointing to a buffer that is not referenced from the
\r
170 pucEthernetBufferPointers[] array. */
\r
171 uip_buf = &( ucEthernetBuffer[ archNUM_BUFFERS - 1 ][ 0 ] );
\r
173 /* Query the computer the simulation is being executed on to find the
\r
174 network interfaces it has installed. */
\r
175 pxAllNetworkInterfaces = prvPrintAvailableNetworkInterfaces();
\r
177 /* Open the network interface. The number of the interface to be opened is
\r
178 set by the configNETWORK_INTERFACE_TO_USE constant in FreeRTOSConfig.h.
\r
179 Calling this function will set the pxOpenedInterfaceHandle variable. If,
\r
180 after calling this function, pxOpenedInterfaceHandle is equal to NULL, then
\r
181 the interface could not be opened. */
\r
182 if( pxAllNetworkInterfaces != NULL )
\r
184 prvOpenSelectedNetworkInterface( pxAllNetworkInterfaces );
\r
190 /*-----------------------------------------------------------*/
\r
192 static pcap_if_t * prvPrintAvailableNetworkInterfaces( void )
\r
194 pcap_if_t * pxAllNetworkInterfaces = NULL, *xInterface;
\r
195 long lInterfaceNumber = 1;
\r
197 if( pcap_findalldevs_ex( PCAP_SRC_IF_STRING, NULL, &pxAllNetworkInterfaces, cErrorBuffer ) == -1 )
\r
199 printf( "\r\nCould not obtain a list of network interfaces\r\n%s\r\n", cErrorBuffer );
\r
200 pxAllNetworkInterfaces = NULL;
\r
203 if( pxAllNetworkInterfaces != NULL )
\r
205 /* Print out the list of network interfaces. The first in the list
\r
206 is interface '1', not interface '0'. */
\r
207 for( xInterface = pxAllNetworkInterfaces; xInterface != NULL; xInterface = xInterface->next )
\r
209 printf( "%d. %s", lInterfaceNumber, xInterface->name );
\r
211 if( xInterface->description != NULL )
\r
213 printf( " (%s)\r\n", xInterface->description );
\r
217 printf( " (No description available)\r\n") ;
\r
220 lInterfaceNumber++;
\r
224 if( lInterfaceNumber == 1 )
\r
226 /* The interface number was never incremented, so the above for() loop
\r
227 did not execute meaning no interfaces were found. */
\r
228 printf( " \r\nNo network interfaces were found.\r\n" );
\r
229 pxAllNetworkInterfaces = NULL;
\r
232 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
233 printf( "Attempting to open interface number %d.\r\n", configNETWORK_INTERFACE_TO_USE );
\r
235 if( ( configNETWORK_INTERFACE_TO_USE < 1L ) || ( configNETWORK_INTERFACE_TO_USE > lInterfaceNumber ) )
\r
237 printf("\r\nconfigNETWORK_INTERFACE_TO_USE is not in the valid range.\r\n" );
\r
239 if( pxAllNetworkInterfaces != NULL )
\r
241 /* Free the device list, as no devices are going to be opened. */
\r
242 pcap_freealldevs( pxAllNetworkInterfaces );
\r
243 pxAllNetworkInterfaces = NULL;
\r
247 return pxAllNetworkInterfaces;
\r
249 /*-----------------------------------------------------------*/
\r
251 static void prvOpenSelectedNetworkInterface( pcap_if_t *pxAllNetworkInterfaces )
\r
253 pcap_if_t *xInterface;
\r
256 /* Walk the list of devices until the selected device is located. */
\r
257 xInterface = pxAllNetworkInterfaces;
\r
258 for( x = 0L; x < ( configNETWORK_INTERFACE_TO_USE - 1L ); x++ )
\r
260 xInterface = xInterface->next;
\r
263 /* Open the selected interface. */
\r
264 pxOpenedInterfaceHandle = pcap_open( xInterface->name, /* The name of the selected interface. */
\r
265 UIP_CONF_BUFFER_SIZE, /* The size of the packet to capture. */
\r
266 PCAP_OPENFLAG_PROMISCUOUS, /* Open in promiscious mode as the MAC and
\r
267 IP address is going to be "simulated", and
\r
268 not be the real MAC and IP address. This allows
\r
269 trafic to the simulated IP address to be routed
\r
270 to uIP, and trafic to the real IP address to be
\r
271 routed to the Windows TCP/IP stack. */
\r
272 0xfffffffL, /* The read time out. This is going to block
\r
273 until data is available. */
\r
274 NULL, /* No authentication is required as this is
\r
275 not a remote capture session. */
\r
279 if ( pxOpenedInterfaceHandle == NULL )
\r
281 printf( "\r\n%s is not supported by WinPcap and cannot be opened\r\n", xInterface->name );
\r
285 /* Configure the capture filter to allow blocking reads, and to filter
\r
286 out packets that are not of interest to this demo. */
\r
287 prvConfigureCaptureBehaviour();
\r
290 /* The device list is no longer required. */
\r
291 pcap_freealldevs( pxAllNetworkInterfaces );
\r
293 /*-----------------------------------------------------------*/
\r
295 static void prvConfigureCaptureBehaviour( void )
\r
297 struct bpf_program xFilterCode;
\r
298 const long lMinBytesToCopy = 10L, lBlocking = 0L;
\r
299 unsigned long ulNetMask;
\r
301 /* Unblock a read as soon as anything is received. */
\r
302 pcap_setmintocopy( pxOpenedInterfaceHandle, lMinBytesToCopy );
\r
304 /* Allow blocking. */
\r
305 pcap_setnonblock( pxOpenedInterfaceHandle, lBlocking, cErrorBuffer );
\r
307 /* Set up a filter so only the packets of interest are passed to the uIP
\r
308 stack. cErrorBuffer is used for convenience to create the string. Don't
\r
309 confuse this with an error message. */
\r
310 sprintf( cErrorBuffer, "broadcast or multicast or host %d.%d.%d.%d", configIP_ADDR0, configIP_ADDR1, configIP_ADDR2, configIP_ADDR3 );
\r
312 ulNetMask = ( configNET_MASK3 << 24UL ) | ( configNET_MASK2 << 16UL ) | ( configNET_MASK1 << 8L ) | configNET_MASK0;
\r
314 if( pcap_compile(pxOpenedInterfaceHandle, &xFilterCode, cErrorBuffer, 1, ulNetMask ) < 0 )
\r
316 printf("\r\nThe packet filter string is invalid\r\n" );
\r
320 if( pcap_setfilter( pxOpenedInterfaceHandle, &xFilterCode ) < 0 )
\r
322 printf( "\r\nAn error occurred setting the packet filter.\r\n" );
\r
326 /* Create a task that simulates an interrupt in a real system. This will
\r
327 block waiting for packets, then send a message to the uIP task when data
\r
329 xTaskCreate( prvInterruptSimulator, ( signed char * ) "MAC_ISR", configMINIMAL_STACK_SIZE, NULL, ( configuIP_TASK_PRIORITY - 1 ), NULL );
\r
331 /*-----------------------------------------------------------*/
\r
333 static void prvInterruptSimulator( void *pvParameters )
\r
335 static struct pcap_pkthdr *pxHeader;
\r
336 const unsigned char *pucPacketData;
\r
337 extern xQueueHandle xEMACEventQueue;
\r
338 const unsigned long ulRxEvent = uipETHERNET_RX_EVENT;
\r
341 /* Just to kill the compiler warning. */
\r
342 ( void ) pvParameters;
\r
346 /* Get the next packet. */
\r
347 lResult = pcap_next_ex( pxOpenedInterfaceHandle, &pxHeader, &pucPacketData );
\r
350 /* Is the next buffer into which data should be placed free? */
\r
351 if( lLengthOfDataInBuffer[ ucNextBufferToFill ] == 0L )
\r
353 /* Copy the data from the captured packet into the buffer. */
\r
354 memcpy( pucEthernetBufferPointers[ ucNextBufferToFill ], pucPacketData, pxHeader->len );
\r
356 /* Note the amount of data that was copied. */
\r
357 lLengthOfDataInBuffer[ ucNextBufferToFill ] = pxHeader->len;
\r
359 /* Move onto the next buffer, wrapping around if necessary. */
\r
360 ucNextBufferToFill++;
\r
361 if( ucNextBufferToFill >= archNUM_BUFFER_POINTERS )
\r
363 ucNextBufferToFill = 0U;
\r
366 /* Data was received and stored. Send a message to the uIP task
\r
368 xQueueSendToBack( xEMACEventQueue, &ulRxEvent, portMAX_DELAY );
\r