当前位置:首页 > 工业控制 > 电路设计项目集锦
[导读]对于许多嵌入式系统而言,以太网是标准的通信方式。它最高可达1 Gbps的传输速率,不仅支持数据传输,还能实现系统的配置与控制。以太网的优点显而易见:可远距离运行,并支持路由功能,从而实现分布式系统。

在开发嵌入式系统时,能否在我们的电路板上进行数据的输入和输出,往往是面临的核心挑战之一。

对于许多嵌入式系统而言,以太网是标准的通信方式。它最高可达1 Gbps的传输速率,不仅支持数据传输,还能实现系统的配置与控制。以太网的优点显而易见:可远距离运行,并支持路由功能,从而实现分布式系统。

因此,以太网被广泛应用于各种场景也就不足为奇了,从家庭网络到飞机、车辆,甚至航天器和机器人。

在协议的更高层次上,会使用一些略有不同的协议,例如时间触发以太网(Time-Sensitive Ethernet)或时间敏感网络(Time-Sensitive Networking)。

在本项目中,我们将展示如何利用VEK385高效地处理以太网数据包,并在系统内部进行路由。

在处理以太网时,我们希望以一种能够保持最大吞吐量1000 Mbps的方式对数据帧进行处理。

然而,实际上我们无法达到1000 Mbps(1 Gbps)的速率,因为存在一定的协议开销,这意味着一个理想的解决方案通常只能实现970 Mbps的数据、配置和控制传输。

VEK385

我们曾多次研究过AMD Versal™设备,它们为嵌入式应用提供了高性能的解决方案。在我的咨询工作中,我们已将AMD Versal™设备应用于从波束成形到高性能成像等多种场景。多年来,我们也撰写了多个关于AMD Versal™设备的项目和博客文章,包括广受欢迎的VCK190和VMK180,以及Avnet SoM、Alinx SoM和Trenz解决方案。

所有这些设备都展示了AMD Versal™第一代产品的性能。而VEK385则有所不同,它是AMD Versal™ AI边缘系列第二代产品。

该设备为开发者提供了:应用处理单元中的8个Arm® Cortex® A78AE处理核心,以及实时处理单元中的10个Arm® Cortex® R52处理核心。同时配备AL Engine ML v2模块,并通过片上网络(SoC)实现高性能逻辑的全面互联。

应用程序

本应用旨在展示如何在主机与VEK385之间实现最大吞吐量。

因此,该项目将AMD VEK385改造为一个紧凑型数据包路由实验室。

该应用基于Cortex-A78核心0运行裸机系统,使用LwIP原始UDP API验证简化的报文头,并将每个有效载荷路由至可编程逻辑的BRAM、集成的LPDDR5X存储器、软件处理缓冲区或受控丢弃装置。

演示将采用PL三模以太网媒体接入控制器(TEMAC),该控制器在可编程逻辑中实现千兆以太网接口。

AMD Vivado™设计套件

AMD Vivado™设计套件结构简单:我们通过PL以太网接收包含数据包的以太网帧,并在PS端使用运行轻量级IP协议栈(LwIP)的APU核心进行处理。

这使得LwIP能够将数据路由至PS、PL或LPDDR5X上的任意应用程序。系统中的任何资源均可根据需要访问数据包内容。同时,这也让我们能够演示在AMD Versal™设备内不同终端点协同工作时的性能表现。

设计的方框图如下所示。

可编程逻辑的使用率非常低,以便为设计未来添加更多功能。

AMD Vitis™ 统一软件平台

在硬件平台搭建完成后,我们便可以开发相应的软件应用。

该应用是一个简单的独立(裸机)数据包路由器,它通过PL以太网接口使用LwIP栈接收UDP数据报,并根据数据包头中的路由字段,将每个数据包的有效载荷转发至系统中的多个目标之一。

其原理十分简单:主机PC通过端口5001向板子发送UDP数据包。每个数据包都包含一个32字节的小型头部,用于指示应用程序将有效载荷送往何处。这使我们能够通过单一应用程序,对AMD Versal™设备中的不同数据路径进行测试——包括可编程逻辑BRAM、外部LPDDR5X存储器以及纯软件处理路径,并测量每条路径所需的时间。

