LWIP个人移植心得,平台STM32F4,HAL库,CMSIS_OS系统封装

LWIP个人移植心得,平台STM32F4,HAL库,CMSIS_OS系统封装

1、先在官网下载LWIP源码及例程文件,以1.4.1版本为例分别是lwip-1.4.1和contrib-1.4.1,将lwip-1.4.1的src文件夹全都拷贝到自己工程中,同时先在这个src下新建一个空文件夹命名arch。
2、然后将contrib-1.4.1\ports\win32\include\arch下的bpstruct.h、cc.h、epstruct.h、perf.h拷贝到上面自己新建的arch目录。
3、在自建的arch目录下新建lwipopts.h、sys_arch.c、sys_arch.h文件,src\include\lwip下的sys.h中说明了所有要在sys_arch.c中实现的函数,同时该目录下的opt.h说明了所有对LIWP进行裁剪和盘配置的参数,不要在opt.h中直接修改,因为opt是条件编译的,万一有在别的地方定义过,则你在opt.h中的配置就无效了,可以根据需要另外重新在lwipopts.h进行定义,sys_arch.h主要定义三个操作系统数据类型:
信号量sys_sem_t、消息队列sys_mbox_t、任务sys_thread_t,如果没有定义LWIP_COMPAT_MUTEX为1(LWIP_COMPAT_MUTEX表示是否用信号量来
替代互斥信号量,它被用在sys.h作互斥量的编译条件),则还需要定义互斥量类型sys_mutex_t。

以下是我修改编写的这三个文件

#ifndef __LWIPOPTS_H__
#define __LWIPOPTS_H__

#define LWIP_COMPAT_MUTEX 1    //use sem in place of mutex

#define NO_SYS                     0
#define LWIP_SOCKET               (NO_SYS==0)
#define LWIP_NETCONN              (NO_SYS==0)

#define LWIP_IGMP                  1
#define LWIP_ICMP                  1
#define LWIP_SNMP                  0

#define LWIP_DNS                   1

#define LWIP_HAVE_LOOPIF           1
#define LWIP_NETIF_LOOPBACK        1
#define LWIP_LOOPBACK_MAX_PBUFS    10

#define TCP_LISTEN_BACKLOG         0

#define LWIP_COMPAT_SOCKETS        1
#define LWIP_SO_RCVTIMEO           1
#define LWIP_SO_RCVBUF             1

#define LWIP_TCPIP_CORE_LOCKING    0

#define LWIP_NETIF_LINK_CALLBACK   1
#define LWIP_NETIF_STATUS_CALLBACK 1

#ifdef LWIP_DEBUG

#define LWIP_DBG_MIN_LEVEL         0
#define PPP_DEBUG                  LWIP_DBG_OFF
#define MEM_DEBUG                  LWIP_DBG_OFF
#define MEMP_DEBUG                 LWIP_DBG_OFF
#define PBUF_DEBUG                 LWIP_DBG_OFF
#define API_LIB_DEBUG              LWIP_DBG_OFF
#define API_MSG_DEBUG              LWIP_DBG_OFF
#define TCPIP_DEBUG                LWIP_DBG_OFF
#define NETIF_DEBUG                LWIP_DBG_OFF
#define SOCKETS_DEBUG              LWIP_DBG_OFF
#define DNS_DEBUG                  LWIP_DBG_OFF
#define AUTOIP_DEBUG               LWIP_DBG_OFF
#define DHCP_DEBUG                 LWIP_DBG_OFF
#define IP_DEBUG                   LWIP_DBG_OFF
#define IP_REASS_DEBUG             LWIP_DBG_OFF
#define ICMP_DEBUG                 LWIP_DBG_OFF
#define IGMP_DEBUG                 LWIP_DBG_OFF
#define UDP_DEBUG                  LWIP_DBG_OFF
#define TCP_DEBUG                  LWIP_DBG_OFF
#define TCP_INPUT_DEBUG            LWIP_DBG_OFF
#define TCP_OUTPUT_DEBUG           LWIP_DBG_OFF
#define TCP_RTO_DEBUG              LWIP_DBG_OFF
#define TCP_CWND_DEBUG             LWIP_DBG_OFF
#define TCP_WND_DEBUG              LWIP_DBG_OFF
#define TCP_FR_DEBUG               LWIP_DBG_OFF
#define TCP_QLEN_DEBUG             LWIP_DBG_OFF
#define TCP_RST_DEBUG              LWIP_DBG_OFF
#endif

