锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

GG32F450XX上移植RT-Thread+LWIP协议栈

时间:2022-11-08 03:00:00 220f450v5a三极管f450光电开关传感器

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_INTERRUPT      nvic_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); } 

第二步是LWIP的移植,LWIP1.4.1源码包我是照搬GD32F450XX我们需要修改的主要有两个文件
ethernetif.c/.h 和 sys_arch.c/.h 文件,因为LWIP1.4.信号量和邮箱在1中被广泛使用,因此需要特别注意这两个地方的移植。一开始我不懂源代码,所以我跑去修改问题LWIP里面的源代码越晕,最后发现是因为FreeRtos与RT-Thread邮箱和信号量的使用方式不同。所以LWIP协议栈本身没有问题,经得起考究,不要怀疑官方。所以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 NEGLIGENE 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  * */

#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 


#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_MODE
    enet_ptp_enhanced_descriptors_chain_init(ENET_DMA_TX);
    enet_ptp_enhanced_descriptors_chain_init(ENET_DMA_RX);
#else

    enet_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_MODE
        reval = ENET_NOCOPY_PTPFRAME_TRANSMIT_ENHANCED_MODE(framelength, NULL);
#else
        reval = 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_MODE
    ENET_NOCOPY_PTPFRAME_RECEIVE_ENHANCED_MODE(NULL);
  
#else
    
    ENET_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  * */

/* 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 

#define PRIVILEGED_FUNCTION
#define PRIVILEGED_DATA

void * 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 the mailbox when the mailbox is deallocated, it is an indication of a programming 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 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. */
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;
        else
            t = 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'll return 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  
锐单商城拥有海量元器件数据手册IC替代型号,打造电子元器件IC百科大全!

相关文章