ZYNQ|LWIP协议栈学习(1)

一、创建vivado工程

选择以太网0,选择串口UART1,其他的端口可以根据需要选择

生成output文件,生成xsa文件

二、在vitis中设置

基于生成的xsa文件,创建vitis工程,选择lwip的包

然后配置LWIP相关的参数。可以根据米联客的教程进行修改,也可以选择Socket模式,但是一开始我先还是使用了默认的RAW API,想通过UDP协议练习发送hello world的实验来熟悉LWIP协议栈的工作过程。

        创建工程以后复制代码,添加main.c文件,以及中断系统文件和user_udp.c/h文件

        代码参考文章学会Zynq(14)UDP发送Hello World_xilinx sdk udp server-CSDN博客

 有一个需要注意的是,我使用的是vitis2021.1版本,LWIP的包用的是lwip211,编译的时候出现一个报错

在新版的 lwIP 中,struct ip_addr 被废弃了,而改为使用 ip4_addr 来表示 IPv4 地址。因此需要根据使用的LWIP版本,把结构体的名字修改一下,消除了错误。

三、网络调试助手测试

首先更改电脑的IP地址,win11系统更改IP地址的方式如下:

(1)快捷键win+R,输入control

(2)点击网络和共享中心,更改适配器设置

(3)插上网线以后,会显示以太网,然后右键属性,选择Internet 协议版本 4(TCP/IPV4),更改设置好的IP地址,按照上述程序的话,应该修改为192.168.1.100,子网掩码还是255.255.255.0

然后设置网络调试助手

主要设置左上角的部分,协议类型为UDP,主机地址设置为刚才修改的192.168.1.100

然后下载程序,选择打开,就可以在主界面收到Hello world!的信息!

四、程序代码理解

整体思路:

  • 首先设置开发板的MAC地址,设置他的IP地址,子网掩码和网关;
  • 初始化中断系统;
  • 初始化LWIP库;
  • 用 xemac_add 函数,添加网络接口;并且设置为默认接口
  • 启动网络;
  • 初始化udp
    • 创建udp控制块(udp_new)
    • 绑定本地端口(udp_bind)
    • 设置远程地址(也就是电脑的IP地址)IP4_ADDR(&ipaddr, 192, 168, 1, 100);
    • 连接远程地址(udp_connect)这个只有用send函数发送时需要,并且设置一个连接成功标志位,当确认成功了以后再调用发送
    • 如果用sendto函数发送,就可以在这里直接申请pbuf资源,无需反复申请和释放
  • 将MAC队列中的包传输的LwIP/IP栈中:(一定都要有这一句)xemacif_input(netif);
  • 发送数据 udp_printf
    • 如果用send函数,就先申请pbuf资源(pbuf_alloc),然后把要发送的数写到这个pbuf里面,调用udp send函数发送。最后释放pbuf(pbuf_free)——缺点是每次发送都要申请和释放一次pbuf
    • 如果用sendto函数,就可以直接调用此函数发送

具体函数语句:

(1)LWIP的初始化函数

是封装好的,里面包含了很多协议的初始化函数,可以直接调用

void lwip_init();

 (2)设置IP地址

这个函数用来增强代码可视性。习惯上我们用四个字节数据去表示,在这个函数当中就可以根据我们的习惯来编写,配置IP地址和网管等。

IP4_ADDR(ipaddr, a,b,c,d) 

(3)添加网络接口的函数

第一个参数是 netif 指针,在lwIP中,netif(网络接口)是一个核心的结构体,它代表了一个网络接口,例如以太网接口、Wi-Fi接口等。netif 结构体用于定义和管理这些接口,使lwIP可以在多个接口上运行并进行路由决策。结构体里面通常包括:

  1. 硬件地址:例如MAC地址。
  2. IP地址、子网掩码和网关:这些用于IP层的路由和地址决策。
  3. 状态标志:表示接口的状态,例如是否激活、是否为默认接口等。
  4. 输入和输出函数指针:这些函数用于处理从该接口接收到的数据包或向该接口发送数据包。
  5. 其他驱动特定的数据:例如用于DMA的描述符、缓冲区等。

在写程序的时候需要先定义一个这样的结构体。

存疑一下,这句看起来好奇怪?

然后紧接着的三个参数,看起来分别表示的是IP地址,子网掩码和网关

后面的两个参数是MAC地址还有一个是ETH0外设的一个参数

struct netif *xemac_add (struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask, struct ip_addr *gw, unsigned char *mac_ethernet_address, unsigned mac_baseaddr)

(4)将MAC队列中的包传输的LwIP/IP栈中

该函数只在RAW模式下可用。Xlinx lwIP适配器在中断模式下工作。接收中断处理程序从EMAC/GigE中将包数据移动并存储在队列中。xemacif_input函数从队列中取出这些包,传递给lwIP。因此在RAW mode下,需要使用这个程序。

这个函数在while(1)循环里面使用,该程序会通过回调通知已经接收到的数据。

感觉有点像uart里面的开始接收?

void xemacif_input(struct netif *netif)

(5)UDP连接的初始化函数 user_udp_init

学会Zynq(11)RAW API的TCP和UDP编程_lwip raw 调用 tcp_output-CSDN博客

这里面的函数在文章中有详细讲解

(6)UDP发送数据函数udp_printf

关于具体每个函数的功能可见文章:学会Zynq(14)UDP发送Hello World_xilinx sdk udp server-CSDN博客

(强推这个大佬,让我这个刚上手的小白能找到一点点方向)

总结一下上面函数的大概含义就是:

首先用send_buff 的数组存下我要发送的数据;然后申请 pbuf 资源,把我要发送的数据写进我申请的 pbuf 缓冲区里面,然后调用udp_send函数把 pbuf 中的数据发送出去。最后释放pbuf

中间还有两个概念我不是很理解,比如什么是pcb,是否所有的数据发送都是通过申请 pbuf,然后调用发送函数?

今天是学习LWIP的第一天,明天继续加油!

(所有引用内容都是自学使用,侵删)

  • 38
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Zynq是一种嵌入式处理器,具备高度可编程的特性。要实现TCP协议栈,需要在Zynq的硬件平台上设计和实现一套完整的网络协议堆栈。 首先,需要使用硬件描述语言(HDL)或者可编程逻辑门阵列(FPGA)设计和实现以太网控制器的硬件。这个以太网控制器负责物理层和数据链路层的操作,包括帧的发送和接收,MAC地址的解析,以及硬件的初始化和配置。 其次,需要在Zynq的处理器系统上运行一套网络协议栈的软件。这个软件可以使用开源的网络协议栈库,比如lwIP(lightweight IP)等。lwIP是一个轻量级的TCP/IP协议栈,适用于嵌入式系统。通过在软件层面实现网络协议栈,可以实现IP层、传输层和应用层的功能,包括IP数据包的路由、TCP连接管理、数据传输等。 通过在硬件和软件层面的协同工作,可以在Zynq平台上实现TCP协议栈。具体的实现过程包括:配置和初始化硬件以太网控制器,然后通过软件加载网络协议栈库,并进行必要的配置和初始化。接下来,可以通过对网络协议栈的API和接口进行编程,实现具体的应用逻辑和功能,如网络通信、数据传输、网络协议的处理等。 Zynq实现TCP协议栈的优势在于,它的硬件和软件资源可以高度定制和配置,可以根据具体的应用需求进行优化和扩展。同时,Zynq平台的可编程性使得实现和调试网络协议栈更加灵活和方便。然而,在实际应用,还需要考虑到资源消耗、性能优化、网络安全等方面的问题,以确保整个系统的稳定性和可靠性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值