在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

基于DWC_ether_qos的以太網驅動開發-RTOS環境移植LWIP與性能測試

嵌入式USB開發 ? 來源:嵌入式Lee ? 作者:嵌入式Lee嵌入式 ? 2023-09-11 11:20 ? 次閱讀

本文轉自公眾號,歡迎關注

基于DWC_ether_qos的以太網驅動開發-RTOS環境移植LWIP與性能測試 (qq.com)

https://mp.weixin.qq.com/s/E80GdN3RzrG3NeXfdwi4_Q

一.前言

前面我們基于無OS環境移植了LWIP,這一篇我們來基于RTOS移植LWIP,與無OS環境基本一致,只是需要實現一些系統組件的接口,信號量互斥量等。

二.需要移植文件

我們參考lwipcontribportsfreertos下的移植進行修改,如果使用的是freertos的話直接參考即可。如果用的其他RTOS可以復制一份修改。

復制lwipcontribportsfreertos并添加cc.h和lwipopts.h(這兩個文件可以從contrib下其他樣例代碼中復制)

wKgZomT9Ts-ATRWJAADLKvIGyzM770.png

Cc.h

還是和無OS一樣實現隨機數函數


#ifndef LWIP_ARCH_CC_H
#define LWIP_ARCH_CC_H

#include 

#define LWIP_PLATFORM_ASSERT(x) do {printf("Assertion "%s" failed at line %d in %sn", 
                                     x, __LINE__, __FILE__);} while(0)

extern uint32_t lwip_port_rand(void);
#define LWIP_RAND() (lwip_port_rand())

#endif

Sys_arch.h/sys_arch.c

如果使用的freertos直接使用即可,否則按需修改。

相關接口。

/*
 * Copyright (c) 2017 Simon Goldschmidt
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
 * OF SUCH DAMAGE.
 *
 * This file is part of the lwIP TCP/IP stack.
 *
 * Author: Simon Goldschmdit 
 *
 */
#ifndef LWIP_ARCH_SYS_ARCH_H
#define LWIP_ARCH_SYS_ARCH_H

#include "lwip/opt.h"
#include "lwip/arch.h"

/** This is returned by _fromisr() sys functions to tell the outermost function
 * that a higher priority task was woken and the scheduler needs to be invoked.
 */
#define ERR_NEED_SCHED 123

/* This port includes FreeRTOS headers in sys_arch.c only.
 *  FreeRTOS uses pointers as object types. We use wrapper structs instead of
 * void pointers directly to get a tiny bit of type safety.
 */

void sys_arch_msleep(u32_t delay_ms);
#define sys_msleep(ms) sys_arch_msleep(ms)

#if SYS_LIGHTWEIGHT_PROT
typedef u32_t sys_prot_t;
#endif /* SYS_LIGHTWEIGHT_PROT */

#if !LWIP_COMPAT_MUTEX
struct _sys_mut {
  void *mut;
};
typedef struct _sys_mut sys_mutex_t;
#define sys_mutex_valid_val(mutex)   ((mutex).mut != NULL)
#define sys_mutex_valid(mutex)       (((mutex) != NULL) && sys_mutex_valid_val(*(mutex)))
#define sys_mutex_set_invalid(mutex) ((mutex)->mut = NULL)
#endif /* !LWIP_COMPAT_MUTEX */

struct _sys_sem {
  void *sem;
};
typedef struct _sys_sem sys_sem_t;
#define sys_sem_valid_val(sema)   ((sema).sem != NULL)
#define sys_sem_valid(sema)       (((sema) != NULL) && sys_sem_valid_val(*(sema)))
#define sys_sem_set_invalid(sema) ((sema)->sem = NULL)

struct _sys_mbox {
  void *mbx;
};
typedef struct _sys_mbox sys_mbox_t;
#define sys_mbox_valid_val(mbox)   ((mbox).mbx != NULL)
#define sys_mbox_valid(mbox)       (((mbox) != NULL) && sys_mbox_valid_val(*(mbox)))
#define sys_mbox_set_invalid(mbox) ((mbox)->mbx = NULL)

struct _sys_thread {
  void *thread_handle;
};
typedef struct _sys_thread sys_thread_t;

#if LWIP_NETCONN_SEM_PER_THREAD
sys_sem_t* sys_arch_netconn_sem_get(void);
void sys_arch_netconn_sem_alloc(void);
void sys_arch_netconn_sem_free(void);
#define LWIP_NETCONN_THREAD_SEM_GET()   sys_arch_netconn_sem_get()
#define LWIP_NETCONN_THREAD_SEM_ALLOC() sys_arch_netconn_sem_alloc()
#define LWIP_NETCONN_THREAD_SEM_FREE()  sys_arch_netconn_sem_free()
#endif /* LWIP_NETCONN_SEM_PER_THREAD */

#endif /* LWIP_ARCH_SYS_ARCH_H */

/*
 * Copyright (c) 2017 Simon Goldschmidt
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
 * OF SUCH DAMAGE.
 *
 * This file is part of the lwIP TCP/IP stack.
 *
 * Author: Simon Goldschmidt 
 *
 */

/* lwIP includes. */
#include "lwip/debug.h"
#include "lwip/def.h"
#include "lwip/sys.h"
#include "lwip/mem.h"
#include "lwip/stats.h"
#include "lwip/tcpip.h"
#include "FreeRTOS.h"
#include "semphr.h"
#include "task.h"

/** Set this to 1 if you want the stack size passed to sys_thread_new() to be
 * interpreted as number of stack words (FreeRTOS-like).
 * Default is that they are interpreted as byte count (lwIP-like).
 */
#ifndef LWIP_FREERTOS_THREAD_STACKSIZE_IS_STACKWORDS
#define LWIP_FREERTOS_THREAD_STACKSIZE_IS_STACKWORDS  0
#endif

/** Set this to 1 to use a mutex for SYS_ARCH_PROTECT() critical regions.
 * Default is 0 and locks interrupts/scheduler for SYS_ARCH_PROTECT().
 */
#ifndef LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX
#define LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX     0
#endif

/** Set this to 1 to include a sanity check that SYS_ARCH_PROTECT() and
 * SYS_ARCH_UNPROTECT() are called matching.
 */
#ifndef LWIP_FREERTOS_SYS_ARCH_PROTECT_SANITY_CHECK
#define LWIP_FREERTOS_SYS_ARCH_PROTECT_SANITY_CHECK   0
#endif

/** Set this to 1 to let sys_mbox_free check that queues are empty when freed */
#ifndef LWIP_FREERTOS_CHECK_QUEUE_EMPTY_ON_FREE
#define LWIP_FREERTOS_CHECK_QUEUE_EMPTY_ON_FREE       0
#endif

/** Set this to 1 to enable core locking check functions in this port.
 * For this to work, you'll have to define LWIP_ASSERT_CORE_LOCKED()
 * and LWIP_MARK_TCPIP_THREAD() correctly in your lwipopts.h! */