#define LWIP_DBG_TYPES_ON         (LWIP_DBG_ON|LWIP_DBG_TRACE|LWIP_DBG_STATE|LWIP_DBG_FRESH|LWIP_DBG_HALT)


/* ---------- Memory options ---------- */
/* MEM_ALIGNMENT: should be set to the alignment of the CPU for which
   lwIP is compiled. 4 byte alignment -> define MEM_ALIGNMENT to 4, 2
   byte alignment -> define MEM_ALIGNMENT to 2. */
/* MSVC port: intel processors don't need 4-byte alignment,
   but are faster that way! */
#define MEM_ALIGNMENT           4

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

/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application
   sends a lot of data out of ROM (or other static memory), this
   should be set high. */
#define MEMP_NUM_PBUF           16
/* MEMP_NUM_RAW_PCB: the number of UDP protocol control blocks. One
   per active RAW "connection". */
#define MEMP_NUM_RAW_PCB        3
/* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One
   per active UDP "connection". */
#define MEMP_NUM_UDP_PCB        4
/* MEMP_NUM_TCP_PCB: the number of simulatenously active TCP
   connections. */
#define MEMP_NUM_TCP_PCB        5
/* MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP
   connections. */
#define MEMP_NUM_TCP_PCB_LISTEN 8
/* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP
   segments. */
#define MEMP_NUM_TCP_SEG        16
/* MEMP_NUM_SYS_TIMEOUT: the number of simulateously active
   timeouts. */
#define MEMP_NUM_SYS_TIMEOUT    15

/* The following four are used only with the sequential API and can be
   set to 0 if the application only will use the raw API. */
/* MEMP_NUM_NETBUF: the number of struct netbufs. */
#define MEMP_NUM_NETBUF         2
/* MEMP_NUM_NETCONN: the number of struct netconns. */
#define MEMP_NUM_NETCONN        10
/* MEMP_NUM_TCPIP_MSG_*: the number of struct tcpip_msg, which is used
   for sequential API communication and incoming packets. Used in
   src/api/tcpip.c. */
#define MEMP_NUM_TCPIP_MSG_API   16
#define MEMP_NUM_TCPIP_MSG_INPKT 16


/* ---------- Pbuf options ---------- */
/* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */
#define PBUF_POOL_SIZE          120

/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */
#define PBUF_POOL_BUFSIZE       128

/* PBUF_LINK_HLEN: the number of bytes that should be allocated for a
   link level header. */
#define PBUF_LINK_HLEN          16

/** SYS_LIGHTWEIGHT_PROT
 * define SYS_LIGHTWEIGHT_PROT in lwipopts.h if you want inter-task protection
 * for certain critical regions during buffer allocation, deallocation and memory
 * allocation and deallocation.
 */
#define SYS_LIGHTWEIGHT_PROT    (NO_SYS==0)


/* ---------- TCP options ---------- */
#define LWIP_TCP                1
#define TCP_TTL                 255

/* Controls if TCP should queue segments that arrive out of
   order. Define to 0 if your device is low on memory. */
#define TCP_QUEUE_OOSEQ         1

/* TCP Maximum segment size. */
#define TCP_MSS                 1024

/* TCP sender buffer space (bytes). */
#define TCP_SND_BUF             2048

/* TCP sender buffer space (pbufs). This must be at least = 2 *
   TCP_SND_BUF/TCP_MSS for things to work. */
#define TCP_SND_QUEUELEN       (4 * TCP_SND_BUF/TCP_MSS)

/* TCP writable space (bytes). This must be less than or equal
   to TCP_SND_BUF. It is the amount of space which must be
   available in the tcp snd_buf for select to return writable */
#define TCP_SNDLOWAT           (TCP_SND_BUF/2)

/* TCP receive window. */
#define TCP_WND                 8096

/* Maximum number of retransmissions of data segments. */
#define TCP_MAXRTX              8

