欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

DMA原理解析

程序员文章站 2024-02-22 10:09:04
...

DMA概念

DMA(Direct Memory Access,直接内存存取) ,DMA 传输将数据从一个地址空间复制到另外一个地址空间。采用CPU来初始化这个传输动作,但是传输动作本身是由 DMA 控制器来实行和完成,不需要占用CPU。

DMA控制器(以2440为例)

2440芯片手册第8章为DMA控制器。
2440的DMA控制器支持4个通道

请求源:
DMA原理解析
上图是2440中DMA控制器支持的请求源。

基本时序
DMA原理解析
在请求信号有效之后,经过2个周期DACK信号有效,再经过3个周期,DMA控制器才可获得总线的控制权,开始读写操作。

工作模式
Demond模式:
如果DMA完成一次请求后如果Request仍然有效,那么DMA就认为这是下一次DMA请求,并立即开始下一次的传输。

Handshake模式:
DMA完成一次请求后等待Request信号无效,如果Request 无效,DMA会无效ACK两个时钟周期,再等待下一次Request。

6410芯片的DMA控制器在芯片手册的第11章。

DMA程序设计(2440芯片)

char *buf = "Hello World!";

#define DISRC0     (*(volatile unsigned long*)0x4B000000)
#define DISRCC0    (*(volatile unsigned long*)0x4B000004)
#define DIDST0     (*(volatile unsigned long*)0x4B000008)
#define DIDSTC0    (*(volatile unsigned long*)0x4B00000C)
#define DCON0      (*(volatile unsigned long*)0x4B000010)
#define DMASKTRIG0 (*(volatile unsigned long*)0x4B000020)

#define UTXH0 (volatile unsigned long*)0x50000020

void dma_init()
{   
    //初始化源地址
    DISRC0 = (unsigned int)buf; //向寄存器中填写源地址  
    DISRCC0 = (0<<1)| (0<<0);   //内存使用的是AHB总线,源地址需要增长

    //初始化目的地址
    DIDST0 = UTXH0;             //向串口中传送数据
    DIDSTC0 = (1<<1)| (1<<0);   //串口使用的是APB总线,目的地址总是一个寄存器不增长
    DCON0 = (1<<24)| (1<<23)| (1<<22)| (12<<0); 
    //控制寄存器,选择DMA源,硬件,是否多次发送,数据个数
}

void dma_start()
{
    DMASKTRIG0 = (1<<1);//启动传输
}

DMA程序设计(6410芯片)

/*
S3C6410中DMA操作步骤:
1、决定使用安全DMAC(SDMAC)还是通用DMAC(DMAC);
2、开启DMAC控制,设置DMAC_Configuration寄存器;
3、清除传输结束中断寄存器和错误中断寄存器;
4、选择合适的优先级通道;
5、设置通道的源数据地址和目的数据地址(设置DMACC_SrcAddr和DMACC_DestAddr);
6、设置通道控制寄存器0(设置DMACC_Control0);
7、设置通道控制寄存器1,(传输大小,设置DMACC_Control1);
8、设置通道配置寄存器;(设置DMACC_Configuration)
9、使能相应通道(设置DMACC_Configuratoin);
*/

#define SDMA_SEL            (*((volatile unsigned long *)0x7E00F110))
#define DMACIntTCClear      (*((volatile unsigned long *)0x7DB00008))
#define DMACIntErrClr       (*((volatile unsigned long *)0x7DB00010))
#define DMACConfiguration   (*((volatile unsigned long *)0x7DB00030))
#define DMACSync            (*((volatile unsigned long *)0x7DB00034))
#define DMACC0SrcAddr       (*((volatile unsigned long *)0x7DB00100))
#define DMACC0DestAddr      (*((volatile unsigned long *)0x7DB00104))
#define DMACC0Control0      (*((volatile unsigned long *)0x7DB0010c))
#define DMACC0Control1      (*((volatile unsigned long *)0x7DB00110))
#define DMACC0Configuration (*((volatile unsigned long *)0x7DB00114))

#define UTXH0           (volatile unsigned long *)0x7F005020

char src[100] = "\n\rHello World-> This is a test!\n\r";

void dma_init()
{
    //DMA控制器的选择(SDMAC0)
    SDMA_SEL = 0;

    //DMA控制器使能
    DMACConfiguration = 1;

    //初始化源地址
    DMACC0SrcAddr = (unsigned int)src;

    //初始化目的地址
    DMACC0DestAddr = (unsigned int)UTXH0;

    //对控制寄存器进行配置
    /*
    源地址自增
    目的地址固定、
    目标主机选择AHB主机2
    源主机选择AHB主机1
    */
    DMACC0Control0 =(1<<25) | (1 << 26)| (1<<31);
    DMACC0Control1 = 0x64;     //传输的大小

    /*
    流控制和传输类型:MTP 为 001
    目标外设:DMA_UART0_1,源外设:DMA_MEM
    通道有效: 1
    */
    DMACC0Configuration = (1<<6) | (1<<11) | (1<<14) | (1<<15);             
}

void dma_start()
{
    //开启channel0 DMA
    DMACC0Configuration  = 1;   
}
相关标签: DMA