DMA 简介
DMA (Direct Memory Access ,直接内存存取)是比一种效率比较高的系统内部的一种数据传输方式,在系统运行时经常需要从一个地址空间拷贝大量数据到另一个地址空间,每次拷贝都需要占用cpu大量的时间,不能够去执行其他的工作,而DMA控制器就是为了解决这个问题,当需要拷贝数据时,cpu只要告诉DMA控制器源地址,目标地址,拷贝大小这些参数后就可以去做其他事情了,DMA会接管相关总线,去完成数据拷贝的工作。当DMA完成传输工作后,会通知CPU来进行处理。这样就大大提高了CPU的工作效率。
S3C6410的DMAC
S3C6410 包括4个DMA控制器,每个DMA控制器有8个传输通道,DMA控制器的每个通道都能够无限制的在AXI SYSTEM 总线和AXI PERIPHERAL 总线之间通过AHBtoAXI 桥路传输数据。换句话说,每个通道能够应用在下面的场合:
- 1 源和目标都在SYSTEM总线上
- 2 源在SYSTEM总线但目标在PERIPHREAL 总线
- 3 源在PERIPHREAL总线但是目标在SYSTEM总线
- 4 源和目标都在PERIPHREAL总线上
DMA的主要优势就是在没有CPU的干涉下也能进行数据传输,DMA传输操作可以被软件或硬件驱动,或者是内部外设的请求,或者是外部引脚的请求。
一些特性:
- 4个 DMA 控制器,每个含8个通道,每个通道支持一个单向传输
- 每个DMA控制器提供16个外围DMA请求
- 每个外设能够请求一个突发模式或单次模式的DMA请求,突发模式大小在DMAC寄存器设置
- 支持内存到内存,内存到外设,外设到内存,外设到外设四种请求
- 使用链表支持分散或者聚集的DMA请求
- 硬件DMA优先级区分,每个通道都有固定的优先级,从Chanal 0到Chanal 7 优先级依次降低
- 源或目标源地址自动递增或非递增
- 可编程的突发模式的数据大小,通常为FIFO的一般
- 每个通道4个字的FIFO
- 支持8,16,32bit 宽度传输
- 分离的DMA 错误和DMA 总数中断请求,一个中断能够通过DMA 错误或者DMA count达到0 产生(通常意味着传输完成)
- 中断屏蔽
- 原始中断状态
S3C6410 支持64个DMA 源,四个DMA控制器分为安全DMA控制器和通用DMA控制器两种,通过系统控制模块中的SDMA_SEL寄存器进行选择,64个DMA源如下表:
source
使能一个DMA通道的步骤
- 1、决定使用安全DMA控制器还是通用DMA控制器,若要使用通用的DMA控制器,关闭系统控制器的安全DMA控制寄存器(SDMA_SEL),复位值是SDMAC
- 2、选择一个符合优先级要求的空闲的DMA通道 Chanal 0 到Chanal 7 优先级从高到低
- 3、清空通道中断挂起寄存器和错误寄存器 DMACIntTCClr 和 DMACIntErrClr
- 4、写源地址到源地址寄存器 DMACCxSrcAddr
- 5、写目的地址到目标地址寄存器 DMACCxDestAddr
- 6、写下次链接地址到DMACCxLLI寄存器,如果传输包含一个单数据包,则必须写入这个寄存器
- 7、编程DMACCxControl 寄存器填写控制信息
- 8、编程通道配置信息到DMACCxConfiguration 寄存器,如果使能位被设置,则DMA通道会自动使能
寄存器描述
四个DMA控制器被命名为DMAC0,DMAC1,SDMAC0,SDMAC1,寄存器基地址分别为0x7500_0000,0x7510_0000,0x7DB0_0000和0x7DC0_0000。
reg
reg
reg
-
中断状态寄存器
中断状态寄存器 DMACIntStatus 是一个只读的用来指示屏蔽后的中断状态的寄存器,某位为高表示一个特定的DMA通道中断请求是激活的,请求能够被错误或终端计数中断请求产生。
-
终端计数中断状态寄存器
-
终端计数请求清零寄存器
-
错误中断状态寄存器
-
错误中断状态清零
-
原始终端计数中断寄存器
-
原始错误中断状态寄存器
-
通道使能状态寄存器
-
Burst请求寄存器
-
Single请求寄存器
-
DMACConfiguration 使能寄存器
-
同步寄存器
-
源地址寄存器
-
目标地址寄存器
-
链接表寄存器
-
通道控制寄存器0
-
通道控制寄存器1
-
通道配置寄存器
-
通道配置寄存器-额外
简单代码分析
/*
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控制器的时钟不相同, 要使能"同步逻辑" */
DMACSync = 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;
}
网友评论