当前位置:   article > 正文

Xilinx PCIE DMA--Sparten6/Kintex-7 BMD 搭建

xilinx pcie dma

目录

前言

1、DMA数据流简介

1.1 FPGA发DMA数据到PC

1.2 数据从PC搬到FPGA

2、PCIE 软件开发环境

3、Xapp1052下载

4、Kintex-7 BMD工程搭建

5、Sparten6 BMD工程搭建

参考文献


 

 

前言

本文主要以xapp1052作为学习材料,以Sparten6/Kintex-7芯片作为搭建BMD工程举例。

关于BMD工程的仿真环境的搭建,可以参考“Xilinx PCIE DMA 仿真环境搭建”

相关博客可以参考:

         五、Xilinx PCIE CORE学习

        六、Xilinx PCIE DMA--Sparten6/Kintex-7 BMD

        七、Xilinx PCIE DMA 仿真环境搭建

        八、 win10 jungo windriver

 

 

本文仅是基于xapp1052,搭建两种芯片的BMD工程。

关于xapp1052有几点说明:

(1)首先,官方提供的xapp1052工程,主要用于测试DMA收发数据的效率,

          官方提供完整的DMA收发示例、PIO仿真文件、示例工程可以板级调试;

(2)其次,该xapp1052工程没有将PC发送的FPGA的数据存储下来,而仅是与一个固定数值做比较,测试DMA传输效率;

(3)以及,该xapp1052工程发送的数据,仅是发送 通过PIO配置WDMATLPP寄存器里的数据,即用于测试DMA传输效率;

(4)最后,鉴于本人是初学者,整理的比较浅显,还是请读者多看看参考文献吧!

 

软件:ISE14.4/14.7

官网:xapp1052

 

 

1、DMA数据流简介

简述PIO与DMA的区别:

PIO操作:通常,PIO传输的数据仅有一个,即MWr、CPLD这类TLP报文里,仅包含一个有效数据。

DMA操作:通常,DMA传输的数据有多个,即MWr、CPLD这类TLP报文里,     包含多个有效数据。

                 只不过,为了进行DMA的操作,需要提前配置一些控制寄存器;这些配置控制寄存器的过程,是PIO操作。

                 当MWr、CPLD开始传输多个有效数据时,才是DMA操作。所以,显的复杂一点。

 

DMA数据传输概述:

首先需要说明:

下面介绍的传输类型,是FPGA作为master主动发起读写请求,PC作为从机进行响应;

实际使用中,FPGA、PC谁都可以作为master,下面的介绍仅是一种参考。

 

(1)FPGA发DMA数据到PC

首先,PC通过下文figure3配置步骤1-7,该过程是PIO操作,每次配置一个寄存器;

然后,DMA发送模块,发起 存储器写访问事务(MWr),给PC 发送包含数据的写TLP数据包,举例如下图7-5所示。

即这个TLP数据包,包含 1个头标 +n个DW数据,实现DMA数据的传输!

最后,待数据传输完毕,FPGA应该会发送一个中断信号,提示PC数据传输结束;

(2)PC发DMA数据到FPGA

首先,PC通过下文figure4配置步骤1-6,该过程是PIO操作,每次配置一个寄存器;

然后,FPGA的DMA发送模块,发起存储器读请求事务(MRd),给PC发送一个储器 读请求TLPs,该过程是PIO操作

再然后,PC返回带数据的完成报文CPLD,FPGA的DMA接收模块、接收该数据流,该过程是DMA操作;

PC返回的CPLD报文如下图所示,下图仅是个举例,可能不完全正确

该CPLD数据包,包含:一个头标 + n个数据,实现数据的DMA传输!应该类似于下图吧,下图可能不完全正确!

仅是方便理解,才贴上下图的 .......    =。=

最后,带数据传输完毕,FPGA应该会发送一个中断信号,提示PC数据传输结束;

详细传输流程,见下文吧。

 

1.1 FPGA发DMA数据到PC

有一点需要说明一下,

在上面的步骤4中,组织PCIe Memory Write TLPs时,发送模块发送的是写MEM数据包,即存储器写访问事务(MWr)类型,将待发送的DMA数据发送给PC;

这里FPGA发送模块并不是通过CPLD完成报文的形式将数据发送给PC的。

读者可以细细品味一下两者的区别。

下图是官方提供的xapp1052中,测试FPGA发DMA数据到PC的步骤。

关于下图步骤6有一点需要说明,

PC通过PIO操作配置WDMATLPP寄存器,将测试数据data写入WDMATLPP寄存器;