/* Maximum number of retransmissions of SYN segments. */
#define TCP_SYNMAXRTX           4


/* ---------- ARP options ---------- */
#define LWIP_ARP                1
#define ARP_TABLE_SIZE          10
#define ARP_QUEUEING            1


/* ---------- IP options ---------- */
/* Define IP_FORWARD to 1 if you wish to have 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              1

/* IP reassembly and segmentation.These are orthogonal even
 * if they both deal with IP fragments */
#define IP_REASSEMBLY           1
#define IP_REASS_MAX_PBUFS      10
#define MEMP_NUM_REASSDATA      10
#define IP_FRAG                 1


/* ---------- ICMP options ---------- */
#define ICMP_TTL                255


/* ---------- DHCP options ---------- */
/* Define LWIP_DHCP to 1 if you want DHCP configuration of
   interfaces. */
#define LWIP_DHCP               1

/* 1 if you want to do an ARP check on the offered address
   (recommended). */
#define DHCP_DOES_ARP_CHECK    (LWIP_DHCP)


/* ---------- AUTOIP options ------- */
#define LWIP_AUTOIP             0
#define LWIP_DHCP_AUTOIP_COOP  (LWIP_DHCP && LWIP_AUTOIP)


/* ---------- UDP options ---------- */
#define LWIP_UDP                1
#define LWIP_UDPLITE            1
#define UDP_TTL                 255


/* ---------- Statistics options ---------- */

#define LWIP_STATS              1
#define LWIP_STATS_DISPLAY      1

#if LWIP_STATS
#define LINK_STATS              1
#define IP_STATS                1
#define ICMP_STATS              1
#define IGMP_STATS              1
#define IPFRAG_STATS            1
#define UDP_STATS               1
#define TCP_STATS               1
#define MEM_STATS               1
#define MEMP_STATS              1
#define PBUF_STATS              1
#define SYS_STATS               1
#endif /* LWIP_STATS */


/* ---------- PPP options ---------- */

#define PPP_SUPPORT             0      /* Set > 0 for PPP */

#if PPP_SUPPORT

#define NUM_PPP                 1      /* Max PPP sessions. */


/* Select modules to enable.  Ideally these would be set in the makefile but
 * we're limited by the command line length so you need to modify the settings
 * in this file.
 */
#define PPPOE_SUPPORT           1
#define PPPOS_SUPPORT           1

#define PAP_SUPPORT             1      /* Set > 0 for PAP. */
#define CHAP_SUPPORT            1      /* Set > 0 for CHAP. */
#define MSCHAP_SUPPORT          0      /* Set > 0 for MSCHAP (NOT FUNCTIONAL!) */
#define CBCP_SUPPORT            0      /* Set > 0 for CBCP (NOT FUNCTIONAL!) */
#define CCP_SUPPORT             0      /* Set > 0 for CCP (NOT FUNCTIONAL!) */
#define VJ_SUPPORT              1      /* Set > 0 for VJ header compression. */
#define MD5_SUPPORT             1      /* Set > 0 for MD5 (see also CHAP) */

#endif /* PPP_SUPPORT */

#endif /* __LWIPOPTS_H__ */
/*
*********************************************************************************************************
*                                              lwIP TCP/IP Stack
*                                    	 port for CMSIS_OS RTOS Interface
*
* File : sys_arch.c
* By   : XiaoMing
*********************************************************************************************************
*/
#ifndef __SYS_ARCH_H__
#define __SYS_ARCH_H__
#include "cmsis_os.h"
#include "arch/cc.h"

#define SYS_MBOX_NULL   (void*)0
#define SYS_SEM_NULL    (void*)0

#define MAX_QUEUES        20
#define MAX_QUEUE_ENTRIES 20
 
typedef osSemaphoreId sys_sem_t;
typedef osMessageQId  sys_mbox_t;//the structure defined above
typedef osThreadId  sys_thread_t;

#endif

/*
*********************************************************************************************************
*                                              lwIP TCP/IP Stack
*                                    	 port for CMSIS_OS RTOS Interface
*
* File : sys_arch.c
* By   : XiaoMing
*********************************************************************************************************
*/


#include "lwip/def.h"
#include "lwip/sys.h"
#include "lwip/mem.h"

