ZedBoard--(5)嵌入式Linux下的DMA测试(Direct Register Mode)(PS + PL)
来源:互联网 发布:捷易通软件怎么样 编辑:程序博客网 时间:2024/06/06 07:05
ZedBorad–(5)嵌入式Linux下的DMA测试(PS+PL)
本文将详细介绍如何在ZedBorad上使用AXI接口的DMA IP核。(文末会给出测试代码的下载链接)
DDR控制器、AXI DMA控制器以及PS之间的互连关系如下图所示。
DDR控制器已经包含在PS中,而AXI DMA和数据FIFO是需要我们自己在PL中实现的。由图可知,处理器使用AXI-Lite总线和DMA、DDR控制器进行交互。AXI_MM2S和AXI_S2MM为DDR和DMA之间的交互提供了通道。
- MM2S即Memory-Mapped to Streaming
- 若DMA使用Scatter-Gather模式,DMA和DDR内存控制器之间会有多一条AXI总线(简洁起见,图中省略)
【注意】本文默认读者已经熟悉Vivado、Xilinx SDK的基本使用方法。
硬件部分
下面开始介绍如何在ZedBorad上利用PS和PL实现DMA。
(1)新建Vivado工程,选择Create Block Design,从IP Catalog添加ZYNQ7 Processing System,然后点击Run Block Automation,确认Apply Board Perset前面的勾是勾上的。如下俩图所示。
(2)双击刚刚添加的ZNYQ7 PS,出现Re-Customize的窗口。左侧点击Clock Configuration,右侧展开PL Fabric Clocks,按下图设置。
(3)左侧继续点击PS-PL Configuration,右侧打开GP Master AXI Interface,按下图设置。
(4)然后点击OK,完成后PS变成这样:
(5)我们需要在此基础上连一根线,如下图所示。
(6)从IP Catalog添加AXI Direct Memory Access,然后点击Run Connection Automation,选择/axi_dma_0/S_AXI_LITE,如下图所示。弹出的窗口直接点OK。
这时整个系统的模块连接图应该是这样的:
双击DMA模块,打开配置窗口,去掉Enable Scatter Gather Engine前面的勾。
(7)然后我们需要将DMA的M_AXI_SG、M_AXI_MM2S和M_AXI_S2MM总线与PS的AXI slave接口相连。因为目前PS没有这些接口,因此双击PS进行Re-Customize,左侧点击PS-PL Configuration,右侧打开HP Slave AXI Interface,按下图配置后点击OK。
(8)回到Block Design后,点击Run Connection Automation,选择/processing_system7_0/S_AXI_HP0,如下图所示。
在弹出的对话框中,确保接连接的是DMA,如下图所示。
(9)继续点击Run Connection Automation,选择/axi_dma/M_AXI_SG;完了之后再点击Run Connection Automation,选择/axi_dma/M_AXI_S2MM。
(10)接下来,从IP Catalog中添加AXI4-Stream Data FIFO,按下面4张图进行连接。
(11)由于本设计不需要AXI-Streaming的状态和控制信息,因此需要把它们去掉。双击AXI DMA模块,将Enable Control / Status Stream前面的勾去掉。
(12)接下来需要将DMA的中断信号连接到PS。双击PS,左侧点击Interrupts,按下图配置。
然后从IP Catalog中添加Concat模块,并按照下面3张图片进行连接。
(13)至此,硬件连接完毕。在菜单Tools中点击Validate Design。
如果前面操作正确,将弹出对话框提示成功,如下图所示。
(14)可以点击Regenerate Layout按钮,重新布局一下连接,如下图所示。
完了整个电路图长这样:
(15)调整过走线之后,保存Block Design,并在其上右击选择Create HDL Wrapper,如下俩图所示。
之后就可以生成比特流了,完了之后将工程Export到SDK。菜单File选择Export,如下面几张图所示。
菜单File中选择Launch SDK,如下图所示。
软件部分
经过一长串步骤之后终于转到了SDK。从Vivado转到SDK之后,左边Project Explorer下的design_x_wrapper_hw_platform就是上面Export的硬件。
由于本历程需要在嵌入式Linux下运行,因此首先应该生成BOOT.BIN文件。生成BOOT.BIN的方法在上一篇博客中有介绍:ZedBoard–(4)嵌入式Linux下的LED实验(PS + PL)
然后从File菜单中新建Application Project,如下图所示。
输入工程名字,Hardware Platform选择从Vivado导出的硬件平台;OS Platform选择standalone;BSP选择Create New。点击Next,如下图所示。
选择Hello World,如下图所示。
展开C/C++工程底下的src文件夹,在helloworld.c中输入测试代码:
/** * Using AXI Direct Memory Access v7.1 * Direct Register Mode * * Author: ZMJ@CSE, SEU * Date: 2016-07-12 */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <fcntl.h>#include <termios.h>#include <sys/mman.h>#define DMA_BASE_ADDR 0x40400000 // Phy. address of axi dma#define DMA_TX_ADDR 0x0F000000 // Phy. address of TX buffer#define DMA_RX_ADDR 0x0F800000 // Phy. address of RX buffer// Direct Register Mode Register Address#define MM2S_DMACR 0x00 // MM2S DMA Control Register#define MM2S_DMASR 0x04 // MM2S DMA Status Register#define MM2S_SA 0x18 // MM2S DMA Source Address Register#define MM2S_LENGTH 0x28 // MM2S DMA Transfer Length Register#define S2MM_DMACR 0x30 // S2MM DMA Control Register#define S2MM_DMASR 0x34 // S2MM DMA Status Register#define S2MM_DA 0x48 // S2MM DMA Destination Address Register#define S2MM_LENGTH 0x58 // S2MM DMA Buffer Length Register// Shared Memory Settings#define TX_PKT_SIZE 0x7FFFFF // Size of TX Packet(0~0x7FFFFF)#define RX_PKT_SIZE 0x7FFFFF // Size of RX Packet(0~0x7FFFFF)typedef unsigned int u32;u32* axidma_base; // A pointer to axidma base address.u32* tx_packet; // A pointer to tx buffer area.u32* rx_packet; // A pointer to rx buffer area.void dma_set(u32* addr, int offset, u32 value);u32 dma_get(u32* addr, int offset);void memoryMap(int fd); // Memory map from physical address to logical addressvoid initDMAReg(); // Initialize AXI DMA's register.void startTransfer(); // Start DMA transfer.void waitDMA(); // Wait until current transfer ends.void dma_status(); // Print status of MM2S and S2MM channels.void check(); // Check DMA result.int main(){ // Open /dev/mem which represents the whole physical memory. int fd = open("/dev/mem", O_RDWR | O_SYNC); memoryMap(fd); // Memory map from physical address to logical address initDMAReg(); // Initialize AXI DMA's register. // Test 1 printf("\nSimple DMA Test 1:\n"); int i; for (i = 0; i < TX_PKT_SIZE / 4; i++) tx_packet[i]= i; startTransfer(); // Start DMA transfer. waitDMA(); // Wait until current transfer ends. dma_status(); // Print status of MM2S and S2MM channels. check(); // Check DMA result. // Test 2 printf("\nSimple DMA Test 2:\n"); memset(tx_packet, 0, TX_PKT_SIZE); memset(rx_packet, 0, RX_PKT_SIZE); for (i = 0; i < TX_PKT_SIZE / 4; i++) tx_packet[i]= i; startTransfer(); // Start DMA transfer. waitDMA(); // Wait until current transfer ends. dma_status(); // Print status of MM2S and S2MM channels. check(); // Check DMA result. // Test 3 printf("\nSimple DMA Test 3:\n"); memset(tx_packet, 0, TX_PKT_SIZE); memset(rx_packet, 0, RX_PKT_SIZE); for (i = 0; i < TX_PKT_SIZE / 4; i++) tx_packet[i]= i; startTransfer(); // Start DMA transfer. waitDMA(); // Wait until current transfer ends. dma_status(); // Print status of MM2S and S2MM channels. check(); // Check DMA result. close(fd); return 0;}
【注意】完整的测试代码将在文末给出。
然后有几个地方需要设置一下:
(1)选中刚刚新建的C/C++工程,右键Property,展开C/C++ Build下的Tool Chain Editior,右边的Current toolchain选择Xilinx ARM GNU/Linux Toolchain,并且确保Used Tools和下图一致(如果缺少工具,需要点击Select Tools按钮添加)。设置完之后,将src文件夹下除测试的.c/.cpp文件以外的其他源文件删除。
(2)展开C/C++ Build,点Settings,在Binary Parsers里面,只勾上Xilinx ARM Linux ELF,如下图所示:
(3)检查一下C/C++ General下的Paths and Symbols右边的Libraries和Library Paths。对于本文提供的测试程序,这两个标签页下面应该为空(若不为空,请将原有的内容删除)。读者需要根据自身项目的实际情况添加Library并设置其路径,例如如果需要使用pthread.h的头文件,直接在Libraries下添加pthread的库即可(无需手动添加路径),如下图所示。
设置无误后,Ctrl + B将工程Build一下,如果没有错误将生成.elf的可执行文件。将.elf文件拷贝到SD卡中,在Linux下执行。程序执行时,读者可以在串口看到程序输出的信息。
SDK默认控制台不接收串口信息,所以需要设置一下(如果不想设置,可以打开第三方串口调试助手查看程序输出)。
设置方法如下:
(1)选中新建的Application Project,右键点击Properties。点击Run/Debug Settings,选中右边的.elf,点击Edit按钮,如下图所示:
(2)点击STDIO Connection选项卡,点击Connect STDIO to Console的复选框,设置好开发板所在的串口以及波特率,点击OK即可。如下图所示:
设置完成之后,读者就可以在控制台看到来自开发板的串口信息了。
参考资料
Using the AXI DMA in Vivado
Xilinx PG021
资源下载
AXI DMA测试Vivado工程,含XSDK FSBL Project和Application Project
基于ZedBoard的AXI DMA测试代码
Xilinx官方AXI DMA技术文档(PG021)
- ZedBoard--(5)嵌入式Linux下的DMA测试(Direct Register Mode)(PS + PL)
- ZedBoard--(4)嵌入式Linux下的LED实验(PS + PL)
- Zedboard学习(四):PS+PL搭建SoC最小系统
- Zedboard学习(三):PL下流水灯实验
- Zedboard学习(二):zedboard的Linux下交叉编译环境搭建
- zedboard--ps工程helloworld的建立(六)
- zedboard--单独PL实验(四)
- ZedBoard--(2)嵌入式Linux移植和BOA服务器的搭建
- (zedboard)Ps与pl之间的连接axi_gp,axi_hp,axi_acp
- zedboard--Opencv移植和zedboard测试(十一)
- zedboard--Opencv移植和zedboard测试(十一)
- zedboard--zedboard的qt测试和usb视频采集和显示(十六)
- DMA(Direct Memory Access)直接存储器存取
- DMA(Direct Memory Access直接存储器访问)总结
- DMA(direct memory access)直接内存访问
- Zedboard学习(7)PS下第一个裸奔程序
- ZedBoard学习手记(八) 更大的目标!在Linux下开发图形用户界面
- zedboard---opencv移植与测试(一)
- XGBoost原理解析
- 单元格的边框没有被显示出来
- Android网络加载框架Glide的使用
- JSP 九个内置JSP对象
- Glide的缓存和网络请求方式的配置
- ZedBoard--(5)嵌入式Linux下的DMA测试(Direct Register Mode)(PS + PL)
- 《机器学习实战》小白学习笔记1(kNN_概述和简单实现)
- 编译NS3的visualizer时遇到的转换错误
- Windows dos命令简介
- JVM垃圾收集器总结
- 使用Android Studio阅读整个Android源码
- 远程访问jupyter notebook
- 协程
- 【JAVA技术库】删除列表选中的多个数据