STM32F7 Ethernet interface for nucleo STM32F767

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