使用PingPong DMA实时数据采集的参考设计

前言

在嵌入式系统设计中,我们经常有实时数据采集的需求。低速率的数据一般处理难度不高,但是随着数据速率的提高,可能需要面对有限的硬件资源与系统性能的矛盾。这时候,就对软、硬件的设计要求有了更高的要求。

比如处理高速率的数据的时候,经常需要更大的硬件资源,比如片上RAM,FIFO来缓冲数据,以提高数据的吞吐率。但是一般FPGA内部的片上资源很有限。在这种情况下,如果提高硬件资源的利用率在工程上将是很大的挑战。

此教程介绍一种通过双通道DMA,采用PingPong传输的方式,以提高实时数据的处理能力,减小对硬件资源的依赖。

简介

单通道DMA传输方式

如图1所示,只用一个DMA通道传输数据,DMA的传输块大小为FPGA内部的缓冲区大小。

如果实时同步对DMA采集到的数据做处理的话,那么软件的抖动和延时可能会使DMA暂停超过缓冲区的缓冲时间,这将会带来严重的后果——数据溢出。在对数据完整性要求高的应用场合是致使的,尤其是在高速实时系统中,

单通道DMA传输方式.png

双通道PingPong DMA传输方式

双通道DMA的示意图如图2所示,两个DMA同时开启,FPGA在同一时间只会响应其中一个DMA,当其传输完成后,由于另外一个DMA已经发出了请求,所以要FPGA内部以硬件的时序快速切换到另外一个DMA。与此同时,之前的DMA可以同步做一个数据处理的工作。如此反复,两个DMA以PingPong的方式交替运行。

双通道PingPong DMA传输方式.png

可以看出,在采用PingPong DMA方式后,可以明显减小对FPGA片上缓冲区的依赖,极大的提高系统的吞吐量。

系统设计框图

在我们的测试系统中,实例化了两个AXI CDMA的实例,分别负责两个DMA通道的传输。IP方面,增加了DmaManager模块,负责对两个DMA的AXI请求做PingPong的管理,并输出AXI接口到FPGA内部的BRAM上。

DMA工作在100MHz,如果需要测试更高的速度,可以修改PL的时钟,或者通过Clock Wizard生成时间。

系统设计框图.png

软件架构

我们在上位机软件中,启动了三个线程,包括

1. 两个DMA启动和关闭的线程

2. 一个数据处理线程。

这三个线程之间通过concurrent_queue结构共享数据,即两个DMA线程通过PingPong的方式交替向queue里面填写数据,第三个线程通过异步的方式从queue里面取出数据块,并进行处理。

concurrent_queue的设计利用了C++11的特性,以简洁易读的方式实现了一个线程安全的队列模板。

示例工程

文末包括了完整的样例工程,目录的结构说明如下:

  • hw文件夹里面包含了基于ZC706开发板的Vivado工程。

  • fw文件夹是对应的petalinux工程。

  • sw是上柆机软件,可以运行在PS侧,也可以运行在windows或者linux平台,通过CMake工具生成项目文件。

测试结果

  • 使用Vivado2022.2打开hw目录下的Fpga0.xpr工程,综合,实现,并生成比特文件。

  • 进行到fw文件夹,执行petalinux-build生成内核文件,然后执行

petalinux-package --boot --u-boot --fpga xxx/hw/Fpga0.runs/impl_1/system_wrapper.bit –force生成BOOT.BIN启动镜像。

  • 拷贝fw/images/linux/目录下的BOOT.BIN,boot.scr和image.ub至SD卡,插入SD卡至开发板,切换启动模式到SD卡,上电启动。

  • 进行到sw目录下,新建build目录,运行CMake工具,选择Visual Studio模板,生成工程后用Visual Studio打开,编译软件。

  • 直接运行app01

  • 观察控制台的输出,可以看到两个DMA交替输出。

  • 在Vivado下JTAG连接开发板,选择合适的触发源,观察DMA以PingPong的方式运行。

文章来源:AMD开发者社区

最新文章

最新文章