mirror of https://github.com/ARMmbed/mbed-os.git
626 lines
22 KiB
C
626 lines
22 KiB
C
/* Copyright (C) 2012 mbed.org, MIT License
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
|
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
|
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
|
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in all copies or
|
|
* substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
|
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
*/
|
|
#include <string.h>
|
|
|
|
/* mbed includes */
|
|
#include "mbed_error.h"
|
|
#include "mbed_interface.h"
|
|
#include "mbed_rtos_storage.h"
|
|
|
|
/* lwIP includes. */
|
|
#include "lwip/opt.h"
|
|
#include "lwip/debug.h"
|
|
#include "lwip/def.h"
|
|
#include "lwip/sys.h"
|
|
#include "lwip/mem.h"
|
|
|
|
/* Define the heap ourselves to give us section placement control */
|
|
#ifndef ETHMEM_SECTION
|
|
#if defined(TARGET_LPC4088) || defined(TARGET_LPC4088_DM)
|
|
# if defined (__ICCARM__)
|
|
# define ETHMEM_SECTION
|
|
# elif defined(TOOLCHAIN_GCC_CR)
|
|
# define ETHMEM_SECTION __attribute__((section(".data.$RamPeriph32")))
|
|
# else
|
|
# define ETHMEM_SECTION __attribute__((section("AHBSRAM1"),aligned))
|
|
# endif
|
|
#elif defined(TARGET_LPC1768)
|
|
# if defined (__ICCARM__)
|
|
# define ETHMEM_SECTION
|
|
# elif defined(TOOLCHAIN_GCC_CR)
|
|
# define ETHMEM_SECTION __attribute__((section(".data.$RamPeriph32")))
|
|
# else
|
|
# define ETHMEM_SECTION __attribute__((section("AHBSRAM0"),aligned))
|
|
# endif
|
|
#else
|
|
#define ETHMEM_SECTION
|
|
#endif
|
|
#endif
|
|
|
|
/* LWIP's mem.c doesn't give visibility of its overhead; memory area has to be big
|
|
* enough to hold "MEM_SIZE" (which we specify) plus mem.c's overhead. Have to work
|
|
* it all out here, copying code from mem.c */
|
|
struct mem {
|
|
/** index (-> ram[next]) of the next struct */
|
|
mem_size_t next;
|
|
/** index (-> ram[prev]) of the previous struct */
|
|
mem_size_t prev;
|
|
/** 1: this area is used; 0: this area is unused */
|
|
u8_t used;
|
|
};
|
|
|
|
#define SIZEOF_STRUCT_MEM LWIP_MEM_ALIGN_SIZE(sizeof(struct mem))
|
|
#define MEM_SIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(MEM_SIZE)
|
|
|
|
#if defined (__ICCARM__)
|
|
#pragma location = ".ethusbram"
|
|
#endif
|
|
LWIP_DECLARE_MEMORY_ALIGNED(lwip_ram_heap, MEM_SIZE_ALIGNED + (2U*SIZEOF_STRUCT_MEM)) ETHMEM_SECTION;
|
|
|
|
#if NO_SYS==1
|
|
#include "cmsis.h"
|
|
|
|
/* Saved total time in ms since timer was enabled */
|
|
static volatile u32_t systick_timems;
|
|
|
|
/* Enable systick rate and interrupt */
|
|
void SysTick_Init(void) {
|
|
if (SysTick_Config(SystemCoreClock / 1000)) {
|
|
while (1); /* Capture error */
|
|
}
|
|
}
|
|
|
|
/** \brief SysTick IRQ handler and timebase management
|
|
*
|
|
* This function keeps a timebase for the sysTick that can be
|
|
* used for other functions. It also calls an external function
|
|
* (SysTick_User) that must be defined outside this handler.
|
|
*/
|
|
void SysTick_Handler(void) {
|
|
systick_timems++;
|
|
}
|
|
|
|
/* Delay for the specified number of milliSeconds */
|
|
void osDelay(uint32_t ms) {
|
|
uint32_t to = ms + systick_timems;
|
|
while (to > systick_timems);
|
|
}
|
|
|
|
/* Returns the current time in mS. This is needed for the LWIP timers */
|
|
u32_t sys_now(void) {
|
|
return (u32_t) systick_timems;
|
|
}
|
|
|
|
#else
|
|
/* CMSIS-RTOS implementation of the lwip operating system abstraction */
|
|
#include "arch/sys_arch.h"
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* Routine: sys_mbox_new
|
|
*---------------------------------------------------------------------------*
|
|
* Description:
|
|
* Creates a new mailbox
|
|
* Inputs:
|
|
* sys_mbox_t mbox -- Handle of mailbox
|
|
* int queue_sz -- Size of elements in the mailbox
|
|
* Outputs:
|
|
* err_t -- ERR_OK if message posted, else ERR_MEM
|
|
*---------------------------------------------------------------------------*/
|
|
err_t sys_mbox_new(sys_mbox_t *mbox, int queue_sz) {
|
|
if (queue_sz > MB_SIZE)
|
|
error("sys_mbox_new size error\n");
|
|
|
|
memset(mbox, 0, sizeof(*mbox));
|
|
|
|
mbox->attr.cb_mem = &mbox->data;
|
|
mbox->attr.cb_size = sizeof(mbox->data);
|
|
mbox->id = osEventFlagsNew(&mbox->attr);
|
|
if (mbox->id == NULL)
|
|
error("sys_mbox_new create error\n");
|
|
|
|
osEventFlagsSet(mbox->id, SYS_MBOX_POST_EVENT);
|
|
|
|
return ERR_OK;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* Routine: sys_mbox_free
|
|
*---------------------------------------------------------------------------*
|
|
* Description:
|
|
* Deallocates a mailbox. If there are messages still present in the
|
|
* mailbox when the mailbox is deallocated, it is an indication of a
|
|
* programming error in lwIP and the developer should be notified.
|
|
* Inputs:
|
|
* sys_mbox_t *mbox -- Handle of mailbox
|
|
*---------------------------------------------------------------------------*/
|
|
void sys_mbox_free(sys_mbox_t *mbox) {
|
|
if (mbox->post_idx != mbox->fetch_idx)
|
|
error("sys_mbox_free error\n");
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* Routine: sys_mbox_post
|
|
*---------------------------------------------------------------------------*
|
|
* Description:
|
|
* Post the "msg" to the mailbox.
|
|
* Inputs:
|
|
* sys_mbox_t mbox -- Handle of mailbox
|
|
* void *msg -- Pointer to data to post
|
|
*---------------------------------------------------------------------------*/
|
|
void sys_mbox_post(sys_mbox_t *mbox, void *msg) {
|
|
osEventFlagsWait(mbox->id, SYS_MBOX_POST_EVENT,
|
|
osFlagsWaitAny | osFlagsNoClear, osWaitForever);
|
|
|
|
int state = osKernelLock();
|
|
|
|
mbox->queue[mbox->post_idx % MB_SIZE] = msg;
|
|
mbox->post_idx += 1;
|
|
|
|
osEventFlagsSet(mbox->id, SYS_MBOX_FETCH_EVENT);
|
|
if (mbox->post_idx - mbox->fetch_idx == MB_SIZE-1)
|
|
osEventFlagsClear(mbox->id, SYS_MBOX_POST_EVENT);
|
|
|
|
osKernelRestoreLock(state);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* Routine: sys_mbox_trypost
|
|
*---------------------------------------------------------------------------*
|
|
* Description:
|
|
* Try to post the "msg" to the mailbox. Returns immediately with
|
|
* error if cannot.
|
|
* Inputs:
|
|
* sys_mbox_t mbox -- Handle of mailbox
|
|
* void *msg -- Pointer to data to post
|
|
* Outputs:
|
|
* err_t -- ERR_OK if message posted, else ERR_MEM
|
|
* if not.
|
|
*---------------------------------------------------------------------------*/
|
|
err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg) {
|
|
uint32_t flags = osEventFlagsWait(mbox->id, SYS_MBOX_POST_EVENT,
|
|
osFlagsWaitAny | osFlagsNoClear, 0);
|
|
if ((flags & osFlagsError) || !(flags & SYS_MBOX_POST_EVENT))
|
|
return ERR_MEM;
|
|
|
|
int state = osKernelLock();
|
|
|
|
mbox->queue[mbox->post_idx % MB_SIZE] = msg;
|
|
mbox->post_idx += 1;
|
|
|
|
osEventFlagsSet(mbox->id, SYS_MBOX_FETCH_EVENT);
|
|
if (mbox->post_idx - mbox->fetch_idx == MB_SIZE-1)
|
|
osEventFlagsClear(mbox->id, SYS_MBOX_POST_EVENT);
|
|
|
|
osKernelRestoreLock(state);
|
|
return ERR_OK;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* Routine: sys_arch_mbox_fetch
|
|
*---------------------------------------------------------------------------*
|
|
* Description:
|
|
* Blocks the thread until a message arrives in the mailbox, but does
|
|
* not block the thread longer than "timeout" milliseconds (similar to
|
|
* the sys_arch_sem_wait() function). The "msg" argument is a result
|
|
* parameter that is set by the function (i.e., by doing "*msg =
|
|
* ptr"). The "msg" parameter maybe NULL to indicate that the message
|
|
* should be dropped.
|
|
*
|
|
* The return values are the same as for the sys_arch_sem_wait() function:
|
|
* Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a
|
|
* timeout.
|
|
*
|
|
* Note that a function with a similar name, sys_mbox_fetch(), is
|
|
* implemented by lwIP.
|
|
* Inputs:
|
|
* sys_mbox_t mbox -- Handle of mailbox
|
|
* void **msg -- Pointer to pointer to msg received
|
|
* u32_t timeout -- Number of milliseconds until timeout
|
|
* Outputs:
|
|
* u32_t -- SYS_ARCH_TIMEOUT if timeout, else number
|
|
* of milliseconds until received.
|
|
*---------------------------------------------------------------------------*/
|
|
u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout) {
|
|
uint32_t start = osKernelGetTickCount();
|
|
uint32_t flags = osEventFlagsWait(mbox->id, SYS_MBOX_FETCH_EVENT,
|
|
osFlagsWaitAny | osFlagsNoClear, (timeout ? timeout : osWaitForever));
|
|
if ((flags & osFlagsError) || !(flags & SYS_MBOX_FETCH_EVENT))
|
|
return SYS_ARCH_TIMEOUT;
|
|
|
|
int state = osKernelLock();
|
|
|
|
if (msg)
|
|
*msg = mbox->queue[mbox->fetch_idx % MB_SIZE];
|
|
mbox->fetch_idx += 1;
|
|
|
|
osEventFlagsSet(mbox->id, SYS_MBOX_POST_EVENT);
|
|
if (mbox->post_idx == mbox->fetch_idx)
|
|
osEventFlagsClear(mbox->id, SYS_MBOX_FETCH_EVENT);
|
|
|
|
osKernelRestoreLock(state);
|
|
return osKernelGetTickCount() - start;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* Routine: sys_arch_mbox_tryfetch
|
|
*---------------------------------------------------------------------------*
|
|
* Description:
|
|
* Similar to sys_arch_mbox_fetch, but if message is not ready
|
|
* immediately, we'll return with SYS_MBOX_EMPTY. On success, 0 is
|
|
* returned.
|
|
* Inputs:
|
|
* sys_mbox_t mbox -- Handle of mailbox
|
|
* void **msg -- Pointer to pointer to msg received
|
|
* Outputs:
|
|
* u32_t -- SYS_MBOX_EMPTY if no messages. Otherwise,
|
|
* return ERR_OK.
|
|
*---------------------------------------------------------------------------*/
|
|
u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg) {
|
|
uint32_t flags = osEventFlagsWait(mbox->id, SYS_MBOX_FETCH_EVENT,
|
|
osFlagsWaitAny | osFlagsNoClear, 0);
|
|
if ((flags & osFlagsError) || !(flags & SYS_MBOX_FETCH_EVENT))
|
|
return SYS_MBOX_EMPTY;
|
|
|
|
int state = osKernelLock();
|
|
|
|
if (msg)
|
|
*msg = mbox->queue[mbox->fetch_idx % MB_SIZE];
|
|
mbox->fetch_idx += 1;
|
|
|
|
osEventFlagsSet(mbox->id, SYS_MBOX_POST_EVENT);
|
|
if (mbox->post_idx == mbox->fetch_idx)
|
|
osEventFlagsClear(mbox->id, SYS_MBOX_FETCH_EVENT);
|
|
|
|
osKernelRestoreLock(state);
|
|
return ERR_OK;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* Routine: sys_sem_new
|
|
*---------------------------------------------------------------------------*
|
|
* Description:
|
|
* Creates and returns a new semaphore. The "ucCount" argument specifies
|
|
* the initial state of the semaphore.
|
|
* NOTE: Currently this routine only creates counts of 1 or 0
|
|
* Inputs:
|
|
* sys_sem_t sem -- Handle of semaphore
|
|
* u8_t count -- Initial count of semaphore
|
|
* Outputs:
|
|
* err_t -- ERR_OK if semaphore created
|
|
*---------------------------------------------------------------------------*/
|
|
err_t sys_sem_new(sys_sem_t *sem, u8_t count) {
|
|
memset(sem, 0, sizeof(*sem));
|
|
sem->attr.cb_mem = &sem->data;
|
|
sem->attr.cb_size = sizeof(sem->data);
|
|
sem->id = osSemaphoreNew(UINT16_MAX, count, &sem->attr);
|
|
if (sem->id == NULL)
|
|
error("sys_sem_new create error\n");
|
|
|
|
return ERR_OK;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* Routine: sys_arch_sem_wait
|
|
*---------------------------------------------------------------------------*
|
|
* Description:
|
|
* Blocks the thread while waiting for the semaphore to be
|
|
* signaled. If the "timeout" argument is non-zero, the thread should
|
|
* only be blocked for the specified time (measured in
|
|
* milliseconds).
|
|
*
|
|
* If the timeout argument is non-zero, the return value is the number of
|
|
* milliseconds spent waiting for the semaphore to be signaled. If the
|
|
* semaphore wasn't signaled within the specified time, the return value is
|
|
* SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore
|
|
* (i.e., it was already signaled), the function may return zero.
|
|
*
|
|
* Notice that lwIP implements a function with a similar name,
|
|
* sys_sem_wait(), that uses the sys_arch_sem_wait() function.
|
|
* Inputs:
|
|
* sys_sem_t sem -- Semaphore to wait on
|
|
* u32_t timeout -- Number of milliseconds until timeout
|
|
* Outputs:
|
|
* u32_t -- Time elapsed or SYS_ARCH_TIMEOUT.
|
|
*---------------------------------------------------------------------------*/
|
|
u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout) {
|
|
u32_t start = osKernelGetTickCount();
|
|
|
|
if (osSemaphoreAcquire(sem->id, (timeout != 0)?(timeout):(osWaitForever)) != osOK)
|
|
return SYS_ARCH_TIMEOUT;
|
|
|
|
return osKernelGetTickCount() - start;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* Routine: sys_sem_signal
|
|
*---------------------------------------------------------------------------*
|
|
* Description:
|
|
* Signals (releases) a semaphore
|
|
* Inputs:
|
|
* sys_sem_t sem -- Semaphore to signal
|
|
*---------------------------------------------------------------------------*/
|
|
void sys_sem_signal(sys_sem_t *data) {
|
|
if (osSemaphoreRelease(data->id) != osOK)
|
|
mbed_die(); /* Can be called by ISR do not use printf */
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* Routine: sys_sem_free
|
|
*---------------------------------------------------------------------------*
|
|
* Description:
|
|
* Deallocates a semaphore
|
|
* Inputs:
|
|
* sys_sem_t sem -- Semaphore to free
|
|
*---------------------------------------------------------------------------*/
|
|
void sys_sem_free(sys_sem_t *sem) {}
|
|
|
|
/** Create a new mutex
|
|
* @param mutex pointer to the mutex to create
|
|
* @return a new mutex */
|
|
err_t sys_mutex_new(sys_mutex_t *mutex) {
|
|
memset(mutex, 0, sizeof(*mutex));
|
|
mutex->attr.name = "lwip_mutex";
|
|
mutex->attr.cb_mem = &mutex->data;
|
|
mutex->attr.cb_size = sizeof(mutex->data);
|
|
mutex->id = osMutexNew(&mutex->attr);
|
|
if (mutex->id == NULL)
|
|
return ERR_MEM;
|
|
|
|
return ERR_OK;
|
|
}
|
|
|
|
/** Lock a mutex
|
|
* @param mutex the mutex to lock */
|
|
void sys_mutex_lock(sys_mutex_t *mutex) {
|
|
if (osMutexAcquire(mutex->id, osWaitForever) != osOK)
|
|
error("sys_mutex_lock error\n");
|
|
}
|
|
|
|
/** Unlock a mutex
|
|
* @param mutex the mutex to unlock */
|
|
void sys_mutex_unlock(sys_mutex_t *mutex) {
|
|
if (osMutexRelease(mutex->id) != osOK)
|
|
error("sys_mutex_unlock error\n");
|
|
}
|
|
|
|
/** Delete a mutex
|
|
* @param mutex the mutex to delete */
|
|
void sys_mutex_free(sys_mutex_t *mutex) {}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* Routine: sys_init
|
|
*---------------------------------------------------------------------------*
|
|
* Description:
|
|
* Initialize sys arch
|
|
*---------------------------------------------------------------------------*/
|
|
osMutexId_t lwip_sys_mutex;
|
|
osMutexAttr_t lwip_sys_mutex_attr;
|
|
mbed_rtos_storage_mutex_t lwip_sys_mutex_data;
|
|
|
|
void sys_init(void) {
|
|
lwip_sys_mutex_attr.name = "lwip_sys_mutex";
|
|
lwip_sys_mutex_attr.cb_mem = &lwip_sys_mutex_data;
|
|
lwip_sys_mutex_attr.cb_size = sizeof(lwip_sys_mutex_data);
|
|
lwip_sys_mutex = osMutexNew(&lwip_sys_mutex_attr);
|
|
if (lwip_sys_mutex == NULL)
|
|
error("sys_init error\n");
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* Routine: sys_jiffies
|
|
*---------------------------------------------------------------------------*
|
|
* Description:
|
|
* Used by PPP as a timestamp-ish value
|
|
*---------------------------------------------------------------------------*/
|
|
u32_t sys_jiffies(void) {
|
|
return osKernelGetTickCount();
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* Routine: sys_arch_protect
|
|
*---------------------------------------------------------------------------*
|
|
* Description:
|
|
* This optional function does a "fast" critical region protection and
|
|
* returns the previous protection level. This function is only called
|
|
* during very short critical regions. An embedded system which supports
|
|
* ISR-based drivers might want to implement this function by disabling
|
|
* interrupts. Task-based systems might want to implement this by using
|
|
* a mutex or disabling tasking. This function should support recursive
|
|
* calls from the same task or interrupt. In other words,
|
|
* sys_arch_protect() could be called while already protected. In
|
|
* that case the return value indicates that it is already protected.
|
|
*
|
|
* sys_arch_protect() is only required if your port is supporting an
|
|
* operating system.
|
|
* Outputs:
|
|
* sys_prot_t -- Previous protection level (not used here)
|
|
*---------------------------------------------------------------------------*/
|
|
sys_prot_t sys_arch_protect(void) {
|
|
if (osMutexAcquire(lwip_sys_mutex, osWaitForever) != osOK)
|
|
error("sys_arch_protect error\n");
|
|
return (sys_prot_t) 1;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* Routine: sys_arch_unprotect
|
|
*---------------------------------------------------------------------------*
|
|
* Description:
|
|
* This optional function does a "fast" set of critical region
|
|
* protection to the value specified by pval. See the documentation for
|
|
* sys_arch_protect() for more information. This function is only
|
|
* required if your port is supporting an operating system.
|
|
* Inputs:
|
|
* sys_prot_t -- Previous protection level (not used here)
|
|
*---------------------------------------------------------------------------*/
|
|
void sys_arch_unprotect(sys_prot_t p) {
|
|
if (osMutexRelease(lwip_sys_mutex) != osOK)
|
|
error("sys_arch_unprotect error\n");
|
|
}
|
|
|
|
u32_t sys_now(void) {
|
|
return osKernelGetTickCount();
|
|
}
|
|
|
|
void sys_msleep(u32_t ms) {
|
|
osDelay(ms);
|
|
}
|
|
|
|
osThreadId_t lwip_tcpip_thread_id = 0;
|
|
|
|
void sys_tcpip_thread_set(void)
|
|
{
|
|
lwip_tcpip_thread_id = osThreadGetId();
|
|
}
|
|
|
|
bool sys_tcpip_thread_check(void)
|
|
{
|
|
return osThreadGetId() == lwip_tcpip_thread_id;
|
|
}
|
|
|
|
// Keep a pool of thread structures
|
|
static int thread_pool_index = 0;
|
|
static sys_thread_data_t thread_pool[SYS_THREAD_POOL_N];
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* Routine: sys_thread_new
|
|
*---------------------------------------------------------------------------*
|
|
* Description:
|
|
* Starts a new thread with priority "prio" that will begin its
|
|
* execution in the function "thread()". The "arg" argument will be
|
|
* passed as an argument to the thread() function. The id of the new
|
|
* thread is returned. Both the id and the priority are system
|
|
* dependent.
|
|
* Inputs:
|
|
* char *name -- Name of thread
|
|
* void (*thread)(void *arg) -- Pointer to function to run.
|
|
* void *arg -- Argument passed into function
|
|
* int stacksize -- Required stack amount in bytes
|
|
* int priority -- Thread priority
|
|
* Outputs:
|
|
* sys_thread_t -- Pointer to thread handle.
|
|
*---------------------------------------------------------------------------*/
|
|
#ifndef MBED_TZ_DEFAULT_ACCESS
|
|
#define MBED_TZ_DEFAULT_ACCESS 0
|
|
#endif
|
|
|
|
sys_thread_t sys_thread_new(const char *pcName,
|
|
void (*thread)(void *arg),
|
|
void *arg, int stacksize, int priority) {
|
|
LWIP_DEBUGF(SYS_DEBUG, ("New Thread: %s\n", pcName));
|
|
|
|
if (thread_pool_index >= SYS_THREAD_POOL_N)
|
|
error("sys_thread_new number error\n");
|
|
sys_thread_t t = (sys_thread_t)&thread_pool[thread_pool_index];
|
|
thread_pool_index++;
|
|
|
|
memset(t, 0, sizeof(*t));
|
|
t->attr.name = pcName ? pcName : "lwip_unnamed_thread";
|
|
t->attr.priority = (osPriority_t)priority;
|
|
t->attr.cb_size = sizeof(t->data);
|
|
t->attr.cb_mem = &t->data;
|
|
t->attr.stack_size = stacksize;
|
|
t->attr.stack_mem = malloc(stacksize);
|
|
t->attr.tz_module = MBED_TZ_DEFAULT_ACCESS;
|
|
if (t->attr.stack_mem == NULL) {
|
|
error("Error allocating the stack memory");
|
|
}
|
|
t->id = osThreadNew((osThreadFunc_t)thread, arg, &t->attr);
|
|
if (t->id == NULL)
|
|
error("sys_thread_new create error\n");
|
|
|
|
return t;
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef LWIP_DEBUG
|
|
|
|
#include <stdbool.h>
|
|
|
|
#if MBED_CONF_LWIP_USE_MBED_TRACE
|
|
#include "mbed-trace/mbed_trace.h"
|
|
|
|
void lwip_mbed_tracef_debug(const char *fmt, ...)
|
|
{
|
|
va_list ap;
|
|
va_start(ap, fmt);
|
|
mbed_vtracef(TRACE_LEVEL_DEBUG, "lwIP", fmt, ap);
|
|
va_end(ap);
|
|
}
|
|
|
|
void lwip_mbed_tracef_warn(const char *fmt, ...)
|
|
{
|
|
va_list ap;
|
|
va_start(ap, fmt);
|
|
mbed_vtracef(TRACE_LEVEL_WARN, "lwIP", fmt, ap);
|
|
va_end(ap);
|
|
}
|
|
|
|
void lwip_mbed_tracef_error(const char *fmt, ...)
|
|
{
|
|
va_list ap;
|
|
va_start(ap, fmt);
|
|
mbed_vtracef(TRACE_LEVEL_ERROR, "lwIP", fmt, ap);
|
|
va_end(ap);
|
|
}
|
|
|
|
void lwip_mbed_assert_fail(const char *msg, const char *func, const char *file, unsigned int line)
|
|
{
|
|
mbed_tracef(TRACE_LEVEL_ERROR, "lwIP", "Assertion failed: %s, function %s, file %s, line %u.", msg, func, file, line);
|
|
exit(EXIT_FAILURE); // XXX how about abort? mbed_assert uses exit, so follow suit
|
|
}
|
|
#else // MBED_CONF_LWIP_USE_MBED_TRACE
|
|
|
|
/** \brief Displays an error message on assertion
|
|
|
|
This function will display an error message on an assertion
|
|
to the debug output.
|
|
|
|
\param[in] msg Error message to display
|
|
\param[in] line Line number in file with error
|
|
\param[in] file Filename with error
|
|
*/
|
|
void assert_printf(char *msg, int line, char *file) {
|
|
if (msg)
|
|
error("%s:%d in file %s\n", msg, line, file);
|
|
else
|
|
error("LWIP ASSERT\n");
|
|
}
|
|
#endif // MBED_CONF_LWIP_USE_MBED_TRACE
|
|
|
|
#if TRACE_TO_ASCII_HEX_DUMP
|
|
void trace_to_ascii_hex_dump(char *prefix, int len, char *data)
|
|
{
|
|
int line_len = 0;
|
|
|
|
for (int i = 0; i < len; i++) {
|
|
if ((line_len % 16) == 0) {
|
|
if (line_len != 0) {
|
|
LWIP_PLATFORM_DIAG(("\n"));
|
|
}
|
|
LWIP_PLATFORM_DIAG(("%s %06x", prefix, line_len));
|
|
}
|
|
line_len++;
|
|
LWIP_PLATFORM_DIAG((" %02x", data[i]));
|
|
}
|
|
LWIP_PLATFORM_DIAG(("\n"));
|
|
}
|
|
#endif
|
|
|
|
#endif /* LWIP_DEBUG */
|