#ifndef LWIP_FREERTOS_CHECK_CORE_LOCKING
#define LWIP_FREERTOS_CHECK_CORE_LOCKING              1
#endif

/** Set this to 0 to implement sys_now() yourself, e.g. using a hw timer.
 * Default is 1, where FreeRTOS ticks are used to calculate back to ms.
 */
#ifndef LWIP_FREERTOS_SYS_NOW_FROM_FREERTOS
#define LWIP_FREERTOS_SYS_NOW_FROM_FREERTOS           1
#endif

#if !configSUPPORT_DYNAMIC_ALLOCATION
# error "lwIP FreeRTOS port requires configSUPPORT_DYNAMIC_ALLOCATION"
#endif
#if !INCLUDE_vTaskDelay
# error "lwIP FreeRTOS port requires INCLUDE_vTaskDelay"
#endif
#if !INCLUDE_vTaskSuspend
# error "lwIP FreeRTOS port requires INCLUDE_vTaskSuspend"
#endif
#if LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX || !LWIP_COMPAT_MUTEX
#if !configUSE_MUTEXES
# error "lwIP FreeRTOS port requires configUSE_MUTEXES"
#endif
#endif

#if SYS_LIGHTWEIGHT_PROT && LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX
static SemaphoreHandle_t sys_arch_protect_mutex;
#endif
#if SYS_LIGHTWEIGHT_PROT && LWIP_FREERTOS_SYS_ARCH_PROTECT_SANITY_CHECK
static sys_prot_t sys_arch_protect_nesting;
#endif

/* Initialize this module (see description in sys.h) */
void
sys_init(void)
{
#if SYS_LIGHTWEIGHT_PROT && LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX
  /* initialize sys_arch_protect global mutex */
  sys_arch_protect_mutex = xSemaphoreCreateRecursiveMutex();
  LWIP_ASSERT("failed to create sys_arch_protect mutex",
    sys_arch_protect_mutex != NULL);
#endif /* SYS_LIGHTWEIGHT_PROT && LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX */
}

#if configUSE_16_BIT_TICKS == 1
#error This port requires 32 bit ticks or timer overflow will fail
#endif

#if LWIP_FREERTOS_SYS_NOW_FROM_FREERTOS
u32_t
sys_now(void)
{
  return xTaskGetTickCount() * portTICK_PERIOD_MS;
}
#endif

u32_t
sys_jiffies(void)
{
  return xTaskGetTickCount();
}

#if SYS_LIGHTWEIGHT_PROT

sys_prot_t
sys_arch_protect(void)
{
#if LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX
  BaseType_t ret;
  LWIP_ASSERT("sys_arch_protect_mutex != NULL", sys_arch_protect_mutex != NULL);

  ret = xSemaphoreTakeRecursive(sys_arch_protect_mutex, portMAX_DELAY);
  LWIP_ASSERT("sys_arch_protect failed to take the mutex", ret == pdTRUE);
#else /* LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX */
  taskENTER_CRITICAL();
#endif /* LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX */
#if LWIP_FREERTOS_SYS_ARCH_PROTECT_SANITY_CHECK
  {
    /* every nested call to sys_arch_protect() returns an increased number */
    sys_prot_t ret = sys_arch_protect_nesting;
    sys_arch_protect_nesting++;
    LWIP_ASSERT("sys_arch_protect overflow", sys_arch_protect_nesting > ret);
    return ret;
  }
#else
  return 1;
#endif
}

void
sys_arch_unprotect(sys_prot_t pval)
{
#if LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX
  BaseType_t ret;
#endif
#if LWIP_FREERTOS_SYS_ARCH_PROTECT_SANITY_CHECK
  LWIP_ASSERT("unexpected sys_arch_protect_nesting", sys_arch_protect_nesting > 0);
  sys_arch_protect_nesting--;
  LWIP_ASSERT("unexpected sys_arch_protect_nesting", sys_arch_protect_nesting == pval);
#endif

#if LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX
  LWIP_ASSERT("sys_arch_protect_mutex != NULL", sys_arch_protect_mutex != NULL);

  ret = xSemaphoreGiveRecursive(sys_arch_protect_mutex);
  LWIP_ASSERT("sys_arch_unprotect failed to give the mutex", ret == pdTRUE);
#else /* LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX */
  taskEXIT_CRITICAL();
#endif /* LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX */
  LWIP_UNUSED_ARG(pval);
}

#endif /* SYS_LIGHTWEIGHT_PROT */

void
sys_arch_msleep(u32_t delay_ms)
{
  TickType_t delay_ticks = delay_ms / portTICK_RATE_MS;
  vTaskDelay(delay_ticks);
}

#if !LWIP_COMPAT_MUTEX

/* Create a new mutex*/
err_t
sys_mutex_new(sys_mutex_t *mutex)
{
  LWIP_ASSERT("mutex != NULL", mutex != NULL);

  mutex->mut = xSemaphoreCreateRecursiveMutex();
  if(mutex->mut == NULL) {
    SYS_STATS_INC(mutex.err);
    return ERR_MEM;
  }
  SYS_STATS_INC_USED(mutex);
  return ERR_OK;
}

void
sys_mutex_lock(sys_mutex_t *mutex)
{
  BaseType_t ret;
  LWIP_ASSERT("mutex != NULL", mutex != NULL);
  LWIP_ASSERT("mutex->mut != NULL", mutex->mut != NULL);

  ret = xSemaphoreTakeRecursive(mutex->mut, portMAX_DELAY);
  LWIP_ASSERT("failed to take the mutex", ret == pdTRUE);
}

void
sys_mutex_unlock(sys_mutex_t *mutex)
{
  BaseType_t ret;
  LWIP_ASSERT("mutex != NULL", mutex != NULL);
  LWIP_ASSERT("mutex->mut != NULL", mutex->mut != NULL);

  ret = xSemaphoreGiveRecursive(mutex->mut);
  LWIP_ASSERT("failed to give the mutex", ret == pdTRUE);
}

void
sys_mutex_free(sys_mutex_t *mutex)
{
  LWIP_ASSERT("mutex != NULL", mutex != NULL);
  LWIP_ASSERT("mutex->mut != NULL", mutex->mut != NULL);

  SYS_STATS_DEC(mutex.used);
  vSemaphoreDelete(mutex->mut);
  mutex->mut = NULL;
}

#endif /* !LWIP_COMPAT_MUTEX */

err_t
sys_sem_new(sys_sem_t *sem, u8_t initial_count)
{
  LWIP_ASSERT("sem != NULL", sem != NULL);
  LWIP_ASSERT("initial_count invalid (not 0 or 1)",
    (initial_count == 0) || (initial_count == 1));

  sem->sem = xSemaphoreCreateBinary();
  if(sem->sem == NULL) {
    SYS_STATS_INC(sem.err);
    return ERR_MEM;
  }
  SYS_STATS_INC_USED(sem);

  if(initial_count == 1) {
    BaseType_t ret = xSemaphoreGive(sem->sem);
    LWIP_ASSERT("sys_sem_new: initial give failed", ret == pdTRUE);
  }
  return ERR_OK;
}