数据包协议

主机发送的每个数据报包含一个固定的32字节头部,后接最多1440字节的有效载荷(确保整个数据报可轻松容纳在标准以太网帧内)。该头部定义于router_protocol.h中,包含以下内容:

- 一个魔术数(0x504B5452,ASCII码“PKTR”),用于让硬件板拒绝非本机目的的数据。

- 序列号,使应用程序能够检测丢失或乱序的数据包。

- 路由字节,用于选择有效载荷的目的地。

- 标志位:主机可设置回显标志(ECHO flag)以请求确认。

- 头部和有效载荷长度,用于验证。

- 主机时间戳字段和板卡处理时间字段,用于性能测量。

路由字节从四个目的地中选择其一:

- 路由0 — PL BRAM:有效载荷通过AXI BRAM控制器逐字节写入可编程逻辑中的BRAM(在VEK385嵌入式平台上映射为0xB0000000),此过程完全在PL端进行。

- 路由1 — LPDDR5X:有效载荷被复制到外部存储器中的一块1MB环形缓冲区,从而利用处理器访问外部LPDDR5X的路径。

- 路线2 — 软件:数据有效载荷被保留在片上缓冲区中,并通过软件计算其CRC32值。这为我们提供了一条以计算量为主的比较路径。

- 路线3 — 丢弃:数据包经过验证并计数后被丢弃。这为接收路径本身提供了无数据传输的基准线。

应用程序的工作原理

该应用程序遵循LwIP独立示例的常见结构。在main()函数中,我们初始化平台(启用缓存并设置50毫秒的周期性定时器),初始化LwIP栈,并将PL以太网控制器作为网络接口添加进去。分配一个静态IP地址192.168.10.10。无需DHCP服务器,只需将板子直接连接到主机PC。

然后,我们创建一个用户数据报协议(UDP)协议控制块,将其绑定到端口5001,并注册接收回调函数。

主循环仅轮询xemacif_input()函数,将接收到的数据帧传递给LwIP栈。每秒通过UART打印一行统计信息:总数据包和字节数、各路由的数据包数量、被拒绝的数据包、序列间隙以及最新的软件CRC32值。

当数据报到达时,接收回调函数会将它从LwIP的pbuf链中复制到一个线性缓冲区,并将其传递给packet_router_process(),后者执行实际处理工作:

•验证 — 检查头部是否包含正确的魔数、有效的头部长度、有效且在范围内的有效载荷长度以及有效的路由信息。任何检测失败的内容均被视为被拒绝并丢弃。

•路由 — 将有效载荷复制到选定的目标地址。LPDDR5X路径使用高效的环形缓冲区内存拷贝memcpy操作,而软件路径则计算CRC32校验和。

•定时 — 处理步骤通过调用XTime_GetTime()进行时间标记,以便准确了解路由操作所消耗的周期数。

•计数 — 比较序列号与预期值以检测是否有数据丢失,同时更新统计计数器。

如果主机在头部设置了ECHO标志,应用程序会直接将32字节的头部作为确认信息返回,设置ACK标志,并将测量到的处理时间填入board_proc_cycles字段。由于头部也包含了主机原始的发送时间戳,主机可以计算出完整的往返时间,并分离出板卡处理所占的时间,这是一种简单而有效的方法,用于表征每条数据路径的延迟。

Python 应用程序

在完成 Vivado™ 设计和 Vitis™ 应用程序后,我们已准备好创建一个生成数据包的程序。最简单的方法是使用 Python。

为此,我们创建了两个小型 Python 文件:packet_protocol.py,用于定义数据线格式;以及 udp_sender.py,这是一个命令行工具,可向板卡发送测试数据包流并报告结果。

在 Python 中定义协议

协议的定义位于 packet_protocol.py 文件中,这实际上是 C 头文件 router_protocol.h 的 Python 版本。它定义了相同的常量,如“PKTR”魔数、32 字节的头部大小、UDP 端口 5001,以及最大 1440 字节的有效载荷。

