移植LWIP(ENC28J60)
上图就是整个移植的基本思路,非常清晰的三个层次。其实想想,本质上就是收发数据,只是LWIP协议通过对数据的封装可以实现网络传输。从图中我们就可以看到这里首先需要ENC28J60的驱动,这个驱动需要实现数据的收发,驱动可以在网上找一个。其次就是要移植并修改LWIP协议了。
移植
1.下载LWIP1.4.1和contrib-1.4.1,可以到网上找一个下载,本质上LWIP1.4.1就是LWIP协议的全部,当时我们需要contrib-1.4.1才能完成整个移植。
2.将LWIP1.4.1拷贝到keil新建的工程下面,LWIP下的src是源文件,
在keil工程中添加几个组,LWIP-API,LWIP-CORE,LWIP-CORE-IPV4,LWIP-NETIF,LWIP-ARCH。分别将lwip1.4.1下的src中的api全部文件添加到LWIP-API,中,将core中的文件添加到LWIP-CORE中,将core下的ipv4下的文件全部添加到LWIP-CORE-IPV4,将netif中的文件添加到LWIP-NETIF中。到这里lwip的移植就结束了。
下面就是将H文件添加在keil中了。
3.在lwip的同一目录下,新建ARCH,NET,netconfig文件。在contrib-1.4.1\contrib-1.4.1\ports\win32目录下找到sys_arch.c,在contrib-1.4.1\contrib-1.4.1\ports\win32\include找到lwipopts.h和arch文件夹下的文件,将这些文件都拷贝到keil工程中新建的ARCH目录下。在netconfig目录下新建netconfig.c和netconfig.h文件,在NET目录下新建udp_app.c和udp_app.h文件。
4.好了,移植了这么多的文件也是够乱了,现在来解释一下。ARCH中的cc.h文件里是一些数据类型的定义,为了保证平台的无关性,协议栈只使用了自己定义的数据类型,此外cc中还定义了一些调试信息输出的宏。lwipopts.h定义了内核的预编译的宏,有些文件或服务不需要使用,可以改变这个文件中的宏定义取消编译。这个文件是内核的参数配置文件,非常的重要。sys_arch.c文件只有一个sys_now()函数是有用的,其余的都可以注释掉,这里也要修改一下sys_now()函数。其余的文件都不需要修改。
u32_t sys_now()
{
return LocaTime;
}
接着我们需要将ENC28J60的接收发送函数与LWIP协议的底层数据接发接口对接起来。这里对接文件是lwip-1.4.1\src\netif下的ethernetif文件,这个文件定义了五个函数,
static void low_level_init(struct netif *netif)
static err_t low_level_output(struct netif *netif, struct pbuf *p)
static struct pbuf* low_level_input(struct netif *netif)
static void ethernetif_input(struct netif *netif)
err_t ethernetif_init(struct netif *netif)
low_level_init函数初始化mac地址,
static void
low_level_init(struct netif *netif)
{
/* set MAC hardware address length */
netif->hwaddr_len = ETHARP_HWADDR_LEN;
/* set MAC hardware address */
netif->hwaddr[0] = macaddress[0];
netif->hwaddr[1] = macaddress[1];
netif->hwaddr[2] = macaddress[2];
netif->hwaddr[3] = macaddress[3];
netif->hwaddr[4] = macaddress[4];
netif->hwaddr[5] = macaddress[5];
/* maximum transfer unit */
netif->mtu = netifMTU;
/* 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. */
enc28j60Init(netif->hwaddr);
}
我们将ENC28J60的初始化放在这里。
low_level_output函数是传递数据到内核里,我们将enc28j60PacketSend放在里面
static err_t
low_level_output(struct netif *netif, struct pbuf *p)
{
struct pbuf *q;
unsigned int i = 0;
#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. */
memcpy(&Tx_Data_Buf[i], (u8_t*)q->payload, q->len);
i = i + q->len;
}
enc28j60PacketSend(i,Tx_Data_Buf); //·¢ËÍÊý¾Ý°ü
#if ETH_PAD_SIZE
pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
#endif
LINK_STATS_INC(link.xmit);
return ERR_OK;
low_level_input函数接受内核数据,我们将enc28j60PacketReceive放到里面
static struct pbuf *
low_level_input(struct netif *netif)
{
struct pbuf *p, *q;
u16_t len;
unsigned int i =0;
/* Obtain the size of the packet and put it into the "len"
variable. */
len = enc28j60PacketReceive(1520 *4, Data_Buf);
if(len == 0) return 0;
#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.
*/
memcpy((u8_t*)q->payload, (u8_t*)&Data_Buf[i], q->len);
i = i + q->len;
}
#if ETH_PAD_SIZE
pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
#endif
LINK_STATS_INC(link.recv);
} else {
//drop packet();
LINK_STATS_INC(link.memerr);
LINK_STATS_INC(link.drop);
}
return p;
}
其余的就不需要我们了,这里直接移植的ethernetif文件默认是不编译的,我们将#if 0给取消掉。
新建的netconfig文件就是配置网络参数了,比如ip地址,mac地址,还有最重要的LwIP_Periodic_Handle函数,处理内核的定时函数,如何TCP定时,ARP定时。定时采用systick进行定时,每20ms中断一次,执行一次LwIP_Periodic_Handle。
基本上lwip的移植就结束了。
移植LWIP(ENC28J60)的更多相关文章
- STM32F107移植LWIP
STM32F107上移植LWIP2.0.3 因为最近需要在STM32F107上实现TCP/IP协议栈,所以网上查了一下,准备使用LWIP,虽然大多数用的是1.4.1版本但是官方说2系大版本修复了1.4 ...
- LwIP学习笔记——STM32 ENC28J60移植与入门
0.前言 去年(2013年)的整理了LwIP相关代码,并在STM32上"裸奔"成功.一直没有时间深入整理,在这里借博文整理总结.LwIP的移植过程细节很多,博文也不可能一一 ...
- ALIENTEK 战舰ENC28J60 LWIP和UIP补充例程(LWIP WEB有惊喜)
前面的话:自从接触网络模块,到现在有一阵子时间了,未来必定是网络的世界.学一些网络方面的知识是有必要的.我们ALINTEK 推出的ENC28J60网络模块块作为入门还是不错的.详细见此贴:http:/ ...
- LwIP移植和使用
LwIP移植和使用 本手册基于lwip-1.4.x编写,本人没有移植过1.4.0之前的版本,更早的版本或许有差别.如果看官发现问题欢迎联系<QQ: 937431539 email: 93743 ...
- LWIP的移植笔记
第一次发表博客,文章摘录于还不懂同学的专栏 lwIp的作者做了大量的工作以方便像我这种懒人移植该协议栈,基本上只需修改一个配置头文件和改写3个函数即可完成lwIP的移植.要改写的函数位于lwIP-1. ...
- zedboard - 轻量级以太网控制器LWIP
ipconfig/all route print 显示本机所有的网络 网关是什么 那么网关到底是什么呢?网关实质上是一个网络通向其他网络的IP地址.比如有网络A和网络B,网络A的IP地址范围为&qu ...
- LWIP互联网资料汇总
本文主要搜集了下互联网上关于LWIP的资料和教程 欢迎补充 第一部分:移植 LWIP在UCOS上移植 LWIP 在STM32上移植 http://www.docin.com/p-459242028 ...
- 我的RTOS 之六 -- Touch移植(s5pv210+threadx+ucgui+touch)
非常久没有关注RTOS了,所以也一直没有更新.近期闲了,把GPIO I2C调通了.简单移植了Touch.在S5PV210上使用. 调试I2C时.废了非常多周折,最后借助示波器才发现一个小小的错误.折腾 ...
- 5、 LwIP协议栈规范翻译——操作系统仿真层
为了使lwIP可移植,操作系统特定的函数调用和数据结构不直接在协议的代码中使用.相反,当需要这样的函数调用和数据结构时,直接使用操作系统仿真层. 操作系统仿真层为操作系统服务提供统一的接口,如定时器, ...
随机推荐
- window cmd
切换目录盘 直接 d: (e: f:) 在目录下切换文件用cd 文件名(可以加绝对路径 绝对路径可以到复制 也可以加相对路径) javac XXX.java 编译成字节码 Ja ...
- 完全卸载gitlab
完全卸载删除gitlab 2017年5月29日 wuhao 暂无评论 4,089次浏览 完全卸载删除gitlab 1.停止gitlab 1 gitlab-ctl stop 2.卸载gitlab ...
- node-wechat 微信推送消息
https://github.com/nswbmw/node-wechat/blob/master/index.js
- TCP和Http的区别!(转) 真心有帮助!!!
一.From:http://thisliy.javaeye.com/blog/710122 http://wenku.baidu.com/view/14a30d0102020740be1e9b84.h ...
- JSON和list之间的转换
谷歌的Gson.jar: //list转换为json Gson gson = new Gson(); List<Person> persons = new ArrayList<Per ...
- New Concept English three (42)
21 33 Cave exploration, or pot-holing, as it has come to be known, is a relatively new sport. Perhap ...
- 【数据库】python访问mysql
import MySQLdb 所有的数据库遵循相同的python database API 需要建立connection对象连接数据库,之后建立cursor对象处理数据. conn = MySQLdb ...
- Flask 的 template模板 与 jinja2语法
Flask 的 template模板 与 jinja2语法 Flask使用的是Jinja2模板,所以其语法和Django基本无差别 1.模板基本数据的渲染 变量 {{..}} 列表 {% for it ...
- Ubuntu安装最新版的nodejs
安装玩Ubuntu的虚拟机之后安装nodejs发现npm的版本才3.5.2,这都多老了?于是Google了一下,发现是由于Ubuntu官方维护的包源太老了,想要安装nodejs的最新版,两种方法,一种 ...
- 关于json解析和所需jar
以解析字符串数组为例: String parameter= [{"id":"pdTNKcY1YS55oG2M",.......}] 1. 关于net.sf.js ...