然后,当启动DMA操作时,发送引擎将WDMATLPP中的数据data重复发送给PC,用以测试DMA写MEM(指PC内存)的效率。

下图是官方提供xapp1052中发送模块对应的几种事务类型,这里引用博主CLGo 的博客里的相关介绍。

值得注意的是:

(1)BMD_64_CPLD_FMT_TYPE是PIO模式

       标志着发送一个带数据的完成包,这个使用在PC端向FPGA发送一个存储器读请求后,FPGA通过这个报文将存储器信息返回到PC端;

(2)BMD_64_MWR_FMT_TYPE、BMD_64_MWR64_FMT_TYPE:是DMA模式

       标志着FPGA发送储器 写请求TLPs(MWr),这个使用在启动DMA写时,发送引擎组建存储器写请求包将数据发送到PC上; 

(3)BMD_64_MRD_FMT_TYPE、BMD_64_MRD64_FMT_TYPE :是DMA模式,

       标志着FPGA发送储器 读请求TLPs(MRd)

       这个使用在PC配置启动DMA读时,发送引擎组建存储器读请求包,PC发送带数据的完成包到FPGA上,被接收引擎接收。

1.2 数据从PC搬到FPGA

大概过程如下:

(1)首先电脑申请一片连续内存,

(2)接着电脑通过PIO模式配置FPGA上的控制状态寄存器(就是表格中的Step1~Step6),

(3)然后FPGA检测到读DMA请求后,发送引擎组装 储器 读请求报文(MRd) 并发送,

(4)接收引擎接收电脑反馈的完成包CPLD,

(5)最后,FPGA发送中断结束传输。

下图是官方提供的Xapp1052中,测试PC发DMA数据到FPGA的步骤。

关于Xapp1052提供的BMD接收引擎,并结合上面的步骤(4)和下面的步骤1-8有一点需要说明一下:

在接收引擎开始接收来自PC返回的CPLD数据包时,接收引擎并没有将该DMA数据存入FPGA内部缓存MEM,

而是将接收到的数据与RDMATLPP寄存器中的数据进行数据比较,但配置RDMATLPP寄存器的过程,却没有在下面的步骤1-8中体现。在xapp1052的PDF中,相关描述如下:

 

下图是官方提供xapp1052中接收模块对应的几种事务类型,这里引用博主CLGo 的博客里的相关介绍。

值得注意的是:

(1)BMD_MEM_RD32_FMT_TYPE 、BMD_MEM_WR32_FMT_TYPE :是PIO事务

         两种标头对应的TLP是以PIO的模式传输,其作用是上位机读写DMA控制状态寄存器,就是上文的DMA体系结构中的Control and Status Registers。

(2)BMD_CPL_FMT_TYPE 、BMD_CPLD_FMT_TYPE :是DMA事务,

        是FPGA发送 DMA读请求(MRd)后,PC端反馈的完成包CPLD是DMA模式。 
 

下图是PIO配置一些寄存器的整理:

 

2、PCIE 软件开发环境

        目前对PCIe 部分的上位机驱动开发的软件比较常用的是windriver 和DDK 这2 款开发工具。DDK 是Device Development Kit,设备开发包的意思。为windows 设备驱动程序开发包。一般是在VC 或者VS 软件环境下进行开发。相对于Windriver,DDK 需要开发人员对驱动更加深入的了解。
         Windriver 是jungo 公司为驱动程序开发提供的一个工具,特别适合初学者使用。它把PC 硬件系统的驱动程序开发进行了高度的集成和封装,开发者甚至不需要设计驱动程序,所需要做的工作几乎仅仅是保证设备的硬件和相应固件设计正确,然后进行
应用程序的设计,而应用程序的设计也可以通过对Windriver 产生的debug 程序进行修改而得到。

        WinDriver™ PCI / ISA User's Manual

 

        软件驱动开发
        安装好Windriver后,即可完成PCIe驱动的开发了。首先你需要安装VS2008,用来打开Windriver的驱动源码,并进行修改和测试。下面我们来详细的了解整个软件
         开发和测试的流程。
         Step1 : 我们首先找到Windriver的安装目录,如图所示,在安装目录下有各个公司的开发工程以及开发软件包。这里我们找到xilinx文件夹,进入下一步。

         打开Windriver 软件,并新建工程项目,用户可以为自己的设备生成相关的INF 驱动文件,这里如果用户下载了我们板卡所提供的PCIE 文件至开发板,则可在如图8-2-4 中找到我们的XILINX PCIe 设备,点击Gneratate .INF file。

          如图8-2-5所示,用户可以自定义厂商的ID,设备ID以及设备类型,修改相关属性后,勾选上automatically install the INF file,即可完成PCIE的驱动安装。

        安装完成后,用户即可在设备管理器中找到自定义的设备