我们使用 Python 的 struct 模块对头部进行打包和解包,以符合板上应用软件所期望的序列顺序。

此外,还提供了一个名为 make_payload() 的辅助函数,用于通过重复数据包的序列号生成有效载荷。这意味着对于任意给定的序列号,有效载荷内容都是可重现的;这在后续验证实际进入 PL BRAM 或 LPDDR5X 缓存环中的数据,或检查板卡计算的 CRC32 与主机计算值是否一致时非常有用。

发件人

udp_sender.py 是实际发送已创建数据包的程序。最简单的情况下,我们将其指向板卡,它会发送一连串的数据包:

命令行选项允许我们控制实验过程:

--route 用于选择目标路径:0 表示 PL BRAM,1 表示 LPDDR5X,2 表示软件 CRC 路径,3 表示丢弃,或采用轮询方式(默认),以循环使用所有四种路径,确保每条路径都以相同的流量被测试。

--payload-bytes 和 --count 分别设置有效载荷大小和数据包数量。

--rate-mbps 通过计算每个数据包的时间预算并等待剩余时间来限制发送速率;若设为零,则根据 Python 的能力尽可能快速发送。

--echo 会在每个报文中设置 ECHO 标志,要求板卡返回确认信息。

脚本执行完成后,会打印统计结果。

使用回显模式测量延迟

当设置 --echo 时,脚本在每次发送数据包后等待板卡返回 32 字节的确认信息。它检查回复是否来自正确地址、携带匹配的序列号,并且 ACK 标志已设置,然后记录两次测量值。往返总时间由主机上的高分辨率计数器以及板卡自身的处理时间测量得出,VEK385 应用程序会将这些数据填入 board_proc_cycles 字段,然后回传报文头。

运行结束时,脚本会打印确认计数(以便我们识别丢失的数据包),并显示往返时间与板卡处理周期的最小值、中位数和最大值。通过比较这两组数值,我们就能准确区分网络和堆栈开销与板卡实际用于传输有效载荷的时间。通过使用不同的 --route 值运行相同命令,我们可以在相同条件下直接对比 PL 到 PL 路径、LPDDR5X 路径以及软件 CRC 路径的性能。

综合分析

为了测试这一点,我们可以连接以太网,将主机的网络适配器设置为 192.168.10.x 子网,然后启动 VEK385 应用程序。

执行以下命令将显示不同路由的性能表现。

运行后,我们将获得四种延迟曲线:一种是相同的流量模式,另一种是板卡的 UART 统计信息。这是一个简单的设置,但仅需主机上使用 Python 标准库即可提供我们对 AMD Versal™ 设备中数据路径进行建模所需的一切功能。

然而,Python 的原生网络功能可能会限制性能,因此我们需要确保在主机端采用最佳的性能方案。

这意味着我们必须使用 WinSockets 来处理网络通信。

Web 应用

我还希望创建一个美观的交互式界面,用于测试并方便地控制在硬件上运行的演示程序。

为此,我请 Codex 为我创建一个简单的 Web 界面,以构建该网页应用。

性能

在硬件性能和测试方面,我们看到的结果令人印象深刻。

首先展示的是使用Python网络接口的PL BRAM路径,该路径实现了835.0 Mbps的吞吐量目标。

使用原生Python网络接口将数据包存储在LPDDR5X中时,吞吐量为760.9 Mbps,略低。

采用原生Python网络处理的最终路径是OCM软件与CRC组合,其性能达到777.1 Mbps,表现良好。

切换至WinSock网络支持,并针对PL BRAM进行测试后,吞吐量提升至969.0 Mbps。

同样地,使用WinSock对LPDDR5X进行测试时,性能提升至969.7 Mbps。

再次使用WinSock进行测试后,最终结果达到968.6 Mbps。

所有这些路径的共同特点是,数据速率相近,且均处于我们预期的上限水平。因此我认为,该项目表明我们已成功实现1G以太网链路的最大性能。

如果您安装了Wireshark,还可以通过Web应用程序查看正在传输的数据包。

本文编译自hackster.io

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除( 邮箱:macysun@21ic.com )。
关闭