GD官方提供的例程ENET例程是FreeRtos+LWIP协议的,所以本人自己又重新做了一下移植(RT-Thread nano + LWIP1.4.1)。
总结以下几点:
1,第一步是ENET的初始化,首先需要保证单片机emac能通过RMII与物理芯片通信。保证能通信的前提是RMII_REF_CLK引脚上有时钟信号,然后是RMII访问的物理芯片地址正确。以下是ENET的初始化代码,可以参照官方例程。

void enet_system_setup(void)
{uint32_t ahb_frequency = 0;#ifdef USE_ENET_INTERRUPTnvic_configuration();
#endif /* USE_ENET_INTERRUPT *//* configure the GPIO ports for ethernet pins */enet_gpio_config();/* configure the ethernet MAC/DMA */enet_mac_dma_config();if (0 == enet_init_status){while(1){}}enet_interrupt_enable(ENET_DMA_INT_NIE);enet_interrupt_enable(ENET_DMA_INT_RIE);
}

2,第二步就是LWIP的移植,LWIP1.4.1源码包我是照搬GD32F450XX的官方例程拷贝的,我们需要修改的地方主要有两个文件
ethernetif.c/.h 和 sys_arch.c/.h 文件,因为LWIP1.4.1中大量使用了信号量和邮箱,所以特别需要注意这两个地方的移植,我一开始没看懂源码,所以出了问题跑去修改LWIP里边的源码,导致越该越晕,到最后发现是因为FreeRtos与RT-Thread的邮箱和信号量使用方式不一样导致的。所以LWIP协议栈本身是没有问题的,是经得起考究的,不要怀疑官方。这两个文件中也是涉及邮箱和信号量这一部分。贴源码:
ethernetif.c

