是木科技

  • 97 主题
  • 285 帖子
  • 2536 积分
  • 身份:版主
  • 优秀版主
  • E币:1457

【MYD-C7Z010/20开发板 试用体验】DMA应用笔记

2019-12-1 16:35:12 显示全部楼层
本帖最后由 是木科技 于 2019-12-1 17:00 编辑

    显卡实验肯定是要用到DMA的,这边就和大家一起学习一下,zynq的DMA使用。
    思路是这样,也是米尔科技demo的思路,首先PS通过AXI-lite配置DMA的工作模式,然后,PS将数据写入DDR,再然后,PS控制DMA读出之前写入的数据,将数据流写入FIFO(读完后DMA会向PS发送中断),再然后,PS控制DMA将FIFO的数据流再通过AXI总线写回DDR(写完后DMA会向PS发送中断),PS判断写入的数据和读出的数据是否一致,完成实验。

02.png
    在讨论Zynq DMA的设计细节之前,让我们先要解释几个DMA控制器的原则:
典型的DMA控制器可以工作在以下三种模式:
1.突发模式-以一个连续的操作方式来传输一个完整的数据包,在许多应用中,DMA的突发模式传输会拒绝处理器的总线访问,对于不同的系统而言,这有利有弊(可以是件好事,也可能是一件非常糟糕的事情。)
2. 周期挪用模式-跟处理器一起交替完成单独的DMA字节或者字传输的总线访问,这种模式可以防止处理器无法访问总线。
3.透明模式-效率最高的传输模式,只有在处理器在执行任务而不需要访问外部系统总线的时候,DMA才能传输数据。
    DMA控制器支持scatter/gather操作,这是一个非常有用的特性,这个特性允许多个数据源的数据传输到同一个目的地址,或者同一个源地址的数据传输到不同的目的地址(也可以称为“buffers”)
    Zyng SoC是基于ARM内核的处理系统,它有一个DMA控制器,该DMA控制器连接在Zynq的AXI4中央互连架构上,通过AXI总线来传输数据,它在系统 存储器和Zynq的可编程逻辑单元(PL)之间完成64位的AXI总线传输。如下图所示,Zynq DMA有8个通道,可以同时执行8个DMA传输操作。
06.jpg
    DMA控制器具有以下的特点:
* 8个独立的通道,4个可用于PL—PS间数据管理,每个通道有1024Byte的MFIFO;
* 使用CPU_2x 时钟搬运数据,CPU_2x = (CPU frq/6)*2;
* 执行自定义内存区域内的DMA指令运行DMA;
* AHB控制寄存器支持安全和非安全模式;
* 每个通道内置4字Cache;
*可以访问SoC的以下映射物理地址:DDR、OCM、PL、Linear QSPI Read、SMC和M_AXI_GP设备,访问设备的互联结构如下图所示:


07.jpg
    之前跳过搭建工程环节,我们来看看这次需要添加哪些IP,如下图
03.jpg
    有点模糊,我一个个截图出来,这样可以放大了看清楚,包含了zynq内核,DMA模块,中断,FIFO,内部链等,如下图:
04.jpg
     接下来生成顶层文件,启动SDK,把demo代码copy进去,最后编译,生成镜像文件,通过SD卡烧录到办卡里面,先把硬件连接好:
08.jpg
   看下实现的函数,如果输入输出数据一致就会打印:Successfully ran AXI DMA SG Polling Example
  1. static int CheckDmaResult(XAxiDma * AxiDmaInstPtr)
  2. {
  3.         XAxiDma_BdRing *TxRingPtr;
  4.         XAxiDma_BdRing *RxRingPtr;
  5.         XAxiDma_Bd *BdPtr;
  6.         int ProcessedBdCount;
  7.         int FreeBdCount;
  8.         int Status;

  9.         TxRingPtr = XAxiDma_GetTxRing(AxiDmaInstPtr);
  10.         RxRingPtr = XAxiDma_GetRxRing(AxiDmaInstPtr);

  11.         /* Wait until the one BD TX transaction is done */
  12.         while ((ProcessedBdCount = XAxiDma_BdRingFromHw(TxRingPtr,
  13.                                                        XAXIDMA_ALL_BDS,
  14.                                                        &BdPtr)) == 0) {
  15.         }

  16.         /* Free all processed TX BDs for future transmission */
  17.         Status = XAxiDma_BdRingFree(TxRingPtr, ProcessedBdCount, BdPtr);
  18.         if (Status != XST_SUCCESS) {
  19.                 xil_printf("Failed to free %d tx BDs %d\r\n",
  20.                     ProcessedBdCount, Status);
  21.                 return XST_FAILURE;
  22.         }

  23.         /* Wait until the data has been received by the Rx channel */
  24.         while ((ProcessedBdCount = XAxiDma_BdRingFromHw(RxRingPtr,
  25.                                                        XAXIDMA_ALL_BDS,
  26.                                                        &BdPtr)) == 0) {
  27.         }

  28.         /* Check received data */
  29.         if (CheckData() != XST_SUCCESS) {

  30.                 return XST_FAILURE;
  31.         }

  32.         /* Free all processed RX BDs for future transmission */
  33.         Status = XAxiDma_BdRingFree(RxRingPtr, ProcessedBdCount, BdPtr);
  34.         if (Status != XST_SUCCESS) {
  35.                 xil_printf("Failed to free %d rx BDs %d\r\n",
  36.                     ProcessedBdCount, Status);
  37.                 return XST_FAILURE;
  38.         }

  39.         /* Return processed BDs to RX channel so we are ready to receive new
  40.          * packets:
  41.          *    - Allocate all free RX BDs
  42.          *    - Pass the BDs to RX channel
  43.          */
  44.         FreeBdCount = XAxiDma_BdRingGetFreeCnt(RxRingPtr);
  45.         Status = XAxiDma_BdRingAlloc(RxRingPtr, FreeBdCount, &BdPtr);
  46.         if (Status != XST_SUCCESS) {
  47.                 xil_printf("bd alloc failed\r\n");
  48.                 return XST_FAILURE;
  49.         }

  50.         Status = XAxiDma_BdRingToHw(RxRingPtr, FreeBdCount, BdPtr);
  51.         if (Status != XST_SUCCESS) {
  52.                 xil_printf("Submit %d rx BDs failed %d\r\n", FreeBdCount, Status);
  53.                 return XST_FAILURE;
  54.         }

  55.         return XST_SUCCESS;
  56. }
    实现最终验证如图:
05.png
附上源代码哟: DMA.part01.rar (10 MB, 下载次数: 1)