void
sys_sem_signal(sys_sem_t *sem)
{
  BaseType_t ret;
  LWIP_ASSERT("sem != NULL", sem != NULL);
  LWIP_ASSERT("sem->sem != NULL", sem->sem != NULL);

  ret = xSemaphoreGive(sem->sem);
  /* queue full is OK, this is a signal only... */
  LWIP_ASSERT("sys_sem_signal: sane return value",
    (ret == pdTRUE) || (ret == errQUEUE_FULL));
}

u32_t
sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout_ms)
{
  BaseType_t ret;
  LWIP_ASSERT("sem != NULL", sem != NULL);
  LWIP_ASSERT("sem->sem != NULL", sem->sem != NULL);

  if(!timeout_ms) {
    /* wait infinite */
    ret = xSemaphoreTake(sem->sem, portMAX_DELAY);
    LWIP_ASSERT("taking semaphore failed", ret == pdTRUE);
  } else {
    TickType_t timeout_ticks = timeout_ms / portTICK_RATE_MS;
    ret = xSemaphoreTake(sem->sem, timeout_ticks);
    if (ret == errQUEUE_EMPTY) {
      /* timed out */
      return SYS_ARCH_TIMEOUT;
    }
    LWIP_ASSERT("taking semaphore failed", ret == pdTRUE);
  }

  /* Old versions of lwIP required us to return the time waited.
     This is not the case any more. Just returning != SYS_ARCH_TIMEOUT
     here is enough. */
  return 1;
}

void
sys_sem_free(sys_sem_t *sem)
{
  LWIP_ASSERT("sem != NULL", sem != NULL);
  LWIP_ASSERT("sem->sem != NULL", sem->sem != NULL);

  SYS_STATS_DEC(sem.used);
  vSemaphoreDelete(sem->sem);
  sem->sem = NULL;
}

err_t
sys_mbox_new(sys_mbox_t *mbox, int size)
{
  LWIP_ASSERT("mbox != NULL", mbox != NULL);
  LWIP_ASSERT("size > 0", size > 0);

  mbox->mbx = xQueueCreate((UBaseType_t)size, sizeof(void *));
  if(mbox->mbx == NULL) {
    SYS_STATS_INC(mbox.err);
    return ERR_MEM;
  }
  SYS_STATS_INC_USED(mbox);
  return ERR_OK;
}

void
sys_mbox_post(sys_mbox_t *mbox, void *msg)
{
  BaseType_t ret;
  LWIP_ASSERT("mbox != NULL", mbox != NULL);
  LWIP_ASSERT("mbox->mbx != NULL", mbox->mbx != NULL);

  ret = xQueueSendToBack(mbox->mbx, &msg, portMAX_DELAY);
  LWIP_ASSERT("mbox post failed", ret == pdTRUE);
}

err_t
sys_mbox_trypost(sys_mbox_t *mbox, void *msg)
{
  BaseType_t ret;
  LWIP_ASSERT("mbox != NULL", mbox != NULL);
  LWIP_ASSERT("mbox->mbx != NULL", mbox->mbx != NULL);

  ret = xQueueSendToBack(mbox->mbx, &msg, 0);
  if (ret == pdTRUE) {
    return ERR_OK;
  } else {
    LWIP_ASSERT("mbox trypost failed", ret == errQUEUE_FULL);
    SYS_STATS_INC(mbox.err);
    return ERR_MEM;
  }
}

err_t
sys_mbox_trypost_fromisr(sys_mbox_t *mbox, void *msg)
{
  BaseType_t ret;
  BaseType_t xHigherPriorityTaskWoken = pdFALSE;
  LWIP_ASSERT("mbox != NULL", mbox != NULL);
  LWIP_ASSERT("mbox->mbx != NULL", mbox->mbx != NULL);

  ret = xQueueSendToBackFromISR(mbox->mbx, &msg, &xHigherPriorityTaskWoken);
  if (ret == pdTRUE) {
    if (xHigherPriorityTaskWoken == pdTRUE) {
      return ERR_NEED_SCHED;
    }
    return ERR_OK;
  } else {
    LWIP_ASSERT("mbox trypost failed", ret == errQUEUE_FULL);
    SYS_STATS_INC(mbox.err);
    return ERR_MEM;
  }
}

u32_t
sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout_ms)
{
  BaseType_t ret;
  void *msg_dummy;
  LWIP_ASSERT("mbox != NULL", mbox != NULL);
  LWIP_ASSERT("mbox->mbx != NULL", mbox->mbx != NULL);

  if (!msg) {
    msg = &msg_dummy;
  }

  if (!timeout_ms) {
    /* wait infinite */
    ret = xQueueReceive(mbox->mbx, &(*msg), portMAX_DELAY);
    LWIP_ASSERT("mbox fetch failed", ret == pdTRUE);
  } else {
    TickType_t timeout_ticks = timeout_ms / portTICK_RATE_MS;
    ret = xQueueReceive(mbox->mbx, &(*msg), timeout_ticks);
    if (ret == errQUEUE_EMPTY) {
      /* timed out */
      *msg = NULL;
      return SYS_ARCH_TIMEOUT;
    }
    LWIP_ASSERT("mbox fetch failed", ret == pdTRUE);
  }

  /* Old versions of lwIP required us to return the time waited.
     This is not the case any more. Just returning != SYS_ARCH_TIMEOUT
     here is enough. */
  return 1;
}

u32_t
sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg)
{
  BaseType_t ret;
  void *msg_dummy;
  LWIP_ASSERT("mbox != NULL", mbox != NULL);
  LWIP_ASSERT("mbox->mbx != NULL", mbox->mbx != NULL);

  if (!msg) {
    msg = &msg_dummy;
  }

  ret = xQueueReceive(mbox->mbx, &(*msg), 0);
  if (ret == errQUEUE_EMPTY) {
    *msg = NULL;
    return SYS_MBOX_EMPTY;
  }
  LWIP_ASSERT("mbox fetch failed", ret == pdTRUE);

  return 0;
}

void
sys_mbox_free(sys_mbox_t *mbox)
{
  LWIP_ASSERT("mbox != NULL", mbox != NULL);
  LWIP_ASSERT("mbox->mbx != NULL", mbox->mbx != NULL);

#if LWIP_FREERTOS_CHECK_QUEUE_EMPTY_ON_FREE
  {
    UBaseType_t msgs_waiting = uxQueueMessagesWaiting(mbox->mbx);
    LWIP_ASSERT("mbox quence not empty", msgs_waiting == 0);

    if (msgs_waiting != 0) {
      SYS_STATS_INC(mbox.err);
    }
  }
#endif

  vQueueDelete(mbox->mbx);

  SYS_STATS_DEC(mbox.used);
}

