ARM PL330 DMA控制器开发

一、DMA介绍

DMA作为一种CPU与外设传输数据的技术,现在广泛用于各种计算机架构中,它最大的优点就是无需CPU干涉下,完成数据从内存到外设的传递。本文讲解一下S5PC100中的DMA控制器的操作方法。文中例举的代码都是在FS_S5PC100平台上经过验证的。在华清远见的FS_S5PC100平台上通过PL330 DMA控制器实现了内存到内存、内存到串口、串口到串口等多种DMA传输方式。
首先简单介绍下什么是DMAC,DMAC 是一个自适应先进的微控制器总线体系的控制器,它由ARM公司设计并基于PrimeCell技术标准,DMAC提供了一个AXI接口用来执行DMA传输,以及两个APB接口用来控制这个操作,DMAC在安全模式技术下用一个APB接口执行TrustZone技术,其他操作则在非安全模式下执行。DMAC包括了一个小型的指令集,用来提供一些灵活便捷的操作,为了缩小内存需求,DMAC则使用了变长指令。
不同于ARM11以及以前系列的芯片,S5PC100使用了基于PrimeCell技术标准的PL330(DMA控制器核心)有了很大的变化,从编程方式上看,它提供了灵活的指令集,使得你有更多的组合方式用来操作DMA,从硬件上看,它实现了硬件上的多线程管理,一次编写代码即可让它正常的完成所需的工作,因此这个DMA的开发是有一定困难的。

二、PL330简述

      DMAC包含了一个执行指令的模块,并且控制了数据的传输,DMAC通过AXI接口来存取这些存储在了内存中的指令,DMAC还可以将一些临时的指令存放在Cache中,我们能够配置行宽度以及深度。
当然,DMAC的8个通道都是可配置的,且每个都可支持单个并发线程的操作,除此之外,还有一个管理线程专门用来初始化DMA通道的线程。它是用来确保每个线程都在正常工作,它使用了round-robin来处理当选择执行下一个活动期的DMA通道。
DMAC使用了变长指令集,范围在1到6字节之间,并还为每个通道提供了单独的PC寄存器,当一个线程需要执行一条指令时,将先从Cache中搜索,如果匹配上则立刻供给数据,另外,线程停止的话,DMAC将使用AXI接口来执行一次Cache线填充。
当一个DMA通道线程执行一次load/store指令,DMAC将添加指令到有关的读队列和写队列中,DMAC使用这些队列作为一个指令存储区,它用来优先执行存储在其中的指令,DMAC还有包含了一个MFIFO数据缓存区,它用来存储DMA传输中读/写的数据。

DMAC还提供多个中断输出,在微处理器的不干扰下,外设的request接口还有内存到外设和外设到内存的传输能力,双APB接口支持安全以及非安全两种模式,编程时,可通过APB接口来访问状态寄存器和直接执行DMAC指令。



 

图1 S5PC100中的DMA模块图

 

图2 DMAC模块图

从图中可以看出,APB从机接口下有安全模式以及非安全模式两种接口,它们分别能在不同的模式下执行不同需求的功能,当然寄存器是彼此独立的,也就是各自有自己的一套寄存器,另外,我们还能看到READ/WRITE指令队列,当DMAC从指令中取到后则先存放在相应的队列中等待执行,MFIFO则是前文提到的数据缓冲区域,这是一个可配置大小的缓存区,当执行读指令后,DMAC从源地址中获得数据后,将其先存放在MFIFO中,当满足事先设定的触发写条件时,DMAC则会从MFIFO中写数据到目的地址。

三PL330详解

3.1 PL330指令集