#include "arch/sys_arch.h" 

const void * const pvNullPointer;

static char pcQueueMemoryPool[MAX_QUEUES * 4 ];
osPoolDef_t osPoolDef_t0={MAX_QUEUES,4,pcQueueMemoryPool};


/*-----------------------------------------------------------------------------------*/
/* This func should be called first in lwip task!
 * -------------------------------------------------		*/
sys_mutex_t lwip_prot_mutex;
// Initialize sys arch
void sys_init(void)
{
  if(sys_mutex_new(&lwip_prot_mutex)!=ERR_OK){
		printf("error at %s line %d",__FILE__,__LINE__);
		while(1){}
	}
}


/*-----------------------------------------------------------------------------------*/
err_t sys_sem_new(sys_sem_t *sem, u8_t count){
    osSemaphoreDef(pSem);
		*sem=osSemaphoreCreate (osSemaphore(pSem),count);
		return *sem!=NULL?ERR_OK:ERR_MEM;
}
/*-----------------------------------------------------------------------------------*/
void sys_sem_free(sys_sem_t *sem)
{
	osSemaphoreDelete(*sem);
}

/*-----------------------------------------------------------------------------------*/

void sys_sem_signal(sys_sem_t*sem)
{
	osSemaphoreRelease(*sem);
}
/*-----------------------------------------------------------------------------------*/

u32_t sys_arch_sem_wait(sys_sem_t*sem, u32_t timeout)
{
	u32_t t=osKernelSysTick();
	osSemaphoreWait(*sem,timeout);
	t=osKernelSysTick()-t;
	if(t>timeout)
		t=SYS_ARCH_TIMEOUT;
	return t;
}


/*-----------------------------------------------------------------------------------*/
err_t sys_mbox_new(sys_mbox_t *mbox, int size)
{
	osMessageQDef(Q,size,void*);
	*mbox=osMessageCreate (osMessageQ(Q),NULL);
	return *mbox!=NULL?ERR_OK:ERR_MEM;
}
/*-----------------------------------------------------------------------------------*/
void sys_mbox_free(sys_mbox_t *mbox){
	osMessageDelete(*mbox);
}

/*-----------------------------------------------------------------------------------*/
void sys_mbox_post(sys_mbox_t *mbox, void *msg){
	osMessagePut (*mbox,(uint32_t)msg,osWaitForever);
}
err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg){
	return osMessagePut (*mbox,(uint32_t)msg,0);
}
/*-----------------------------------------------------------------------------------*/
u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout){
	u32_t t=osKernelSysTick();
	osEvent e= osMessageGet(*mbox,timeout);
	t=osKernelSysTick()-t;
	if(e.status==osEventMessage){
		*msg=e.value.p;
		return t;
	}
	return SYS_ARCH_TIMEOUT;
}

u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg){
	osEvent e= osMessageGet(*mbox,0);
	if(e.status==osEventMessage){
		*msg=e.value.p;
		return 0;
	}
	else return SYS_MBOX_EMPTY;
}
/*----------------------------------------------------------------------*/


/*------------------------------------------------------------------------*/
sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio){
	const osThreadDef_t os_thread_def = 
	{  (char*)name,(void(*)(const void*arg))(thread), (osPriority)(prio), (0), (stacksize)};
	return osThreadCreate (&os_thread_def,arg);
}
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;   
}
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; 
}

sys_prot_t sys_arch_protect(void)
{
  sys_mutex_lock(lwip_prot_mutex);
  return (sys_prot_t)1;
}

void sys_arch_unprotect(sys_prot_t pval)
{
  ( void ) pval;
  sys_mutex_unlock(lwip_prot_mutex);
}



4、给自己工程添加LIWP源码,src\api下所有c代码,src\arch下的sys_arch.c,src\core下所有c代码及src\core\ipv4下所有c代码,src\netif下
的etharp.c和ethernetif.c。其他文件一般都用不到。
5、给自己工程添加头文件目录:…\src\include;…\src\include\ipv4;…\src\include\netif;…\src\include\lwip;…\src;…\src\arch。
到这工程已经可以编译通过了,但还不能正常使用,因为还没实现网卡的驱动。
6、根据自己的硬件编写ethernetif.c中的网卡驱动(最容易出问题的部分),需要修改的函数有