sys_thread_t
sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio)
{
  TaskHandle_t rtos_task;
  BaseType_t ret;
  sys_thread_t lwip_thread;
  size_t rtos_stacksize;

  LWIP_ASSERT("invalid stacksize", stacksize > 0);
#if LWIP_FREERTOS_THREAD_STACKSIZE_IS_STACKWORDS
  rtos_stacksize = (size_t)stacksize;
#else
  rtos_stacksize = (size_t)stacksize / sizeof(StackType_t);
#endif

  /* lwIP's lwip_thread_fn matches FreeRTOS' TaskFunction_t, so we can pass the
     thread function without adaption here. */
  ret = xTaskCreate(thread, name, (configSTACK_DEPTH_TYPE)rtos_stacksize, arg, prio, &rtos_task);
  LWIP_ASSERT("task creation failed", ret == pdTRUE);

  lwip_thread.thread_handle = rtos_task;
  return lwip_thread;
}

#if LWIP_NETCONN_SEM_PER_THREAD
#if configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0

sys_sem_t *
sys_arch_netconn_sem_get(void)
{
  void* ret;
  TaskHandle_t task = xTaskGetCurrentTaskHandle();
  LWIP_ASSERT("task != NULL", task != NULL);

  ret = pvTaskGetThreadLocalStoragePointer(task, 0);
  return ret;
}

void
sys_arch_netconn_sem_alloc(void)
{
  void *ret;
  TaskHandle_t task = xTaskGetCurrentTaskHandle();
  LWIP_ASSERT("task != NULL", task != NULL);

  ret = pvTaskGetThreadLocalStoragePointer(task, 0);
  if(ret == NULL) {
    sys_sem_t *sem;
    err_t err;
    /* need to allocate the memory for this semaphore */
    sem = mem_malloc(sizeof(sys_sem_t));
    LWIP_ASSERT("sem != NULL", sem != NULL);
    err = sys_sem_new(sem, 0);
    LWIP_ASSERT("err == ERR_OK", err == ERR_OK);
    LWIP_ASSERT("sem invalid", sys_sem_valid(sem));
    vTaskSetThreadLocalStoragePointer(task, 0, sem);
  }
}

void sys_arch_netconn_sem_free(void)
{
  void* ret;
  TaskHandle_t task = xTaskGetCurrentTaskHandle();
  LWIP_ASSERT("task != NULL", task != NULL);

  ret = pvTaskGetThreadLocalStoragePointer(task, 0);
  if(ret != NULL) {
    sys_sem_t *sem = ret;
    sys_sem_free(sem);
    mem_free(sem);
    vTaskSetThreadLocalStoragePointer(task, 0, NULL);
  }
}

#else /* configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 */
#error LWIP_NETCONN_SEM_PER_THREAD needs configNUM_THREAD_LOCAL_STORAGE_POINTERS
#endif /* configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 */

#endif /* LWIP_NETCONN_SEM_PER_THREAD */

#if LWIP_FREERTOS_CHECK_CORE_LOCKING
#if LWIP_TCPIP_CORE_LOCKING

/** Flag the core lock held. A counter for recursive locks. */
static u8_t lwip_core_lock_count;
static TaskHandle_t lwip_core_lock_holder_thread;

void
sys_lock_tcpip_core(void)
{
   sys_mutex_lock(&lock_tcpip_core);
   if (lwip_core_lock_count == 0) {
     lwip_core_lock_holder_thread = xTaskGetCurrentTaskHandle();
   }
   lwip_core_lock_count++;
}

void
sys_unlock_tcpip_core(void)
{
   lwip_core_lock_count--;
   if (lwip_core_lock_count == 0) {
       lwip_core_lock_holder_thread = 0;
   }
   sys_mutex_unlock(&lock_tcpip_core);
}

#endif /* LWIP_TCPIP_CORE_LOCKING */

#if !NO_SYS
static TaskHandle_t lwip_tcpip_thread;
#endif

void
sys_mark_tcpip_thread(void)
{
#if !NO_SYS
  lwip_tcpip_thread = xTaskGetCurrentTaskHandle();
#endif
}

void
sys_check_core_locking(void)
{
  /* Embedded systems should check we are NOT in an interrupt context here */
  /* E.g. core Cortex-M3/M4 ports:
         configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );

     Instead, we use more generic FreeRTOS functions here, which should fail from ISR: */
  taskENTER_CRITICAL();
  taskEXIT_CRITICAL();

#if !NO_SYS
  if (lwip_tcpip_thread != 0) {
    TaskHandle_t current_thread = xTaskGetCurrentTaskHandle();

#if LWIP_TCPIP_CORE_LOCKING
    LWIP_ASSERT("Function called without core lock",
                current_thread == lwip_core_lock_holder_thread && lwip_core_lock_count > 0);
#else /* LWIP_TCPIP_CORE_LOCKING */
    LWIP_ASSERT("Function called from wrong thread", current_thread == lwip_tcpip_thread);
#endif /* LWIP_TCPIP_CORE_LOCKING */
  }
#endif /* !NO_SYS */
}

#endif /* LWIP_FREERTOS_CHECK_CORE_LOCKING*/

Lwipopts.h

配置


/**
 * @file
 *
 * lwIP Options Configuration
 */

/*
 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
 * OF SUCH DAMAGE.
 *
 * This file is part of the lwIP TCP/IP stack.
 *
 * Author: Adam Dunkels 
 *
 */
#ifndef LWIP_LWIPOPTS_H
#define LWIP_LWIPOPTS_H

/*
 * Include user defined options first. Anything not defined in these files
 * will be set to standard values. Override anything you don't like!
 */
#include "lwipopts.h"
#include "lwip/debug.h"
#include "os_mem.h"

#define LWIP_PROVIDE_ERRNO 1
#define LWIP_COMPAT_MUTEX 0
#define LWIP_DEBUG 1

#define DEFAULT_THREAD_PRIO 7
#define DEFAULT_THREAD_STACKSIZE 1024
#define TCPIP_THREAD_STACKSIZE 1024
#define TCPIP_THREAD_PRIO 7
#define SNMP_STACK_SIZE  1024
#define SNMP_THREAD_PRIO 7
#define SLIPIF_THREAD_STACKSIZE 1024
#define SLIPIF_THREAD_PRIO 7

#define MEMP_MEM_MALLOC 1
#define MEM_LIBC_MALLOC 1
#define mem_clib_malloc(size) os_mem_malloc(0,size)
#define mem_clib_free os_mem_free
#define mem_clib_calloc(cnt,size) os_mem_calloc(0,(cnt)*(size))

