您现在的位置: 主页 > MCU > 单片机应用 > LwIP学习笔记——STM32 ENC28J60移植与入门 -
本文所属标签:
为本文创立个标签吧:

LwIP学习笔记——STM32 ENC28J60移植与入门 -

来源: 网络用户发布,如有版权联系网管删除 2018-09-11 

[导读]0.前言 去年(2013年)的整理了LwIP相关代码,并在STM32上“裸奔”成功。一直没有时间深入整理,在这里借博文整理总结。LwIP的移植过程细节很多,博文也不可能一一详解个别部分只能点到为止。 【本文要点】 【1】

0.前言

本文引用地址: http://www.21ic.com/app/mcu/201809/781764.htm

去年(2013年)的整理了LwIP相关代码,并在STM32上“裸奔”成功。一直没有时间深入整理,在这里借博文整理总结。LwIP的移植过程细节很多,博文也不可能一一详解个别部分只能点到为止。

【本文要点】

【1】不带操作系统的LwIP移植,LwIP版本为1.4.1。

【2】MCU为STM32F103VE,网卡为ENC28J60。

【3】移植过程重点描述ethernetif.c和LwIP宏配置等。

【4】一个简单的TCP echo例子。

【5】力求简单,没有DHCP功能,甚至没有用到网卡中断。

【代码仓库】

代码仓库位于Bitbucket(要源代码请点击这里)。博文中不能把每个细节描述清楚,更多内容请参考代码仓库中的具体代码。

【硬件说明】

测试平台使用奋斗版,原理图请参考代码仓库中的DOC目录。


【参考博文】

学习嵌入式网络是一个循序渐进的过程,从浅入深从简单到复杂。

【1】ENC28J60学习笔记——学习网卡

【2】STM32NET学习笔记——索引——理解TCPIP协议栈

【3】uIP学习笔记——初次应用协议栈

【4】Yeelink平台使用——远程控制 RT Thread + LwIP+ STM32——更加实用的做法

1.ethernetif.c的相关修改

虽然LwIP移植过程比较复杂,但是只要结合网卡具体功能,耐心修改ethernetif.c即可。ethernetif.c重点实现网卡的三个功能,初始化,发送和接收。

为了更好的配合lwIP,修改了ENC28J60学习笔记中部分驱动函数。(换句话说,想要从0开始移植LwIP必须对操作网卡非常熟悉)

【1】初始化


staticvoid

low_level_init(structnetif*netif)

{

structethernetif*ethernetif=netif->state;

/*setMAChardwareaddresslength*/

netif->hwaddr_len=ETHARP_HWADDR_LEN;

/*setMAChardwareaddress*/

netif->hwaddr[0]='A';

netif->hwaddr[1]='R';

netif->hwaddr[2]='M';

netif->hwaddr[3]='N';

netif->hwaddr[4]='E';

netif->hwaddr[5]='T';

/*maximumtransferunit*/

netif->mtu=1500;

/*devicecapabilities*/

/*don'tsetNETIF_FLAG_ETHARPifthisdeviceisnotanethernetone*/

netif->flags=NETIF_FLAG_BROADCAST|NETIF_FLAG_ETHARP|NETIF_FLAG_LINK_UP;

/*Dowhateverelseisneededtoinitializeinterface.*/

enc28j60_init(netif->hwaddr);//【1】

}

【说明】

【1】enc28j60_init(netif->hwaddr); low_level_init中指定了enc28j60中的网卡地址。

【2】发送


staticerr_t

low_level_output(structnetif*netif,structpbuf*p)

