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