移植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可移植,操作系统特定的函数调用和数据结构不直接在协议的代码中使用.相反,当需要这样的函数调用和数据结构时,直接使用操作系统仿真层. 操作系统仿真层为操作系统服务提供统一的接口,如定时器, ...
随机推荐
- JNI_Z_04_属性的操作(非String类型的属性)
1.步骤 : (1).获取 jclass (2).获取 类属性字段的id(最后一个参数是 属性字段 的签名) (3).获取/设置 类属性字段的值 ZC: 貌似 JNI里面 操作 类属性字段,完全是 无 ...
- JavaScript全屏显示
JavaScript全屏显示 需要引入的库 https://cdn.bootcss.com/jquery/1.9.0/jquery.min.js https://cdn.bootcss.com/scr ...
- socket编程 TCP 粘包和半包 的问题及解决办法
一般在socket处理大数据量传输的时候会产生粘包和半包问题,有的时候tcp为了提高效率会缓冲N个包后再一起发出去,这个与缓存和网络有关系. 粘包 为x.5个包 半包 为0.5个包 由于网络原因 一次 ...
- yii2:多表查询
啥都不说了,上代码: $list = static::find() ->leftJoin('book', 'book.RID = prices.RID')->select('prices. ...
- Updated: Database Partitioning with EBS Whitepaper
Partitioning allows a single database table and its associated indexes to be broken into smaller com ...
- [6644] 02 Apr 23:11:58.976 # Creating Server TCP listening socket *:6379: bind: No such file or directory
redis报错: [6644] 02 Apr 23:11:58.976 # Creating Server TCP listening socket *:6379: bind: No such fil ...
- 【河南第十届省赛-B】情报传递
题目描述 抗日战争时期,在国共合作的大背景下,中共不断发展壮大,其情报工作也开始由获取警报性.保卫性信息,向获取军政战略性情报转变.各系统情报组织遵循"荫蔽精干,长期埋伏,积蓄力量,以待时机 ...
- TF随笔-4
>>> import tensorflow as tf>>> a=tf.constant([[1,2],[3,4]])>>> b=tf.const ...
- C++中const指针用法汇总
这里以int类型为例,进行说明,在C++中const是类型修饰符: int a; 定义一个普通的int类型变量a,可对此变量的值进行修改. const int a = 3;与 int const a ...
- Arcgis andoid开发之应用百度地图接口实现精准定位与显示
怀着激动.兴奋的心情,在这个漫天柳絮的季节写下了这片博文,为什么呢,因为困扰我很久的一个技术性的问题得到了解决,发次博文,供大家参观.学习,同时,也以慰藉我长期困扰的心情,好了,废话不再,言归正传,看 ...