low_level_init(struct netif *netif);
static err_t low_level_output(struct netif *netif, struct pbuf *p);
static void  ethernetif_input(struct netif *netif);

low_level_init用于完成完成底层硬件的初始化,一般包括数据链路层和物理层的初始化,
ethernetif_input负责调用底层实际输入接收函数,
low_level_output负责调用底层实际输出发送函数。

以下是我针对STM32F4的板子修改的网卡驱动

/*
 * This file is a skeleton for developing Ethernet network interface
 * drivers for lwIP. Add code to the low_level functions and do a
 * search-and-replace for the word "ethernetif" to replace it with
 * something that better describes your network interface.
 */

#include "lwip/opt.h"

#if 1 /* don't build, this is only a skeleton, see previous comment */

#include "lwip/def.h"
#include "lwip/mem.h"
#include "lwip/pbuf.h"
#include 
#include 
#include "netif/etharp.h"
#include "netif/ppp_oe.h"
#include "eth.h"
#include "sys.h"
#include "string.h"

/* Define those to better describe your network interface. */
#define IFNAME0 'e'
#define IFNAME1 'n'

/**
 * Helper struct to hold private data used to operate your ethernet interface.
 * Keeping the ethernet address of the MAC in this struct is not necessary
 * as it is already kept in the struct netif.
 * But this is only an example, anyway...
 */
struct ethernetif {
  struct eth_addr *ethaddr;
  /* Add whatever per-interface state that is needed here. */
};

/* Forward declarations. */
static void  ethernetif_input(struct netif *netif);

sys_sem_t sem;
void eth_input_task(void*argument){
	while(1){
		sys_arch_sem_wait(&sem,osWaitForever);
		ethernetif_input((struct netif *)argument);
	}
}
/**
 * In this function, the hardware should be initialized.
 * Called from ethernetif_init().
 *
 * @param netif the already initialized lwip network interface structure
 *        for this ethernetif
 */
__ALIGN_BEGIN ETH_DMADescTypeDef  DMARxDscrTab[ETH_RXBUFNB] __ALIGN_END;
__ALIGN_BEGIN ETH_DMADescTypeDef  DMATxDscrTab[ETH_TXBUFNB] __ALIGN_END;
__ALIGN_BEGIN uint8_t Rx_Buff[ETH_RXBUFNB][ETH_RX_BUF_SIZE] __ALIGN_END;
__ALIGN_BEGIN uint8_t Tx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE] __ALIGN_END;

static void
low_level_init(struct netif *netif)
{
  struct ethernetif *ethernetif = netif->state;
  
  /* set MAC hardware address length */
  netif->hwaddr_len = ETHARP_HWADDR_LEN;

  /* set MAC hardware address */
  netif->hwaddr[0] = 0x00;
  netif->hwaddr[1] = 0x80;
  netif->hwaddr[2] = 0xE1;
  netif->hwaddr[3] = 0x00;
  netif->hwaddr[4] = 0x00;
  netif->hwaddr[5] = 0x00;

  /* maximum transfer unit */
  netif->mtu = 1500;
  
  /* device capabilities */
  /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
  netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
 
  /* Do whatever else is needed to initialize interface. */ 
  /* Initialize Tx Descriptors list: Chain Mode */
  HAL_ETH_DMATxDescListInit(&heth, DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB);
     
  /* Initialize Rx Descriptors list: Chain Mode  */
  HAL_ETH_DMARxDescListInit(&heth, DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB); 
	
	sys_sem_new(&sem,ETH_RXBUFNB);
	for(int i=0;iBuffer1Addr);
  uint32_t bufferoffset = 0;
  bufferoffset = 0;
  
  /* copy frame from pbufs to driver buffers */
  for(q = p; q != NULL; q = q->next)
	{
		/* Copy the remaining bytes */
		memcpy( (uint8_t*)buffer + bufferoffset,(uint8_t*)q->payload, q->len );
		bufferoffset = bufferoffset + q->len;
	}
  
  /* Prepare transmit descriptors to give to DMA */ 
  HAL_ETH_TransmitFrame(&heth, bufferoffset);
  
  errval = ERR_OK;
 
  return errval;
}

