]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/ARM7_LPC2368_Rowley/webserver/uIP_Task.c
d3ac6ec1d7e7f62264a813911c16928a63f42b61
[freertos] / FreeRTOS / Demo / ARM7_LPC2368_Rowley / webserver / uIP_Task.c
1 /*\r
2  * FreeRTOS Kernel V10.3.0\r
3  * Copyright (C) 2020 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.\r
14  *\r
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
17  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
18  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
19  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
20  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
21  *\r
22  * http://www.FreeRTOS.org\r
23  * http://aws.amazon.com/freertos\r
24  *\r
25  * 1 tab == 4 spaces!\r
26  */\r
27 /* Standard includes. */\r
28 #include <string.h>\r
29 \r
30 /* Scheduler includes. */\r
31 #include "FreeRTOS.h"\r
32 #include "task.h"\r
33 #include "semphr.h"\r
34 \r
35 /* uip includes. */\r
36 #include "uip.h"\r
37 #include "uip_arp.h"\r
38 #include "httpd.h"\r
39 #include "timer.h"\r
40 #include "clock-arch.h"\r
41 \r
42 /* Demo includes. */\r
43 #include "emac.h"\r
44 #include "partest.h"\r
45 \r
46 /*-----------------------------------------------------------*/\r
47 \r
48 /* MAC address configuration. */\r
49 #define uipMAC_ADDR0    0x00\r
50 #define uipMAC_ADDR1    0x12\r
51 #define uipMAC_ADDR2    0x13\r
52 #define uipMAC_ADDR3    0x10\r
53 #define uipMAC_ADDR4    0x15\r
54 #define uipMAC_ADDR5    0x11\r
55 \r
56 /* IP address configuration. */\r
57 #define uipIP_ADDR0             192\r
58 #define uipIP_ADDR1             168\r
59 #define uipIP_ADDR2             0\r
60 #define uipIP_ADDR3             200     \r
61 \r
62 /* How long to wait before attempting to connect the MAC again. */\r
63 #define uipINIT_WAIT    200\r
64 \r
65 /* Shortcut to the header within the Rx buffer. */\r
66 #define xHeader ((struct uip_eth_hdr *) &uip_buf[ 0 ])\r
67 \r
68 /* Standard constant. */\r
69 #define uipTOTAL_FRAME_HEADER_SIZE      54\r
70 \r
71 /*-----------------------------------------------------------*/\r
72 \r
73 /* \r
74  * Send the uIP buffer to the MAC. \r
75  */\r
76 static void prvENET_Send(void);\r
77 \r
78 /*\r
79  * Setup the MAC address in the MAC itself, and in the uIP stack.\r
80  */\r
81 static void prvSetMACAddress( void );\r
82 \r
83 /*\r
84  * Port functions required by the uIP stack.\r
85  */\r
86 void clock_init( void );\r
87 clock_time_t clock_time( void );\r
88 \r
89 /*-----------------------------------------------------------*/\r
90 \r
91 /* The semaphore used by the ISR to wake the uIP task. */\r
92 extern SemaphoreHandle_t xEMACSemaphore;\r
93 \r
94 /*-----------------------------------------------------------*/\r
95 \r
96 void clock_init(void)\r
97 {\r
98         /* This is done when the scheduler starts. */\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 portBASE_TYPE i;\r
111 uip_ipaddr_t xIPAddr;\r
112 struct timer periodic_timer, arp_timer;\r
113 extern void ( vEMAC_ISR_Wrapper )( void );\r
114 \r
115         /* Create the semaphore used by the ISR to wake this task. */\r
116         vSemaphoreCreateBinary( xEMACSemaphore );\r
117         \r
118         /* Initialise the uIP stack. */\r
119         timer_set( &periodic_timer, configTICK_RATE_HZ / 2 );\r
120         timer_set( &arp_timer, configTICK_RATE_HZ * 10 );\r
121         uip_init();\r
122         uip_ipaddr( xIPAddr, uipIP_ADDR0, uipIP_ADDR1, uipIP_ADDR2, uipIP_ADDR3 );\r
123         uip_sethostaddr( xIPAddr );\r
124         httpd_init();\r
125 \r
126         /* Initialise the MAC. */\r
127         while( Init_EMAC() != pdPASS )\r
128     {\r
129         vTaskDelay( uipINIT_WAIT );\r
130     }\r
131 \r
132         portENTER_CRITICAL();\r
133         {\r
134         IntEnable = INT_RX_DONE;\r
135         VICIntEnable |= 0x00200000;\r
136         VICVectAddr21 = ( long ) vEMAC_ISR_Wrapper;\r
137                 prvSetMACAddress();\r
138         }\r
139         portEXIT_CRITICAL();\r
140         \r
141 \r
142         for( ;; )\r
143         {\r
144                 /* Is there received data ready to be processed? */\r
145                 uip_len = uiGetEMACRxData( uip_buf );\r
146                 \r
147                 if( uip_len > 0 )\r
148                 {\r
149                         /* Standard uIP loop taken from the uIP manual. */\r
150                         if( xHeader->type == htons( UIP_ETHTYPE_IP ) )\r
151                         {\r
152                                 uip_arp_ipin();\r
153                                 uip_input();\r
154 \r
155                                 /* If the above function invocation resulted in data that \r
156                                 should be sent out on the network, the global variable \r
157                                 uip_len is set to a value > 0. */\r
158                                 if( uip_len > 0 )\r
159                                 {\r
160                                         uip_arp_out();\r
161                                         prvENET_Send();\r
162                                 }\r
163                         }\r
164                         else if( xHeader->type == htons( UIP_ETHTYPE_ARP ) )\r
165                         {\r
166                                 uip_arp_arpin();\r
167 \r
168                                 /* If the above function invocation resulted in data that \r
169                                 should be sent out on the network, the global variable \r
170                                 uip_len is set to a value > 0. */\r
171                                 if( uip_len > 0 )\r
172                                 {\r
173                                         prvENET_Send();\r
174                                 }\r
175                         }\r
176                 }\r
177                 else\r
178                 {\r
179                         if( timer_expired( &periodic_timer ) )\r
180                         {\r
181                                 timer_reset( &periodic_timer );\r
182                                 for( i = 0; i < UIP_CONNS; i++ )\r
183                                 {\r
184                                         uip_periodic( i );\r
185         \r
186                                         /* If the above function invocation resulted in data that \r
187                                         should be sent out on the network, the global variable \r
188                                         uip_len is set to a value > 0. */\r
189                                         if( uip_len > 0 )\r
190                                         {\r
191                                                 uip_arp_out();\r
192                                                 prvENET_Send();\r
193                                         }\r
194                                 }       \r
195         \r
196                                 /* Call the ARP timer function every 10 seconds. */\r
197                                 if( timer_expired( &arp_timer ) )\r
198                                 {\r
199                                         timer_reset( &arp_timer );\r
200                                         uip_arp_timer();\r
201                                 }\r
202                         }\r
203                         else\r
204                         {                       \r
205                                 /* We did not receive a packet, and there was no periodic\r
206                                 processing to perform.  Block for a fixed period.  If a packet\r
207                                 is received during this period we will be woken by the ISR\r
208                                 giving us the Semaphore. */\r
209                                 xSemaphoreTake( xEMACSemaphore, configTICK_RATE_HZ / 2 );                       \r
210                         }\r
211                 }\r
212         }\r
213 }\r
214 /*-----------------------------------------------------------*/\r
215 \r
216 static void prvENET_Send(void)\r
217 {\r
218     RequestSend();\r
219 \r
220     /* Copy the header into the Tx buffer. */\r
221     CopyToFrame_EMAC( uip_buf, uipTOTAL_FRAME_HEADER_SIZE );\r
222     if( uip_len > uipTOTAL_FRAME_HEADER_SIZE )\r
223     {\r
224         CopyToFrame_EMAC( uip_appdata, ( uip_len - uipTOTAL_FRAME_HEADER_SIZE ) );\r
225     }\r
226 \r
227     DoSend_EMAC( uip_len );\r
228 \r
229     RequestSend();\r
230 \r
231     /* Copy the header into the Tx buffer. */\r
232     CopyToFrame_EMAC( uip_buf, uipTOTAL_FRAME_HEADER_SIZE );\r
233     if( uip_len > uipTOTAL_FRAME_HEADER_SIZE )\r
234     {\r
235         CopyToFrame_EMAC( uip_appdata, ( uip_len - uipTOTAL_FRAME_HEADER_SIZE ) );\r
236     }\r
237 \r
238     DoSend_EMAC( uip_len );\r
239 }\r
240 /*-----------------------------------------------------------*/\r
241 \r
242 static void prvSetMACAddress( void )\r
243 {\r
244 struct uip_eth_addr xAddr;\r
245 \r
246         /* Configure the MAC address in the uIP stack. */\r
247         xAddr.addr[ 0 ] = uipMAC_ADDR0;\r
248         xAddr.addr[ 1 ] = uipMAC_ADDR1;\r
249         xAddr.addr[ 2 ] = uipMAC_ADDR2;\r
250         xAddr.addr[ 3 ] = uipMAC_ADDR3;\r
251         xAddr.addr[ 4 ] = uipMAC_ADDR4;\r
252         xAddr.addr[ 5 ] = uipMAC_ADDR5;\r
253         uip_setethaddr( xAddr );\r
254 }\r
255 /*-----------------------------------------------------------*/\r
256 \r
257 void vApplicationProcessFormInput( char *pcInputString, portBASE_TYPE xInputLength )\r
258 {\r
259 char *c, *pcText;\r
260 static char cMessageForDisplay[ 32 ];\r
261 extern QueueHandle_t xLCDQueue;\r
262 xLCDMessage xLCDMessage;\r
263 \r
264         /* Process the form input sent by the IO page of the served HTML. */\r
265 \r
266         c = strstr( pcInputString, "?" );\r
267     if( c )\r
268     {\r
269                 /* Turn LED's on or off in accordance with the check box status. */\r
270                 if( strstr( c, "LED0=1" ) != NULL )\r
271                 {\r
272                         vParTestSetLED( 5, 0 );\r
273                 }\r
274                 else\r
275                 {\r
276                         vParTestSetLED( 5, 1 );\r
277                 }               \r
278                 \r
279                 if( strstr( c, "LED1=1" ) != NULL )\r
280                 {\r
281                         vParTestSetLED( 6, 0 );\r
282                 }\r
283                 else\r
284                 {\r
285                         vParTestSetLED( 6, 1 );\r
286                 }               \r
287 \r
288                 if( strstr( c, "LED2=1" ) != NULL )\r
289                 {\r
290                         vParTestSetLED( 7, 0 );\r
291                 }\r
292                 else\r
293                 {\r
294                         vParTestSetLED( 7, 1 );\r
295                 }\r
296 \r
297                 /* Find the start of the text to be displayed on the LCD. */\r
298         pcText = strstr( c, "LCD=" );\r
299         pcText += strlen( "LCD=" );\r
300 \r
301         /* Terminate the file name for further processing within uIP. */\r
302         *c = 0x00;\r
303 \r
304         /* Terminate the LCD string. */\r
305         c = strstr( pcText, " " );\r
306         if( c != NULL )\r
307         {\r
308             *c = 0x00;\r
309         }\r
310 \r
311         /* Add required spaces. */\r
312         while( ( c = strstr( pcText, "+" ) ) != NULL )\r
313         {\r
314             *c = ' ';\r
315         }\r
316     \r
317         /* Write the message to the LCD. */\r
318                 strcpy( cMessageForDisplay, pcText );\r
319                 xLCDMessage.xColumn = 0;\r
320                 xLCDMessage.pcMessage = cMessageForDisplay;\r
321         xQueueSend( xLCDQueue, &xLCDMessage, portMAX_DELAY );\r
322     }\r
323 }\r
324 \r