1、DMAMOV
指令格式: 
这是一条数据转移指令,它可以移动一个立即数到以下3种类型的寄存器中。
功能描述:
<Destination_register>
(1)  源地址寄存器
该寄存器提供了DMA通道的数据源的地址,DMAC从该地址取得数据,每个通道都有自己的数据源地址寄存器,因此需要单独配置。
下图是每个通道的源地址寄存器列表:
该寄存器提供了DMA通道的数据源的地址,DMAC从该地址取得数据,每个通道都有自己的数据源地址寄存器,因此需要单独配置。
下图是每个通道的源地址寄存器列表:
(2)  目标地址寄存器
该寄存器提供了DMA的目标数据存放地址,和数据源地址寄存器是相互对应的。
该寄存器提供了DMA的目标数据存放地址,和数据源地址寄存器是相互对应的。
(3) 通道控制寄存器
该寄存器可以控制DMA 在AXI中的传输,并且该寄存器记录了一些关于目标与源寄存器的基本配置。下图是该寄存器的位分配:
<32bit_immediate>
  该32位立即数可被传到指定的寄存器中。
2、DMALD
这是一条DMAC装载指令,它可以从源数据地址中读取数序到MFIFO中,如果src_int位被设置,则DMAC会自动增加源地址的值。
指令格式:
功能描述:
[S]    如果S位被指定,则bs位被置0,且x转换为0。Request_flag将被下列情况所影响:
Request_flag=Single,,DMAC将执行DMA装载。
Request_flag=Burst ,DMAC将执行控制另DMANOP。
  [B]    如果B位被指定,则bs会置0,且x转换为1,Request_flag将被下列情况所影响:
Request_flag=Single,,DMAC将执行控制另DMANOP。    
Request_flag=Burst , DMAC将执行DMA装载
注意 :如果不指定S,B位的话,则DMAC默认是执行DMA装载的。

3、DMAST
该指令与DMALD相互对应,它是一条DMA存储指令,是将MFIFO中的数据转移到目的地址中。目的地址是由目的地址寄存器所指定的,如果dst_inc被置位,则DMAC会自动增加目的地址的值。
指令格式:
功能描述:
[S]    如果S位被指定,则bs位被置0,且x转换为1。Request_flag将被下列情况所影响:
  Request_flag=Single,DMAC执行单个DMA存储。
  Request_flag=Burst ,DMAC执行空指令。
[B]    如果B位被指定,则bs被设置为1,且x转位1,Request_flag将被下列情况所影响:
  Request_flag=Single, DMAC执行空指令。
  Request_flag=Burst , DMAC将执行DMA存储。
4、DMARMB
读内存栅栏指令,下图是该指令的译码图:
指令格式:

功能描述:
该指令可以使得当前所有读处理全部被强制取消。

5、DMAWMB
写内存栅栏指令,下图是该指令的译码图:
指令格式:
功能描述:
该指令可以使得的那个钱写处理全部被强制取消。

6、DMALP
指令格式: DMALP  <loop_iterations>
   <loop_iterations>
      这是一个8位表示的循环次数。
lc设置为0时,DMAC每写一次值,loop_iterations则减少1,直到循环计数为0结束。
lc设置为1时,DMAC每写一次值,loop_iterations则减少1,直到循环计数为1结束。
    功能描述:  
 循环操作时,将一个指定的8bit数字填入循环计数寄存器,该指令用来指定某个指令段的开始位置,需要DMALPEND指定该指令段的结束位置,一旦指定后,DMAC会循环执行介于DMALP于DMALPEND之间的指令,直到循环次数为0结束。

7、DMALPEND
指令格式:DMALPEND[S|B]
[S]    如果S位被指定,则bs位被置0,且x转换为1。Request_flag将被下列情况所影响:
  Request_flag=Single,DMAC则执行循环。
   Request_flag=Burst ,DMAC执行空指令。
[B]    如果B位被指定,则bs被设置为1,且x转位1,Request_flag将被下列情况所影响:
  Request_flag=Single, DMAC执行空指令。
    Request_flag=Burst , DMAC将执行循环。
功能描述:
    该指令每次执行一遍以后查看循环计数寄存器的值:
如果是 0,DMAC则执行DMANOP指令。
如果不为0,DMAC则更新一次循环计数器的值,并跳转到循环指令段的第一条指令执
8、DMASEV
指令格式:DMASEV <event_num>
<event_num>
5位立即数。
功能描述:
使用该命令可以产生一个事件信号。可以有以下两种模式:
产生一个事件<event_num>。
产生一个中断信号,irq<event_num>。