/**
 * 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;
  struct pbuf *q = NULL;
  uint16_t len = 0;
  uint8_t *buffer;
  __IO ETH_DMADescTypeDef *dmarxdesc;
  uint32_t bufferoffset = 0;
  
  /* get received frame */
  if (HAL_ETH_GetReceivedFrame_IT(&heth) != HAL_OK)
    return NULL;
  
  /* Obtain the size of the packet and put it into the "len" variable. */
  len = heth.RxFrameInfos.length;
  buffer = (uint8_t *)heth.RxFrameInfos.buffer;
  
  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)
  {
    bufferoffset = 0;
    for(q = p; q != NULL; q = q->next)
    {
      /* Copy remaining data in pbuf */
      memcpy( (uint8_t*)q->payload, (uint8_t*)buffer + bufferoffset, q->len);
      bufferoffset = bufferoffset + q->len;
    }
  }  
  
	/* Release descriptors to DMA */
	dmarxdesc = heth.RxFrameInfos.FSRxDesc;

	/* Set Own bit in Rx descriptors: gives the buffers back to DMA */
	dmarxdesc->Status |= ETH_DMARXDESC_OWN;

	/* Clear Segment_Count */
	heth.RxFrameInfos.SegCount =0;  
  
  /* When Rx Buffer unavailable flag is set: clear it and resume reception */
  if ((heth.Instance->DMASR & ETH_DMASR_RBUS) != (uint32_t)RESET)  
  {
    /* Clear RBUS ETHERNET DMA flag */
    heth.Instance->DMASR = ETH_DMASR_RBUS;
    /* Resume DMA reception */
    heth.Instance->DMARPDR = 0;
  }
  return p;
}

/**
 * This function should be called 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
 */
static void
ethernetif_input(struct netif *netif)
{
  struct ethernetif *ethernetif;
  struct eth_hdr *ethhdr;
  struct pbuf *p;

  ethernetif = netif->state;

  /* move received packet into a new pbuf */
  p = low_level_input(netif);
  /* no packet could be read, silently ignore this */
  if (p == NULL) return;
  /* points to packet payload, which starts with an Ethernet header */
  ethhdr = p->payload;

  switch (htons(ethhdr->type)) {
  /* IP or ARP packet? */
  case ETHTYPE_IP:
  case ETHTYPE_ARP:
#if PPPOE_SUPPORT
  /* PPPoE packet? */
  case ETHTYPE_PPPOEDISC:
  case ETHTYPE_PPPOE:
#endif /* PPPOE_SUPPORT */
    /* full packet send to tcpip_thread to process */
    if (netif->input(p, netif)!=ERR_OK)
     { LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
       pbuf_free(p);
       p = NULL;
     }
    break;

  default:
    pbuf_free(p);
    p = NULL;
    break;
  }
}

/**
 * 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)
{
  struct ethernetif *ethernetif;

  LWIP_ASSERT("netif != NULL", (netif != NULL));
    
  ethernetif = mem_malloc(sizeof(struct ethernetif));
  if (ethernetif == NULL) {
    LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n"));
    return ERR_MEM;
  }

#if LWIP_NETIF_HOSTNAME
  /* Initialize interface hostname */
  netif->hostname = "lwip";
#endif /* LWIP_NETIF_HOSTNAME */

  /*
   * Initialize the snmp variables and counters inside the struct netif.
   * The last argument should be replaced with your link speed, in units
   * of bits per second.
   */
  NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS);

  netif->state = ethernetif;
  netif->name[0] = IFNAME0;
  netif->name[1] = IFNAME1;
  /* We directly use etharp_output() here to save a function call.
   * You can instead declare your own function an call etharp_output()
   * from it if you have to do some checks before sending (e.g. if link
   * is available...) */
  netif->output = etharp_output;
  netif->linkoutput = low_level_output;
  
  ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);
  
  /* initialize the hardware */
  low_level_init(netif);

  return ERR_OK;
}

#endif /* 0 */

7、总之、需要自己编写修改的文件只有四个lwipopts.h、sys_arch.c、sys_arch.h、ethernetif.c。
完整工程下载

你可能感兴趣的:(LWIP带OS移植)