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。
完整工程下载