#define DEFAULT_RAW_RECVMBOX_SIZE 10
#define DEFAULT_UDP_RECVMBOX_SIZE 10
#define DEFAULT_TCP_RECVMBOX_SIZE 10
#define TCPIP_MBOX_SIZE  10
#define DEFAULT_ACCEPTMBOX_SIZE 10

#define TCP_MSS (1500 - 40)

#define TCP_SND_BUF (11*TCP_MSS)
#define TCP_WND (11*TCP_MSS)
/*
   -----------------------------------------------
   ---------- Platform specific locking ----------
   -----------------------------------------------
*/

/**
 * SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain
 * critical regions during buffer allocation, deallocation and memory
 * allocation and deallocation.
 */
#define SYS_LIGHTWEIGHT_PROT            0

/**
 * NO_SYS==1: Provides VERY minimal functionality. Otherwise,
 * use lwIP facilities.
 */
#define NO_SYS                          0

/*
   ------------------------------------
   ---------- Memory options ----------
   ------------------------------------
*/

/**
 * MEM_ALIGNMENT: should be set to the alignment of the CPU
 *    4 byte alignment -> #define MEM_ALIGNMENT 4
 *    2 byte alignment -> #define MEM_ALIGNMENT 2
 */
#define MEM_ALIGNMENT                   4U

/**
 * MEM_SIZE: the size of the heap memory. If the application will send
 * a lot of data that needs to be copied, this should be set high.
 */
#define MEM_SIZE                        1600

/*
   ------------------------------------------------
   ---------- Internal Memory Pool Sizes ----------
   ------------------------------------------------
*/
/**
 * MEMP_NUM_PBUF: the number of memp struct pbufs (used for PBUF_ROM and PBUF_REF).
 * If the application sends a lot of data out of ROM (or other static memory),
 * this should be set high.
 */
#define MEMP_NUM_PBUF                   160

/**
 * MEMP_NUM_RAW_PCB: Number of raw connection PCBs
 * (requires the LWIP_RAW option)
 */
#define MEMP_NUM_RAW_PCB                4

/**
 * MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One
 * per active UDP "connection".
 * (requires the LWIP_UDP option)
 */
#define MEMP_NUM_UDP_PCB                4

/**
 * MEMP_NUM_TCP_PCB: the number of simulatenously active TCP connections.
 * (requires the LWIP_TCP option)
 */
#define MEMP_NUM_TCP_PCB                4

/**
 * MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP connections.
 * (requires the LWIP_TCP option)
 */
#define MEMP_NUM_TCP_PCB_LISTEN         4

/**
 * MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP segments.
 * (requires the LWIP_TCP option)
 */
#define MEMP_NUM_TCP_SEG                160

/**
 * MEMP_NUM_REASSDATA: the number of simultaneously IP packets queued for
 * reassembly (whole packets, not fragments!)
 */
#define MEMP_NUM_REASSDATA              1

/**
 * MEMP_NUM_ARP_QUEUE: the number of simulateously queued outgoing
 * packets (pbufs) that are waiting for an ARP request (to resolve
 * their destination address) to finish.
 * (requires the ARP_QUEUEING option)
 */
#define MEMP_NUM_ARP_QUEUE              2

/**
 * MEMP_NUM_SYS_TIMEOUT: the number of simulateously active timeouts.
 * (requires NO_SYS==0)
 */
#define MEMP_NUM_SYS_TIMEOUT            8

/**
 * MEMP_NUM_NETBUF: the number of struct netbufs.
 * (only needed if you use the sequential API, like api_lib.c)
 */
#define MEMP_NUM_NETBUF                 2

/**
 * MEMP_NUM_NETCONN: the number of struct netconns.
 * (only needed if you use the sequential API, like api_lib.c)
 */
#define MEMP_NUM_NETCONN               32

/**
 * MEMP_NUM_TCPIP_MSG_API: the number of struct tcpip_msg, which are used
 * for callback/timeout API communication.
 * (only needed if you use tcpip.c)
 */
#define MEMP_NUM_TCPIP_MSG_API          8

/**
 * MEMP_NUM_TCPIP_MSG_INPKT: the number of struct tcpip_msg, which are used
 * for incoming packets.
 * (only needed if you use tcpip.c)
 */
#define MEMP_NUM_TCPIP_MSG_INPKT        8

/**
 * PBUF_POOL_SIZE: the number of buffers in the pbuf pool.
 */
#define PBUF_POOL_SIZE                  64

/*
   ---------------------------------
   ---------- ARP options ----------
   ---------------------------------
*/
/**
 * LWIP_ARP==1: Enable ARP functionality.
 */
#define LWIP_ARP                        1

/*
   --------------------------------
   ---------- IP options ----------
   --------------------------------
*/
/**
 * IP_FORWARD==1: Enables the ability to forward IP packets across network
 * interfaces. If you are going to run lwIP on a device with only one network
 * interface, define this to 0.
 */
#define IP_FORWARD                      0

/**
 * IP_OPTIONS: Defines the behavior for IP options.
 *      IP_OPTIONS_ALLOWED==0: All packets with IP options are dropped.
 *      IP_OPTIONS_ALLOWED==1: IP options are allowed (but not parsed).
 */
#define IP_OPTIONS_ALLOWED              1

/**
 * IP_REASSEMBLY==1: Reassemble incoming fragmented IP packets. Note that
 * this option does not affect outgoing packet sizes, which can be controlled
 * via IP_FRAG.
 */
#define IP_REASSEMBLY                   1

/**
 * IP_FRAG==1: Fragment outgoing IP packets if their size exceeds MTU. Note
 * that this option does not affect incoming packet sizes, which can be
 * controlled via IP_REASSEMBLY.
 */
#define IP_FRAG                         1

/**
 * IP_REASS_MAXAGE: Maximum time (in multiples of IP_TMR_INTERVAL - so seconds, normally)
 * a fragmented IP packet waits for all fragments to arrive. If not all fragments arrived
 * in this time, the whole packet is discarded.
 */
#define IP_REASS_MAXAGE                 3

/**
 * IP_REASS_MAX_PBUFS: Total maximum amount of pbufs waiting to be reassembled.
 * Since the received pbufs are enqueued, be sure to configure
 * PBUF_POOL_SIZE > IP_REASS_MAX_PBUFS so that the stack is still able to receive
 * packets even if the maximum amount of fragments is enqueued for reassembly!
 */
#define IP_REASS_MAX_PBUFS              4

/**
 * IP_FRAG_USES_STATIC_BUF==1: Use a static MTU-sized buffer for IP
 * fragmentation. Otherwise pbufs are allocated and reference the original
    * packet data to be fragmented.
*/
#define IP_FRAG_USES_STATIC_BUF         0

/**
 * IP_DEFAULT_TTL: Default value for Time-To-Live used by transport layers.
 */
#define IP_DEFAULT_TTL                  255

