]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/lwIP_AVR32_UC3/NETWORK/lwip-port/AT32UC3A/sys_arch.c
Update the demo directory to use the version 8 type naming conventions.
[freertos] / FreeRTOS / Demo / lwIP_AVR32_UC3 / NETWORK / lwip-port / AT32UC3A / sys_arch.c
1 /*This file has been prepared for Doxygen automatic documentation generation.*/\r
2 /*! \file *********************************************************************\r
3  *\r
4  * \brief lwIP abstraction layer for AVR32 UC3.\r
5  *\r
6  * - Compiler:           GNU GCC for AVR32\r
7  * - Supported devices:  All AVR32 devices can be used.\r
8  * - AppNote:\r
9  *\r
10  * \author               Atmel Corporation: http://www.atmel.com \n\r
11  *                       Support and FAQ: http://support.atmel.no/\r
12  *\r
13  *****************************************************************************/\r
14 \r
15 /* Copyright (c) 2007, Atmel Corporation All rights reserved.\r
16  *\r
17  * Redistribution and use in source and binary forms, with or without\r
18  * modification, are permitted provided that the following conditions are met:\r
19  *\r
20  * 1. Redistributions of source code must retain the above copyright notice,\r
21  * this list of conditions and the following disclaimer.\r
22  *\r
23  * 2. Redistributions in binary form must reproduce the above copyright notice,\r
24  * this list of conditions and the following disclaimer in the documentation\r
25  * and/or other materials provided with the distribution.\r
26  *\r
27  * 3. The name of ATMEL may not be used to endorse or promote products derived\r
28  * from this software without specific prior written permission.\r
29  *\r
30  * THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED\r
31  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
32  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND\r
33  * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,\r
34  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r
35  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\r
36  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\r
37  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
38  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\r
39  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
40  */\r
41 \r
42 \r
43 #include "conf_eth.h"\r
44 \r
45 #if (HTTP_USED == 1)\r
46   #include "BasicWEB.h"\r
47 #endif\r
48 \r
49 #if (TFTP_USED == 1)\r
50   #include "BasicTFTP.h"\r
51 #endif\r
52 \r
53 #if (SMTP_USED == 1)\r
54   #include "BasicSMTP.h"\r
55 #endif\r
56 \r
57 /* lwIP includes. */\r
58 #include "lwip/debug.h"\r
59 #include "lwip/def.h"\r
60 #include "lwip/sys.h"\r
61 #include "lwip/mem.h"\r
62 \r
63 /* Message queue constants. */\r
64 #define archMESG_QUEUE_LENGTH ( 6 )\r
65 #define archPOST_BLOCK_TIME_MS  ( ( unsigned long ) 10000 )\r
66 \r
67 struct timeoutlist\r
68 {\r
69   struct sys_timeouts timeouts;\r
70   TaskHandle_t pid;\r
71 };\r
72 \r
73 static struct timeoutlist timeoutlist[SYS_THREAD_MAX];\r
74 static u16_t nextthread = 0;\r
75 int intlevel = 0;\r
76 \r
77 extern void ethernetif_input( void * pvParameters );\r
78 \r
79 /*-----------------------------------------------------------------------------------*/\r
80 //  Creates an empty mailbox.\r
81 sys_mbox_t\r
82 sys_mbox_new(void)\r
83 {\r
84   QueueHandle_t mbox;\r
85 \r
86   mbox = xQueueCreate( archMESG_QUEUE_LENGTH, sizeof( void * ) );\r
87 \r
88   return mbox;\r
89 }\r
90 \r
91 /*-----------------------------------------------------------------------------------*/\r
92 /*\r
93   Deallocates a mailbox. If there are messages still present in the\r
94   mailbox when the mailbox is deallocated, it is an indication of a\r
95   programming error in lwIP and the developer should be notified.\r
96 */\r
97 void\r
98 sys_mbox_free(sys_mbox_t mbox)\r
99 {\r
100   if( uxQueueMessagesWaiting( mbox ) )\r
101   {\r
102     /* Line for breakpoint.  Should never break here! */\r
103     __asm__ __volatile__ ( "nop" );\r
104   }\r
105 \r
106   vQueueDelete( mbox );\r
107 }\r
108 \r
109 /*-----------------------------------------------------------------------------------*/\r
110 //   Posts the "msg" to the mailbox.\r
111 void\r
112 sys_mbox_post(sys_mbox_t mbox, void *data)\r
113 {\r
114   xQueueSend( mbox, &data, ( TickType_t ) ( archPOST_BLOCK_TIME_MS / portTICK_PERIOD_MS ) );\r
115 }\r
116 \r
117 \r
118 /*-----------------------------------------------------------------------------------*/\r
119 /*\r
120   Blocks the thread until a message arrives in the mailbox, but does\r
121   not block the thread longer than "timeout" milliseconds (similar to\r
122   the sys_arch_sem_wait() function). The "msg" argument is a result\r
123   parameter that is set by the function (i.e., by doing "*msg =\r
124   ptr"). The "msg" parameter maybe NULL to indicate that the message\r
125   should be dropped.\r
126 \r
127   The return values are the same as for the sys_arch_sem_wait() function:\r
128   Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a\r
129   timeout.\r
130 \r
131   Note that a function with a similar name, sys_mbox_fetch(), is\r
132   implemented by lwIP.\r
133 */\r
134 u32_t sys_arch_mbox_fetch(sys_mbox_t mbox, void **msg, u32_t timeout)\r
135 {\r
136 void *dummyptr;\r
137 TickType_t StartTime, EndTime, Elapsed;\r
138 \r
139   StartTime = xTaskGetTickCount();\r
140 \r
141   if( msg == NULL )\r
142   {\r
143     msg = &dummyptr;\r
144   }\r
145 \r
146   if( timeout != 0 )\r
147   {\r
148     if(pdTRUE == xQueueReceive( mbox, &(*msg), timeout ) )\r
149     {\r
150       EndTime = xTaskGetTickCount();\r
151       Elapsed = EndTime - StartTime;\r
152       if( Elapsed == 0 )\r
153       {\r
154         Elapsed = 1;\r
155       }\r
156       return ( Elapsed );\r
157     }\r
158     else // timed out blocking for message\r
159     {\r
160       *msg = NULL;\r
161       return SYS_ARCH_TIMEOUT;\r
162     }\r
163   }\r
164   else // block forever for a message.\r
165   {\r
166     while( pdTRUE != xQueueReceive( mbox, &(*msg), 10000 ) ) // time is arbitrary\r
167     {\r
168       ;\r
169     }\r
170     EndTime = xTaskGetTickCount();\r
171     Elapsed = EndTime - StartTime;\r
172     if( Elapsed == 0 )\r
173     {\r
174       Elapsed = 1;\r
175     }\r
176     return ( Elapsed ); // return time blocked TBD test\r
177   }\r
178 }\r
179 \r
180 /*-----------------------------------------------------------------------------------*/\r
181 //  Creates and returns a new semaphore. The "count" argument specifies\r
182 //  the initial state of the semaphore. TBD finish and test\r
183 sys_sem_t\r
184 sys_sem_new(u8_t count)\r
185 {\r
186   SemaphoreHandle_t  xSemaphore = NULL;\r
187 \r
188   portENTER_CRITICAL();\r
189   vSemaphoreCreateBinary( xSemaphore );\r
190   if( xSemaphore == NULL )\r
191   {\r
192     return NULL;  // TBD need assert\r
193   }\r
194   if(count == 0)  // Means we want the sem to be unavailable at init state.\r
195   {\r
196     xSemaphoreTake(xSemaphore,1);\r
197   }\r
198   portEXIT_CRITICAL();\r
199 \r
200   return xSemaphore;\r
201 }\r
202 \r
203 /*-----------------------------------------------------------------------------------*/\r
204 /*\r
205   Blocks the thread while waiting for the semaphore to be\r
206   signaled. If the "timeout" argument is non-zero, the thread should\r
207   only be blocked for the specified time (measured in\r
208   milliseconds).\r
209 \r
210   If the timeout argument is non-zero, the return value is the number of\r
211   milliseconds spent waiting for the semaphore to be signaled. If the\r
212   semaphore wasn't signaled within the specified time, the return value is\r
213   SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore\r
214   (i.e., it was already signaled), the function may return zero.\r
215 \r
216   Notice that lwIP implements a function with a similar name,\r
217   sys_sem_wait(), that uses the sys_arch_sem_wait() function.\r
218 */\r
219 u32_t\r
220 sys_arch_sem_wait(sys_sem_t sem, u32_t timeout)\r
221 {\r
222 TickType_t StartTime, EndTime, Elapsed;\r
223 \r
224   StartTime = xTaskGetTickCount();\r
225 \r
226   if( timeout != 0)\r
227   {\r
228     if( xSemaphoreTake( sem, timeout ) == pdTRUE )\r
229     {\r
230       EndTime = xTaskGetTickCount();\r
231       Elapsed = EndTime - StartTime;\r
232       if( Elapsed == 0 )\r
233       {\r
234         Elapsed = 1;\r
235       }\r
236       return (Elapsed); // return time blocked TBD test\r
237     }\r
238     else\r
239     {\r
240       return SYS_ARCH_TIMEOUT;\r
241     }\r
242   }\r
243   else // must block without a timeout\r
244   {\r
245     while( xSemaphoreTake( sem, 10000 ) != pdTRUE )\r
246     {\r
247       ;\r
248     }\r
249     EndTime = xTaskGetTickCount();\r
250     Elapsed = EndTime - StartTime;\r
251     if( Elapsed == 0 )\r
252     {\r
253       Elapsed = 1;\r
254     }\r
255 \r
256     return ( Elapsed ); // return time blocked\r
257 \r
258   }\r
259 }\r
260 \r
261 /*-----------------------------------------------------------------------------------*/\r
262 // Signals a semaphore\r
263 void\r
264 sys_sem_signal(sys_sem_t sem)\r
265 {\r
266   xSemaphoreGive( sem );\r
267 }\r
268 \r
269 /*-----------------------------------------------------------------------------------*/\r
270 // Deallocates a semaphore\r
271 void\r
272 sys_sem_free(sys_sem_t sem)\r
273 {\r
274   vQueueDelete( sem );\r
275 }\r
276 \r
277 /*-----------------------------------------------------------------------------------*/\r
278 // Initialize sys arch\r
279 void\r
280 sys_init(void)\r
281 {\r
282 \r
283   int i;\r
284 \r
285   // Initialize the the per-thread sys_timeouts structures\r
286   // make sure there are no valid pids in the list\r
287   for(i = 0; i < SYS_THREAD_MAX; i++)\r
288   {\r
289     timeoutlist[i].pid = 0;\r
290     timeoutlist[i].timeouts.next = NULL;\r
291   }\r
292 \r
293   // keep track of how many threads have been created\r
294   nextthread = 0;\r
295 }\r
296 \r
297 /*-----------------------------------------------------------------------------------*/\r
298 /*\r
299   Returns a pointer to the per-thread sys_timeouts structure. In lwIP,\r
300   each thread has a list of timeouts which is represented as a linked\r
301   list of sys_timeout structures. The sys_timeouts structure holds a\r
302   pointer to a linked list of timeouts. This function is called by\r
303   the lwIP timeout scheduler and must not return a NULL value.\r
304 \r
305   In a single threaded sys_arch implementation, this function will\r
306   simply return a pointer to a global sys_timeouts variable stored in\r
307   the sys_arch module.\r
308 */\r
309 struct sys_timeouts *\r
310 sys_arch_timeouts(void)\r
311 {\r
312 int i;\r
313 TaskHandle_t pid;\r
314 struct timeoutlist *tl;\r
315 \r
316   pid = xTaskGetCurrentTaskHandle( );\r
317 \r
318   for(i = 0; i < nextthread; i++)\r
319   {\r
320     tl = &(timeoutlist[i]);\r
321     if(tl->pid == pid)\r
322     {\r
323       return &(tl->timeouts);\r
324     }\r
325   }\r
326 \r
327 \r
328   // If we're here, this means the scheduler gave the focus to the task as it was\r
329   // being created(because of a higher priority). Since timeoutlist[] update is\r
330   // done just after the task creation, the array is not up-to-date.\r
331   // => the last array entry must be the one of the current task.\r
332   return( &( timeoutlist[nextthread].timeouts ) );\r
333 /*\r
334   // Error\r
335   return NULL;\r
336 */\r
337 }\r
338 \r
339 /*-----------------------------------------------------------------------------------*/\r
340 /*-----------------------------------------------------------------------------------*/\r
341 // TBD\r
342 /*-----------------------------------------------------------------------------------*/\r
343 /*\r
344   Starts a new thread with priority "prio" that will begin its execution in the\r
345   function "thread()". The "arg" argument will be passed as an argument to the\r
346   thread() function. The id of the new thread is returned. Both the id and\r
347   the priority are system dependent.\r
348 */\r
349 sys_thread_t sys_thread_new(void (* thread)(void *arg), void *arg, int prio)\r
350 {\r
351 TaskHandle_t CreatedTask;\r
352 int result = pdFAIL;\r
353 static int iCall = 0;\r
354 \r
355   if( thread == ethernetif_input )\r
356   {\r
357     result = xTaskCreate( thread, "ETHINT", netifINTERFACE_TASK_STACK_SIZE, arg, prio, &CreatedTask );\r
358   }\r
359   else if( iCall == 0 )\r
360   {\r
361     /* The first time this is called we are creating the lwIP handler. */\r
362     result = xTaskCreate( thread, "lwIP", lwipINTERFACE_STACK_SIZE, arg, prio, &CreatedTask );\r
363     iCall++;\r
364   }\r
365 #if (HTTP_USED == 1)\r
366   else if (thread == vBasicWEBServer)\r
367   {\r
368     result = xTaskCreate( thread, "WEB", lwipBASIC_WEB_SERVER_STACK_SIZE, arg, prio, &CreatedTask );\r
369   }\r
370 #endif\r
371 #if (TFTP_USED == 1)\r
372   else if (thread == vBasicTFTPServer)\r
373   {\r
374     result = xTaskCreate( thread, "TFTP", lwipBASIC_TFTP_SERVER_STACK_SIZE, arg, prio, &CreatedTask );\r
375   }\r
376 #endif\r
377 #if (SMTP_USED == 1)\r
378   else if (thread == vBasicSMTPClient)\r
379   {\r
380     result = xTaskCreate( thread, "SMTP", lwipBASIC_SMTP_CLIENT_STACK_SIZE, arg, prio, &CreatedTask );\r
381   }\r
382 #endif\r
383 \r
384 \r
385   // For each task created, store the task handle (pid) in the timers array.\r
386   // This scheme doesn't allow for threads to be deleted\r
387   timeoutlist[nextthread++].pid = CreatedTask;\r
388 \r
389   if(result == pdPASS)\r
390   {\r
391     return CreatedTask;\r
392   }\r
393   else\r
394   {\r
395     return NULL;\r
396   }\r
397 }\r
398 \r
399 /*\r
400   This optional function does a "fast" critical region protection and returns\r
401   the previous protection level. This function is only called during very short\r
402   critical regions. An embedded system which supports ISR-based drivers might\r
403   want to implement this function by disabling interrupts. Task-based systems\r
404   might want to implement this by using a mutex or disabling tasking. This\r
405   function should support recursive calls from the same task or interrupt. In\r
406   other words, sys_arch_protect() could be called while already protected. In\r
407   that case the return value indicates that it is already protected.\r
408 \r
409   sys_arch_protect() is only required if your port is supporting an operating\r
410   system.\r
411 */\r
412 sys_prot_t sys_arch_protect(void)\r
413 {\r
414   vPortEnterCritical();\r
415   return 1;\r
416 }\r
417 \r
418 /*\r
419   This optional function does a "fast" set of critical region protection to the\r
420   value specified by pval. See the documentation for sys_arch_protect() for\r
421   more information. This function is only required if your port is supporting\r
422   an operating system.\r
423 */\r
424 void sys_arch_unprotect(sys_prot_t pval)\r
425 {\r
426   ( void ) pval;\r
427   vPortExitCritical();\r
428 }\r
429 \r