软件驱动开发

Step1 : 我们首先找到Windriver的安装目录,如图8-2-7所示,在安装目录下有各个公司的开发工程以及开发软件包。这里我们找到xilinx文件夹,进入下一步。

Step2 : 使用VS2008 打开“安装路径\xilinx\virtex5\bmd\diag\x86\msdev_2008”里的工程,如图8-2-8所示。本工程虽然是Virtex5型号的FPGA PCI驱动代码,但也同样适用于大部分Xilinx公司的PCIE的驱动代码的开发。

Step3 :此时如果你确定已经下载好了PCIE DMA的FPGA文件,我们可以点击菜单栏下的“启动调试(F5)”,来进行工程调试。

 

PCIe功能调试项说明
PCIe功能调试项说明

        这里我们更加关注DMA的相关测试,我们选择测试项7,即Direct memoryaccess(DMA)-Interrupts completion method,按照操作步骤选择open dma,并选择From device或者to device,来确定数据的传输方向,填入TLP的个数,以及TLP的测试数据。

         OK,现在我们大致已经知道如何通过Windriver所提供的开发工具在VS2008的测试与开发,那么接下来我们再来分析下VS2008下的驱动代码。

VS2008驱动代码分析
1.通过VS2008打开Virtex5的BMD工程,如图8-2-11所示,包含6个c文件。图8-2-11 BMD 驱动文件

 

          实际上用户几乎不需要做大量的修改,如果用户只需要进行DMA方面开发的话,只需要通过MenuDMAOpen函数
将需要配置的DMA数据大小,数据缓存,以及完成方式配置到该函数中,并启动DMA即可。

  1. static void MenuDMAOpen(WDC_DEVICE_HANDLE hDev, PDIAG_DMA pDma, BOOL fPolling)
  2. {
  3. DWORD dwStatus, dwOptions, dwTotalCount, i;
  4. UINT32 u32Pattern;
  5. WORD wSize, wCount;
  6. BOOL fIsRead;
  7. BOOL fEnable64bit;
  8. BYTE bTrafficClass;
  9. /* Get input for user */
  10. if (!MenuDMAOpenGetInput(&wCount, &u32Pattern, &dwOptions))
  11. return;
  12. fIsRead = dwOptions & DMA_FROM_DEVICE ? FALSE : TRUE;
  13. pcie_opratetype = dwOptions & DMA_FROM_DEVICE ? FALSE : TRUE;
  14. /* The BMD reference design does not support s/g DMA, so we use contiguous
  15. */
  16. dwOptions |= DMA_KERNEL_BUFFER_ALLOC;
  17. /* Get the max payload size from the device */
  18. wSize = VIRTEX5_DMAGetMaxPacketSize(hDev, fIsRead) / sizeof(UINT32);
  19. dwTotalCount = (DWORD)wCount * (DWORD)wSize;
  20. /* Open DMA handle */
  21. dwStatus = VIRTEX5_DMAOpen(hDev, &pDma->pBuf, dwOptions,dwTotalCount * sizeof(UINT32),
  22. &pDma->hDma);
  23. if (WD_STATUS_SUCCESS != dwStatus)
  24. {
  25. printf("\nFailed to open DMA handle. Error 0x%lx - %s\n", dwStatus,
  26. Stat2Str(dwStatus));
  27. return;
  28. }
  29. printf("\nDMA handle was opened successfully (handle 0x%lx)\n", pDma->hDma);
  30. printf("Payload packet size in dwords 0x%hx\n", wSize);
  31. /* Prepare the device registers for DMA transfer */
  32. fEnable64bit = FALSE;
  33. bTrafficClass = 0;
  34. VIRTEX5_DMADevicePrepare(pDma->hDma, fIsRead, wSize, wCount, u32Pattern,fEnable64bit,
  35. bTrafficClass);
  36. if (!fPolling) /* Enable DMA interrupts (if not polling) */
  37. {
  38. VIRTEX5_DmaIntEnable(hDev, fIsRead);
  39. if (!VIRTEX5_IntIsEnabled(hDev))
  40. {
  41. dwStatus = VIRTEX5_IntEnable(hDev, DiagDmaIntHandler);
  42. if (WD_STATUS_SUCCESS != dwStatus)
  43. {
  44. printf("\nFailed enabling DMA interrupts. Error 0x%lx - %s\n",
  45. dwStatus, Stat2Str(dwStatus));
  46. goto Error;
  47. }
  48. printf("\nDMA interrupts enabled\n");
  49. }
  50. }
  51. else /* Disable interrupts (polling) */
  52. VIRTEX5_DmaIntDisable(hDev, fIsRead);
  53. /*
  54. 在下面代码中
  55. 我们可以将所需要dma写入的数据填入pDma->pBuf,
  56. 该试验我们填入的是一串递增数据i,然后PCIE DMA将会按照用户设置的TLP包的个数,
  57. 当前TLP所支持的最大TLP的数据大小wSize,以及本次操作的读写类型fIsRead设置为0
  58. 选择DMA写。
  59. */
  60. /* Initialize the DMA buffer with user defined pattern */
  61. for (i = 0; i < dwTotalCount; i++)
  62. {
  63. if (fIsRead)
  64. ((UINT32 *)(pDma->pBuf))[i] = i;
  65. else ((UINT32 *)(pDma->pBuf))[i] = 0xdeadbeaf; /* to be overwritten by
  66. WRITE dma */
  67. }
  68. /* Start DMA */
  69. printf("Start DMA transfer\n");
  70. VIRTEX5_DMAStart(pDma->hDma, fIsRead);
  71. TimeStart();
  72. /* Poll for completion (if polling selected) */
  73. if (fPolling)
  74. {
  75. if (VIRTEX5_DMAPollCompletion(pDma->hDma, fIsRead))
  76. {
  77. DmaTransferVerify(hDev, pDma->pBuf, dwTotalCount, u32Pattern,
  78. fIsRead);
  79. }
  80. else
  81. printf("timeout\n");
  82. }
  83. return;
  84. Error:
  85. DIAG_DMAClose(hDev, pDma);
  86. }