/*
   ----------------------------------
   ---------- ICMP options ----------
   ----------------------------------
*/
/**
 * LWIP_ICMP==1: Enable ICMP module inside the IP stack.
 * Be careful, disable that make your product non-compliant to RFC1122
 */
#define LWIP_ICMP                       1

/*
   ---------------------------------
   ---------- RAW options ----------
   ---------------------------------
*/
/**
 * LWIP_RAW==1: Enable application layer to hook into the IP layer itself.
 */
#define LWIP_RAW                        1

/*
   ----------------------------------
   ---------- DHCP options ----------
   ----------------------------------
*/
/**
 * LWIP_DHCP==1: Enable DHCP module.
 */
#define LWIP_DHCP                       0


/*
   ------------------------------------
   ---------- AUTOIP options ----------
   ------------------------------------
*/
/**
 * LWIP_AUTOIP==1: Enable AUTOIP module.
 */
#define LWIP_AUTOIP                     0

/*
   ----------------------------------
   ---------- SNMP options ----------
   ----------------------------------
*/
/**
 * LWIP_SNMP==1: Turn on SNMP module. UDP must be available for SNMP
 * transport.
 */
#define LWIP_SNMP                       0

/*
   ----------------------------------
   ---------- IGMP options ----------
   ----------------------------------
*/
/**
 * LWIP_IGMP==1: Turn on IGMP module.
 */
#define LWIP_IGMP                       0

/*
   ----------------------------------
   ---------- DNS options -----------
   ----------------------------------
*/
/**
 * LWIP_DNS==1: Turn on DNS module. UDP must be available for DNS
 * transport.
 */
#define LWIP_DNS                        0

/*
   ---------------------------------
   ---------- UDP options ----------
   ---------------------------------
*/
/**
 * LWIP_UDP==1: Turn on UDP.
 */
#define LWIP_UDP                        1

/*
   ---------------------------------
   ---------- TCP options ----------
   ---------------------------------
*/
/**
 * LWIP_TCP==1: Turn on TCP.
 */
#define LWIP_TCP                        1

#define LWIP_LISTEN_BACKLOG             0

/*
   ----------------------------------
   ---------- Pbuf options ----------
   ----------------------------------
*/
/**
 * PBUF_LINK_HLEN: the number of bytes that should be allocated for a
 * link level header. The default is 14, the standard value for
 * Ethernet.
 */
#define PBUF_LINK_HLEN                  16

/**
 * PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. The default is
 * designed to accommodate single full size TCP frame in one pbuf, including
 * TCP_MSS, IP header, and link header.
*
 */
#define PBUF_POOL_BUFSIZE               LWIP_MEM_ALIGN_SIZE(TCP_MSS+40+PBUF_LINK_HLEN)

/*
   ------------------------------------
   ---------- LOOPIF options ----------
   ------------------------------------
*/
/**
 * LWIP_HAVE_LOOPIF==1: Support loop interface (127.0.0.1) and loopif.c
 */
#define LWIP_HAVE_LOOPIF                0

/*
   ----------------------------------------------
   ---------- Sequential layer options ----------
   ----------------------------------------------
*/

/**
 * LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c)
 */
#define LWIP_NETCONN                    1

/*
   ------------------------------------
   ---------- Socket options ----------
   ------------------------------------
*/
/**
 * LWIP_SOCKET==1: Enable Socket API (require to use sockets.c)
 */
#define LWIP_SOCKET                     1

/**
 * SO_REUSE==1: Enable SO_REUSEADDR
 */
#define SO_REUSE                        1

/*
   ----------------------------------------
   ---------- Statistics options ----------
   ----------------------------------------
*/
/**
 * LWIP_STATS==1: Enable statistics collection in lwip_stats.
 */
#define LWIP_STATS                      0
/*
   ---------------------------------
   ---------- PPP options ----------
   ---------------------------------
*/
/**
 * PPP_SUPPORT==1: Enable PPP.
 */
#define PPP_SUPPORT                     0



/*
   ---------------------------------------
   ---------- Threading options ----------
   ---------------------------------------
*/

#define LWIP_TCPIP_CORE_LOCKING    0

#if !NO_SYS
void sys_check_core_locking(void);
#define LWIP_ASSERT_CORE_LOCKED()  sys_check_core_locking()
#endif

#endif /* LWIP_LWIPOPTS_H */

Perf.c/h


#ifndef LWIP_ARCH_PERF_H
#define LWIP_ARCH_PERF_H

#include 

struct tms {
  uint32_t    tms_utime;    /* user time */
  uint32_t  tms_stime;    /* system time */
  uint32_t  tms_cutime;    /* user time, children */
  uint32_t  tms_cstime;    /* system time, children */
};

void perf_times(struct tms *t);
void perf_print_times(struct tms *start, struct tms *end, char *key);

//#define PERF 1

#ifdef PERF
#define PERF_START   struct tms __perf_start;
                     struct tms __perf_end; 
                     perf_times(&__perf_start)
#define PERF_STOP(x) perf_times(&__perf_end); 
                     perf_print_times(&__perf_start, &__perf_end, x);
#else /* PERF */
#define PERF_START    /* null definition */
#define PERF_STOP(x)  /* null definition */
#endif /* PERF */

#endif /* LWIP_ARCH_PERF_H */


#include 

#include "arch/perf.h"

extern uint32_t sys_now(void);
void perf_times(struct tms *t)
{
  t->tms_stime = sys_now();
}

void perf_print_times(struct tms *start, struct tms *end, char *key)
{
  printf("%s: %lumSn", key, end->tms_stime - start->tms_stime);
}

Portethif.c/f


#ifndef LWIP_ARCH_PERF_H
#define LWIP_ARCH_PERF_H

#include 

struct tms {
  uint32_t    tms_utime;    /* user time */
  uint32_t  tms_stime;    /* system time */
  uint32_t  tms_cutime;    /* user time, children */
  uint32_t  tms_cstime;    /* system time, children */
};

void perf_times(struct tms *t);
void perf_print_times(struct tms *start, struct tms *end, char *key);

//#define PERF 1

#ifdef PERF
#define PERF_START   struct tms __perf_start;
                     struct tms __perf_end; 
                     perf_times(&__perf_start)
#define PERF_STOP(x) perf_times(&__perf_end); 
                     perf_print_times(&__perf_start, &__perf_end, x);
#else /* PERF */
#define PERF_START    /* null definition */
#define PERF_STOP(x)  /* null definition */
#endif /* PERF */

#endif /* LWIP_ARCH_PERF_H */


#include 

#include "arch/perf.h"

extern uint32_t sys_now(void);
void perf_times(struct tms *t)
{
  t->tms_stime = sys_now();
}

void perf_print_times(struct tms *start, struct tms *end, char *key)
{
  printf("%s: %lumSn", key, end->tms_stime - start->tms_stime);
}

系統接口

Lwipopts.h中

有OS則NO_SYS配置為0