/**
* @file
* Ethernet Interface Skeleton
*
*//*
* 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 <adam@sics.se>
*
*/#include "lwip/opt.h"
#include "lwip/def.h"
#include "lwip/mem.h"
#include "lwip/pbuf.h"
#include "lwip/lwip_timers.h"
#include "netif/etharp.h"
#include "err.h"
#include "ethernetif.h"#include "main.h"
#include "gd32f4xx_enet.h"
#include <string.h>#define ETHERNETIF_INPUT_TASK_STACK_SIZE          (350)
#define ETHERNETIF_INPUT_TASK_PRIO                (configMAX_PRIORITIES - 1)
#define LOWLEVEL_OUTPUT_WAITING_TIME              (250)
/* The time to block waiting for input */
#define LOWLEVEL_INPUT_WAITING_TIME               ((uint32_t )100)/* define those to better describe your network interface */
#define IFNAME0 'G'
#define IFNAME1 'D'/* ENET RxDMA/TxDMA descriptor */
extern enet_descriptors_struct  rxdesc_tab[ENET_RXBUF_NUM], txdesc_tab[ENET_TXBUF_NUM];/* ENET receive buffer  */
extern uint8_t rx_buff[ENET_RXBUF_NUM][ENET_RXBUF_SIZE]; /* ENET transmit buffer */
extern uint8_t tx_buff[ENET_TXBUF_NUM][ENET_TXBUF_SIZE]; /*global transmit and receive descriptors pointers */
extern enet_descriptors_struct  *dma_current_txdesc;
extern enet_descriptors_struct  *dma_current_rxdesc;/* preserve another ENET RxDMA/TxDMA ptp descriptor for normal mode */
enet_descriptors_struct  ptp_txstructure[ENET_TXBUF_NUM];
enet_descriptors_struct  ptp_rxstructure[ENET_RXBUF_NUM];static struct netif *low_netif = NULL;
sys_sem_t g_rx_semaphore = NULL;/**
* In this function, the hardware should be initialized.
* Called from ethernetif_init().
*
* @param netif the already initialized lwip network interface structure
*        for this ethernetif
*/
static void low_level_init(struct netif *netif)
{uint32_t i;rt_thread_t t;/* set netif MAC hardware address length */netif->hwaddr_len = ETHARP_HWADDR_LEN;/* set netif MAC hardware address */netif->hwaddr[0] =  MAC_ADDR0;netif->hwaddr[1] =  MAC_ADDR1;netif->hwaddr[2] =  MAC_ADDR2;netif->hwaddr[3] =  MAC_ADDR3;netif->hwaddr[4] =  MAC_ADDR4;netif->hwaddr[5] =  MAC_ADDR5;/* set netif maximum transfer unit */netif->mtu = 1500;/* accept broadcast address and ARP traffic */netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;low_netif =netif;/* create binary semaphore used for informing ethernetif of frame reception */if (g_rx_semaphore == NULL){g_rx_semaphore = rt_sem_create("sem", 1, RT_IPC_FLAG_FIFO);rt_sem_take(g_rx_semaphore, 0);}/* initialize MAC address in ethernet MAC */ enet_mac_address_set(ENET_MAC_ADDRESS0, netif->hwaddr);/* initialize descriptors list: chain/ring mode */
#ifdef SELECT_DESCRIPTORS_ENHANCED_MODEenet_ptp_enhanced_descriptors_chain_init(ENET_DMA_TX);enet_ptp_enhanced_descriptors_chain_init(ENET_DMA_RX);
#elseenet_descriptors_chain_init(ENET_DMA_TX);enet_descriptors_chain_init(ENET_DMA_RX);//    enet_descriptors_ring_init(ENET_DMA_TX);
//    enet_descriptors_ring_init(ENET_DMA_RX);#endif /* SELECT_DESCRIPTORS_ENHANCED_MODE *//* enable ethernet Rx interrrupt */{   int i;for(i=0; i<ENET_RXBUF_NUM; i++){ enet_rx_desc_immediate_receive_complete_interrupt(&rxdesc_tab[i]);}}#ifdef CHECKSUM_BY_HARDWARE/* enable the TCP, UDP and ICMP checksum insertion for the Tx frames */for(i=0; i < ENET_TXBUF_NUM; i++){enet_transmit_checksum_config(&txdesc_tab[i], ENET_CHECKSUM_TCPUDPICMP_FULL);}
#endif /* CHECKSUM_BY_HARDWARE *//* create thread */t = rt_thread_create("ETHERNETIF_INPUT", ethernetif_input, RT_NULL, ETHERNETIF_INPUT_TASK_STACK_SIZE, ETHERNETIF_INPUT_TASK_PRIO, 1);RT_ASSERT(t != RT_NULL);/* startup thread */rt_thread_startup(t);/* enable MAC and DMA transmission and reception */enet_enable();
}/**
* This function should do the actual transmission of the packet. The packet is
* contained in the pbuf that is passed to the function. This pbuf
* might be chained.
*
* @param netif the lwip network interface structure for this ethernetif
* @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
* @return ERR_OK if the packet could be sent
*         an err_t value if the packet couldn't be sent
*
* @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
*       strange results. You might consider waiting for space in the DMA queue
*       to become availale since the stack doesn't retry to send a packet
*       dropped because of memory failure (except for the TCP timers).
*/static err_t low_level_output(struct netif *netif, struct pbuf *p)
{static sys_sem_t s_tx_semaphore = NULL;struct pbuf *q;uint8_t *buffer ;uint16_t framelength = 0;ErrStatus reval = ERROR;SYS_ARCH_DECL_PROTECT(sr);if (s_tx_semaphore == NULL){s_tx_semaphore = rt_sem_create("sem", 1, RT_IPC_FLAG_FIFO);}if (RT_EOK == rt_sem_take(s_tx_semaphore, LOWLEVEL_OUTPUT_WAITING_TIME)){    SYS_ARCH_PROTECT(sr);while((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_DAV)){}    buffer = (uint8_t *)(enet_desc_information_get(dma_current_txdesc, TXDESC_BUFFER_1_ADDR));for(q = p; q != NULL; q = q->next){ memcpy((uint8_t *)&buffer[framelength], q->payload, q->len);framelength = framelength + q->len;}/* transmit descriptors to give to DMA */
#ifdef SELECT_DESCRIPTORS_ENHANCED_MODEreval = ENET_NOCOPY_PTPFRAME_TRANSMIT_ENHANCED_MODE(framelength, NULL);
#elsereval = ENET_NOCOPY_FRAME_TRANSMIT(framelength);
#endif /* SELECT_DESCRIPTORS_ENHANCED_MODE */SYS_ARCH_UNPROTECT(sr);/* give semaphore and exit */rt_sem_release(s_tx_semaphore);}if(SUCCESS == reval){return ERR_OK;}else{while(1){}}}/**
* Should allocate a pbuf and transfer the bytes of the incoming
* packet from the interface into the pbuf.
*
* @param netif the lwip network interface structure for this ethernetif
* @return a pbuf filled with the received packet (including MAC header)
*         NULL on memory error
*/
static struct pbuf * low_level_input(struct netif *netif)
{struct pbuf *p= NULL, *q;uint32_t l =0;u16_t len;uint8_t *buffer;/* obtain the size of the packet and put it into the "len" variable. */len = enet_desc_information_get(dma_current_rxdesc, RXDESC_FRAME_LENGTH);buffer = (uint8_t *)(enet_desc_information_get(dma_current_rxdesc, RXDESC_BUFFER_1_ADDR));if (len > 0){/* We allocate a pbuf chain of pbufs from the Lwip buffer pool */p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);}if (p != NULL){for(q = p; q != NULL; q = q->next){memcpy((uint8_t *)q->payload, (u8_t*)&buffer[l], q->len);l = l + q->len;}}
#ifdef SELECT_DESCRIPTORS_ENHANCED_MODEENET_NOCOPY_PTPFRAME_RECEIVE_ENHANCED_MODE(NULL);#elseENET_NOCOPY_FRAME_RECEIVE();
#endif /* SELECT_DESCRIPTORS_ENHANCED_MODE */return p;
}/**
* This function is the ethernetif_input task, it is processed when a packet
* is ready to be read from the interface. It uses the function low_level_input()
* that should handle the actual reception of bytes from the network
* interface. Then the type of the received packet is determined and
* the appropriate input function is called.
*
* @param netif the lwip network interface structure for this ethernetif
*/
void ethernetif_input( void * pvParameters )
{struct pbuf *p;SYS_ARCH_DECL_PROTECT(sr);for( ;; ){   if(0 == rt_sem_take(g_rx_semaphore, LOWLEVEL_INPUT_WAITING_TIME)){
TRY_GET_NEXT_FRAME:SYS_ARCH_PROTECT(sr);p = low_level_input( low_netif );SYS_ARCH_UNPROTECT(sr);if   (p != NULL){if (ERR_OK != low_netif->input( p, low_netif)){pbuf_free(p);}else{goto TRY_GET_NEXT_FRAME;}}}}
}/**
* Should be called at the beginning of the program to set up the
* network interface. It calls the function low_level_init() to do the
* actual setup of the hardware.
*
* This function should be passed as a parameter to netif_add().
*
* @param netif the lwip network interface structure for this ethernetif
* @return ERR_OK if the loopif is initialized
*         ERR_MEM if private data couldn't be allocated
*         any other err_t on error
*/
err_t ethernetif_init(struct netif *netif)
{LWIP_ASSERT("netif != NULL", (netif != NULL));#if LWIP_NETIF_HOSTNAME/* initialize interface hostname */netif->hostname = "lwip";
#endif /* LWIP_NETIF_HOSTNAME */netif->name[0] = IFNAME0;netif->name[1] = IFNAME1;netif->output = etharp_output;netif->linkoutput = low_level_output;/* initialize the hardware */low_level_init(netif);return ERR_OK;
}

sys_arch.c

/** Copyright (c) 2001-2003 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 <adam@sics.se>**//* lwIP includes. */
#include "lwip/debug.h"
#include "lwip/def.h"
#include "lwip/sys.h"
#include "lwip/mem.h"
#include "lwip/stats.h"
#include "rtthread.h"
#include <rthw.h>#define PRIVILEGED_FUNCTION
#define PRIVILEGED_DATAvoid * xTaskGetCurrentTaskHandle( void ) PRIVILEGED_FUNCTION;static u16_t s_nextthread = 0;/*-----------------------------------------------------------------------------------*///Creates an empty mailbox.
err_t sys_mbox_new(sys_mbox_t *mbox, int size)
{static unsigned short counter = 0;char tname[RT_NAME_MAX];sys_mbox_t tmpmbox;RT_DEBUG_NOT_IN_INTERRUPT;rt_snprintf(tname, RT_NAME_MAX, "%s%d", SYS_LWIP_MBOX_NAME, counter);counter ++;tmpmbox = rt_mb_create(tname, size, RT_IPC_FLAG_FIFO);if (tmpmbox == RT_NULL){return ERR_MEM;}*mbox = tmpmbox;return ERR_OK;
}/*-----------------------------------------------------------------------------------*/
/*Deallocates a mailbox. If there are messages still present in themailbox when the mailbox is deallocated, it is an indication of aprogramming error in lwIP and the developer should be notified.
*/
void sys_mbox_free(sys_mbox_t *mbox)
{RT_DEBUG_NOT_IN_INTERRUPT;rt_mb_delete(*mbox);return;
}/*-----------------------------------------------------------------------------------*/
//   Posts the "msg" to the mailbox.
void sys_mbox_post(sys_mbox_t *mbox, void *data)
{RT_DEBUG_NOT_IN_INTERRUPT;rt_mb_send_wait(*mbox, (rt_uint32_t)data, RT_WAITING_FOREVER);return;
}/*-----------------------------------------------------------------------------------*/
//   Try to post the "msg" to the mailbox.
err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg)
{err_t result;if (rt_mb_send(*mbox, (rt_uint32_t)msg) == RT_EOK)return ERR_OK;return ERR_MEM;
}/*-----------------------------------------------------------------------------------*/
/*Blocks the thread until a message arrives in the mailbox, but doesnot block the thread longer than "timeout" milliseconds (similar tothe sys_arch_sem_wait() function). The "msg" argument is a resultparameter that is set by the function (i.e., by doing "*msg =ptr"). The "msg" parameter maybe NULL to indicate that the messageshould 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 atimeout.Note that a function with a similar name, sys_mbox_fetch(), isimplemented by lwIP.
*/
u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout)
{rt_err_t ret;s32_t t;u32_t tick;RT_DEBUG_NOT_IN_INTERRUPT;/* get the begin tick */tick = rt_tick_get();if(timeout == 0)t = RT_WAITING_FOREVER;else{/* convirt msecond to os tick */if (timeout < (1000/RT_TICK_PER_SECOND))t = 1;elset = timeout / (1000/RT_TICK_PER_SECOND);}ret = rt_mb_recv(*mbox, (rt_ubase_t *)msg, t);if(ret != RT_EOK){return SYS_ARCH_TIMEOUT;}/* get elapse msecond */tick = rt_tick_get() - tick;/* convert tick to msecond */tick = tick * (1000 / RT_TICK_PER_SECOND);if (tick == 0)tick = 1;return tick;
}/*-----------------------------------------------------------------------------------*/
/*Similar to sys_arch_mbox_fetch, but if message is not ready immediately, we'llreturn with SYS_MBOX_EMPTY.  On success, 0 is returned.
*/
u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg)
{int ret;ret = rt_mb_recv(*mbox, (rt_ubase_t *)msg, 0);if(ret == RT_EOK){return ERR_OK;}else{return SYS_MBOX_EMPTY;}
}
/*----------------------------------------------------------------------------------*/
int sys_mbox_valid(sys_mbox_t *mbox)
{      if (*mbox == SYS_MBOX_NULL){return 0;} else{return 1;}
}
/*-----------------------------------------------------------------------------------*/
void sys_mbox_set_invalid(sys_mbox_t *mbox)
{                                             *mbox = SYS_MBOX_NULL;
}                                             /*-----------------------------------------------------------------------------------*/
//  Creates a new semaphore. The "count" argument specifies
//  the initial state of the semaphore.
err_t sys_sem_new(sys_sem_t *sem, u8_t count)
{static unsigned short counter = 0;char tname[RT_NAME_MAX];sys_sem_t tmpsem;RT_DEBUG_NOT_IN_INTERRUPT;rt_snprintf(tname, RT_NAME_MAX, "%s%d", SYS_LWIP_SEM_NAME, counter);counter ++;tmpsem = rt_sem_create(tname, count, RT_IPC_FLAG_FIFO);if (tmpsem == RT_NULL)return ERR_MEM;*sem = tmpsem;// Means it can't be taken
//    if(count == 0){
//        rt_sem_take(*sem,1);
//    }return ERR_OK;
}/*-----------------------------------------------------------------------------------*/
/*Blocks the thread while waiting for the semaphore to besignaled. If the "timeout" argument is non-zero, the thread shouldonly be blocked for the specified time (measured inmilliseconds).If the timeout argument is non-zero, the return value is the number ofmilliseconds spent waiting for the semaphore to be signaled. If thesemaphore wasn't signaled within the specified time, the return value isSYS_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.
*/
u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout)
{rt_err_t ret;s32_t t;u32_t tick;RT_DEBUG_NOT_IN_INTERRUPT;/* get the begin tick */tick = rt_tick_get();if (timeout == 0)t = RT_WAITING_FOREVER;else{/* convert msecond to os tick */if (timeout < (1000/RT_TICK_PER_SECOND))t = 1;elset = timeout / (1000/RT_TICK_PER_SECOND);}ret = rt_sem_take(*sem, t);if (ret == -RT_ETIMEOUT)return SYS_ARCH_TIMEOUT;else{if (ret == RT_EOK)ret = 1;}/* get elapse msecond */tick = rt_tick_get() - tick;/* convert tick to msecond */tick = tick * (1000 / RT_TICK_PER_SECOND);if (tick == 0)tick = 1;return tick;
}/*-----------------------------------------------------------------------------------*///Signals a semaphore
void sys_sem_signal(sys_sem_t *sem)
{rt_sem_release(*sem);
}/*-----------------------------------------------------------------------------------*/
// Deallocates a semaphore
void sys_sem_free(sys_sem_t *sem)
{RT_DEBUG_NOT_IN_INTERRUPT;rt_sem_delete(*sem);
}
/*-----------------------------------------------------------------------------------*/
int sys_sem_valid(sys_sem_t *sem)
{if (*sem == SYS_SEM_NULL){return 0;}    else{return 1; }
}/*-----------------------------------------------------------------------------------*/
void sys_sem_set_invalid(sys_sem_t *sem)
{                                                                               *sem = SYS_SEM_NULL;
} /*-----------------------------------------------------------------------------------*/
// Initialize sys arch
void sys_init(void)
{// keep track of how many threads have been createds_nextthread = 0;
}
/*-----------------------------------------------------------------------------------*//* Mutexes*/
/*-----------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------*/
#if LWIP_COMPAT_MUTEX == 0
/* Create a new mutex*/
err_t sys_mutex_new(sys_mutex_t *mutex)
{*mutex = xSemaphoreCreateMutex();if(*mutex == NULL){
#if SYS_STATS++lwip_stats.sys.mutex.err;
#endif /* SYS_STATS */return ERR_MEM;}#if SYS_STATS++lwip_stats.sys.mutex.used;if(lwip_stats.sys.mutex.max < lwip_stats.sys.mutex.used){lwip_stats.sys.mutex.max = lwip_stats.sys.mutex.used;}
#endif /* SYS_STATS */return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
/* Deallocate a mutex*/
void sys_mutex_free(sys_mutex_t *mutex)
{
#if SYS_STATS--lwip_stats.sys.mutex.used;
#endif /* SYS_STATS */vQueueDelete(*mutex);
}
/*-----------------------------------------------------------------------------------*/
/* Lock a mutex*/
void sys_mutex_lock(sys_mutex_t *mutex)
{sys_arch_sem_wait(*mutex, 0);
}/*-----------------------------------------------------------------------------------*/
/* Unlock a mutex*/
void sys_mutex_unlock(sys_mutex_t *mutex)
{rt_sem_release(*mutex);
}
#endif /*LWIP_COMPAT_MUTEX*/
/*-----------------------------------------------------------------------------------*/
// TODO
/*-----------------------------------------------------------------------------------*/
/*Starts a new thread with priority "prio" that will begin its execution in thefunction "thread()". The "arg" argument will be passed as an argument to thethread() function. The id of the new thread is returned. Both the id andthe priority are system dependent.
*/
sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread , void *arg, int stacksize, int prio)
{rt_thread_t t;RT_DEBUG_NOT_IN_INTERRUPT;/* create thread */t = rt_thread_create(name, thread, arg, stacksize, prio, 20);RT_ASSERT(t != RT_NULL);/* startup thread */rt_thread_startup(t);return t;
}/*This optional function does a "fast" critical region protection and returnsthe previous protection level. This function is only called during very shortcritical regions. An embedded system which supports ISR-based drivers mightwant to implement this function by disabling interrupts. Task-based systemsmight want to implement this by using a mutex or disabling tasking. Thisfunction should support recursive calls from the same task or interrupt. Inother words, sys_arch_protect() could be called while already protected. Inthat case the return value indicates that it is already protected.sys_arch_protect() is only required if your port is supporting an operatingsystem.
*/
sys_prot_t sys_arch_protect(void)
{rt_base_t level;/* disable interrupt */level = rt_hw_interrupt_disable();return level;
}/*This optional function does a "fast" set of critical region protection to thevalue specified by pval. See the documentation for sys_arch_protect() formore information. This function is only required if your port is supportingan operating system.
*/
void sys_arch_unprotect(sys_prot_t pval)
{/* enable interrupt */rt_hw_interrupt_enable(pval);
}/** Prints an assertion messages and aborts execution.*/
void sys_assert( const char *msg )
{( void ) msg;/*FSL:only needed for debuggingprintf(msg);printf("\n\r");*/rt_base_t level;/* disable interrupt */level = rt_hw_interrupt_disable();for(;;);
}
/*-----------------------------------------------------------------------------------*/
这两个文件复制到工程中然后编译过后,LWIP协议的移植基本也没什么问题了。
总结以下:
LWIP的移植最重要的一点就是信号量和邮箱接口的使用,如果遇到问题可以跟进以下代码,把关于邮箱和信号量的部分好好看看。
欢迎大家提问与指正,谢谢!

GG32F450XX上移植RT-Thread+LWIP协议栈相关推荐

  1. Yeelink平台使用——远程控制 RT Thread + LwIP+ STM32

    1.前言     [2014年4月重写该博文]     经过若干时间的努力终于搞定了STM32+LwIP和yeelink平台的数据互通,在学习的过程中大部分时间花在以太网协议栈学习上,但是在RT Th ...

  2. LwIP 协议栈移植教程

    一.什么是 LwIP,以及何时使用 LwIP ? 官网地址:lwIP - A Lightweight TCP/IP stack - Summary [Savannah] 按照官网的描述:lwIP is ...

  3. RT Thread Free Modbus移植问题整理

    RT Thread Free Modbus移植问题整理 问题描述: 在读写寄存器中,写数据正常,只能读1个寄存器的值,多个值会异常. 在移植过程中发现串口(或RS485)数据接收长度异常. 一.环境描 ...

  4. 正点原子delay函数移植到rt thread操作系统(HAL库)

    正点原子教程中涉及到的操作系统只涉及了UCOS的教程,其中例程的system文件夹中的delay.c函数只是适配了UCOS. 下面将delay.c函数移植到rt thread中,使用的bsp是rt t ...

  5. 基于rt thread smart构建EtherCAT主站

    我把源码开源到到了gitee,https://gitee.com/rathon/rt-thread-smart-soem 有兴趣的去可以下载下来跑一下 软件工程推荐用vscode 打开.rt thre ...

  6. lwip协议栈在linux运行,LwIP协议栈在uCOS II下的实现

    1.概述: LwIP协议栈在设计时就考虑到了将来的移植问题,因此把所有与硬件.OS.编译器相关的部份独立出来,放在ucosii&LwIPsource etlwiparch目录下.因此LwIP在 ...

  7. lwip路由实现_基于LWIP协议栈对路由缓存数据结构实现改进设计

    LWIP(Light Weight Internet Protoco1)是瑞士计算机科学院(Swedish Institute of C++omputer Science)AdamDunkels等人开 ...

  8. rt thread studio使用QBOOT和片外flash实现OTA升级

    我们这里要使用单片机外部flash作为OTA的下载分区,外部flash硬件连接关系 PB3-->SPI3_CLK PB4-->SPI3_MISO PB5-->SPI3_MOSI PE ...

  9. LwIP应用笔记(三):在RTOS环境下运行LwIP协议栈

    前言 这篇文章是 LwIP应用笔记(二):无操作系统支持下的RAW API移植 的后续,以下所有内容都是建立在已经完成RAW API移植的前提下.本文可能不会太纠结于代码细节,因为本文的目标并不是演示 ...

最新文章

  1. Java中实现多线程关键词整理
  2. Linux中的SELinux与chcon以及Samba实现【转】
  3. Eclipse 应用的初步认识
  4. CF-547E(Mike and Friends)后缀数组+线段树 AC自动机+DFS序+树状数组
  5. Unity3d官方测试插件学习-单元测试,集成测试
  6. SAP License:ERP系统中供应商管理怎么做?
  7. 如何进行 JVM 调优
  8. struts2拦截器原理
  9. 200Smart PLC 与丹佛斯变频器MODBUS RTU通讯实例
  10. 编辑python用什么输入法_用Python从0开始实现一个中文拼音输入法!
  11. Chrome开发工具Network没有显示完整的http request和response对话
  12. MapServer 7.0.3 Documentation 翻译
  13. IDC许可证是什么证?IDC办理条件及材料
  14. QT使用QStackedWidget实现切页显示
  15. Java 之父求职被嫌年纪大,硅谷公司现在喜欢“小鲜肉”,不爱“老古董” 作者:程序媛Adele
  16. 阿玛尼美妆宣布泰莎·汤普森成为品牌最新美妆代言人
  17. ansys用什么cpu_学ansys软件需要什么样的电脑配置才能运行?
  18. 如何通过一张图片找到你的位置?
  19. ds6708 symbol 驱动_SymbolDS6708
  20. numpy的Y.shape和Y.shape[0]的区别

热门文章

  1. javascript里裁切图片插件库
  2. 周报-暑假留校第三份
  3. phonegap-第三方登陆-andriod插件
  4. 4.1_[Java 输入输出]-全网最全 Java 控制台输入输出
  5. bat文件刷屏,请规范命名
  6. 开关电源环路学习笔记(3)-系统框图
  7. Proxy ARP--即ARP代理
  8. 面试题:25匹马最快3匹及扩展
  9. The Matrix--庄生晓梦迷蝴蝶
  10. 思考“手绘家谱”的算法