]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_Kinetis_K60_Tower_IAR/uIP_Task.c
Update to MIT licensed FreeRTOS V10.0.0 - see https://www.freertos.org/History.txt
[freertos] / FreeRTOS / Demo / CORTEX_Kinetis_K60_Tower_IAR / uIP_Task.c
1 /*\r
2  * FreeRTOS Kernel V10.0.0\r
3  * Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
4  *\r
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
6  * this software and associated documentation files (the "Software"), to deal in\r
7  * the Software without restriction, including without limitation the rights to\r
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
9  * the Software, and to permit persons to whom the Software is furnished to do so,\r
10  * subject to the following conditions:\r
11  *\r
12  * The above copyright notice and this permission notice shall be included in all\r
13  * copies or substantial portions of the Software. If you wish to use our Amazon\r
14  * FreeRTOS name, please do so in a fair use way that does not cause confusion.\r
15  *\r
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
18  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
19  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
20  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
22  *\r
23  * http://www.FreeRTOS.org\r
24  * http://aws.amazon.com/freertos\r
25  *\r
26  * 1 tab == 4 spaces!\r
27  */\r
28 \r
29 /* Standard includes. */\r
30 #include <string.h>\r
31 \r
32 /* Scheduler includes. */\r
33 #include "FreeRTOS.h"\r
34 #include "task.h"\r
35 #include "queue.h"\r
36 #include "timers.h"\r
37 \r
38 /* uip includes. */\r
39 #include "net/uip.h"\r
40 #include "net/uip_arp.h"\r
41 #include "apps/httpd/httpd.h"\r
42 #include "sys/timer.h"\r
43 #include "net/clock-arch.h"\r
44 #include "emac.h"\r
45 \r
46 /* Demo includes. */\r
47 #include "ParTest.h"\r
48 \r
49 /* The buffer used by the uIP stack to both receive and send.  In this case,\r
50 because the Ethernet driver is implemented to be zero copy - the uip_buf\r
51 variable is just a pointer to an Ethernet buffer, and not a buffer in its own\r
52 right. */\r
53 extern unsigned char *uip_buf;\r
54 \r
55 /* The ARP timer and the periodic timer share a callback function, so the\r
56 respective timer IDs are used to determine which timer actually expired.  These\r
57 constants are assigned to the timer IDs. */\r
58 #define uipARP_TIMER                            0\r
59 #define uipPERIODIC_TIMER                       1\r
60 \r
61 /* The length of the queue used to send events from timers or the Ethernet\r
62 driver to the uIP stack. */\r
63 #define uipEVENT_QUEUE_LENGTH           10\r
64 \r
65 /* A block time of zero simply means "don't block". */\r
66 #define uipDONT_BLOCK                           0UL\r
67 \r
68 /* Shortcut to the header within the Rx buffer. */\r
69 #define xHeader ((struct uip_eth_hdr *) &uip_buf[ 0 ])\r
70 \r
71 /*-----------------------------------------------------------*/\r
72 \r
73 /*\r
74  * Setup the MAC address in the MAC itself, and in the uIP stack.\r
75  */\r
76 static void prvSetMACAddress( void );\r
77 \r
78 /*\r
79  * Perform any uIP initialisation required to ready the stack for http\r
80  * processing.\r
81  */\r
82 static void prvInitialise_uIP( void );\r
83 \r
84 /*\r
85  * The callback function that is assigned to both the periodic timer and the\r
86  * ARP timer.\r
87  */\r
88 static void prvUIPTimerCallback( TimerHandle_t xTimer );\r
89 \r
90 /*\r
91  * Port functions required by the uIP stack.\r
92  */\r
93 clock_time_t clock_time( void );\r
94 \r
95 /*-----------------------------------------------------------*/\r
96 \r
97 /* The queue used to send TCP/IP events to the uIP stack. */\r
98 QueueHandle_t xEMACEventQueue = NULL;\r
99 \r
100 /*-----------------------------------------------------------*/\r
101 \r
102 clock_time_t clock_time( void )\r
103 {\r
104         return xTaskGetTickCount();\r
105 }\r
106 /*-----------------------------------------------------------*/\r
107 \r
108 void vuIP_Task( void *pvParameters )\r
109 {\r
110 long i;\r
111 unsigned long ulNewEvent = 0UL, ulUIP_Events = 0UL;\r
112 unsigned short usPacketLength;\r
113 \r
114         /* Just to prevent compiler warnings about the unused parameter. */\r
115         ( void ) pvParameters;\r
116 \r
117         /* Initialise the uIP stack, configuring for web server usage. */\r
118         prvInitialise_uIP();\r
119 \r
120         /* Initialise the MAC and PHY. */\r
121         vEMACInit();\r
122 \r
123         for( ;; )\r
124         {\r
125                 /* Is there received data ready to be processed? */\r
126                 usPacketLength = usEMACRead();\r
127 \r
128                 /* Statements to be executed if data has been received on the Ethernet. */\r
129                 if( ( usPacketLength > 0U ) && ( uip_buf != NULL ) )\r
130                 {\r
131                         uip_len = usPacketLength;\r
132 \r
133                         if( xHeader->type == htons( UIP_ETHTYPE_IP ) )\r
134                         {\r
135                                 uip_arp_ipin();\r
136                                 uip_input();\r
137 \r
138                                 /* If the above function invocation resulted in data that\r
139                                 should be sent out on the network, the global variable\r
140                                 uip_len is set to a value > 0. */\r
141                                 if( uip_len > 0 )\r
142                                 {\r
143                                         uip_arp_out();\r
144                                         vEMACWrite();\r
145                                 }\r
146                         }\r
147                         else if( xHeader->type == htons( UIP_ETHTYPE_ARP ) )\r
148                         {\r
149                                 uip_arp_arpin();\r
150 \r
151                                 /* If the above function invocation resulted in data that\r
152                                 should be sent out on the network, the global variable\r
153                                 uip_len is set to a value > 0. */\r
154                                 if( uip_len > 0 )\r
155                                 {\r
156                                         vEMACWrite();\r
157                                 }\r
158                         }\r
159                 }\r
160                 else\r
161                 {\r
162                         /* Clear the RX event latched in ulUIP_Events - if one was latched. */\r
163                         ulUIP_Events &= ~uipETHERNET_RX_EVENT;\r
164                 }\r
165 \r
166                 /* Statements to be executed if the TCP/IP period timer has expired. */\r
167                 if( ( ulUIP_Events & uipPERIODIC_TIMER_EVENT ) != 0UL )\r
168                 {\r
169                         ulUIP_Events &= ~uipPERIODIC_TIMER_EVENT;\r
170 \r
171                         if( uip_buf != NULL )\r
172                         {\r
173                                 for( i = 0; i < UIP_CONNS; i++ )\r
174                                 {\r
175                                         uip_periodic( i );\r
176 \r
177                                         /* If the above function invocation resulted in data that\r
178                                         should be sent out on the network, the global variable\r
179                                         uip_len is set to a value > 0. */\r
180                                         if( uip_len > 0 )\r
181                                         {\r
182                                                 uip_arp_out();\r
183                                                 vEMACWrite();\r
184                                         }\r
185                                 }\r
186                         }\r
187                 }\r
188 \r
189                 /* Statements to be executed if the ARP timer has expired. */\r
190                 if( ( ulUIP_Events & uipARP_TIMER_EVENT ) != 0 )\r
191                 {\r
192                         ulUIP_Events &= ~uipARP_TIMER_EVENT;\r
193                         uip_arp_timer();\r
194                 }\r
195 \r
196                 /* If all latched events have been cleared - block until another event\r
197                 occurs. */\r
198                 if( ulUIP_Events == pdFALSE )\r
199                 {\r
200                         xQueueReceive( xEMACEventQueue, &ulNewEvent, portMAX_DELAY );\r
201                         ulUIP_Events |= ulNewEvent;\r
202                 }\r
203         }\r
204 }\r
205 /*-----------------------------------------------------------*/\r
206 \r
207 static void prvSetMACAddress( void )\r
208 {\r
209 struct uip_eth_addr xAddr;\r
210 \r
211         /* Configure the MAC address in the uIP stack. */\r
212         xAddr.addr[ 0 ] = configMAC_ADDR0;\r
213         xAddr.addr[ 1 ] = configMAC_ADDR1;\r
214         xAddr.addr[ 2 ] = configMAC_ADDR2;\r
215         xAddr.addr[ 3 ] = configMAC_ADDR3;\r
216         xAddr.addr[ 4 ] = configMAC_ADDR4;\r
217         xAddr.addr[ 5 ] = configMAC_ADDR5;\r
218         uip_setethaddr( xAddr );\r
219 }\r
220 /*-----------------------------------------------------------*/\r
221 \r
222 static void prvInitialise_uIP( void )\r
223 {\r
224 uip_ipaddr_t xIPAddr;\r
225 TimerHandle_t xARPTimer, xPeriodicTimer;\r
226 \r
227         uip_init();\r
228         uip_ipaddr( &xIPAddr, configIP_ADDR0, configIP_ADDR1, configIP_ADDR2, configIP_ADDR3 );\r
229         uip_sethostaddr( &xIPAddr );\r
230         uip_ipaddr( &xIPAddr, configNET_MASK0, configNET_MASK1, configNET_MASK2, configNET_MASK3 );\r
231         uip_setnetmask( &xIPAddr );\r
232         prvSetMACAddress();\r
233         httpd_init();\r
234 \r
235         /* Create the queue used to sent TCP/IP events to the uIP stack. */\r
236         xEMACEventQueue = xQueueCreate( uipEVENT_QUEUE_LENGTH, sizeof( unsigned long ) );\r
237 \r
238         /* Create and start the uIP timers. */\r
239         xARPTimer = xTimerCreate(       "ARPTimer", /* Just a name that is helpful for debugging, not used by the kernel. */\r
240                                                                 ( 10000UL / portTICK_PERIOD_MS ), /* Timer period. */\r
241                                                                 pdTRUE, /* Autor-reload. */\r
242                                                                 ( void * ) uipARP_TIMER,\r
243                                                                 prvUIPTimerCallback\r
244                                                         );\r
245 \r
246         xPeriodicTimer = xTimerCreate(  "PeriodicTimer",\r
247                                                                         ( 500UL / portTICK_PERIOD_MS ),\r
248                                                                         pdTRUE, /* Autor-reload. */\r
249                                                                         ( void * ) uipPERIODIC_TIMER,\r
250                                                                         prvUIPTimerCallback\r
251                                                                 );\r
252 \r
253         /* Sanity check that the timers were indeed created. */\r
254         configASSERT( xARPTimer );\r
255         configASSERT( xPeriodicTimer );\r
256         configASSERT( xEMACEventQueue );\r
257 \r
258         /* These commands will block indefinitely until they succeed, so there is\r
259         no point in checking their return values. */\r
260         xTimerStart( xARPTimer, portMAX_DELAY );\r
261         xTimerStart( xPeriodicTimer, portMAX_DELAY );\r
262 }\r
263 /*-----------------------------------------------------------*/\r
264 \r
265 static void prvUIPTimerCallback( TimerHandle_t xTimer )\r
266 {\r
267 static const unsigned long ulARPTimerExpired = uipARP_TIMER_EVENT;\r
268 static const unsigned long ulPeriodicTimerExpired = uipPERIODIC_TIMER_EVENT;\r
269 \r
270         /* This is a time callback, so calls to xQueueSend() must not attempt to\r
271         block.  As this callback is assigned to both the ARP and Periodic timers, the\r
272         first thing to do is ascertain which timer it was that actually expired. */\r
273         switch( ( int ) pvTimerGetTimerID( xTimer ) )\r
274         {\r
275                 case uipARP_TIMER               :       xQueueSend( xEMACEventQueue, &ulARPTimerExpired, uipDONT_BLOCK );\r
276                                                                         break;\r
277 \r
278                 case uipPERIODIC_TIMER  :       xQueueSend( xEMACEventQueue, &ulPeriodicTimerExpired, uipDONT_BLOCK );\r
279                                                                         break;\r
280 \r
281                 default                                 :       /* Should not get here. */\r
282                                                                         break;\r
283         }\r
284 }\r
285 /*-----------------------------------------------------------*/\r
286 \r
287 void vApplicationProcessFormInput( char *pcInputString )\r
288 {\r
289 char *c;\r
290 const unsigned long ulYellowLED = 2UL;\r
291 \r
292         /* Only interested in processing form input if this is the IO page. */\r
293         c = strstr( pcInputString, "io.shtml" );\r
294 \r
295         if( c )\r
296         {\r
297                 /* Is there a command in the string? */\r
298                 c = strstr( pcInputString, "?" );\r
299             if( c )\r
300             {\r
301                         /* Turn the LEDs on or off in accordance with the check box status. */\r
302                         if( strstr( c, "LED0=1" ) != NULL )\r
303                         {\r
304                                 /* Turn the LEDs on. */\r
305                                 vParTestSetLED( ulYellowLED, pdTRUE );\r
306                         }\r
307                         else\r
308                         {\r
309                                 /* Turn the LEDs off. */\r
310                                 vParTestSetLED( ulYellowLED, pdFALSE );\r
311                         }\r
312             }\r
313                 else\r
314                 {\r
315                         /* Some browsers will only imply that a check box is off. */\r
316                         vParTestSetLED( ulYellowLED, pdFALSE );\r
317                 }\r
318         }\r
319 }\r
320 /*-----------------------------------------------------------*/\r