#define NO_SYS 0

此時Sys_arch.h/sys_arch.c需要實現以下接口

sys_init

sys_now 獲取ms值

sys_jiffies獲取滴答值

sys_arch_msleep

sys_sem_new

sys_sem_signal

sys_arch_sem_wait

sys_sem_free

LWIP_COMPAT_MUTEX為0時實現以下互斥量接口,否則自動使用信號量實現

sys_mutex_new

sys_mutex_lock

sys_mutex_unlock

sys_mutex_free

sys_mbox_new

sys_mbox_post

sys_mbox_trypost

sys_mbox_trypost_fromisr

sys_arch_mbox_fetch

sys_arch_mbox_tryfetch

sys_mbox_free

需要設置消息郵箱的大小


#define DEFAULT_RAW_RECVMBOX_SIZE 10

#define DEFAULT_UDP_RECVMBOX_SIZE 10

#define DEFAULT_TCP_RECVMBOX_SIZE 10

#define TCPIP_MBOX_SIZE  10

sys_thread_new

配置默認線程棧大小和優先級


#define DEFAULT_THREAD_PRIO 7

#define DEFAULT_THREAD_STACKSIZE 1024

#define TCPIP_THREAD_STACKSIZE 1024

#define TCPIP_THREAD_PRIO 7

#define SNMP_STACK_SIZE  1024

#define SNMP_THREAD_PRIO 7

#define SLIPIF_THREAD_STACKSIZE 1024

#define SLIPIF_THREAD_PRIO 7

如果使能LWIP_NETCONN_SEM_PER_THREAD

sys_arch_netconn_sem_get

sys_arch_netconn_sem_alloc

sys_arch_netconn_sem_free

如果使能LWIP_FREERTOS_CHECK_CORE_LOCKING和

LWIP_TCPIP_CORE_LOCKING

sys_lock_tcpip_core

sys_unlock_tcpip_core

sys_mark_tcpip_thread

sys_check_core_locking

SYS_LIGHTWEIGHT_PROT使能時

sys_arch_protect

sys_arch_unprotect

錯誤碼處理

Lwipopts.h中

#define LWIP_PROVIDE_ERRNO 1

則使用LWIP自己實現的errno.h相關錯誤碼和接口。

互斥量使用

如果有互斥量則

Lwipopts.h中

#define LWIP_COMPAT_MUTEX 0

如果定義為1則使用信號量替代互斥量

Sys.h中


#define sys_mutex_t                   sys_sem_t

#define sys_mutex_new(mutex)          sys_sem_new(mutex, 1)

#define sys_mutex_lock(mutex)         sys_sem_wait(mutex)

#define sys_mutex_unlock(mutex)       sys_sem_signal(mutex)

#define sys_mutex_free(mutex)         sys_sem_free(mutex)

#define sys_mutex_valid(mutex)        sys_sem_valid(mutex)

#define sys_mutex_set_invalid(mutex)  sys_sem_set_invalid(mutex)

LOCK Check

Sys_arch.c中

#define LWIP_FREERTOS_CHECK_CORE_LOCKING 1

Lwipopts.h中

#define LWIP_TCPIP_CORE_LOCKING 1

堆配置

有OS了我們可以直接使用OS提供的堆管理,LWIP的堆和內存池參見前兩篇文章分析。

Lwipopts.h中

配置內存池memp.c使用堆實現mem_malloc,mem_free

#define MEMP_MEM_MALLOC 1

配置使用系統的堆管理

#define MEM_LIBC_MALLOC 1

此時MEM_USE_POOLS必須為0

實現以下幾個接口

mem_clib_free

mem_clib_malloc

mem_clib_calloc

另外就是配置使用內存池的各個組建的內存池大小

MEMP_NUM_xxx

時間

在系統接口中實現

sys_now

sys_jiffies

斷言

不定義LWIP_ASSERT

debug.h中


#ifndef LWIP_NOASSERT

#define LWIP_ASSERT(message, assertion) do { if (!(assertion)) { 

LWIP_PLATFORM_ASSERT(message); }} while(0)

#else  /* LWIP_NOASSERT */

#define LWIP_ASSERT(message, assertion)

#endif /* LWIP_NOASSERT */

未定義LWIP_PLATFORM_ASSERT則


#ifndef LWIP_PLATFORM_ASSERT

#define LWIP_PLATFORM_ASSERT(x) do {printf("Assertion "%s" failed at line %d in %sn", 

                                   x, __LINE__, __FILE__); fflush(NULL); abort();} while(0)

#include 

#include 

#endif

如果有printf可以cc.h中定義為

#define LWIP_PLATFORM_ASSERT(x) do {printf("Assertion "%s" failed at line %d in %sn", 

                                   x, __LINE__, __FILE__);} while(0)

調試

使能配置LWIP_DEBUG

實現LWIP_PLATFORM_DIAG行

arch.h中默認是


#ifndef LWIP_PLATFORM_DIAG

#define LWIP_PLATFORM_DIAG(x) do {printf x;} while(0)

#include 

#include 

#endif

LWIP_DBG_ON

LWIP_DBG_TYPES_ON

LWIP_DBG_MASK_LEVEL

三.tcp測試

復制contribappstcpecho下的tcpeco.c/h到自己工程中

調用

tcpecho_init

初始化

關鍵初始化過程

tcpip_init(0,0);

netif_add(&netif, (const ip_addr_t *)&ipaddr, (const ip_addr_t *)&netmask, (const ip_addr_t *)&gw, NULL, &lwip_port_eth_init, eernet_input);

netif_set_default(&netif);

if (netif_is_link_up(&netif))

{

netif_set_up(&netif);

}

else

{

netif_set_down(&netif);

}

tcpecho_init(); //port 7

PC作為客戶端

wKgaomT9Ts-AOPTPAAGR5G1XOU0308.png

四.tcp性能測試

添加以下代碼到自己的工程

srcappslwiperflwiperf.c

srcincludelwipappslwiperf.h

contribexampleslwiperflwiperf_example.c/h

端口為lwiperf.h中定義

#define LWIPERF_TCP_PORT_DEFAULT 5001

調用

lwiperf_example_init();

初始化

使用Jperf

PC為client模式

wKgZomT9Ts-AbXqTAAGLL7Ux3Qs046.png


審核編輯 黃宇
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 測試
    +關注

    關注

    8

    文章

    5299

    瀏覽量

    126636
  • 以太網
    +關注

    關注

    40

    文章

    5423

    瀏覽量

    171683
  • RTOS
    +關注

    關注

    22

    文章

    812

    瀏覽量

    119625
  • LwIP
    +關注

    關注

    2

    文章

    86

    瀏覽量

    27166
  • 驅動開發
    +關注

    關注

    0

    文章

    130

    瀏覽量

    12075
