网络LWIP协议使用心得记录整理
20180227
年前在STM32上使用两种PHY芯片对LWIP协议进行了移植通信,一个是STM32F4+ENC28J60+LWIP+RAWAPI使用固定IP地址作为TCP客户端与服务器进行局域网通信,另一个是STM32F746+LAN8742A+FREERTOS+LWIP+NetconnAPI使用DHCP作为TCP客户端与网络NTRIP服务器通信获取GPS差分数据。在实现过程中,经历了LWIP协议栈移植到PHY芯片,初始的链路PING不通,ping延迟很大,绑定不了服务器,向服务器长时间发送数据卡死,网线不能任意插拔,能和局域网通信却不能与网络服务器通信,网线状态的检测,DHCP在网线插拔时的异常,线程间CPU占用让出等等等等,虽然经历了一个月左右坎坎坷坷的都实现了相应的功能,但是感觉对LWIP网络这块还是有些模模糊糊,因此,写这篇心得进行下梳理记录。
这篇文章的框架是按照实际项目分成两个部分,一个是STM32F4+LWIP不带系统,另一个是STM32F7+LWIP+FREERTOS,大家可以对比这两个的区别,进而从大面上去理解LWIP,当然如果有什么不对或者不合适的还请大家讨论指正,共同学习,参考的例子是xiaoyan大神的帖子http://www.openedv.com/thread-25178-1-1.html。
不带操作系统的LWIP协议栈的实现:
实现的功能:
A.作为TCP客户端与客户的TCP服务器进行通信;
B.实现网线的任意插拔功能。
首先
1、LWIP协议栈的移植
对于LWIP协议栈的介绍和由来就不做介绍,网上有很多,也不是我们关注的重点,因此直接上协议栈的移植。
协议栈的移植的重点在ethernetif.c接口文件中的3个函数上,包括:low_level_init(), low_level_output(),low_level_input()三个函数,这3个函数对PHY的硬件和接收发送进行了初始化,不同的PHY芯片需要相应修改这部分内容,厦门大概说一下这3个函数的作用:
A. Low_level_init(structnetif *netif)
网络开始初始化的时候,会首先调用ethernetif_init(struct netif *netif)这个函数用来注册建立网络接口,但是这个函数会调用Low_level_init(structnetif *netif)来完成实际的硬件初始化,包括网络的MAC地址,最大传输单元,然后再初始化PHY芯片ENC28J60,如果初始化失败则返回错误给上层调用的函数。
B. Low_level_output(structnetif *netif , struct pbuf *p)
修改底层发送包的函数,在这个函数中将LWIP数据包中的缓冲区pbuf 复制到待发送的缓冲区lwip_buf中来,然后利用ENC28J60的发包函数发出去,如果是其他的PHY芯片,则需要修改这个函数中的PHY芯片发送函数,即:enc28j60_packet_send(send_len,lwip_buf)。
C. Low_level_input(structnetif *netif)
这个过程就是把PHY芯片接收缓冲区lwip_buf中的数据复制到LWIP的pbuf中,如果收到了