]> git.sur5r.net Git - freertos/blob - Demo/CORTEX_A2F200_SoftConsole/uIP_Task.c
7e64f3b704905426d967d00aa9dbe2b5683da58b
[freertos] / Demo / CORTEX_A2F200_SoftConsole / uIP_Task.c
1 /*\r
2     FreeRTOS V7.0.0 - Copyright (C) 2011 Real Time Engineers Ltd.\r
3         \r
4 \r
5     ***************************************************************************\r
6      *                                                                       *\r
7      *    FreeRTOS tutorial books are available in pdf and paperback.        *\r
8      *    Complete, revised, and edited pdf reference manuals are also       *\r
9      *    available.                                                         *\r
10      *                                                                       *\r
11      *    Purchasing FreeRTOS documentation will not only help you, by       *\r
12      *    ensuring you get running as quickly as possible and with an        *\r
13      *    in-depth knowledge of how to use FreeRTOS, it will also help       *\r
14      *    the FreeRTOS project to continue with its mission of providing     *\r
15      *    professional grade, cross platform, de facto standard solutions    *\r
16      *    for microcontrollers - completely free of charge!                  *\r
17      *                                                                       *\r
18      *    >>> See http://www.FreeRTOS.org/Documentation for details. <<<     *\r
19      *                                                                       *\r
20      *    Thank you for using FreeRTOS, and thank you for your support!      *\r
21      *                                                                       *\r
22     ***************************************************************************\r
23 \r
24 \r
25     This file is part of the FreeRTOS distribution.\r
26 \r
27     FreeRTOS is free software; you can redistribute it and/or modify it under\r
28     the terms of the GNU General Public License (version 2) as published by the\r
29     Free Software Foundation AND MODIFIED BY the FreeRTOS exception.\r
30     >>>NOTE<<< The modification to the GPL is included to allow you to\r
31     distribute a combined work that includes FreeRTOS without being obliged to\r
32     provide the source code for proprietary components outside of the FreeRTOS\r
33     kernel.  FreeRTOS is distributed in the hope that it will be useful, but\r
34     WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
35     or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for\r
36     more details. You should have received a copy of the GNU General Public\r
37     License and the FreeRTOS license exception along with FreeRTOS; if not it\r
38     can be viewed here: http://www.freertos.org/a00114.html and also obtained\r
39     by writing to Richard Barry, contact details for whom are available on the\r
40     FreeRTOS WEB site.\r
41 \r
42     1 tab == 4 spaces!\r
43 \r
44     http://www.FreeRTOS.org - Documentation, latest information, license and\r
45     contact details.\r
46 \r
47     http://www.SafeRTOS.com - A version that is certified for use in safety\r
48     critical systems.\r
49 \r
50     http://www.OpenRTOS.com - Commercial support, development, porting,\r
51     licensing and training services.\r
52 */\r
53 \r
54 /* Standard includes. */\r
55 #include <string.h>\r
56 \r
57 /* Scheduler includes. */\r
58 #include "FreeRTOS.h"\r
59 #include "task.h"\r
60 #include "queue.h"\r
61 #include "timers.h"\r
62 \r
63 /* uip includes. */\r
64 #include "net/uip.h"\r
65 #include "net/uip_arp.h"\r
66 #include "apps/httpd/httpd.h"\r
67 #include "sys/timer.h"\r
68 #include "net/clock-arch.h"\r
69 \r
70 /* Demo includes. */\r
71 #include "ParTest.h"\r
72 \r
73 /* Hardware driver includes. */\r
74 #include "mss_ethernet_mac_regs.h"\r
75 #include "mss_ethernet_mac.h"\r
76 \r
77 /* The buffer used by the uIP stack to both receive and send.  This points to\r
78 one of the Ethernet buffers when its actually in use. */\r
79 extern unsigned char *uip_buf;\r
80 \r
81 static const unsigned char ucMACAddress[] = { configMAC_ADDR0, configMAC_ADDR1, configMAC_ADDR2, configMAC_ADDR3, configMAC_ADDR4, configMAC_ADDR5 };\r
82 \r
83 #define uipARP_TIMER                            0\r
84 #define uipPERIODIC_TIMER                       1\r
85 \r
86 #define uipEVENT_QUEUE_LENGTH           10\r
87 \r
88 #define uipETHERNET_RX_EVENT            0x01UL\r
89 #define uipETHERNET_TX_EVENT            0x02UL\r
90 #define uipARP_TIMER_EVENT                      0x04UL\r
91 #define uipPERIODIC_TIMER_EVENT         0x08UL\r
92 #define uipAPPLICATION_SEND_EVENT       0x10UL\r
93 \r
94 #define uipDONT_BLOCK                           0UL\r
95 \r
96 /*-----------------------------------------------------------*/\r
97 \r
98 /* How long to wait before attempting to connect the MAC again. */\r
99 #define uipINIT_WAIT    ( 100 / portTICK_RATE_MS )\r
100 \r
101 /* Shortcut to the header within the Rx buffer. */\r
102 #define xHeader ((struct uip_eth_hdr *) &uip_buf[ 0 ])\r
103 \r
104 /* Standard constant. */\r
105 #define uipTOTAL_FRAME_HEADER_SIZE      54\r
106 \r
107 /*-----------------------------------------------------------*/\r
108 \r
109 /*\r
110  * Setup the MAC address in the MAC itself, and in the uIP stack.\r
111  */\r
112 static void prvSetMACAddress( void );\r
113 \r
114 /*\r
115  * Perform any uIP initialisation required to ready the stack for http\r
116  * processing.
117  */\r
118 static void prvInitialise_uIP( void );\r
119 \r
120 /*\r
121  * Handles Ethernet interrupt events.
122  */\r
123 static void prvEMACEventListener( unsigned long ulISREvents );\r
124 \r
125 static void prvUIPTimerCallback( xTimerHandle xTimer );\r
126 \r
127 /*\r
128  * Initialise the MAC hardware.
129  */\r
130 static void prvInitEmac( void );\r
131 \r
132 void vEMACWrite( void );\r
133 \r
134 long lEMACWaitForLink( void );\r
135 \r
136 /*\r
137  * Port functions required by the uIP stack.\r
138  */\r
139 void clock_init( void );\r
140 clock_time_t clock_time( void );\r
141 \r
142 /*-----------------------------------------------------------*/\r
143 \r
144 /* The queue used to send TCP/IP events to the uIP stack. */\r
145 xQueueHandle xEMACEventQueue = NULL;\r
146 \r
147 static unsigned long ulUIP_Events = 0UL;\r
148 \r
149 /*-----------------------------------------------------------*/\r
150 \r
151 void clock_init(void)\r
152 {\r
153         /* This is done when the scheduler starts. */\r
154 }\r
155 /*-----------------------------------------------------------*/\r
156 \r
157 clock_time_t clock_time( void )\r
158 {\r
159         return xTaskGetTickCount();\r
160 }\r
161 /*-----------------------------------------------------------*/\r
162 \r
163 void vuIP_Task( void *pvParameters )\r
164 {\r
165 portBASE_TYPE i;\r
166 unsigned long ulNewEvent;\r
167 \r
168         ( void ) pvParameters;\r
169 \r
170         /* Initialise the uIP stack, configuring for web server usage. */\r
171         prvInitialise_uIP();\r
172 \r
173         /* Initialise the MAC. */\r
174         prvInitEmac();\r
175 \r
176         for( ;; )\r
177         {\r
178                 if( ( ulUIP_Events & uipETHERNET_TX_EVENT ) != 0UL )\r
179                 {\r
180                         ulUIP_Events &= ~uipETHERNET_TX_EVENT;\r
181                         MSS_MAC_TxBufferCompleted();\r
182                 }\r
183 \r
184                 if( ( ulUIP_Events & uipETHERNET_RX_EVENT ) != 0UL )\r
185                 {\r
186                         ulUIP_Events &= ~uipETHERNET_RX_EVENT;\r
187 \r
188                         /* Is there received data ready to be processed? */\r
189                         uip_len = MSS_MAC_rx_packet();\r
190 \r
191                         if( ( uip_len > 0 ) && ( uip_buf != NULL ) )\r
192                         {\r
193                                 /* Standard uIP loop taken from the uIP manual. */\r
194                                 if( xHeader->type == htons( UIP_ETHTYPE_IP ) )\r
195                                 {\r
196                                         uip_arp_ipin();\r
197                                         uip_input();\r
198 \r
199                                         /* If the above function invocation resulted in data that\r
200                                         should be sent out on the network, the global variable\r
201                                         uip_len is set to a value > 0. */\r
202                                         if( uip_len > 0 )\r
203                                         {\r
204                                                 uip_arp_out();\r
205                                                 vEMACWrite();\r
206                                         }\r
207                                 }\r
208                                 else if( xHeader->type == htons( UIP_ETHTYPE_ARP ) )\r
209                                 {\r
210                                         uip_arp_arpin();\r
211 \r
212                                         /* If the above function invocation resulted in data that\r
213                                         should be sent out on the network, the global variable\r
214                                         uip_len is set to a value > 0. */\r
215                                         if( uip_len > 0 )\r
216                                         {\r
217                                                 vEMACWrite();\r
218                                         }\r
219                                 }\r
220                         }\r
221                 }\r
222 \r
223                 if( ( ulUIP_Events & uipPERIODIC_TIMER_EVENT ) != 0UL )\r
224                 {\r
225                         ulUIP_Events &= ~uipPERIODIC_TIMER_EVENT;\r
226 \r
227                         for( i = 0; i < UIP_CONNS; i++ )\r
228                         {\r
229                                 uip_periodic( i );\r
230 \r
231                                 /* If the above function invocation resulted in data that\r
232                                 should be sent out on the network, the global variable\r
233                                 uip_len is set to a value > 0. */\r
234                                 if( uip_len > 0 )\r
235                                 {\r
236                                         uip_arp_out();\r
237                                         vEMACWrite();\r
238                                 }\r
239                         }\r
240                 }\r
241 \r
242                 /* Call the ARP timer function every 10 seconds. */\r
243                 if( ( ulUIP_Events & uipARP_TIMER_EVENT ) != 0 )\r
244                 {\r
245                         ulUIP_Events &= ~uipARP_TIMER_EVENT;\r
246                         uip_arp_timer();\r
247                 }\r
248 \r
249                 if( ulUIP_Events == pdFALSE )\r
250                 {\r
251                         xQueueReceive( xEMACEventQueue, &ulNewEvent, portMAX_DELAY );\r
252                         ulUIP_Events |= ulNewEvent;\r
253                 }\r
254         }\r
255 }\r
256 /*-----------------------------------------------------------*/\r
257 \r
258 static void prvSetMACAddress( void )\r
259 {\r
260 struct uip_eth_addr xAddr;\r
261 \r
262         /* Configure the MAC address in the uIP stack. */\r
263         xAddr.addr[ 0 ] = configMAC_ADDR0;\r
264         xAddr.addr[ 1 ] = configMAC_ADDR1;\r
265         xAddr.addr[ 2 ] = configMAC_ADDR2;\r
266         xAddr.addr[ 3 ] = configMAC_ADDR3;\r
267         xAddr.addr[ 4 ] = configMAC_ADDR4;\r
268         xAddr.addr[ 5 ] = configMAC_ADDR5;\r
269         uip_setethaddr( xAddr );\r
270 }\r
271 /*-----------------------------------------------------------*/\r
272 \r
273 void vApplicationProcessFormInput( char *pcInputString )\r
274 {\r
275 char *c;\r
276 \r
277         /* Only interested in processing form input if this is the IO page. */\r
278         c = strstr( pcInputString, "io.shtml" );\r
279         \r
280         if( c )\r
281         {\r
282                 /* Is there a command in the string? */\r
283                 c = strstr( pcInputString, "?" );\r
284             if( c )\r
285             {\r
286                         /* Turn the LED's on or off in accordance with the check box status. */\r
287                         if( strstr( c, "LED0=1" ) != NULL )\r
288                         {\r
289                                 /* Turn the LEDs on. */\r
290                                 vParTestSetLED( 7, 1 );\r
291                                 vParTestSetLED( 8, 1 );\r
292                                 vParTestSetLED( 9, 1 );\r
293                                 vParTestSetLED( 10, 1 );\r
294                         }\r
295                         else\r
296                         {\r
297                                 /* Turn the LEDs off. */\r
298                                 vParTestSetLED( 7, 0 );\r
299                                 vParTestSetLED( 8, 0 );\r
300                                 vParTestSetLED( 9, 0 );\r
301                                 vParTestSetLED( 10, 0 );\r
302                         }\r
303             }\r
304                 else\r
305                 {\r
306                         /* Commands to turn LEDs off are not always explicit. */\r
307                         vParTestSetLED( 7, 0 );\r
308                         vParTestSetLED( 8, 0 );\r
309                         vParTestSetLED( 9, 0 );\r
310                         vParTestSetLED( 10, 0 );\r
311                 }\r
312         }\r
313 }\r
314 /*-----------------------------------------------------------*/\r
315 \r
316 static void prvInitialise_uIP( void )\r
317 {\r
318 uip_ipaddr_t xIPAddr;\r
319 xTimerHandle xARPTimer, xPeriodicTimer;\r
320 \r
321         uip_init();\r
322         uip_ipaddr( &xIPAddr, configIP_ADDR0, configIP_ADDR1, configIP_ADDR2, configIP_ADDR3 );\r
323         uip_sethostaddr( &xIPAddr );\r
324         uip_ipaddr( &xIPAddr, configNET_MASK0, configNET_MASK1, configNET_MASK2, configNET_MASK3 );\r
325         uip_setnetmask( &xIPAddr );\r
326         prvSetMACAddress();\r
327         httpd_init();\r
328 \r
329         /* Create the queue used to sent TCP/IP events to the uIP stack. */\r
330         xEMACEventQueue = xQueueCreate( uipEVENT_QUEUE_LENGTH, sizeof( unsigned long ) );\r
331 \r
332         /* Create and start the uIP timers. */\r
333         xARPTimer = xTimerCreate(       ( const signed char * const ) "ARPTimer", /* Just a name that is helpful for debugging, not used by the kernel. */\r
334                                                                 ( 500 / portTICK_RATE_MS ), /* Timer period. */\r
335                                                                 pdTRUE, /* Autor-reload. */\r
336                                                                 ( void * ) uipARP_TIMER,\r
337                                                                 prvUIPTimerCallback\r
338                                                         );\r
339 \r
340         xPeriodicTimer = xTimerCreate(  ( const signed char * const ) "PeriodicTimer",\r
341                                                                         ( 5000 / portTICK_RATE_MS ),\r
342                                                                         pdTRUE, /* Autor-reload. */\r
343                                                                         ( void * ) uipPERIODIC_TIMER,\r
344                                                                         prvUIPTimerCallback\r
345                                                                 );\r
346 \r
347         configASSERT( xARPTimer );\r
348         configASSERT( xPeriodicTimer );\r
349 \r
350         xTimerStart( xARPTimer, portMAX_DELAY );\r
351         xTimerStart( xPeriodicTimer, portMAX_DELAY );\r
352 }\r
353 /*-----------------------------------------------------------*/\r
354 \r
355 static void prvEMACEventListener( unsigned long ulISREvents )\r
356 {\r
357 long lHigherPriorityTaskWoken = pdFALSE;\r
358 unsigned long ulUIPEvents = 0UL;\r
359 \r
360         configASSERT( xEMACEventQueue );\r
361 \r
362         if( ( ulISREvents & MSS_MAC_EVENT_PACKET_SEND ) != 0UL )\r
363         {\r
364                 ulUIP_Events |= uipETHERNET_TX_EVENT;\r
365         }\r
366 \r
367         if( ( ulISREvents & MSS_MAC_EVENT_PACKET_RECEIVED ) != 0UL )\r
368         {\r
369                 /* Wake the uIP task as new data has arrived. */\r
370                 ulUIPEvents |= uipETHERNET_RX_EVENT;\r
371         }\r
372 \r
373         if( ulUIPEvents != 0UL )\r
374         {\r
375                 xQueueSendFromISR( xEMACEventQueue, &ulUIPEvents, &lHigherPriorityTaskWoken );\r
376         }\r
377 \r
378         portEND_SWITCHING_ISR( lHigherPriorityTaskWoken );\r
379 }\r
380 /*-----------------------------------------------------------*/\r
381 \r
382 static void prvInitEmac( void )\r
383 {\r
384 const unsigned char ucPHYAddress = 1;\r
385 \r
386         MSS_MAC_init( ucPHYAddress );\r
387 \r
388         MSS_MAC_set_callback( prvEMACEventListener );\r
389 \r
390     /* Setup the EMAC and the NVIC for MAC interrupts. */\r
391     NVIC_SetPriority( EthernetMAC_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY );\r
392     NVIC_EnableIRQ( EthernetMAC_IRQn );\r
393 }\r
394 /*-----------------------------------------------------------*/\r
395 \r
396 void vEMACWrite( void )\r
397 {\r
398 const long lMaxAttempts = 10;\r
399 long lAttempt;\r
400 const portTickType xShortDelay = ( 10 / portTICK_RATE_MS );\r
401 \r
402         for( lAttempt = 0; lAttempt < lMaxAttempts; lAttempt++ )\r
403         {\r
404                 if( MSS_MAC_tx_packet( uip_len ) != 0 )\r
405                 {\r
406                         break;\r
407                 }\r
408                 else\r
409                 {\r
410                         vTaskDelay( xShortDelay );\r
411                 }\r
412         }\r
413 }\r
414 /*-----------------------------------------------------------*/\r
415 \r
416 long lEMACWaitForLink( void )\r
417 {\r
418 long lReturn = pdFAIL;\r
419 unsigned long ulStatus;\r
420 \r
421         ulStatus = MSS_MAC_link_status();\r
422         if( ( ulStatus & ( unsigned long ) MSS_MAC_LINK_STATUS_LINK ) != 0UL )\r
423         {\r
424                 lReturn = pdPASS;\r
425         }\r
426 \r
427         return lReturn;\r
428 }\r
429 /*-----------------------------------------------------------*/\r
430 \r
431 static void prvUIPTimerCallback( xTimerHandle xTimer )\r
432 {\r
433 static const unsigned long ulARPTimerExpired = uipARP_TIMER_EVENT;\r
434 static const unsigned long ulPeriodicTimerExpired = uipPERIODIC_TIMER_EVENT;\r
435 \r
436         /* This is a time callback, so calls to xQueueSend() must not attempt to\r
437         block. */\r
438         switch( ( int ) pvTimerGetTimerID( xTimer ) )\r
439         {\r
440                 case uipARP_TIMER               :       xQueueSend( xEMACEventQueue, &ulARPTimerExpired, uipDONT_BLOCK );\r
441                                                                         break;\r
442 \r
443                 case uipPERIODIC_TIMER  :       xQueueSend( xEMACEventQueue, &ulPeriodicTimerExpired, uipDONT_BLOCK );\r
444                                                                         break;\r
445 \r
446                 default                                 :       /* Should not get here. */\r
447                                                                         break;\r
448         }\r
449 }\r
450 /*-----------------------------------------------------------*/\r