9、DMAEND
指令格式:DMAEND
功能描述:
该指令用来通知DMAC结束一次操作集合,换句话说就是,告诉DMAC某个线程停止一切的动作,使其为停止态,这时DMAC会刷新MFIFO,并且清空所有相关的Cache。

3.2 其它相关寄存器详解

1、DBGINST0
此寄存器可控制调试指令,通道,DMAC线程信息,下图是寄存器的详细解释:
2、DBGINST1
该寄存器控制内存中设置的指令段首地址,也就是DMAC第一次取指令的地址,
下图是该寄存器的解释:
3、DBGCMD
该寄存器控制调试命令的执行,通过配置它,可以控制DMAC去执行一些指定的工作。
该寄存器的详细解释如下图所示:


四、S5PC100 PL330测试例子

由于PL330学习起来略显烦琐,因此建议在理解代码的基础上做实验,这样才能对DMA的学习有一定的深入。篇幅有限这里只给出核心的代码,若读者想参考完整源代码,请去华清远见官方论坛上下载。

下面的代码目标要实现内存间的数据拷贝。对于S5PC100,有3DMA控制器。要实现内存间的DMA访问,需要使用DMA_mem

如下图所示为DMAC控制流程

DMAC控制流程

配合上面的流程图,可以编写代码如下。

1)相关的宏定义。

#define MAX 100

#define Inp(addr)            (*(volatileunsigned int *)(addr))

#define Outp(addr, data)     (*(volatileunsigned int *)(addr) = (data))

 

extern void printf(const char *fmt, ...);

void int_dma();

volatile char sour[32] = "012345678901234567890123456789\n";

volatile char dest[32] = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n"; 

//最终实现将32个字节从sour的数据传输到dest

2)设置SARCCRDAR寄存器。

//main函数开始

uart0_init();

volatile char instr_seq[MAX];

int size = 0, x;

int loopstart, loopnum = 2;  //每个循环传输16个字节,传输2

unsigned int source, destination,start, temp;

source = (unsigned int)sour;

destination = (unsigned int)dest;

start = (unsigned int)instr_seq;   //记录DMA指令的首地址

/*DMAMOV SAR0*/

instr_seq[size + 0] =(char)(0xbc);

instr_seq[size + 1] = (char)(0x0);

instr_seq[size + 2] =(char)((source>>0) & 0xff);  //设置数据源地址

instr_seq[size + 3] =(char)((source>>8) & 0xff);

instr_seq[size + 4] =(char)((source>>16) & 0xff);

instr_seq[size + 5] =(char)((source>>24) & 0xff);

size = 6;

/*DMAMOV DAR0*/

instr_seq[size + 0] = (char)(0xbc);

instr_seq[size + 1] = (char)(0x2);

instr_seq[size + 2] =(char)((destination>>0) & 0xff); //设置数据目标地址

instr_seq[size + 3] =(char)((destination>>8) & 0xff);

instr_seq[size + 4] =(char)((destination>>16) & 0xff);

instr_seq[size + 5] = (char)((destination>>24)& 0xff);

size += 6;

/*DMAMOV CC0. burst_size 8byte,burst_len 2*/ 

instr_seq[size + 0] =(char)(0xbc);

instr_seq[size + 1] = (char)(0x1);

//设置数据传输规则,每个循环传输burst_size* burst_len、原和目标地址变化规则、burst操作等

instr_seq[size + 2] = (char)(0x17);

instr_seq[size + 3] =(char)(0xc0);

instr_seq[size + 4] = (char)(0x5);

instr_seq[size + 5] = (char)(0x0);

size += 6;

3)设置指令段的起始地址及执行第一次数据装载并输出FIFO

/*DMALP LC0*/

instr_seq[size + 0] =(char)(0x20);

instr_seq[size + 1] =(char)(loopnum - 1);// 记录循环的次数

