Zynq PS DMA控制器应用笔记

Zynq PS DMA应用笔记

Hello,Panda

Zynq-7000系列器件PS端的DMA控制器采用ARM的IP核DMA-330(PL-330)实现。有关DMA控制器的硬件细节及相关指令集、编程实例内容参考ARM官方文档:

      DDI0424D:dma330_r1p2_trm.pdf

      DAI0239A:dma330_example_programs.pdf

本文开发环境为Xilinx SDK2015.2,DMA库版本为dmaps_v2_1。

1 结构特点

DMA控制器具有以下的特点:

n      8个独立的通道,4个可用于PL—PS间数据管理,每个通道有1024Byte的MFIFO;

n      使用CPU_2x 时钟搬运数据,CPU_2x = (CPU frq/6)*2;

n      执行自定义内存区域内的DMA指令运行DMA;

n      AHB控制寄存器支持安全和非安全模式;

n      每个通道内置4字Cache;

n      可以访问SoC的以下映射物理地址:

DDR、OCM、PL、Linear QSPI Read、SMC和M_AXI_GP设备,访问设备的互联结构如图1所示。

 

Zynq PS DMA控制器应用笔记_第1张图片

                                                                               图1 Zynq 访问互联结构图

 

从图1可以看出DMA控制器可以访问连接到Central Interconnect上的所有设备,并提供了四个通道的外设管理接口可用于控制PL的数据搬运。

 Zynq系列器件中DMA控制器采用ARM PL-330 IP和r1p1版,结构框图如图2所示。

 

Zynq PS DMA控制器应用笔记_第2张图片

 

                                                       图2 Zynq DMA控制器结构框图

如图2所示,DMA控制器由指令加速引擎,AXI Master数据接口,AXI APB寄存器访问接口以及可以连接到PL的外设请求接口,数据缓冲FIFO和控制及状态产生单元组成。

从图2可以看到,DMA PL330的设计思想是:DMA控制器通过DMA指令执行引擎执行自己的指令,并将执行状态通过APB总线和中断等形式反馈给CPU,达到数据搬运不占用CPU的目的。

DMA控制器共有八个通道,其中四个通道负责互联到Central Interconnectcun存储单元上的数据搬运;四个数据通道为外设请求接口,可用于PL AXI互联接口的数据访问管理。

每个DMA通道都执行自己的指令,拥有自己的独立线程,通道间互不影响。指令执行引擎有自己独立的Cache线。

2 编程模型

本文不考虑外设请求接口,DMA控制器编程分为以下几个部分:

u     DMA控制器初始化;

u     组织DMA引擎执行代码;

u     启动或停止DMA传输;

u     异常处理。

2.1 DMA控制器初始化

DMA控制器初始化,DMA初始化包括配置时钟、复位,安全状态,中断服务等,如下表1所示。

表1 DMAC初始化配置

步骤

配置项

相关寄存器

描述

1

配置时钟

 

使能APB时钟,一般已经使能

slcr.AER_CLK_CTRL

[DMA_CPU_2XCLKACT]=1’b1

使能CPU_2x时钟给AXI

2

配置安全状态

SLCR. TZ_DMA_NS = 1

非安全

SLCR. TZ_DMA_IRQ_NS=1

非安全

SLCR. TZ_DMA_PERIPH_NS=1

非安全

3

复位

slcr.DMAC_RST_CLTR[DMAC_RST]

复位DMAC

4

中断

 

设置中断服务函数

一般的时钟和复位都在FSBL里面完成,用户只需要设置DMA的APB总线安全模式和中断服务函数即可。特别要注意对安全模式的设置,否则在非安全模式下访问安全模式寄存器无任何有效应答。

2.2  组织DMA引擎执行代码

 Xilinx SDK(gcc)不支持编译DMA引擎指令,因此需要自己对照ARM官方文档”DDI0424D_dma330_r1p2_trm.pdf”对指令集的描述一条一条的组织指令,特别注意执行指令的长度应为Cache线的整数倍,不足的用NOP补齐。

下面以DMAMOV指令为例,说明如何编写指令引擎执行的机器码,图3是DMAMOV指令的编码。

Zynq PS DMA控制器应用笔记_第3张图片

                                                                 图3 DMAMOV指令的编码

本条指令编码由48位(6字节)构成,如图3中的编码:

①   rd[2:0]:表示寄存器地址,000为源地址寄存器SAR,001为通道控制寄存器CCR,DAR为目的地址寄存器。

②   imm[31:0],为以上三个寄存器的配置值。