{

structethernetif*ethernetif=netif->state;

structpbuf*q;

enc28j60_init_send(p->tot_len);//【1】initiatetransfer();

#ifETH_PAD_SIZE

pbuf_header(p,-ETH_PAD_SIZE);/*dropthepaddingword*/

#endif

for(q=p;q!=NULL;q=q->next){

/*Sendthedatafromthepbuftotheinterface,onepbufata

time.Thesizeofthedataineachpbufiskeptinthe->len

variable.*/

enc28j60_writebuf(q->payload,q->len);//【2】senddatafrom(q->payload,q->len);

}

enc28j60_start_send();//【3】signalthatpacketshouldbesent();

#ifETH_PAD_SIZE

pbuf_header(p,ETH_PAD_SIZE);/*reclaimthepaddingword*/

#endif

LINK_STATS_INC(link.xmit);

returnERR_OK;

}

【说明】

【1】enc28j60_init_send(p->tot_len);初始化发送缓冲区大小,pbuf结构为一个链表,第一个pbuf结构体中的tot_len字段代表整个以太网数据包的大小。

【2】enc28j60_writebuf( q->payload, q->len ); 通过遍历链表把内容填入ENC28J60的缓冲区中。

【3】enc28j60_start_send();启动网卡发送。

【3】接收


staticstructpbuf*

low_level_input(structnetif*netif)

{

structethernetif*ethernetif=netif->state;

structpbuf*p,*q;

u16_tlen;

len=enc28j60_packet_getlen();//【1】

#ifETH_PAD_SIZE

len+=ETH_PAD_SIZE;/*allowroomforEthernetpadding*/

#endif

/*Weallocateapbufchainofpbufsfromthepool.*/

p=pbuf_alloc(PBUF_RAW,len,PBUF_POOL);

if(p!=NULL){

#ifETH_PAD_SIZE

pbuf_header(p,-ETH_PAD_SIZE);/*dropthepaddingword*/

#endif

for(q=p;q!=NULL;q=q->next){

enc28j60_readbuf(q->payload,q->len);//【2】readdatainto(q->payload,q->len);

}

enc28j60_finish_receive();//【3】acknowledgethatpackethasbeenread();

#ifETH_PAD_SIZE

pbuf_header(p,ETH_PAD_SIZE);/*reclaimthepaddingword*/

#endif

LINK_STATS_INC(link.recv);

}else{

enc28j60_finish_receive();//【4】droppacket();

LINK_STATS_INC(link.memerr);

LINK_STATS_INC(link.drop);

}

returnp;

}

【说明】

【1】len = enc28j60_packet_getlen(); 获得网卡中数据包的长度。

【2】enc28j60_readbuf (q->payload, q->len);把网卡中的内容复制到内存池中。

【3】enc28j60_finish_receive();接收完成,移动网卡中缓冲区指针。

【4】应用

【1】LwIP网卡硬件初始化调用ethernetif_init即可,该函数中调用了low_level_init,并指定了网卡输出函数low_level_output。

【2】一旦网卡有数据进入,应立即代用ethernetif_input函数。可以使用中断方法或查询方法。

2.lwipopt.h配置简述

lwip中的配置选项非常的多,了解所有的配置非常不容易。本博文参考STM32官方的两个例子总结得到。


#ifndef__LWIPOPTS_H__

#define__LWIPOPTS_H__

#defineSYS_LIGHTWEIGHT_PROT0

#defineNO_SYS1

#defineNO_SYS_NO_TIMERS1

/*----------Memoryoptions----------*/

/*MEM_ALIGNMENT:shouldbesettothealignmentoftheCPUforwhich

lwIPiscompiled.4bytealignment->defineMEM_ALIGNMENTto4,2

bytealignment->defineMEM_ALIGNMENTto2.*/

#defineMEM_ALIGNMENT4

/*MEM_SIZE:thesizeoftheheapmemory.Iftheapplicationwillsend

a lot of data that needs to be copied, this



              查看评论 回复



嵌入式交流网主页 > MCU > 单片机应用 > LwIP学习笔记——STM32 ENC28J60移植与入门 -
 

"LwIP学习笔记——STM32 ENC28J60移植与入门 -"的相关文章

网站地图

围观()