size += 2;

loopstart = size;

/*DMALD*/

instr_seq[size + 0] =(char)(0x04);   //从源读数据

size += 1;

/*DMARMB*/

instr_seq[size + 0] =(char)(0x12);

size += 1;

/*DMAST*/

instr_seq[size + 0] =(char)(0x08);  //写数据到目标地址

size += 1;

/*DMAWMB*/

instr_seq[size + 0] =(char)(0x13);

size += 1;

4)产生中断,并延时一段时间。

/*可以在DMA指令执行过程中做延时。此处可以利用延时保证DMA传输完成后再停止DMA*/

/*DMALP LC0*/

instr_seq[size + 0] = (char)(0x20);

instr_seq[size + 1] = (char)(250);   //循环次数

size += 2;

loopstart = size;

/*DMANOP*/

instr_seq[size + 0] = (char)(0x18);   //DMANOP空指令,可以实现延时

size += 1;

/*DMALPEND 0*/

instr_seq[size + 0] = (char)(0x38);

instr_seq[size + 1] = (char)(size - loopstart);

size += 2;

/*DMASEV*/

instr_seq[size + 0] = (char)(0x34);

instr_seq[size + 1] = (char)(1<<3);  //通过DMA通道1发出中断申请,也可以选择其它的通道

size += 2;

#endif

5)结束DMAC控制。

/*DMAEND*/

instr_seq[size + 0] = (char)(0x0);

size += 1;

6)开始DMAC控制,设置相应的中断处理,并进行测试结果。

VIC0VECADDR18 = (unsigned int)int_dma;//DMA_mem的处理函数

INTERRUPT.VIC0INTENABLE |= 1<<18;        //使能中断控制器对应的中断位

Outp(0xE8100000+0x20, 0x2); //使能控制器的1中断通道,此处可以选择其它的通道,要和DMASEV对应

/*DMAGO*/

do{

      x = Inp(0xE8100D00);//检测DMA状态,确认可以操作

} while ((x&0x1)==0x1);

Outp(0xE8100D00+0x8,(0<<24)|(0xa0<<16)|(0<<8)|(0<<0));//DBGINST0  通道1

Outp(0xE8100D00+0xC, start);//DBGINST1

Outp(0xE8100D00+0x4, 0);//DBGCMD  执行DBGINST01中的DMAGO指令,start为开始地址

while(1);

//main函数结束

7ISR函数的实现如下。

void do_irq()

{

printf("in do_irq\n");

((void (*)(void))VIC0ADDRESS)();

}

/*ISR*/

void int_dma()

{

VIC0ADDRESS = 0;

Outp(0xE8100000+0x2C, 0x2);//清处DMA中断挂起位,因为上面选择的是通道1,所以清楚对应的位

printf("DMA Ending!\n");

printf("sour = %s", sour);

printf("dest = %s", dest);

}

实验调试过程与结果:

1)将程序编译后生成.bin文件,打开终端使用ubootdnw命令通过USB线将.bin文件下载到0x20008000这个地址,接着使用go命令去执行测试程序。

2)可以看到下图所示的测试结果,如图所示。

五、小节

