1 /*This file has been prepared for Doxygen automatic documentation generation.*/
\r
2 /*! \file *********************************************************************
\r
4 * \brief lwIP abstraction layer for AVR32 UC3.
\r
6 * - Compiler: GNU GCC for AVR32
\r
7 * - Supported devices: All AVR32 devices can be used.
\r
10 * \author Atmel Corporation: http://www.atmel.com \n
\r
11 * Support and FAQ: http://support.atmel.no/
\r
13 *****************************************************************************/
\r
15 /* Copyright (c) 2007, Atmel Corporation All rights reserved.
\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
20 * 1. Redistributions of source code must retain the above copyright notice,
\r
21 * this list of conditions and the following disclaimer.
\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
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
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
43 #include "conf_eth.h"
\r
45 #if (HTTP_USED == 1)
\r
46 #include "BasicWEB.h"
\r
49 #if (TFTP_USED == 1)
\r
50 #include "BasicTFTP.h"
\r
53 #if (SMTP_USED == 1)
\r
54 #include "BasicSMTP.h"
\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
63 /* Message queue constants. */
\r
64 #define archMESG_QUEUE_LENGTH ( 6 )
\r
65 #define archPOST_BLOCK_TIME_MS ( ( unsigned long ) 10000 )
\r
69 struct sys_timeouts timeouts;
\r
73 static struct timeoutlist timeoutlist[SYS_THREAD_MAX];
\r
74 static u16_t nextthread = 0;
\r
77 extern void ethernetif_input( void * pvParameters );
\r
79 /*-----------------------------------------------------------------------------------*/
\r
80 // Creates an empty mailbox.
\r
86 mbox = xQueueCreate( archMESG_QUEUE_LENGTH, sizeof( void * ) );
\r
91 /*-----------------------------------------------------------------------------------*/
\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
98 sys_mbox_free(sys_mbox_t mbox)
\r
100 if( uxQueueMessagesWaiting( mbox ) )
\r
102 /* Line for breakpoint. Should never break here! */
\r
103 __asm__ __volatile__ ( "nop" );
\r
106 vQueueDelete( mbox );
\r
109 /*-----------------------------------------------------------------------------------*/
\r
110 // Posts the "msg" to the mailbox.
\r
112 sys_mbox_post(sys_mbox_t mbox, void *data)
\r
114 xQueueSend( mbox, &data, ( TickType_t ) ( archPOST_BLOCK_TIME_MS / portTICK_PERIOD_MS ) );
\r
118 /*-----------------------------------------------------------------------------------*/
\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
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
131 Note that a function with a similar name, sys_mbox_fetch(), is
\r
132 implemented by lwIP.
\r
134 u32_t sys_arch_mbox_fetch(sys_mbox_t mbox, void **msg, u32_t timeout)
\r
137 TickType_t StartTime, EndTime, Elapsed;
\r
139 StartTime = xTaskGetTickCount();
\r
148 if(pdTRUE == xQueueReceive( mbox, &(*msg), timeout ) )
\r
150 EndTime = xTaskGetTickCount();
\r
151 Elapsed = EndTime - StartTime;
\r
156 return ( Elapsed );
\r
158 else // timed out blocking for message
\r
161 return SYS_ARCH_TIMEOUT;
\r
164 else // block forever for a message.
\r
166 while( pdTRUE != xQueueReceive( mbox, &(*msg), 10000 ) ) // time is arbitrary
\r
170 EndTime = xTaskGetTickCount();
\r
171 Elapsed = EndTime - StartTime;
\r
176 return ( Elapsed ); // return time blocked TBD test
\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
184 sys_sem_new(u8_t count)
\r
186 SemaphoreHandle_t xSemaphore = NULL;
\r
188 portENTER_CRITICAL();
\r
189 vSemaphoreCreateBinary( xSemaphore );
\r
190 if( xSemaphore == NULL )
\r
192 return NULL; // TBD need assert
\r
194 if(count == 0) // Means we want the sem to be unavailable at init state.
\r
196 xSemaphoreTake(xSemaphore,1);
\r
198 portEXIT_CRITICAL();
\r
203 /*-----------------------------------------------------------------------------------*/
\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
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
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
220 sys_arch_sem_wait(sys_sem_t sem, u32_t timeout)
\r
222 TickType_t StartTime, EndTime, Elapsed;
\r
224 StartTime = xTaskGetTickCount();
\r
228 if( xSemaphoreTake( sem, timeout ) == pdTRUE )
\r
230 EndTime = xTaskGetTickCount();
\r
231 Elapsed = EndTime - StartTime;
\r
236 return (Elapsed); // return time blocked TBD test
\r
240 return SYS_ARCH_TIMEOUT;
\r
243 else // must block without a timeout
\r
245 while( xSemaphoreTake( sem, 10000 ) != pdTRUE )
\r
249 EndTime = xTaskGetTickCount();
\r
250 Elapsed = EndTime - StartTime;
\r
256 return ( Elapsed ); // return time blocked
\r
261 /*-----------------------------------------------------------------------------------*/
\r
262 // Signals a semaphore
\r
264 sys_sem_signal(sys_sem_t sem)
\r
266 xSemaphoreGive( sem );
\r
269 /*-----------------------------------------------------------------------------------*/
\r
270 // Deallocates a semaphore
\r
272 sys_sem_free(sys_sem_t sem)
\r
274 vQueueDelete( sem );
\r
277 /*-----------------------------------------------------------------------------------*/
\r
278 // Initialize sys arch
\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
289 timeoutlist[i].pid = 0;
\r
290 timeoutlist[i].timeouts.next = NULL;
\r
293 // keep track of how many threads have been created
\r
297 /*-----------------------------------------------------------------------------------*/
\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
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
309 struct sys_timeouts *
\r
310 sys_arch_timeouts(void)
\r
314 struct timeoutlist *tl;
\r
316 pid = xTaskGetCurrentTaskHandle( );
\r
318 for(i = 0; i < nextthread; i++)
\r
320 tl = &(timeoutlist[i]);
\r
323 return &(tl->timeouts);
\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
339 /*-----------------------------------------------------------------------------------*/
\r
340 /*-----------------------------------------------------------------------------------*/
\r
342 /*-----------------------------------------------------------------------------------*/
\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
349 sys_thread_t sys_thread_new(void (* thread)(void *arg), void *arg, int prio)
\r
351 TaskHandle_t CreatedTask;
\r
352 int result = pdFAIL;
\r
353 static int iCall = 0;
\r
355 if( thread == ethernetif_input )
\r
357 result = xTaskCreate( thread, "ETHINT", netifINTERFACE_TASK_STACK_SIZE, arg, prio, &CreatedTask );
\r
359 else if( iCall == 0 )
\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
365 #if (HTTP_USED == 1)
\r
366 else if (thread == vBasicWEBServer)
\r
368 result = xTaskCreate( thread, "WEB", lwipBASIC_WEB_SERVER_STACK_SIZE, arg, prio, &CreatedTask );
\r
371 #if (TFTP_USED == 1)
\r
372 else if (thread == vBasicTFTPServer)
\r
374 result = xTaskCreate( thread, "TFTP", lwipBASIC_TFTP_SERVER_STACK_SIZE, arg, prio, &CreatedTask );
\r
377 #if (SMTP_USED == 1)
\r
378 else if (thread == vBasicSMTPClient)
\r
380 result = xTaskCreate( thread, "SMTP", lwipBASIC_SMTP_CLIENT_STACK_SIZE, arg, prio, &CreatedTask );
\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
389 if(result == pdPASS)
\r
391 return CreatedTask;
\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
409 sys_arch_protect() is only required if your port is supporting an operating
\r
412 sys_prot_t sys_arch_protect(void)
\r
414 vPortEnterCritical();
\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
424 void sys_arch_unprotect(sys_prot_t pval)
\r
427 vPortExitCritical();
\r