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] = 'A';
netif->hwaddr[1] = 'R';
netif->hwaddr[2] = 'M';
netif->hwaddr[3] = 'N';
netif->hwaddr[4] = 'E';
netif->hwaddr[5] = 'T';
/* 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. */
enc28j60_init(netif->hwaddr); // 【1】
}static err_t
low_level_output(struct netif *netif, struct pbuf *p)
{
struct ethernetif *ethernetif = netif->state;
struct pbuf *q;
enc28j60_init_send(p->tot_len); //【1】initiate transfer();
#if ETH_PAD_SIZE
pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
#endif
for(q = p; q != NULL; q = q->next) {
/* Send the data from the pbuf to the interface, one pbuf at a
time. The size of the data in each pbuf is kept in the ->len
variable. */
enc28j60_writebuf( q->payload, q->len ); //【2】send data from(q->payload, q->len);
}
enc28j60_start_send(); //【3】signal that packet should be sent();
#if ETH_PAD_SIZE
pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
#endif
LINK_STATS_INC(link.xmit);
return ERR_OK;
}static struct pbuf *
low_level_input(struct netif *netif)
{
struct ethernetif *ethernetif = netif->state;
struct pbuf *p, *q;
u16_t len;
/* Obtain the size of the packet and put it into the "len"
variable. */
len = enc28j60_packet_getlen(); // 【1】
#if ETH_PAD_SIZE
len += ETH_PAD_SIZE; /* allow room for Ethernet padding */
#endif
/* We allocate a pbuf chain of pbufs from the pool. */
p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
if (p != NULL) {
#if ETH_PAD_SIZE
pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
#endif
/* We iterate over the pbuf chain until we have read the entire
* packet into the pbuf. */
for(q = p; q != NULL; q = q->next) {
/* Read enough bytes to fill this pbuf in the chain. The
* available data in the pbuf is given by the q->len
* variable.
* This does not necessarily have to be a memcpy, you can also preallocate
* pbufs for a DMA-enabled MAC and after receiving truncate it to the
* actually received size. In this case, ensure the tot_len member of the
* pbuf is the sum of the chained pbuf len members.
*/
enc28j60_readbuf (q->payload, q->len ); //【2】read data into(q->payload, q->len);
}
enc28j60_finish_receive(); //【3】acknowledge that packet has been read();
#if ETH_PAD_SIZE
pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
#endif
LINK_STATS_INC(link.recv);
} else {
enc28j60_finish_receive(); //【4】drop packet();
LINK_STATS_INC(link.memerr);
LINK_STATS_INC(link.drop);
}
return p;
}#ifndef __LWIPOPTS_H__ #define __LWIPOPTS_H__ /** * 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 1 /** * NO_SYS_NO_TIMERS==1: Drop support for sys_timeout when NO_SYS==1 * Mainly for compatibility to old versions. */ #define NO_SYS_NO_TIMERS 1 /* ---------- 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. */ #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 (5*1024) /* 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 10 /* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One per active UDP "connection". */ #define MEMP_NUM_UDP_PCB 6 /* MEMP_NUM_TCP_PCB: the number of simulatenously active TCP connections. */ #define MEMP_NUM_TCP_PCB 10 /* MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP connections. */ #define MEMP_NUM_TCP_PCB_LISTEN 6 /* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP segments. */ #define MEMP_NUM_TCP_SEG 12 /* MEMP_NUM_SYS_TIMEOUT: the number of simulateously active timeouts. */ #define MEMP_NUM_SYS_TIMEOUT 3 /* ---------- Pbuf options ---------- */ /* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */ #define PBUF_POOL_SIZE 10 /* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */ #define PBUF_POOL_BUFSIZE 1500 /* ---------- 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 0 /* TCP Maximum segment size. */ #define TCP_MSS (1500 - 40) /* TCP_MSS = (Ethernet MTU - IP header size - TCP header size) */ /* TCP sender buffer space (bytes). */ #define TCP_SND_BUF (2*TCP_MSS) /* TCP sender buffer space (pbufs). This must be at least = 2 * TCP_SND_BUF/TCP_MSS for things to work. */ #define TCP_SND_QUEUELEN (6 * TCP_SND_BUF)/TCP_MSS /* TCP receive window. */ #define TCP_WND (2*TCP_MSS) /* ---------- ICMP options ---------- */ #define LWIP_ICMP 1 /* ---------- DHCP options ---------- */ /* Define LWIP_DHCP to 1 if you want DHCP configuration of interfaces. DHCP is not implemented in lwIP 0.5.1, however, so turning this on does currently not work. */ #define LWIP_DHCP 0 /* ---------- UDP options ---------- */ #define LWIP_UDP 1 #define UDP_TTL 255 /* ---------- Statistics options ---------- */ #define LWIP_STATS 0 #define LWIP_PROVIDE_ERRNO 1 /* -------------------------------------- ---------- Checksum options ---------- -------------------------------------- */ /* ---------------------------------------------- ---------- Sequential layer options ---------- ---------------------------------------------- */ /** * LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c) */ #define LWIP_NETCONN 0 /* ------------------------------------ ---------- Socket options ---------- ------------------------------------ */ /** * LWIP_SOCKET==1: Enable Socket API (require to use sockets.c) */ #define LWIP_SOCKET 0 #endif /* __LWIPOPTS_H__ */
void LwIP_Config (void)
{
struct ip_addr ipaddr;
struct ip_addr netmask;
struct ip_addr gw;
// 调用LWIP初始化函数
lwip_init();
IP4_ADDR(&ipaddr, 192, 168, 1, 16); // 设置网络接口的ip地址
IP4_ADDR(&netmask, 255, 255, 255, 0); // 子网掩码
IP4_ADDR(&gw, 192, 168, 1, 1); // 网关
// 初始化enc28j60与LWIP的接口,参数为网络接口结构体、ip地址、
// 子网掩码、网关、网卡信息指针、初始化函数、输入函数
netif_add(&enc28j60, &ipaddr, &netmask, &gw, NULL, ðernetif_init, ðernet_input);
// 把enc28j60设置为默认网卡
netif_set_default(&enc28j60);
netif_set_up(&enc28j60);
} timer_typedef tcp_timer, arp_timer;
/* 设定查询定时器 ARP定时器 */
timer_set(&tcp_timer, CLOCK_SECOND / 10); // tcp处理定时器 100ms
timer_set(&arp_timer, CLOCK_SECOND * 5); // arp处理定时器 5s
while (1) {
if (enc28j60_packet_getcount() != 0) {
ethernetif_input(&enc28j60);
}
// TCP 定时处理
if (timer_expired(&tcp_timer)) {
timer_set(&tcp_timer, CLOCK_SECOND / 4);
tcp_tmr();
}
// ARP 定时处理
if (timer_expired(&arp_timer)) {
timer_set(&arp_timer, CLOCK_SECOND * 5);
etharp_tmr();
}
}

原文地址:http://blog.csdn.net/xukai871105/article/details/37995079