## 一、使用DMA的優點及DMA支持的請求源
1、DMA優點是其進行數據傳輸時不需要CPU的干涉,可以大大提高CPU的工作效率。
2、DMA在大容量數據傳輸中非常重要,比如圖像數據傳輸,SD卡數據傳輸,USB數據傳輸等。
3、S3C2440有四個DMA,每個DMA支持的工作方式基本相同,但支持的DMA請求源可能略有不同。如下為四個DMA通道分別支持的DMA請求源:
Ch0:??? nXDREQ0,? ? ? UART0,????? SDI,??????????? Timer,???????? USB EP1
Ch1:??? nXDREQ1,? ? ? UART1,????? I2SSDI,?????? SPI0,????????? USB EP2
Ch2:??? I2SSDO,????????? I2SSDI,????? SDI,??????????? Timer,???????? USB EP3
Ch3:??? UART1,?????????? SDI,??????????? SPI1,????????? Timer, ??????? USB EP4
那么怎么使用DMA呢,S3C2440內部集成了DMA控制器,我們只需要簡單的配置一下寄存器就可以實現DMA的傳輸了。
## 二、DMA配置步驟及要點: (參考[點擊打開鏈接](http://blog.csdn.net/cybertan/article/details/4697516))
1.數據從哪里來,到哪里去?
使用DMA首先我們要知道數據的流向,DISRCx寄存器是DMA初始源寄存器,存放了數據的源地址。DIDSTx是DMA的初始目的寄存器,存放數據的目的地址。
2.數據走的什么總線?地址是否是固定的?
我們還要知道源與目的數據存儲設備在什么總線上(AHB系統總線,一般是高速的比如內存,APB外圍總線,低速的比如SD,UART;具體走什么總線可以在datasheet上查到);以及數據傳輸結束以后起始地址還原到發送前的起始地址呢,還是在現在的末尾+1做為新的起始地址。這些設置在DISRCCx與DIDSTCx兩個寄存器里面配置。
3.數據以什么方式傳輸?源與目的是什么設備?要不要自動重載?
需要確定數據的傳輸方式有請求還是握手,根據上面的總線確定與什么時鐘同步(HCLK,PCLK),是單元傳輸還是突發傳輸,是以字節傳輸還是字傳輸,是否重載。是單服務(只發送一次)還是多服務(不停循環發送),以及數據的傳送大小。選擇源與目的設備。最后還要確定中斷是不是傳輸結束發生(CURR_TC記數是不是0)。這些都在DCONx中設置。
4.怎么開始傳輸DMA和停止DMA,這些在DMASKTRIG中設置。
## 三、操作實例(以DMA傳輸一段字符到控制臺為例)
~~~
/*
*版權所有(C)2015,ZJU
*
*文件名稱:dma.c
*內容摘要:關于DMA的配置
*其它說明:開發板型號: TX2440
* 注意Uart_Init中,設置UCON0寄存器時TX的方式要設置為DMA模式
*當前版本:V1.0
*作 者:Frank
*完成日期:2015.12.19
*
*/
#define DISRC0 (*(volatile unsigned long *)0x4B000000) //DMA 0 initial source register
#define DISRCC0 (*(volatile unsigned long *)0x4B000004) //DMA 0 initial source control register
#define DIDST0 (*(volatile unsigned long *)0x4B000008) //DMA 0 initial destination register
#define DIDSTC0 (*(volatile unsigned long *)0x4B00000C) //DMA 0 initial destination control register
#define DCON0 (*(volatile unsigned long *)0x4B000010) //DMA 0 control register
#define DMASKTRIG0 (*(volatile unsigned long *)0x4B000020) //DMA 0 mask trigger register
#define UTXH0 (volatile unsigned long *)0x50000020 //UART channel 0 transmit buffer register
char *buf = "Hello World!";
/*******************************************************************
*函數名稱:Dma_Init()
*功能描述:DMA初始化函數
*其他說明:
*創建日期:2015.12.19
*******************************************************************/
void Dma_Init(void)
{
//初始化源地址
DISRC0 = (unsigned int)buf;
DISRCC0 = (0 << 1) | (0 << 0); //DMA起始地址在AHB總線(Memory), 地址遞增
//初始化目的地址
DIDST0 = (unsigned int)UTXH0; //目的地址為 UTXH0
DIDSTC0 = (1 << 1) | (1 << 0); /*DMA目的地址在APB總線(UART0), 地址不
變(因為要發送的字符總是傳到UTXH0)*/
DCON0 = (1 << 24) | (1 << 23) | (1 << 22) | (12 << 0); //設置DMA請求源及工作模式
}
/*******************************************************************
*函數名稱:Dma_Start()
*功能描述:DMA啟動函數
*其他說明:
*創建日期:2015.12.19
*******************************************************************/
void Dma_Start(void)
{
DMASKTRIG0 = (1 << 1); //啟動DMA通道
}
~~~
需要注意的幾點是:
①沒有使用DMA中斷;
②使用的是Demand模式,實測發現Handshake模式也是可以的(推薦);
③在Uart_Init中,要將UCON0寄存器設置為發送采用DMA模式(開始就是沒有設置,所以一直無法看到實驗現象);
④源地址和目的地址要使用unsigned int強制轉換為整數放進寄存器中;