Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

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