CCR为AXI总线配置寄存器,参见文档DDI0424D中 3.3.15 Channel Control Registers章节的描述;有关AXI总线协议接口描述自行参照ARM官方文档IHI 0022D:AMBA AXI andACE Protocol Specification。

那么生成DMAMOV机器码的函数如下所示:

INLINE int XDmaPs_Instr_DMAMOV(char *DmaProg, unsigned Rd, u32 Imm)

{

    /*

     * DMAMOV encoding

     * 15 4 3 2 1 10 ... 8 7 6 5 4 3 2 1 0

     *  0 0 00 0 |rd[2:0]|1 0 1 1 1 1 0 0

     *

     * 47 ... 16

     *  imm[32:0]

     *

     * rd: b000 for SAR, b001 CCR, b010 DAR

     */

    *DmaProg= 0xBC;

    *(DmaProg+ 1) = Rd & 0x7;

    XDmaPs_Memcpy4(DmaProg+ 2, (char *)&Imm);

    return 6;

}

  那么,看下面一段汇编代码,代码完成160K数据搬运,数据源和目的都是DDR:

   DMAMOV  SAR  #SrcAddr

 DMAMOV DAR   #DstAddr

 DMAMOV CCR   #CCRn

 DMALP lc1 outerloop

      DMALP lc0 innerloop

          DMALD

          DMAST

      DMALPEND lc0

      DMALD

      DMAST

 DMALPEND lc1

 DMASEV

  DMAEND

 DMAC提供了两个计数器lc0和lc1,都是8bit的,因此每层循环的次数都不能超过256次。指令执行到DMASEV时控制器发出完成中断,执行过程中遇到任何错误或异常均发出Abrot中断。

     在本例中SrcAddr=0x10000000,DstAddr = 0x11000000,数据长度为160KB,CCRn的参数如下:

   CCRn.EndianSwapSize = 0x00;

    CCRn.DstCacheCtrl   =0x00;

    CCRn.DstProtCtrl   = 0x00;

    CCRn.DstBurstLen   = 0x07;

    CCRn.DstBurstSize  = 0x03;

    CCRn.DstInc          =0x01;

    CCRn.SrcCacheCtrl  = 0x00;

    CCRn.SrcProtCtrl   = 0x00;

    CCRn.SrcBurstLen   = 0x07;

    CCRn.SrcBurstSize  = 0x03;

CCRn.SrcInc          =0x01;

那么通过库函数XDmaPs_BuildDmaProg生成的可执行机器码就是:

[Addr]Code

[0] BC

[1] 0

[2] 0

[3] 0

[4] 0

[5] 10

[6] BC

[7] 2

[8] 0

[9] 0

[A] 0

[B] 11

[C] BC

[D] 1

[E] 77

[F] C0

[10] 1D

[11] 0

[12] 22

[13] 9

[14] 20

[15] FF

[16] 4

[17] 8

[18] 38

[19] 2

[1A] 3C

[1B] 6

[1C] 34

[1D] 0

[1E] 0

代码正常执行完成后产生SEV中断,需在中断服务程序中清除当前的中断状态。

2.3 启动或停止DMA传输

在DMA控制器的诸多寄存器中,绝大部分仅是反映DMA引擎的当前执行情况,用于实施跟踪执行状态。至关重要的寄存器DBGSTATUS、DBGCMD、DBGINST0、DBGINST1用于控制DMA的开始、中断和终止。也就是DMA指令中的DMAGO、DMASEV和DMAKILL,由于APB接口和DMA引擎间的异步关系,指令执行存在一定的延时,在下发下条指令前一定要通过读取DBGSTATUS的值轮询上次指令是否执行完毕。

2.4 异常处理

遇到DMA Abrot中断事件,都必须下发DMAKILL指令终止当前线程。

3 总结

ARM PL330 DMA控制器乍看来似乎难以理解,实际上它是把DMAC当成一个协处理来看待,有自己的指令执行引擎。用户组织好执行机器码后存到内存,用户通过APB接口发出DMAGO指令告诉DMAC的指令执行引擎执行代码的首地址并启动DMA指令引擎直到指令执行到DMAEND停止。

 

备注:比如将SDK安装到了D:\Vivado\SDK目录下,版本为2015.2,那么DMAC参考示例代码就存放在“D:\Vivado\SDK\2015.2\data\embeddedsw\

XilinxProcessorIPLib\drivers\dmaps_v2_1\examples”路径下。

你可能感兴趣的:(xilinx随笔)