takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

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         MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_NETWORK_STACK, MBED_ERROR_CODE_INVALID_SIZE), "sys_mbox_new size error\n", queue_sz);
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         MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_NETWORK_STACK, MBED_ERROR_CODE_FAILED_OPERATION), "sys_mbox_new create error\n", (u32_t)mbox);
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         MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_NETWORK_STACK, MBED_ERROR_CODE_INVALID_INDEX), "sys_mbox_free error\n", (u32_t)mbox->fetch_idx);
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         MBED_WARNING1(MBED_MAKE_ERROR(MBED_MODULE_NETWORK_STACK, MBED_ERROR_CODE_FAILED_OPERATION), "sys_mbox_trypost error\n", flags);
00199         return ERR_MEM;
00200     }
00201 
00202     int state = osKernelLock();
00203 
00204     mbox->queue[mbox->post_idx % MB_SIZE] = msg;
00205     mbox->post_idx += 1;
00206 
00207     osEventFlagsSet(mbox->id, SYS_MBOX_FETCH_EVENT);
00208     if (mbox->post_idx - mbox->fetch_idx == MB_SIZE-1)
00209         osEventFlagsClear(mbox->id, SYS_MBOX_POST_EVENT);
00210 
00211     osKernelRestoreLock(state);
00212     return ERR_OK;
00213 }
00214 
00215 /*---------------------------------------------------------------------------*
00216  * Routine:  sys_arch_mbox_fetch
00217  *---------------------------------------------------------------------------*
00218  * Description:
00219  *      Blocks the thread until a message arrives in the mailbox, but does
00220  *      not block the thread longer than "timeout" milliseconds (similar to
00221  *      the sys_arch_sem_wait() function). The "msg" argument is a result
00222  *      parameter that is set by the function (i.e., by doing "*msg =
00223  *      ptr"). The "msg" parameter maybe NULL to indicate that the message
00224  *      should be dropped.
00225  *
00226  *      The return values are the same as for the sys_arch_sem_wait() function:
00227  *      Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a
00228  *      timeout.
00229  *
00230  *      Note that a function with a similar name, sys_mbox_fetch(), is
00231  *      implemented by lwIP.
00232  * Inputs:
00233  *      sys_mbox_t mbox         -- Handle of mailbox
00234  *      void **msg              -- Pointer to pointer to msg received
00235  *      u32_t timeout           -- Number of milliseconds until timeout
00236  * Outputs:
00237  *      u32_t                   -- SYS_ARCH_TIMEOUT if timeout, else number
00238  *                                  of milliseconds until received.
00239  *---------------------------------------------------------------------------*/
00240 u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout) {
00241     uint32_t start = osKernelGetTickCount();
00242     uint32_t flags = osEventFlagsWait(mbox->id, SYS_MBOX_FETCH_EVENT,
00243             osFlagsWaitAny | osFlagsNoClear, (timeout ? timeout : osWaitForever));
00244     if ((flags & osFlagsError) || !(flags & SYS_MBOX_FETCH_EVENT)) {
00245         MBED_WARNING1(MBED_MAKE_ERROR(MBED_MODULE_NETWORK_STACK, MBED_ERROR_CODE_TIME_OUT), "sys_arch_mbox_fetch time-out\n", flags);
00246         return SYS_ARCH_TIMEOUT;
00247     }
00248 
00249     int state = osKernelLock();
00250 
00251     if (msg)
00252         *msg = mbox->queue[mbox->fetch_idx % MB_SIZE];
00253     mbox->fetch_idx += 1;
00254 
00255     osEventFlagsSet(mbox->id, SYS_MBOX_POST_EVENT);
00256     if (mbox->post_idx == mbox->fetch_idx)
00257         osEventFlagsClear(mbox->id, SYS_MBOX_FETCH_EVENT);
00258 
00259     osKernelRestoreLock(state);
00260     return osKernelGetTickCount() - start;
00261 }
00262 
00263 /*---------------------------------------------------------------------------*
00264  * Routine:  sys_arch_mbox_tryfetch
00265  *---------------------------------------------------------------------------*
00266  * Description:
00267  *      Similar to sys_arch_mbox_fetch, but if message is not ready
00268  *      immediately, we'll return with SYS_MBOX_EMPTY.  On success, 0 is
00269  *      returned.
00270  * Inputs:
00271  *      sys_mbox_t mbox         -- Handle of mailbox
00272  *      void **msg              -- Pointer to pointer to msg received
00273  * Outputs:
00274  *      u32_t                   -- SYS_MBOX_EMPTY if no messages.  Otherwise,
00275  *                                  return ERR_OK.
00276  *---------------------------------------------------------------------------*/
00277 u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg) {
00278     uint32_t flags = osEventFlagsWait(mbox->id, SYS_MBOX_FETCH_EVENT,
00279             osFlagsWaitAny | osFlagsNoClear, 0);
00280     if ((flags & osFlagsError) || !(flags & SYS_MBOX_FETCH_EVENT)) {
00281         MBED_WARNING1(MBED_MAKE_ERROR(MBED_MODULE_NETWORK_STACK, MBED_ERROR_CODE_FAILED_OPERATION), "sys_arch_mbox_tryfetch empty\n", flags);
00282         return SYS_MBOX_EMPTY;
00283     }
00284 
00285     int state = osKernelLock();
00286 
00287     if (msg)
00288         *msg = mbox->queue[mbox->fetch_idx % MB_SIZE];
00289     mbox->fetch_idx += 1;
00290 
00291     osEventFlagsSet(mbox->id, SYS_MBOX_POST_EVENT);
00292     if (mbox->post_idx == mbox->fetch_idx)
00293         osEventFlagsClear(mbox->id, SYS_MBOX_FETCH_EVENT);
00294 
00295     osKernelRestoreLock(state);
00296     return ERR_OK;
00297 }
00298 
00299 /*---------------------------------------------------------------------------*
00300  * Routine:  sys_sem_new
00301  *---------------------------------------------------------------------------*
00302  * Description:
00303  *      Creates and returns a new semaphore. The "ucCount" argument specifies
00304  *      the initial state of the semaphore.
00305  *      NOTE: Currently this routine only creates counts of 1 or 0
00306  * Inputs:
00307  *      sys_sem_t sem         -- Handle of semaphore
00308  *      u8_t count            -- Initial count of semaphore
00309  * Outputs:
00310  *      err_t                 -- ERR_OK if semaphore created
00311  *---------------------------------------------------------------------------*/
00312 err_t sys_sem_new(sys_sem_t *sem, u8_t count) {
00313     memset(sem, 0, sizeof(*sem));
00314     sem->attr.cb_mem = &sem->data;
00315     sem->attr.cb_size = sizeof(sem->data);
00316     sem->id = osSemaphoreNew(UINT16_MAX, count, &sem->attr);
00317     if (sem->id == NULL)
00318         MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_NETWORK_STACK, MBED_ERROR_CODE_FAILED_OPERATION), "sys_sem_new create error\n", (u32_t)sem);
00319     
00320     return ERR_OK;
00321 }
00322 
00323 /*---------------------------------------------------------------------------*
00324  * Routine:  sys_arch_sem_wait
00325  *---------------------------------------------------------------------------*
00326  * Description:
00327  *      Blocks the thread while waiting for the semaphore to be
00328  *      signaled. If the "timeout" argument is non-zero, the thread should
00329  *      only be blocked for the specified time (measured in
00330  *      milliseconds).
00331  *
00332  *      If the timeout argument is non-zero, the return value is the number of
00333  *      milliseconds spent waiting for the semaphore to be signaled. If the
00334  *      semaphore wasn't signaled within the specified time, the return value is
00335  *      SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore
00336  *      (i.e., it was already signaled), the function may return zero.
00337  *
00338  *      Notice that lwIP implements a function with a similar name,
00339  *      sys_sem_wait(), that uses the sys_arch_sem_wait() function.
00340  * Inputs:
00341  *      sys_sem_t sem           -- Semaphore to wait on
00342  *      u32_t timeout           -- Number of milliseconds until timeout
00343  * Outputs:
00344  *      u32_t                   -- Time elapsed or SYS_ARCH_TIMEOUT.
00345  *---------------------------------------------------------------------------*/
00346 u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout) {
00347     u32_t start = osKernelGetTickCount();
00348     
00349     if (osSemaphoreAcquire(sem->id, (timeout != 0)?(timeout):(osWaitForever)) != osOK) {
00350         MBED_WARNING1(MBED_MAKE_ERROR(MBED_MODULE_NETWORK_STACK, MBED_ERROR_CODE_TIME_OUT), "sys_arch_sem_wait time out\n", (u32_t)sem);
00351         return SYS_ARCH_TIMEOUT;
00352     }
00353     
00354     return osKernelGetTickCount() - start;
00355 }
00356 
00357 /*---------------------------------------------------------------------------*
00358  * Routine:  sys_sem_signal
00359  *---------------------------------------------------------------------------*
00360  * Description:
00361  *      Signals (releases) a semaphore
00362  * Inputs:
00363  *      sys_sem_t sem           -- Semaphore to signal
00364  *---------------------------------------------------------------------------*/
00365 void sys_sem_signal(sys_sem_t *data) {
00366     if (osSemaphoreRelease(data->id) != osOK)
00367         MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_NETWORK_STACK, MBED_ERROR_CODE_SEMAPHORE_UNLOCK_FAILED), "sys_sem_signal error\n", (u32_t)data->id);
00368 }
00369 
00370 /*---------------------------------------------------------------------------*
00371  * Routine:  sys_sem_free
00372  *---------------------------------------------------------------------------*
00373  * Description:
00374  *      Deallocates a semaphore
00375  * Inputs:
00376  *      sys_sem_t sem           -- Semaphore to free
00377  *---------------------------------------------------------------------------*/
00378 void sys_sem_free(sys_sem_t *sem) {}
00379 
00380 /** Create a new mutex
00381  * @param mutex pointer to the mutex to create
00382  * @return a new mutex */
00383 err_t sys_mutex_new(sys_mutex_t *mutex) {
00384     memset(mutex, 0, sizeof(*mutex));
00385     mutex->attr.name = "lwip_mutex";
00386     mutex->attr.cb_mem = &mutex->data;
00387     mutex->attr.cb_size = sizeof(mutex->data);
00388     mutex->id = osMutexNew(&mutex->attr);
00389     if (mutex->id == NULL) {
00390         MBED_WARNING1(MBED_MAKE_ERROR(MBED_MODULE_NETWORK_STACK, MBED_ERROR_CODE_FAILED_OPERATION), "sys_mutex_new error\n", (u32_t)mutex);
00391         return ERR_MEM;
00392     }
00393     
00394     return ERR_OK;
00395 }
00396 
00397 /** Lock a mutex
00398  * @param mutex the mutex to lock */
00399 void sys_mutex_lock(sys_mutex_t *mutex) {
00400     if (osMutexAcquire(mutex->id, osWaitForever) != osOK)
00401         MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_NETWORK_STACK, MBED_ERROR_CODE_MUTEX_LOCK_FAILED), "sys_mutex_lock error\n", (u32_t)mutex);
00402 }
00403 
00404 /** Unlock a mutex
00405  * @param mutex the mutex to unlock */
00406 void sys_mutex_unlock(sys_mutex_t *mutex) {
00407     if (osMutexRelease(mutex->id) != osOK)
00408         MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_NETWORK_STACK, MBED_ERROR_CODE_MUTEX_UNLOCK_FAILED), "sys_mutex_unlock error\n", (u32_t)mutex);
00409 }
00410 
00411 /** Delete a mutex
00412  * @param mutex the mutex to delete */
00413 void sys_mutex_free(sys_mutex_t *mutex) {}
00414 
00415 /*---------------------------------------------------------------------------*
00416  * Routine:  sys_init
00417  *---------------------------------------------------------------------------*
00418  * Description:
00419  *      Initialize sys arch
00420  *---------------------------------------------------------------------------*/
00421 osMutexId_t lwip_sys_mutex;
00422 osMutexAttr_t lwip_sys_mutex_attr;
00423 mbed_rtos_storage_mutex_t lwip_sys_mutex_data;
00424 
00425 void sys_init(void) {
00426     lwip_sys_mutex_attr.name = "lwip_sys_mutex";
00427     lwip_sys_mutex_attr.cb_mem = &lwip_sys_mutex_data;
00428     lwip_sys_mutex_attr.cb_size = sizeof(lwip_sys_mutex_data);
00429     lwip_sys_mutex = osMutexNew(&lwip_sys_mutex_attr);
00430     if (lwip_sys_mutex == NULL)
00431         MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_NETWORK_STACK, MBED_ERROR_CODE_INITIALIZATION_FAILED), "sys_init error, mutex initialization failed\n");
00432 }
00433 
00434 /*---------------------------------------------------------------------------*
00435  * Routine:  sys_jiffies
00436  *---------------------------------------------------------------------------*
00437  * Description:
00438  *      Used by PPP as a timestamp-ish value
00439  *---------------------------------------------------------------------------*/
00440 u32_t sys_jiffies(void) {
00441     return osKernelGetTickCount();
00442 }
00443 
00444 /*---------------------------------------------------------------------------*
00445  * Routine:  sys_arch_protect
00446  *---------------------------------------------------------------------------*
00447  * Description:
00448  *      This optional function does a "fast" critical region protection and
00449  *      returns the previous protection level. This function is only called
00450  *      during very short critical regions. An embedded system which supports
00451  *      ISR-based drivers might want to implement this function by disabling
00452  *      interrupts. Task-based systems might want to implement this by using
00453  *      a mutex or disabling tasking. This function should support recursive
00454  *      calls from the same task or interrupt. In other words,
00455  *      sys_arch_protect() could be called while already protected. In
00456  *      that case the return value indicates that it is already protected.
00457  *
00458  *      sys_arch_protect() is only required if your port is supporting an
00459  *      operating system.
00460  * Outputs:
00461  *      sys_prot_t              -- Previous protection level (not used here)
00462  *---------------------------------------------------------------------------*/
00463 sys_prot_t sys_arch_protect(void) {
00464     if (osMutexAcquire(lwip_sys_mutex, osWaitForever) != osOK)
00465         MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_NETWORK_STACK, MBED_ERROR_CODE_MUTEX_LOCK_FAILED), "sys_arch_protect error\n");
00466     return (sys_prot_t) 1;
00467 }
00468 
00469 /*---------------------------------------------------------------------------*
00470  * Routine:  sys_arch_unprotect
00471  *---------------------------------------------------------------------------*
00472  * Description:
00473  *      This optional function does a "fast" set of critical region
00474  *      protection to the value specified by pval. See the documentation for
00475  *      sys_arch_protect() for more information. This function is only
00476  *      required if your port is supporting an operating system.
00477  * Inputs:
00478  *      sys_prot_t              -- Previous protection level (not used here)
00479  *---------------------------------------------------------------------------*/
00480 void sys_arch_unprotect(sys_prot_t p) {
00481     if (osMutexRelease(lwip_sys_mutex) != osOK)
00482         MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_NETWORK_STACK, MBED_ERROR_CODE_MUTEX_UNLOCK_FAILED), "sys_arch_unprotect error\n");
00483 }
00484 
00485 u32_t sys_now(void) {
00486     return osKernelGetTickCount();
00487 }
00488 
00489 void sys_msleep(u32_t ms) {
00490     osDelay(ms);
00491 }
00492 
00493 osThreadId_t lwip_tcpip_thread_id = 0;
00494 
00495 void sys_tcpip_thread_set(void)
00496 {
00497     lwip_tcpip_thread_id = osThreadGetId();
00498 }
00499 
00500 bool sys_tcpip_thread_check(void)
00501 {
00502     return osThreadGetId() == lwip_tcpip_thread_id;
00503 }
00504 
00505 // Keep a pool of thread structures
00506 static int thread_pool_index = 0;
00507 static sys_thread_data_t thread_pool[SYS_THREAD_POOL_N];
00508 
00509 /*---------------------------------------------------------------------------*
00510  * Routine:  sys_thread_new
00511  *---------------------------------------------------------------------------*
00512  * Description:
00513  *      Starts a new thread with priority "prio" that will begin its
00514  *      execution in the function "thread()". The "arg" argument will be
00515  *      passed as an argument to the thread() function. The id of the new
00516  *      thread is returned. Both the id and the priority are system
00517  *      dependent.
00518  * Inputs:
00519  *      char *name                -- Name of thread
00520  *      void (*thread)(void *arg) -- Pointer to function to run.
00521  *      void *arg                 -- Argument passed into function
00522  *      int stacksize             -- Required stack amount in bytes
00523  *      int priority              -- Thread priority
00524  * Outputs:
00525  *      sys_thread_t              -- Pointer to thread handle.
00526  *---------------------------------------------------------------------------*/
00527 #ifndef MBED_TZ_DEFAULT_ACCESS
00528 #define MBED_TZ_DEFAULT_ACCESS   0
00529 #endif    
00530 
00531  sys_thread_t sys_thread_new(const char *pcName,
00532                             void (*thread)(void *arg),
00533                             void *arg, int stacksize, int priority) {
00534     LWIP_DEBUGF(SYS_DEBUG, ("New Thread: %s\n", pcName));
00535 
00536     if (thread_pool_index >= SYS_THREAD_POOL_N)
00537         MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_NETWORK_STACK, MBED_ERROR_CODE_THREAD_CREATE_FAILED), "sys_thread_new number error\n", thread_pool_index);
00538     sys_thread_t t = (sys_thread_t)&thread_pool[thread_pool_index];
00539     thread_pool_index++;
00540 
00541     memset(t, 0, sizeof(*t));
00542     t->attr.name = pcName ? pcName : "lwip_unnamed_thread";
00543     t->attr.priority = (osPriority_t)priority;
00544     t->attr.cb_size = sizeof(t->data);
00545     t->attr.cb_mem = &t->data;
00546     t->attr.stack_size = stacksize;
00547     t->attr.stack_mem = malloc(stacksize);
00548     t->attr.tz_module = MBED_TZ_DEFAULT_ACCESS;
00549     if (t->attr.stack_mem == NULL) {
00550       MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_NETWORK_STACK, MBED_ERROR_CODE_OUT_OF_MEMORY), "unable to allocate thread stack\n", stacksize);
00551     }
00552     t->id = osThreadNew((osThreadFunc_t)thread, arg, &t->attr);
00553     if (t->id == NULL)
00554         MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_NETWORK_STACK, MBED_ERROR_CODE_THREAD_CREATE_FAILED), "sys_thread_new create error\n");
00555     
00556     return t;
00557 }
00558 
00559 #endif
00560 
00561 #ifdef LWIP_DEBUG
00562 
00563 #include <stdbool.h>
00564 
00565 #if MBED_CONF_LWIP_USE_MBED_TRACE
00566 #include "mbed-trace/mbed_trace.h"
00567 
00568 void lwip_mbed_tracef_debug(const char *fmt, ...)
00569 {
00570     va_list ap;
00571     va_start(ap, fmt);
00572     mbed_vtracef(TRACE_LEVEL_DEBUG, "lwIP", fmt, ap);
00573     va_end(ap);
00574 }
00575 
00576 void lwip_mbed_tracef_warn(const char *fmt, ...)
00577 {
00578     va_list ap;
00579     va_start(ap, fmt);
00580     mbed_vtracef(TRACE_LEVEL_WARN, "lwIP", fmt, ap);
00581     va_end(ap);
00582 }
00583 
00584 void lwip_mbed_tracef_error(const char *fmt, ...)
00585 {
00586     va_list ap;
00587     va_start(ap, fmt);
00588     mbed_vtracef(TRACE_LEVEL_ERROR, "lwIP", fmt, ap);
00589     va_end(ap);
00590 }
00591 
00592 void lwip_mbed_assert_fail(const char *msg, const char *func, const char *file, unsigned int line)
00593 {
00594     mbed_tracef(TRACE_LEVEL_ERROR, "lwIP", "Assertion failed: %s, function %s, file %s, line %u.", msg, func, file, line);
00595     exit(EXIT_FAILURE); // XXX how about abort? mbed_assert uses exit, so follow suit
00596 }
00597 #else // MBED_CONF_LWIP_USE_MBED_TRACE
00598 
00599 /** \brief  Displays an error message on assertion
00600 
00601     This function will display an error message on an assertion
00602     to the debug output.
00603 
00604     \param[in]    msg   Error message to display
00605     \param[in]    line  Line number in file with error
00606     \param[in]    file  Filename with error
00607  */
00608 void assert_printf(char *msg, int line, char *file) {
00609     if (msg)
00610         error("%s:%d in file %s\n", msg, line, file);
00611     else
00612         error("LWIP ASSERT\n");
00613 }
00614 #endif // MBED_CONF_LWIP_USE_MBED_TRACE
00615 
00616 #if TRACE_TO_ASCII_HEX_DUMP
00617 void trace_to_ascii_hex_dump(char *prefix, int len, char *data)
00618 {
00619     int line_len = 0;
00620 
00621     for (int i = 0; i < len; i++) {
00622        if ((line_len % 16) == 0) {
00623            if (line_len != 0) {
00624                LWIP_PLATFORM_DIAG(("\n"));
00625            }
00626            LWIP_PLATFORM_DIAG(("%s %06x", prefix, line_len));
00627        }
00628        line_len++;
00629        LWIP_PLATFORM_DIAG((" %02x", data[i]));
00630     }
00631     LWIP_PLATFORM_DIAG(("\n"));
00632 }
00633 #endif
00634 
00635 #endif /* LWIP_DEBUG */