如果用户需要读取从PCIE的设备端返回的数据,则从中断处理函DiagDmaIntHandler中读取pIntResult->pBuf即可,如下表代码所示。

  1. static BOOL DIAG_DMAVerifyPattern(WDC_DEVICE_HANDLE hDev, PVOID pBuf,
  2. DWORD dwTotalCount, UINT32 u32Pattern, BOOL fIsRead)
  3. {
  4. DWORD i;
  5. /* Transfer to device, check HW error bit */
  6. if (fIsRead)
  7. return VIRTEX5_DmaIsReadSucceed(hDev);
  8. //Transfer from device, check DMA buffer
  9. for (i = 0; i < dwTotalCount; i++)
  10. {
  11. if (((UINT32 *)(pBuf))[i] != i)
  12. {
  13. VIRTEX5_ERR("Data mismatch, pBuf[%ld] = %08X, u32Pattern = %08X\n",i, ((UINT32
  14. *)(pBuf))[i], u32Pattern);
  15. return FALSE;
  16. }
  17. }
  18. return TRUE;
  19. }

 

 

 

3、Xapp1052下载

Step1:登录www.xilinx.com官网,在搜索栏中输入xapp1052,xapp1052是xilinx专为用户PCIe DMA开发应用的demo,里面包含有PCIE DMA开发与应用的硬件代码与上位机的驱动代码。如图8-3-1所示,用户需要下载图中的xapp1052.pdfxapp1052.zip。

Step2:将xapp1052.zip解压后我们即可发现以下文

 

 

4、Kintex-7 BMD工程搭建

4.1 Generate PCIE DMA IP CORE

4.2 DMA_64工程搭建

在下图的代码中,有几个.V文件需要说明一下,

(1)xilinx_pcie_2_1_ep_7x.v :来自IPCore的 example 的 顶层。

         在该文件里,例化的app pcie_app_7x 可能一些管脚比较多,而这些多出来的管脚,在pcie_app_7x_bmd.v文件里不存在,这样会导致PIO仿真报错。因此注意对比删除。

(2)pcie_app_7x_bmd.v        :来自xapp1052里的128事例工程,复制过来后,需要将128修改为64即可。

(3)axi_trn_top.v等                :来自xapp1052里的128事例工程,直接复制过来即可。

(4)其他所有文件                  :从xapp1052里复制即可。

代码层次如下:

将BMD_PCIE_20.V如下图所示,设置为全局的文件。这样我们的工程就基本建立完成。

5、Sparten6 BMD工程搭建

暂不更新

 

 

>>点击这里返回导航页<<

 

 

 

 

参考文献

 

 

 

 

 

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/一键难忘520/article/detail/743146
推荐阅读
相关标签
  

闽ICP备14008679号