Knight KE / Mbed OS Game_Master
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers lwip_sys_arch.c Source File

lwip_sys_arch.c

00001 /* Copyright (C) 2012 mbed.org, MIT License
00002  *
00003  * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
00004  * and associated documentation files (the "Software"), to deal in the Software without restriction,
00005  * including without limitation the rights to use, copy, modify, merge, publish, distribute,
00006  * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
00007  * furnished to do so, subject to the following conditions:
00008  *
00009  * The above copyright notice and this permission notice shall be included in all copies or
00010  * substantial portions of the Software.
00011  *
00012  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
00013  * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00014  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
00015  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00016  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00017  */
00018 #include <string.h>
00019 
00020 /* mbed includes */
00021 #include "mbed_error.h"
00022 #include "mbed_interface.h"
00023 #include "mbed_rtos_storage.h"
00024 
00025 /* lwIP includes. */
00026 #include "lwip/opt.h"
00027 #include "lwip/debug.h"
00028 #include "lwip/def.h"
00029 #include "lwip/sys.h"
00030 #include "lwip/mem.h"
00031 
00032 /* Define the heap ourselves to give us section placement control */
00033 #ifndef ETHMEM_SECTION
00034 #if defined(TARGET_LPC4088) || defined(TARGET_LPC4088_DM)
00035 #  if defined (__ICCARM__)
00036 #     define ETHMEM_SECTION
00037 #  elif defined(TOOLCHAIN_GCC_CR)
00038 #     define ETHMEM_SECTION __attribute__((section(".data.$RamPeriph32")))
00039 #  else
00040 #     define ETHMEM_SECTION __attribute__((section("AHBSRAM1"),aligned))
00041 #  endif
00042 #elif defined(TARGET_LPC1768)
00043 #  if defined (__ICCARM__)
00044 #     define ETHMEM_SECTION
00045 #  elif defined(TOOLCHAIN_GCC_CR)
00046 #     define ETHMEM_SECTION __attribute__((section(".data.$RamPeriph32")))
00047 #  else
00048 #     define ETHMEM_SECTION __attribute__((section("AHBSRAM0"),aligned))
00049 #  endif
00050 #else
00051 #define ETHMEM_SECTION
00052 #endif
00053 #endif
00054 
00055 /* LWIP's mem.c doesn't give visibility of its overhead; memory area has to be big
00056  * enough to hold "MEM_SIZE" (which we specify) plus mem.c's overhead. Have to work
00057  * it all out here, copying code from mem.c */
00058 struct mem {
00059   /** index (-> ram[next]) of the next struct */
00060   mem_size_t next;
00061   /** index (-> ram[prev]) of the previous struct */
00062   mem_size_t prev;
00063   /** 1: this area is used; 0: this area is unused */
00064   u8_t used;
00065 };
00066 
00067 #define SIZEOF_STRUCT_MEM    LWIP_MEM_ALIGN_SIZE(sizeof(struct mem))
00068 #define MEM_SIZE_ALIGNED     LWIP_MEM_ALIGN_SIZE(MEM_SIZE)
00069 
00070 #if defined (__ICCARM__)
00071 #pragma location = ".ethusbram"
00072 #endif
00073 LWIP_DECLARE_MEMORY_ALIGNED(lwip_ram_heap, MEM_SIZE_ALIGNED + (2U*SIZEOF_STRUCT_MEM)) ETHMEM_SECTION;
00074 
00075  #if NO_SYS==1
00076 #include "cmsis.h"
00077 
00078 /* Saved total time in ms since timer was enabled */
00079 static volatile u32_t systick_timems;
00080 
00081 /* Enable systick rate and interrupt */
00082 void SysTick_Init(void) {
00083     if (SysTick_Config(SystemCoreClock / 1000)) {
00084         while (1);     /* Capture error */
00085     }
00086 }
00087 
00088 /** \brief  SysTick IRQ handler and timebase management
00089  *
00090  *  This function keeps a timebase for the sysTick that can be
00091  * used for other functions. It also calls an external function
00092  * (SysTick_User) that must be defined outside this handler.
00093  */
00094 void SysTick_Handler(void) {
00095     systick_timems++;
00096 }
00097 
00098 /* Delay for the specified number of milliSeconds */
00099 void osDelay(uint32_t ms) {
00100     uint32_t to = ms + systick_timems;
00101     while (to > systick_timems);
00102 }
00103 
00104 /* Returns the current time in mS. This is needed for the LWIP timers */
00105 u32_t sys_now(void) {
00106   return (u32_t) systick_timems;
00107 }
00108 
00109 #else
00110 /* CMSIS-RTOS implementation of the lwip operating system abstraction */
00111 #include "arch/sys_arch.h"
00112 
00113 /*---------------------------------------------------------------------------*
00114  * Routine:  sys_mbox_new
00115  *---------------------------------------------------------------------------*
00116  * Description:
00117  *      Creates a new mailbox
00118  * Inputs:
00119  *      sys_mbox_t mbox         -- Handle of mailbox
00120  *      int queue_sz            -- Size of elements in the mailbox
00121  * Outputs:
00122  *      err_t                   -- ERR_OK if message posted, else ERR_MEM
00123  *---------------------------------------------------------------------------*/
00124 err_t sys_mbox_new(sys_mbox_t *mbox, int queue_sz) {
00125     if (queue_sz > MB_SIZE)
00126         error("sys_mbox_new size error\n");
00127 
00128     memset(mbox, 0, sizeof(*mbox));
00129 
00130     mbox->attr.cb_mem = &mbox->data;
00131     mbox->attr.cb_size = sizeof(mbox->data);
00132     mbox->id = osEventFlagsNew(&mbox->attr);
00133     if (mbox->id == NULL)
00134         error("sys_mbox_new create error\n");
00135 
00136     osEventFlagsSet(mbox->id, SYS_MBOX_POST_EVENT);
00137 
00138     return ERR_OK;
00139 }
00140 
00141 /*---------------------------------------------------------------------------*
00142  * Routine:  sys_mbox_free
00143  *---------------------------------------------------------------------------*
00144  * Description:
00145  *      Deallocates a mailbox. If there are messages still present in the
00146  *      mailbox when the mailbox is deallocated, it is an indication of a
00147  *      programming error in lwIP and the developer should be notified.
00148  * Inputs:
00149  *      sys_mbox_t *mbox         -- Handle of mailbox
00150  *---------------------------------------------------------------------------*/
00151 void sys_mbox_free(sys_mbox_t *mbox) {
00152     if (mbox->post_idx != mbox->fetch_idx)
00153         error("sys_mbox_free error\n");
00154 }
00155 
00156 /*---------------------------------------------------------------------------*
00157  * Routine:  sys_mbox_post
00158  *---------------------------------------------------------------------------*
00159  * Description:
00160  *      Post the "msg" to the mailbox.
00161  * Inputs:
00162  *      sys_mbox_t mbox        -- Handle of mailbox
00163  *      void *msg              -- Pointer to data to post
00164  *---------------------------------------------------------------------------*/
00165 void sys_mbox_post(sys_mbox_t *mbox, void *msg) {
00166     osEventFlagsWait(mbox->id, SYS_MBOX_POST_EVENT,
00167             osFlagsWaitAny | osFlagsNoClear, osWaitForever);
00168 
00169     int state = osKernelLock();
00170 
00171     mbox->queue[mbox->post_idx % MB_SIZE] = msg;
00172     mbox->post_idx += 1;
00173 
00174     osEventFlagsSet(mbox->id, SYS_MBOX_FETCH_EVENT);
00175     if (mbox->post_idx - mbox->fetch_idx == MB_SIZE-1)
00176         osEventFlagsClear(mbox->id, SYS_MBOX_POST_EVENT);
00177 
00178     osKernelRestoreLock(state);
00179 }
00180 
00181 /*---------------------------------------------------------------------------*
00182  * Routine:  sys_mbox_trypost
00183  *---------------------------------------------------------------------------*
00184  * Description:
00185  *      Try to post the "msg" to the mailbox.  Returns immediately with
00186  *      error if cannot.
00187  * Inputs:
00188  *      sys_mbox_t mbox         -- Handle of mailbox
00189  *      void *msg               -- Pointer to data to post
00190  * Outputs:
00191  *      err_t                   -- ERR_OK if message posted, else ERR_MEM
00192  *                                  if not.
00193  *---------------------------------------------------------------------------*/
00194 err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg) {
00195     uint32_t flags = osEventFlagsWait(mbox->id, SYS_MBOX_POST_EVENT,
00196             osFlagsWaitAny | osFlagsNoClear, 0);
00197     if ((flags & osFlagsError) || !(flags & SYS_MBOX_POST_EVENT))
00198         return ERR_MEM;
00199 
00200     int state = osKernelLock();
00201 
00202     mbox->queue[mbox->post_idx % MB_SIZE] = msg;
00203     mbox->post_idx += 1;
00204 
00205     osEventFlagsSet(mbox->id, SYS_MBOX_FETCH_EVENT);
00206     if (mbox->post_idx - mbox->fetch_idx == MB_SIZE-1)
00207         osEventFlagsClear(mbox->id, SYS_MBOX_POST_EVENT);
00208 
00209     osKernelRestoreLock(state);
00210     return ERR_OK;
00211 }
00212 
00213 /*---------------------------------------------------------------------------*
00214  * Routine:  sys_arch_mbox_fetch
00215  *---------------------------------------------------------------------------*
00216  * Description:
00217  *      Blocks the thread until a message arrives in the mailbox, but does
00218  *      not block the thread longer than "timeout" milliseconds (similar to
00219  *      the sys_arch_sem_wait() function). The "msg" argument is a result
00220  *      parameter that is set by the function (i.e., by doing "*msg =
00221  *      ptr"). The "msg" parameter maybe NULL to indicate that the message
00222  *      should be dropped.
00223  *
00224  *      The return values are the same as for the sys_arch_sem_wait() function:
00225  *      Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a
00226  *      timeout.
00227  *
00228  *      Note that a function with a similar name, sys_mbox_fetch(), is
00229  *      implemented by lwIP.
00230  * Inputs:
00231  *      sys_mbox_t mbox         -- Handle of mailbox
00232  *      void **msg              -- Pointer to pointer to msg received
00233  *      u32_t timeout           -- Number of milliseconds until timeout
00234  * Outputs:
00235  *      u32_t                   -- SYS_ARCH_TIMEOUT if timeout, else number
00236  *                                  of milliseconds until received.
00237  *---------------------------------------------------------------------------*/
00238 u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout) {
00239     uint32_t start = osKernelGetTickCount();
00240     uint32_t flags = osEventFlagsWait(mbox->id, SYS_MBOX_FETCH_EVENT,
00241             osFlagsWaitAny | osFlagsNoClear, (timeout ? timeout : osWaitForever));
00242     if ((flags & osFlagsError) || !(flags & SYS_MBOX_FETCH_EVENT))
00243         return SYS_ARCH_TIMEOUT;
00244 
00245     int state = osKernelLock();
00246 
00247     if (msg)
00248         *msg = mbox->queue[mbox->fetch_idx % MB_SIZE];
00249     mbox->fetch_idx += 1;
00250 
00251     osEventFlagsSet(mbox->id, SYS_MBOX_POST_EVENT);
00252     if (mbox->post_idx == mbox->fetch_idx)
00253         osEventFlagsClear(mbox->id, SYS_MBOX_FETCH_EVENT);
00254 
00255     osKernelRestoreLock(state);
00256     return osKernelGetTickCount() - start;
00257 }
00258 
00259 /*---------------------------------------------------------------------------*
00260  * Routine:  sys_arch_mbox_tryfetch
00261  *---------------------------------------------------------------------------*
00262  * Description:
00263  *      Similar to sys_arch_mbox_fetch, but if message is not ready
00264  *      immediately, we'll return with SYS_MBOX_EMPTY.  On success, 0 is
00265  *      returned.
00266  * Inputs:
00267  *      sys_mbox_t mbox         -- Handle of mailbox
00268  *      void **msg              -- Pointer to pointer to msg received
00269  * Outputs:
00270  *      u32_t                   -- SYS_MBOX_EMPTY if no messages.  Otherwise,
00271  *                                  return ERR_OK.
00272  *---------------------------------------------------------------------------*/
00273 u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg) {
00274     uint32_t flags = osEventFlagsWait(mbox->id, SYS_MBOX_FETCH_EVENT,
00275             osFlagsWaitAny | osFlagsNoClear, 0);
00276     if ((flags & osFlagsError) || !(flags & SYS_MBOX_FETCH_EVENT))
00277         return SYS_MBOX_EMPTY;
00278 
00279     int state = osKernelLock();
00280 
00281     if (msg)
00282         *msg = mbox->queue[mbox->fetch_idx % MB_SIZE];
00283     mbox->fetch_idx += 1;
00284 
00285     osEventFlagsSet(mbox->id, SYS_MBOX_POST_EVENT);
00286     if (mbox->post_idx == mbox->fetch_idx)
00287         osEventFlagsClear(mbox->id, SYS_MBOX_FETCH_EVENT);
00288 
00289     osKernelRestoreLock(state);
00290     return ERR_OK;
00291 }
00292 
00293 /*---------------------------------------------------------------------------*
00294  * Routine:  sys_sem_new
00295  *---------------------------------------------------------------------------*
00296  * Description:
00297  *      Creates and returns a new semaphore. The "ucCount" argument specifies
00298  *      the initial state of the semaphore.
00299  *      NOTE: Currently this routine only creates counts of 1 or 0
00300  * Inputs:
00301  *      sys_sem_t sem         -- Handle of semaphore
00302  *      u8_t count            -- Initial count of semaphore
00303  * Outputs:
00304  *      err_t                 -- ERR_OK if semaphore created
00305  *---------------------------------------------------------------------------*/
00306 err_t sys_sem_new(sys_sem_t *sem, u8_t count) {
00307     memset(sem, 0, sizeof(*sem));
00308     sem->attr.cb_mem = &sem->data;
00309     sem->attr.cb_size = sizeof(sem->data);
00310     sem->id = osSemaphoreNew(UINT16_MAX, count, &sem->attr);
00311     if (sem->id == NULL)
00312         error("sys_sem_new create error\n");
00313     
00314     return ERR_OK;
00315 }
00316 
00317 /*---------------------------------------------------------------------------*
00318  * Routine:  sys_arch_sem_wait
00319  *---------------------------------------------------------------------------*
00320  * Description:
00321  *      Blocks the thread while waiting for the semaphore to be
00322  *      signaled. If the "timeout" argument is non-zero, the thread should
00323  *      only be blocked for the specified time (measured in
00324  *      milliseconds).
00325  *
00326  *      If the timeout argument is non-zero, the return value is the number of
00327  *      milliseconds spent waiting for the semaphore to be signaled. If the
00328  *      semaphore wasn't signaled within the specified time, the return value is
00329  *      SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore
00330  *      (i.e., it was already signaled), the function may return zero.
00331  *
00332  *      Notice that lwIP implements a function with a similar name,
00333  *      sys_sem_wait(), that uses the sys_arch_sem_wait() function.
00334  * Inputs:
00335  *      sys_sem_t sem           -- Semaphore to wait on
00336  *      u32_t timeout           -- Number of milliseconds until timeout
00337  * Outputs:
00338  *      u32_t                   -- Time elapsed or SYS_ARCH_TIMEOUT.
00339  *---------------------------------------------------------------------------*/
00340 u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout) {
00341     u32_t start = osKernelGetTickCount();
00342     
00343     if (osSemaphoreAcquire(sem->id, (timeout != 0)?(timeout):(osWaitForever)) != osOK)
00344         return SYS_ARCH_TIMEOUT;
00345     
00346     return osKernelGetTickCount() - start;
00347 }
00348 
00349 /*---------------------------------------------------------------------------*
00350  * Routine:  sys_sem_signal
00351  *---------------------------------------------------------------------------*
00352  * Description:
00353  *      Signals (releases) a semaphore
00354  * Inputs:
00355  *      sys_sem_t sem           -- Semaphore to signal
00356  *---------------------------------------------------------------------------*/
00357 void sys_sem_signal(sys_sem_t *data) {
00358     if (osSemaphoreRelease(data->id) != osOK)
00359         mbed_die(); /* Can be called by ISR do not use printf */
00360 }
00361 
00362 /*---------------------------------------------------------------------------*
00363  * Routine:  sys_sem_free
00364  *---------------------------------------------------------------------------*
00365  * Description:
00366  *      Deallocates a semaphore
00367  * Inputs:
00368  *      sys_sem_t sem           -- Semaphore to free
00369  *---------------------------------------------------------------------------*/
00370 void sys_sem_free(sys_sem_t *sem) {}
00371 
00372 /** Create a new mutex
00373  * @param mutex pointer to the mutex to create
00374  * @return a new mutex */
00375 err_t sys_mutex_new(sys_mutex_t *mutex) {
00376     memset(mutex, 0, sizeof(*mutex));
00377     mutex->attr.name = "lwip_mutex";
00378     mutex->attr.cb_mem = &mutex->data;
00379     mutex->attr.cb_size = sizeof(mutex->data);
00380     mutex->id = osMutexNew(&mutex->attr);
00381     if (mutex->id == NULL)
00382         return ERR_MEM;
00383     
00384     return ERR_OK;
00385 }
00386 
00387 /** Lock a mutex
00388  * @param mutex the mutex to lock */
00389 void sys_mutex_lock(sys_mutex_t *mutex) {
00390     if (osMutexAcquire(mutex->id, osWaitForever) != osOK)
00391         error("sys_mutex_lock error\n");
00392 }
00393 
00394 /** Unlock a mutex
00395  * @param mutex the mutex to unlock */
00396 void sys_mutex_unlock(sys_mutex_t *mutex) {
00397     if (osMutexRelease(mutex->id) != osOK)
00398         error("sys_mutex_unlock error\n");
00399 }
00400 
00401 /** Delete a mutex
00402  * @param mutex the mutex to delete */
00403 void sys_mutex_free(sys_mutex_t *mutex) {}
00404 
00405 /*---------------------------------------------------------------------------*
00406  * Routine:  sys_init
00407  *---------------------------------------------------------------------------*
00408  * Description:
00409  *      Initialize sys arch
00410  *---------------------------------------------------------------------------*/
00411 osMutexId_t lwip_sys_mutex;
00412 osMutexAttr_t lwip_sys_mutex_attr;
00413 mbed_rtos_storage_mutex_t lwip_sys_mutex_data;
00414 
00415 void sys_init(void) {
00416     lwip_sys_mutex_attr.name = "lwip_sys_mutex";
00417     lwip_sys_mutex_attr.cb_mem = &lwip_sys_mutex_data;
00418     lwip_sys_mutex_attr.cb_size = sizeof(lwip_sys_mutex_data);
00419     lwip_sys_mutex = osMutexNew(&lwip_sys_mutex_attr);
00420     if (lwip_sys_mutex == NULL)
00421         error("sys_init error\n");
00422 }
00423 
00424 /*---------------------------------------------------------------------------*
00425  * Routine:  sys_jiffies
00426  *---------------------------------------------------------------------------*
00427  * Description:
00428  *      Used by PPP as a timestamp-ish value
00429  *---------------------------------------------------------------------------*/
00430 u32_t sys_jiffies(void) {
00431     return osKernelGetTickCount();
00432 }
00433 
00434 /*---------------------------------------------------------------------------*
00435  * Routine:  sys_arch_protect
00436  *---------------------------------------------------------------------------*
00437  * Description:
00438  *      This optional function does a "fast" critical region protection and
00439  *      returns the previous protection level. This function is only called
00440  *      during very short critical regions. An embedded system which supports
00441  *      ISR-based drivers might want to implement this function by disabling
00442  *      interrupts. Task-based systems might want to implement this by using
00443  *      a mutex or disabling tasking. This function should support recursive
00444  *      calls from the same task or interrupt. In other words,
00445  *      sys_arch_protect() could be called while already protected. In
00446  *      that case the return value indicates that it is already protected.
00447  *
00448  *      sys_arch_protect() is only required if your port is supporting an
00449  *      operating system.
00450  * Outputs:
00451  *      sys_prot_t              -- Previous protection level (not used here)
00452  *---------------------------------------------------------------------------*/
00453 sys_prot_t sys_arch_protect(void) {
00454     if (osMutexAcquire(lwip_sys_mutex, osWaitForever) != osOK)
00455         error("sys_arch_protect error\n");
00456     return (sys_prot_t) 1;
00457 }
00458 
00459 /*---------------------------------------------------------------------------*
00460  * Routine:  sys_arch_unprotect
00461  *---------------------------------------------------------------------------*
00462  * Description:
00463  *      This optional function does a "fast" set of critical region
00464  *      protection to the value specified by pval. See the documentation for
00465  *      sys_arch_protect() for more information. This function is only
00466  *      required if your port is supporting an operating system.
00467  * Inputs:
00468  *      sys_prot_t              -- Previous protection level (not used here)
00469  *---------------------------------------------------------------------------*/
00470 void sys_arch_unprotect(sys_prot_t p) {
00471     if (osMutexRelease(lwip_sys_mutex) != osOK)
00472         error("sys_arch_unprotect error\n");
00473 }
00474 
00475 u32_t sys_now(void) {
00476     return osKernelGetTickCount();
00477 }
00478 
00479 void sys_msleep(u32_t ms) {
00480     osDelay(ms);
00481 }
00482 
00483 osThreadId_t lwip_tcpip_thread_id = 0;
00484 
00485 void sys_tcpip_thread_set(void)
00486 {
00487     lwip_tcpip_thread_id = osThreadGetId();
00488 }
00489 
00490 bool sys_tcpip_thread_check(void)
00491 {
00492     return osThreadGetId() == lwip_tcpip_thread_id;
00493 }
00494 
00495 // Keep a pool of thread structures
00496 static int thread_pool_index = 0;
00497 static sys_thread_data_t thread_pool[SYS_THREAD_POOL_N];
00498 
00499 /*---------------------------------------------------------------------------*
00500  * Routine:  sys_thread_new
00501  *---------------------------------------------------------------------------*
00502  * Description:
00503  *      Starts a new thread with priority "prio" that will begin its
00504  *      execution in the function "thread()". The "arg" argument will be
00505  *      passed as an argument to the thread() function. The id of the new
00506  *      thread is returned. Both the id and the priority are system
00507  *      dependent.
00508  * Inputs:
00509  *      char *name                -- Name of thread
00510  *      void (*thread)(void *arg) -- Pointer to function to run.
00511  *      void *arg                 -- Argument passed into function
00512  *      int stacksize             -- Required stack amount in bytes
00513  *      int priority              -- Thread priority
00514  * Outputs:
00515  *      sys_thread_t              -- Pointer to thread handle.
00516  *---------------------------------------------------------------------------*/
00517 #ifndef MBED_TZ_DEFAULT_ACCESS
00518 #define MBED_TZ_DEFAULT_ACCESS   0
00519 #endif    
00520 
00521  sys_thread_t sys_thread_new(const char *pcName,
00522                             void (*thread)(void *arg),
00523                             void *arg, int stacksize, int priority) {
00524     LWIP_DEBUGF(SYS_DEBUG, ("New Thread: %s\n", pcName));
00525 
00526     if (thread_pool_index >= SYS_THREAD_POOL_N)
00527         error("sys_thread_new number error\n");
00528     sys_thread_t t = (sys_thread_t)&thread_pool[thread_pool_index];
00529     thread_pool_index++;
00530 
00531     memset(t, 0, sizeof(*t));
00532     t->attr.name = pcName ? pcName : "lwip_unnamed_thread";
00533     t->attr.priority = (osPriority_t)priority;
00534     t->attr.cb_size = sizeof(t->data);
00535     t->attr.cb_mem = &t->data;
00536     t->attr.stack_size = stacksize;
00537     t->attr.stack_mem = malloc(stacksize);
00538     t->attr.tz_module = MBED_TZ_DEFAULT_ACCESS;
00539     if (t->attr.stack_mem == NULL) {
00540       error("Error allocating the stack memory");
00541     }
00542     t->id = osThreadNew((osThreadFunc_t)thread, arg, &t->attr);
00543     if (t->id == NULL)
00544         error("sys_thread_new create error\n");
00545     
00546     return t;
00547 }
00548 
00549 #endif
00550 
00551 #ifdef LWIP_DEBUG
00552 
00553 #include <stdbool.h>
00554 
00555 #if MBED_CONF_LWIP_USE_MBED_TRACE
00556 #include "mbed-trace/mbed_trace.h"
00557 
00558 void lwip_mbed_tracef_debug(const char *fmt, ...)
00559 {
00560     va_list ap;
00561     va_start(ap, fmt);
00562     mbed_vtracef(TRACE_LEVEL_DEBUG, "lwIP", fmt, ap);
00563     va_end(ap);
00564 }
00565 
00566 void lwip_mbed_tracef_warn(const char *fmt, ...)
00567 {
00568     va_list ap;
00569     va_start(ap, fmt);
00570     mbed_vtracef(TRACE_LEVEL_WARN, "lwIP", fmt, ap);
00571     va_end(ap);
00572 }
00573 
00574 void lwip_mbed_tracef_error(const char *fmt, ...)
00575 {
00576     va_list ap;
00577     va_start(ap, fmt);
00578     mbed_vtracef(TRACE_LEVEL_ERROR, "lwIP", fmt, ap);
00579     va_end(ap);
00580 }
00581 
00582 void lwip_mbed_assert_fail(const char *msg, const char *func, const char *file, unsigned int line)
00583 {
00584     mbed_tracef(TRACE_LEVEL_ERROR, "lwIP", "Assertion failed: %s, function %s, file %s, line %u.", msg, func, file, line);
00585     exit(EXIT_FAILURE); // XXX how about abort? mbed_assert uses exit, so follow suit
00586 }
00587 #else // MBED_CONF_LWIP_USE_MBED_TRACE
00588 
00589 /** \brief  Displays an error message on assertion
00590 
00591     This function will display an error message on an assertion
00592     to the debug output.
00593 
00594     \param[in]    msg   Error message to display
00595     \param[in]    line  Line number in file with error
00596     \param[in]    file  Filename with error
00597  */
00598 void assert_printf(char *msg, int line, char *file) {
00599     if (msg)
00600         error("%s:%d in file %s\n", msg, line, file);
00601     else
00602         error("LWIP ASSERT\n");
00603 }
00604 #endif // MBED_CONF_LWIP_USE_MBED_TRACE
00605 
00606 #if TRACE_TO_ASCII_HEX_DUMP
00607 void trace_to_ascii_hex_dump(char *prefix, int len, char *data)
00608 {
00609     int line_len = 0;
00610 
00611     for (int i = 0; i < len; i++) {
00612        if ((line_len % 16) == 0) {
00613            if (line_len != 0) {
00614                LWIP_PLATFORM_DIAG(("\n"));
00615            }
00616            LWIP_PLATFORM_DIAG(("%s %06x", prefix, line_len));
00617        }
00618        line_len++;
00619        LWIP_PLATFORM_DIAG((" %02x", data[i]));
00620     }
00621     LWIP_PLATFORM_DIAG(("\n"));
00622 }
00623 #endif
00624 
00625 #endif /* LWIP_DEBUG */