]> git.sur5r.net Git - freertos/blobdiff - Demo/lwIP_AVR32_UC3/NETWORK/lwip-port/AT32UC3A/sys_arch.c
Add AVR32 port and demo files.
[freertos] / Demo / lwIP_AVR32_UC3 / NETWORK / lwip-port / AT32UC3A / sys_arch.c
diff --git a/Demo/lwIP_AVR32_UC3/NETWORK/lwip-port/AT32UC3A/sys_arch.c b/Demo/lwIP_AVR32_UC3/NETWORK/lwip-port/AT32UC3A/sys_arch.c
new file mode 100644 (file)
index 0000000..5d9ee7a
--- /dev/null
@@ -0,0 +1,431 @@
+/* This source file is part of the ATMEL FREERTOS-0.9.0 Release */\r
+\r
+/*This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief lwIP abstraction layer for AVR32 UC3.\r
+ *\r
+ * - Compiler:           GNU GCC for AVR32\r
+ * - Supported devices:  All AVR32 devices can be used.\r
+ * - AppNote:\r
+ *\r
+ * \author               Atmel Corporation: http://www.atmel.com \n\r
+ *                       Support email: avr32@atmel.com\r
+ *\r
+ *****************************************************************************/\r
+\r
+/* Copyright (c) 2007, Atmel Corporation All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above copyright notice,\r
+ * this list of conditions and the following disclaimer.\r
+ *\r
+ * 2. Redistributions in binary form must reproduce the above copyright notice,\r
+ * this list of conditions and the following disclaimer in the documentation\r
+ * and/or other materials provided with the distribution.\r
+ *\r
+ * 3. The name of ATMEL may not be used to endorse or promote products derived\r
+ * from this software without specific prior written permission.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED\r
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND\r
+ * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,\r
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\r
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\r
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\r
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+\r
+\r
+#include "conf_eth.h"\r
+\r
+#if (HTTP_USED == 1)\r
+  #include "BasicWEB.h"\r
+#endif\r
+\r
+#if (TFTP_USED == 1)\r
+  #include "BasicTFTP.h"\r
+#endif\r
+\r
+#if (SMTP_USED == 1)\r
+  #include "BasicSMTP.h"\r
+#endif\r
+\r
+/* lwIP includes. */\r
+#include "lwip/debug.h"\r
+#include "lwip/def.h"\r
+#include "lwip/sys.h"\r
+#include "lwip/mem.h"\r
+\r
+/* Message queue constants. */\r
+#define archMESG_QUEUE_LENGTH ( 6 )\r
+#define archPOST_BLOCK_TIME_MS  ( ( unsigned portLONG ) 10000 )\r
+\r
+struct timeoutlist \r
+{\r
+  struct sys_timeouts timeouts;\r
+  xTaskHandle pid;\r
+};\r
+\r
+static struct timeoutlist timeoutlist[SYS_THREAD_MAX];\r
+static u16_t nextthread = 0;\r
+int intlevel = 0;\r
+\r
+extern void ethernetif_input( void * pvParameters );\r
+\r
+/*-----------------------------------------------------------------------------------*/\r
+//  Creates an empty mailbox.\r
+sys_mbox_t\r
+sys_mbox_new(void)\r
+{\r
+  xQueueHandle mbox;\r
+\r
+  mbox = xQueueCreate( archMESG_QUEUE_LENGTH, sizeof( void * ) );\r
+\r
+  return mbox;\r
+}\r
+\r
+/*-----------------------------------------------------------------------------------*/\r
+/*\r
+  Deallocates a mailbox. If there are messages still present in the\r
+  mailbox when the mailbox is deallocated, it is an indication of a\r
+  programming error in lwIP and the developer should be notified.\r
+*/\r
+void\r
+sys_mbox_free(sys_mbox_t mbox)\r
+{\r
+  if( uxQueueMessagesWaiting( mbox ) )\r
+  {\r
+    /* Line for breakpoint.  Should never break here! */\r
+    __asm volatile ( "NOP" );\r
+  }\r
+\r
+  vQueueDelete( mbox );\r
+}\r
+\r
+/*-----------------------------------------------------------------------------------*/\r
+//   Posts the "msg" to the mailbox.\r
+void\r
+sys_mbox_post(sys_mbox_t mbox, void *data)\r
+{   \r
+  xQueueSend( mbox, &data, ( portTickType ) ( archPOST_BLOCK_TIME_MS / portTICK_RATE_MS ) );\r
+}\r
+\r
+\r
+/*-----------------------------------------------------------------------------------*/\r
+/*\r
+  Blocks the thread until a message arrives in the mailbox, but does\r
+  not block the thread longer than "timeout" milliseconds (similar to\r
+  the sys_arch_sem_wait() function). The "msg" argument is a result\r
+  parameter that is set by the function (i.e., by doing "*msg =\r
+  ptr"). The "msg" parameter maybe NULL to indicate that the message\r
+  should be dropped.\r
+\r
+  The return values are the same as for the sys_arch_sem_wait() function:\r
+  Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a\r
+  timeout.\r
+\r
+  Note that a function with a similar name, sys_mbox_fetch(), is\r
+  implemented by lwIP. \r
+*/\r
+u32_t sys_arch_mbox_fetch(sys_mbox_t mbox, void **msg, u32_t timeout)\r
+{\r
+void *dummyptr;\r
+portTickType StartTime, EndTime, Elapsed;\r
+\r
+  StartTime = xTaskGetTickCount();\r
+\r
+  if( msg == NULL )\r
+  {\r
+    msg = &dummyptr;\r
+  }\r
+  \r
+  if( timeout != 0 )\r
+  {\r
+    if(pdTRUE == xQueueReceive( mbox, &(*msg), timeout ) )\r
+    {\r
+      EndTime = xTaskGetTickCount();\r
+      Elapsed = EndTime - StartTime;\r
+      if( Elapsed == 0 )\r
+      {\r
+        Elapsed = 1;\r
+      }\r
+      return ( Elapsed );\r
+    }\r
+    else // timed out blocking for message\r
+    {\r
+      *msg = NULL;\r
+      return SYS_ARCH_TIMEOUT;\r
+    }\r
+  }\r
+  else // block forever for a message.\r
+  {\r
+    while( pdTRUE != xQueueReceive( mbox, &(*msg), 10000 ) ) // time is arbitrary\r
+    {\r
+      ;\r
+    }\r
+    EndTime = xTaskGetTickCount();\r
+    Elapsed = EndTime - StartTime;\r
+    if( Elapsed == 0 )\r
+    {\r
+      Elapsed = 1;\r
+    }\r
+    return ( Elapsed ); // return time blocked TBD test\r
+  }\r
+}\r
+\r
+/*-----------------------------------------------------------------------------------*/\r
+//  Creates and returns a new semaphore. The "count" argument specifies\r
+//  the initial state of the semaphore. TBD finish and test\r
+sys_sem_t\r
+sys_sem_new(u8_t count)\r
+{\r
+  xSemaphoreHandle  xSemaphore = NULL;\r
+\r
+  portENTER_CRITICAL();\r
+  vSemaphoreCreateBinary( xSemaphore );\r
+  if( xSemaphore == NULL )\r
+  {\r
+    return NULL;  // TBD need assert\r
+  }\r
+  if(count == 0)  // Means we want the sem to be unavailable at init state.\r
+  {\r
+    xSemaphoreTake(xSemaphore,1);\r
+  }\r
+  portEXIT_CRITICAL();\r
+\r
+  return xSemaphore;\r
+}\r
+\r
+/*-----------------------------------------------------------------------------------*/\r
+/*\r
+  Blocks the thread while waiting for the semaphore to be\r
+  signaled. If the "timeout" argument is non-zero, the thread should\r
+  only be blocked for the specified time (measured in\r
+  milliseconds).\r
+\r
+  If the timeout argument is non-zero, the return value is the number of\r
+  milliseconds spent waiting for the semaphore to be signaled. If the\r
+  semaphore wasn't signaled within the specified time, the return value is\r
+  SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore\r
+  (i.e., it was already signaled), the function may return zero.\r
+\r
+  Notice that lwIP implements a function with a similar name,\r
+  sys_sem_wait(), that uses the sys_arch_sem_wait() function.\r
+*/\r
+u32_t\r
+sys_arch_sem_wait(sys_sem_t sem, u32_t timeout)\r
+{\r
+portTickType StartTime, EndTime, Elapsed;\r
+\r
+  StartTime = xTaskGetTickCount();\r
+\r
+  if( timeout != 0)\r
+  {\r
+    if( xSemaphoreTake( sem, timeout ) == pdTRUE )\r
+    {\r
+      EndTime = xTaskGetTickCount();\r
+      Elapsed = EndTime - StartTime;\r
+      if( Elapsed == 0 )\r
+      {\r
+        Elapsed = 1;\r
+      }\r
+      return (Elapsed); // return time blocked TBD test\r
+    }\r
+    else\r
+    {\r
+      return SYS_ARCH_TIMEOUT;\r
+    }\r
+  }\r
+  else // must block without a timeout\r
+  {\r
+    while( xSemaphoreTake( sem, 10000 ) != pdTRUE )\r
+    {\r
+      ;\r
+    }\r
+    EndTime = xTaskGetTickCount();\r
+    Elapsed = EndTime - StartTime;\r
+    if( Elapsed == 0 )\r
+    {\r
+      Elapsed = 1;\r
+    }\r
+\r
+    return ( Elapsed ); // return time blocked\r
+  \r
+  }\r
+}\r
+\r
+/*-----------------------------------------------------------------------------------*/\r
+// Signals a semaphore\r
+void\r
+sys_sem_signal(sys_sem_t sem)\r
+{\r
+  xSemaphoreGive( sem );\r
+}\r
+\r
+/*-----------------------------------------------------------------------------------*/\r
+// Deallocates a semaphore\r
+void\r
+sys_sem_free(sys_sem_t sem)\r
+{\r
+  vQueueDelete( sem );\r
+}\r
+\r
+/*-----------------------------------------------------------------------------------*/\r
+// Initialize sys arch\r
+void\r
+sys_init(void)\r
+{\r
+\r
+  int i;\r
+\r
+  // Initialize the the per-thread sys_timeouts structures\r
+  // make sure there are no valid pids in the list\r
+  for(i = 0; i < SYS_THREAD_MAX; i++)\r
+  {\r
+    timeoutlist[i].pid = 0;\r
+    timeoutlist[i].timeouts.next = NULL;\r
+  }\r
+\r
+  // keep track of how many threads have been created\r
+  nextthread = 0;\r
+}\r
+\r
+/*-----------------------------------------------------------------------------------*/\r
+/*\r
+  Returns a pointer to the per-thread sys_timeouts structure. In lwIP,\r
+  each thread has a list of timeouts which is represented as a linked\r
+  list of sys_timeout structures. The sys_timeouts structure holds a\r
+  pointer to a linked list of timeouts. This function is called by\r
+  the lwIP timeout scheduler and must not return a NULL value. \r
+\r
+  In a single threaded sys_arch implementation, this function will\r
+  simply return a pointer to a global sys_timeouts variable stored in\r
+  the sys_arch module.\r
+*/\r
+struct sys_timeouts *\r
+sys_arch_timeouts(void)\r
+{\r
+int i;\r
+xTaskHandle pid;\r
+struct timeoutlist *tl;  \r
+\r
+  pid = xTaskGetCurrentTaskHandle( );\r
+\r
+  for(i = 0; i < nextthread; i++)\r
+  {\r
+    tl = &(timeoutlist[i]);\r
+    if(tl->pid == pid)\r
+    {\r
+      return &(tl->timeouts);\r
+    }\r
+  }\r
+\r
+\r
+  // If we're here, this means the scheduler gave the focus to the task as it was\r
+  // being created(because of a higher priority). Since timeoutlist[] update is\r
+  // done just after the task creation, the array is not up-to-date.\r
+  // => the last array entry must be the one of the current task.\r
+  return( &( timeoutlist[nextthread].timeouts ) );\r
+/*\r
+  // Error\r
+  return NULL;\r
+*/\r
+}\r
+\r
+/*-----------------------------------------------------------------------------------*/\r
+/*-----------------------------------------------------------------------------------*/\r
+// TBD \r
+/*-----------------------------------------------------------------------------------*/\r
+/*\r
+  Starts a new thread with priority "prio" that will begin its execution in the\r
+  function "thread()". The "arg" argument will be passed as an argument to the\r
+  thread() function. The id of the new thread is returned. Both the id and\r
+  the priority are system dependent.\r
+*/\r
+sys_thread_t sys_thread_new(void (* thread)(void *arg), void *arg, int prio)\r
+{\r
+xTaskHandle CreatedTask;\r
+int result = pdFAIL;\r
+static int iCall = 0;\r
+\r
+  if( thread == ethernetif_input )\r
+  {\r
+    result = xTaskCreate( thread, ( signed portCHAR * ) "ETHINT", netifINTERFACE_TASK_STACK_SIZE, arg, prio, &CreatedTask );\r
+  }\r
+  else if( iCall == 0 )\r
+  {\r
+    /* The first time this is called we are creating the lwIP handler. */\r
+    result = xTaskCreate( thread, ( signed portCHAR * ) "lwIP", lwipINTERFACE_STACK_SIZE, arg, prio, &CreatedTask );\r
+    iCall++;\r
+  }\r
+#if (HTTP_USED == 1)\r
+  else if (thread == vBasicWEBServer)\r
+  {\r
+    result = xTaskCreate( thread, ( signed portCHAR * ) "WEB", lwipBASIC_WEB_SERVER_STACK_SIZE, arg, prio, &CreatedTask );\r
+  }\r
+#endif\r
+#if (TFTP_USED == 1)\r
+  else if (thread == vBasicTFTPServer)\r
+  {\r
+    result = xTaskCreate( thread, ( signed portCHAR * ) "TFTP", lwipBASIC_TFTP_SERVER_STACK_SIZE, arg, prio, &CreatedTask );\r
+  }\r
+#endif\r
+#if (SMTP_USED == 1)\r
+  else if (thread == vBasicSMTPHost)\r
+  {\r
+    result = xTaskCreate( thread, ( signed portCHAR * ) "SMTP", lwipBASIC_SMTP_HOST_STACK_SIZE, arg, prio, &CreatedTask );\r
+  }\r
+#endif\r
+\r
+\r
+  // For each task created, store the task handle (pid) in the timers array.\r
+  // This scheme doesn't allow for threads to be deleted\r
+  timeoutlist[nextthread++].pid = CreatedTask;\r
+\r
+  if(result == pdPASS)\r
+  {\r
+    return CreatedTask;\r
+  }\r
+  else\r
+  {\r
+    return NULL;\r
+  }\r
+}\r
+\r
+/*\r
+  This optional function does a "fast" critical region protection and returns\r
+  the previous protection level. This function is only called during very short\r
+  critical regions. An embedded system which supports ISR-based drivers might\r
+  want to implement this function by disabling interrupts. Task-based systems\r
+  might want to implement this by using a mutex or disabling tasking. This\r
+  function should support recursive calls from the same task or interrupt. In\r
+  other words, sys_arch_protect() could be called while already protected. In\r
+  that case the return value indicates that it is already protected.\r
+\r
+  sys_arch_protect() is only required if your port is supporting an operating\r
+  system.\r
+*/\r
+sys_prot_t sys_arch_protect(void)\r
+{\r
+  vPortEnterCritical();\r
+  return 1;\r
+}\r
+\r
+/*\r
+  This optional function does a "fast" set of critical region protection to the\r
+  value specified by pval. See the documentation for sys_arch_protect() for\r
+  more information. This function is only required if your port is supporting\r
+  an operating system.\r
+*/\r
+void sys_arch_unprotect(sys_prot_t pval)\r
+{ \r
+  ( void ) pval;\r
+  vPortExitCritical();\r
+}\r
+\r