收藏 人收藏

    評論

    相關推薦

    基于DWC_ether_qos以太網驅動開發-MAC幀格式介紹

    本文轉自公眾號,歡迎關注 基于DWC_ether_qos以太網驅動開發-MAC幀格式介紹 (qq.com) 一.前言 ? 在以太網
    的頭像 發表于 08-30 09:23 ?2379次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>-MAC幀格式介紹

    基于DWC_ether_qos以太網驅動開發-MDIO驅動編寫與測試

    本文轉自公眾號歡迎關注 基于DWC_ether_qos以太網驅動開發-MDIO驅動編寫與測試
    的頭像 發表于 08-30 09:37 ?3762次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>-MDIO<b class='flag-5'>驅動</b>編寫與<b class='flag-5'>測試</b>

    基于DWC_ether_qos以太網驅動開發-描述符鏈表介紹

    本文轉自公眾號歡迎關注 一.描述符概述 1.0 前言 對于DWC Ethernet QoS驅動的編寫來說,初始化完成之后,核心操作就是DMA的描述符鏈表配置(linked list
    的頭像 發表于 08-30 09:39 ?4533次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>-描述符鏈表介紹

    基于DWC_ether_qos以太網驅動開發-數據流驗證過程

    轉自公眾號歡迎關注 https://mp.weixin.qq.com/s/klrHhaLMM_0W3FGVwHXFkA 基于DWC_ether_qos以太網驅動開發-數據流驗證過程
    的頭像 發表于 08-31 08:41 ?2048次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>-數據流驗證過程

    基于DWC_ether_qos以太網驅動開發-收發驅動編寫與調試

    本文轉自公眾號,歡迎關注 基于DWC_ether_qos以太網驅動開發-收發驅動編寫與調試 (qq.com) https://mp.wei
    的頭像 發表于 09-05 08:47 ?2339次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>-收發<b class='flag-5'>驅動</b>編寫與調試

    基于DWC_ether_qos以太網驅動開發-無OS環境移植LWIP

    本文轉自公眾號歡迎關注 基于DWC_ether_qos以太網驅動開發-無OS環境移植
    的頭像 發表于 09-06 08:40 ?1610次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>-無OS<b class='flag-5'>環境</b><b class='flag-5'>移植</b><b class='flag-5'>LWIP</b>

    基于DWC_ether_qos以太網驅動開發-LWIP的內存池介紹

    本文轉自公眾號,歡迎關注 https://mp.weixin.qq.com/s/mBoGSf_u9edFF01U_OZT9g 一.前言 lwIP為基礎結構提供了專用的內存池管理,比如netconn
    的頭像 發表于 09-07 08:45 ?1742次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>-<b class='flag-5'>LWIP</b>的內存池介紹

    基于DWC_ether_qos以太網驅動開發-LWIP的堆管理介紹

    本文轉自公眾號歡迎關注 基于DWC_ether_qos以太網驅動開發-LWIP的堆管理介紹 (qq.com) https://mp.wei
    的頭像 發表于 09-08 08:40 ?1316次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>-<b class='flag-5'>LWIP</b>的堆管理介紹

    基于DWC_ether_qos以太網驅動開發-LWIP的堆(內存池)未對齊導致問題的案例分享

    本文轉自公眾號歡迎關注 https://mp.weixin.qq.com/s/ErIa2ss2YZLGYbSwoJEzog 一.?前言 內存未對齊訪問問題這個已經是老生常談的問題了, 由于LWIP
    的頭像 發表于 09-09 08:44 ?1738次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>-<b class='flag-5'>LWIP</b>的堆(內存池)未對齊導致問題的案例分享

    基于DWC_ether_qos以太網驅動開發-LWIP在PC上進行開發調試

    本文轉自公眾號歡迎關注 基于DWC_ether_qos以太網驅動開發-LWIP在PC上進行開發
    的頭像 發表于 09-11 08:40 ?2031次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>-<b class='flag-5'>LWIP</b>在PC上進行<b class='flag-5'>開發</b>調試

    基于DWC_ether_qos以太網驅動開發-LWIP的定時器模塊詳解

    一. 前言 LWIP的定時器模塊,實現了通用的軟件定時器,用于內部的周期事件處理,比如arp,tcp的超時等,用戶也可以使用。這一篇來分析該模塊的實現。 二.代碼分析 2.1源碼 源碼
    的頭像 發表于 09-18 09:33 ?1676次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>-<b class='flag-5'>LWIP</b>的定時器模塊詳解

    基于DWC_ether_qos以太網驅動開發-LWIP的ARP模塊介紹

    TCP/IP通訊第一步需要先調通ARP,否則TCP/IP包都不知道MAC地址要發給誰。這一篇來基于LWIP的ARP實現進行相關的分析。
    的頭像 發表于 09-18 09:34 ?1910次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>-<b class='flag-5'>LWIP</b>的ARP模塊介紹

    以太網Lwip例程

    以太網Lwip例程
    發表于 12-06 16:53 ?28次下載
    <b class='flag-5'>以太網</b><b class='flag-5'>Lwip</b>例程

    設計軟件核心以太網服務質量數據手冊免費下載

    本文描述Synopsys設計軟件核心以太網服務質量DWC以太網QoS核心5.10A。DWC以太網
    發表于 10-23 08:00 ?16次下載
    設計軟件核心<b class='flag-5'>以太網</b>服務質量數據手冊免費下載

    基于DWC_ether_qos以太網驅動開發-包過濾

    以太網上數據非常多,如果所有數據都接收交給軟件去處理軟件負載會非常重,所以一般只需要接收發給自己的數據即可
    的頭像 發表于 09-02 09:19 ?1783次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>-包過濾
    主站蜘蛛池模板: 性久久久久久| 色五月婷婷成人网| 中文在线三级中文字幕| 一级特级片| 三级免费黄色片| 就去干综合| 日本大片黄色| 精品免费久久久久久成人影院| 毛片毛片| 99视频网站| 免费jlzzjlzz在线播放视频| 啪啪网站免费| 69国产| 日韩二级| 国产nv精品你懂得| 热门国产xvideos中文| 丁香激情六月| 亚洲成色999久久网站| 男人都懂的网址在线看片| se在线播放| 福利视频免费看| 狠狠色噜噜狠狠狠狠97不卡 | 亚欧毛片基地国产毛片基地| 亚洲29p| 91大神大战丝袜美女在线观看| 国产午夜精品久久久久九九| 免费在线一区二区三区| 色y情视频免费看| 午夜一级毛片不卡| 欧美性猛交xxxx乱大交| 亚洲国产欧美在线成人aaaa| 岛国午夜| 动漫精品成人免费网站| 午夜久久免影院欧洲| 小泽玛利亚在线观看123| 五月天丁香激情| 亚洲精品成人a在线观看| 6080伦理久久亚洲精品| 日本一区二区不卡视频| 欧美精品成人a多人在线观看| 77se77亚洲欧美在线大屁股|