本文从PL330出发,介绍了基本的S5PC100DMA控制器的操作方式和编程模型,旨在将最新的DMA控制技术以最简单的方式呈现。笔者还实现了串口控制器的收发之间使用DMA传输的例程。读者如果感兴趣可以在华清远见研发中心关于FS_S5PC100平台的论坛上下载。硬件控制器关联的DMA和内存间的DMA控制差别比较大的是DMA每次传输依赖控制器发出申请,DMA需要等待到一次申请后才能完成一次传输。而内存间的DMA可以由程序主动发起。






  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Zynq PL-PS DMA是指Xilinx开发的Zynq系列可编程逻辑和处理系统之间的数据传输机制。Zynq是一种集成了ARM处理系统和可编程逻辑(PL)的SoC(系统级片上系统)芯片。 在Zynq芯片中,处理系统(PS)是由ARM Cortex-A9处理器组成的,用于运行操作系统和处理高级任务,而可编程逻辑(PL)是由可配置的逻辑单元组成的,用于实现硬件加速和高性能计算。而PL-PS DMA是用于在两者之间进行高速数据传输的重要组件。 DMA(Direct Memory Access)是一种数据传输技术,允许数据在内存和外设之间直接进行传输,而不需要CPU的干预。在Zynq PL-PS DMA中,DMA控制器位于PS中,用于管理数据在PL和PS之间的传输。 Zynq PL-PS DMA具有以下特点:高性能、低延迟、高带宽。通过使用DMA,PL可以直接从内存中读取数据,不需要CPU的介入,从而提高了数据传输效率和系统性能。 在使用Zynq PL-PS DMA时,首先需要在PL和PS之间建立合适的数据通道。然后,通过编程配置DMA控制器的寄存器,设置数据传输的起始地址、传输长度、传输方向等参数。最后,启动DMA传输过程,并通过中断或轮询方式检查传输状态,以确保数据正确传输。 总之,Zynq PL-PS DMA是一种用于实现Zynq系列芯片中可编程逻辑和处理系统之间高速数据传输的技术,通过提供高性能、低延迟和高带宽的数据传输通道,提高了系统的数据传输效率和整体性能。 ### 回答2: Zynq PL PS DMA是指Zynq系列中的可编程逻辑(PL),处理系统(PS)和直接内存访问(DMA)的一种配置。 Zynq系列芯片是赛灵思公司针对嵌入式系统设计开发的产品。它将传统的处理器系统和可编程逻辑(FPGA)集成到一个芯片中,为嵌入式系统设计带来更高的灵活性和性能。 PL是可编程的逻辑部分,其中包含了可编程逻辑电路,如FPGA。PL可以用于实现各种不同的功能,例如数字信号处理、图像处理、乘法器等。PL可以被重新配置和优化,以满足不同应用的需求。 PS是指处理系统,它是Zynq芯片中的ARM Cortex-A9核心。PS负责运行嵌入式操作系统(如Linux),管理系统的整体运行和资源分配。PS还可以执行一些实时任务,如控制外部设备等。 DMA是指直接内存访问。DMA可以在处理器不参与的情况下,通过直接从外部设备读取或写入数据到内存中,实现高速的数据传输。DMA可以显著提高数据传输的效率,减少了处理器对数据传输的负担。 Zynq PL PS DMA的配置可以充分发挥Zynq芯片的优势。PL的灵活性可以满足各种不同的应用需求,而PS的处理能力可以支持操作系统的运行和系统管理。DMA的使用可以加快数据传输速度,提高系统的响应速度。 总之,Zynq PL PS DMA的配置充分利用了可编程逻辑、处理系统和直接内存访问的优势,为嵌入式系统设计提供了更高的灵活性、性能和效率。 ### 回答3: Zynq是赛灵思公司(Xilinx)推出的一种嵌入式平台,它将硬件逻辑(PL)与处理系统(PS)集成在一个芯片上。PL是FPGA实现的可编程逻辑部分,而PS则是ARM处理器系统。 DMA(Direct Memory Access)是一种数据传输方式,允许外部设备直接访问系统内存,无需CPU的干预。在Zynq平台中,PL和PS都可以使用DMA进行数据传输。 在PL中使用DMA,我们可以通过定制的硬件逻辑实现高速、低延迟的数据传输。DMA可以从外部设备接收数据,将其存储在PL的内存中,并通过总线接口将数据传输到PS的内存中。这种方式可以减少数据传输的CPU开销,提高系统的性能。 在PS中使用DMA,可以实现高效的数据传输与处理。例如,通过使用DMA,可以将大数据块从外部设备传输到PS的内存中,然后再由CPU进行处理。这样可以提高数据处理的效率,减少CPU的负担。 总之,Zynq平台中的PL和PS均可使用DMA进行数据传输,通过利用DMA可以提高数据传输的效率,降低系统的延迟,从而提升整体性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值