]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/ARM9_STR91X_IAR/webserver/uIP_Task.c
43cf40e9e699f43159849c2ae3eefe9e85017d02
[freertos] / FreeRTOS / Demo / ARM9_STR91X_IAR / webserver / uIP_Task.c
1 /*\r
2  * FreeRTOS Kernel V10.2.1\r
3  * Copyright (C) 2019 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 /* Library includes. */\r
31 #include "91x_lib.h"\r
32 #include "91x_enet.h"\r
33 \r
34 /* Scheduler includes. */\r
35 #include "FreeRTOS.h"\r
36 #include "task.h"\r
37 #include "semphr.h"\r
38 \r
39 /* uip includes. */\r
40 #include "uip.h"\r
41 #include "uip_arp.h"\r
42 #include "httpd.h"\r
43 #include "timer.h"\r
44 #include "clock-arch.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    0x14\r
53 #define uipMAC_ADDR4    0x15\r
54 #define uipMAC_ADDR5    0x20\r
55 \r
56 /* IP address configuration. */\r
57 #define uipIP_ADDR0             172\r
58 #define uipIP_ADDR1             25\r
59 #define uipIP_ADDR2             218\r
60 #define uipIP_ADDR3             11      \r
61 \r
62 /* Netmask configuration. */\r
63 #define uipNET_MASK0    255\r
64 #define uipNET_MASK1    255\r
65 #define uipNET_MASK2    255\r
66 #define uipNET_MASK3    0\r
67 \r
68 /* Gateway address configuration. */\r
69 #define uipGATEWAY_ADDR0 172\r
70 #define uipGATEWAY_ADDR1 25\r
71 #define uipGATEWAY_ADDR2 218\r
72 #define uipGATEWAY_ADDR3 1\r
73 \r
74 /* Shortcut to the header within the Rx buffer. */\r
75 #define xHeader ((struct uip_eth_hdr *) &uip_buf[ 0 ])\r
76 \r
77 /* uIP update frequencies. */\r
78 #define uipMAX_BLOCK_TIME       (configTICK_RATE_HZ / 4)\r
79 \r
80 /* Interrupt status bit definition. */\r
81 #define uipDMI_RX_CURRENT_DONE 0x8000\r
82 \r
83 /* If no buffers are available, then wait this long before looking again. */\r
84 #define uipBUFFER_WAIT_DELAY    ( 10 / portTICK_PERIOD_MS )\r
85 #define uipBUFFER_WAIT_ATTEMPTS ( 10 )\r
86 \r
87 /* Standard constant. */\r
88 #define uipTOTAL_FRAME_HEADER_SIZE      54\r
89 \r
90 /*-----------------------------------------------------------*/\r
91 \r
92 /*\r
93  * Send the uIP buffer to the MAC.\r
94  */\r
95 static void prvENET_Send(void);\r
96 \r
97 /*\r
98  * Setup the MAC address in the MAC itself, and in the uIP stack.\r
99  */\r
100 static void prvSetMACAddress( void );\r
101 \r
102 /*\r
103  * Used to return a pointer to the next buffer to be used.\r
104  */\r
105 extern unsigned char *pcGetNextBuffer( void );\r
106 \r
107 /*\r
108  * Port functions required by the uIP stack.\r
109  */\r
110 void clock_init( void );\r
111 clock_time_t clock_time( void );\r
112 \r
113 /*-----------------------------------------------------------*/\r
114 \r
115 /* The semaphore used by the ISR to wake the uIP task. */\r
116 SemaphoreHandle_t xSemaphore = NULL;\r
117 \r
118 /*-----------------------------------------------------------*/\r
119 \r
120 void clock_init(void)\r
121 {\r
122         /* This is done when the scheduler starts. */\r
123 }\r
124 /*-----------------------------------------------------------*/\r
125 \r
126 clock_time_t clock_time( void )\r
127 {\r
128         return xTaskGetTickCount();\r
129 }\r
130 /*-----------------------------------------------------------*/\r
131 \r
132 void vuIP_Task( void *pvParameters )\r
133 {\r
134 portBASE_TYPE i;\r
135 uip_ipaddr_t xIPAddr;\r
136 struct timer periodic_timer, arp_timer;\r
137 \r
138         /* Create the semaphore used by the ISR to wake this task. */\r
139         vSemaphoreCreateBinary( xSemaphore );\r
140         \r
141         /* Initialise the uIP stack. */\r
142         timer_set( &periodic_timer, configTICK_RATE_HZ / 2 );\r
143         timer_set( &arp_timer, configTICK_RATE_HZ * 10 );\r
144         uip_init();\r
145         uip_ipaddr( xIPAddr, uipIP_ADDR0, uipIP_ADDR1, uipIP_ADDR2, uipIP_ADDR3 );\r
146         uip_sethostaddr( xIPAddr );\r
147         uip_ipaddr( xIPAddr, uipNET_MASK0, uipNET_MASK1, uipNET_MASK2, uipNET_MASK3 );\r
148         uip_setnetmask( xIPAddr );\r
149         uip_ipaddr( xIPAddr, uipGATEWAY_ADDR0, uipGATEWAY_ADDR1, uipGATEWAY_ADDR2, uipGATEWAY_ADDR3 );\r
150         uip_setdraddr( xIPAddr );       \r
151         httpd_init();\r
152 \r
153         /* Initialise the MAC. */\r
154         ENET_InitClocksGPIO();\r
155         ENET_Init();\r
156         portENTER_CRITICAL();\r
157         {\r
158                 ENET_Start();\r
159                 prvSetMACAddress();\r
160                 VIC_Config( ENET_ITLine, VIC_IRQ, 1 );\r
161                 VIC_ITCmd( ENET_ITLine, ENABLE );       \r
162                 ENET_DMA->ISR = uipDMI_RX_CURRENT_DONE;\r
163                 ENET_DMA->IER = uipDMI_RX_CURRENT_DONE;\r
164         }\r
165         portEXIT_CRITICAL();\r
166         \r
167 \r
168         while(1)\r
169         {\r
170                 /* Is there received data ready to be processed? */\r
171                 uip_len = ENET_HandleRxPkt( uip_buf );\r
172                 \r
173                 if( uip_len > 0 )\r
174                 {\r
175                         /* Standard uIP loop taken from the uIP manual. */\r
176                         if( xHeader->type == htons( UIP_ETHTYPE_IP ) )\r
177                         {\r
178                                 uip_arp_ipin();\r
179                                 uip_input();\r
180 \r
181                                 /* If the above function invocation resulted in data that\r
182                                 should be sent out on the network, the global variable\r
183                                 uip_len is set to a value > 0. */\r
184                                 if( uip_len > 0 )\r
185                                 {\r
186                                         uip_arp_out();\r
187                                         prvENET_Send();\r
188                                 }\r
189                         }\r
190                         else if( xHeader->type == htons( UIP_ETHTYPE_ARP ) )\r
191                         {\r
192                                 uip_arp_arpin();\r
193 \r
194                                 /* If the above function invocation resulted in data that\r
195                                 should be sent out on the network, the global variable\r
196                                 uip_len is set to a value > 0. */\r
197                                 if( uip_len > 0 )\r
198                                 {\r
199                                         prvENET_Send();\r
200                                 }\r
201                         }\r
202                 }\r
203                 else\r
204                 {\r
205                         if( timer_expired( &periodic_timer ) )\r
206                         {\r
207                                 timer_reset( &periodic_timer );\r
208                                 for( i = 0; i < UIP_CONNS; i++ )\r
209                                 {\r
210                                         uip_periodic( i );\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                                                 uip_arp_out();\r
218                                                 prvENET_Send();\r
219                                         }\r
220                                 }       \r
221         \r
222                                 /* Call the ARP timer function every 10 seconds. */\r
223                                 if( timer_expired( &arp_timer ) )\r
224                                 {\r
225                                         timer_reset( &arp_timer );\r
226                                         uip_arp_timer();\r
227                                 }\r
228                         }\r
229                         else\r
230                         {                       \r
231                                 /* We did not receive a packet, and there was no periodic\r
232                                 processing to perform.  Block for a fixed period.  If a packet\r
233                                 is received during this period we will be woken by the ISR\r
234                                 giving us the Semaphore. */\r
235                                 xSemaphoreTake( xSemaphore, configTICK_RATE_HZ / 2 );                   \r
236                         }\r
237                 }\r
238         }\r
239 }\r
240 /*-----------------------------------------------------------*/\r
241 \r
242 static void prvENET_Send(void)\r
243 {\r
244 portBASE_TYPE i;\r
245 static unsigned char *pcTxData;\r
246 \r
247         /* Get a DMA buffer into which we can write the data to send. */\r
248         for( i = 0; i < uipBUFFER_WAIT_ATTEMPTS; i++ )\r
249         {\r
250                 pcTxData = pcGetNextBuffer();\r
251 \r
252                 if( pcTxData )\r
253                 {\r
254                         break;\r
255                 }\r
256                 else\r
257                 {\r
258                         vTaskDelay( uipBUFFER_WAIT_DELAY );\r
259                 }\r
260         }\r
261         \r
262         if( pcTxData )\r
263         {\r
264                 /* Copy the header into the Tx buffer. */\r
265                 memcpy( ( void * ) pcTxData, ( void * ) uip_buf, uipTOTAL_FRAME_HEADER_SIZE );\r
266                 if( uip_len > uipTOTAL_FRAME_HEADER_SIZE )\r
267                 {\r
268                         memcpy( ( void * ) &( pcTxData[ uipTOTAL_FRAME_HEADER_SIZE ] ), ( void * ) uip_appdata, ( uip_len - uipTOTAL_FRAME_HEADER_SIZE ) );\r
269                 }\r
270 \r
271                 ENET_TxPkt( &pcTxData, uip_len );\r
272         }\r
273 }\r
274 /*-----------------------------------------------------------*/\r
275 \r
276 void ENET_IRQHandler(void)\r
277 {\r
278 portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;\r
279 \r
280         /* Give the semaphore in case the uIP task needs waking. */\r
281         xSemaphoreGiveFromISR( xSemaphore, &xHigherPriorityTaskWoken );\r
282         \r
283         /* Clear the interrupt. */\r
284         ENET_DMA->ISR = uipDMI_RX_CURRENT_DONE;\r
285         \r
286         /* Switch tasks if necessary. */        \r
287         portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );\r
288 }\r
289 /*-----------------------------------------------------------*/\r
290 \r
291 static void prvSetMACAddress( void )\r
292 {\r
293 struct uip_eth_addr xAddr;\r
294 \r
295         /* Configure the MAC address in the uIP stack. */\r
296         xAddr.addr[ 0 ] = uipMAC_ADDR0;\r
297         xAddr.addr[ 1 ] = uipMAC_ADDR1;\r
298         xAddr.addr[ 2 ] = uipMAC_ADDR2;\r
299         xAddr.addr[ 3 ] = uipMAC_ADDR3;\r
300         xAddr.addr[ 4 ] = uipMAC_ADDR4;\r
301         xAddr.addr[ 5 ] = uipMAC_ADDR5;\r
302         uip_setethaddr( xAddr );\r
303 \r
304         /* Write the MAC address to the MAC. */ \r
305         ENET_MAC->MAL = ( uipMAC_ADDR3 << 24 ) | ( uipMAC_ADDR2 << 16 ) | ( uipMAC_ADDR1 << 8 ) | ( uipMAC_ADDR0 );\r
306         ENET_MAC->MAH = ( uipMAC_ADDR5 << 8 ) | ( uipMAC_ADDR4 );\r
307 }\r
308 \r