本文共 2549 字,大约阅读时间需要 8 分钟。
通过串口发送数据的实质是:内存保存着字符串,cpu将字符一一写入串口寄存器。在这个过程中,cpu被占用着,导致效率低;若有其它硬件可以代替cpu完成该工作,则cpu可以被释放出来。该硬件为DMA控制器,该机制称为DMA。cpu将内存源地址和串口的目的地址告诉DMA控制器,DMA控制器就能从源地址取出数据放到目的地址。
S3C2440支持4通道DMA,请求源与对应的DMA通道关系为:
时序图为:
nXDREQ请求生效并经过2CLK周期同步后,nXDACK响应并开始生效,但至少还要经过3CLK的周期延迟,DMA控制器才可获得总线的控制权,并开始数据传输。
DMA工作模式有两种,
Demond模式:如果DMA完成一次请求后如果Request仍然有效,那么DMA就认为这是下一次DMA请求,并立即开始下一次的传输 Handshake模式:DMA完成一次请求后等待Request信号无效,如果Request无效,DMA会无效ACK两个时钟周期,再等待下一次Request。S3C6410有4个DMA控制器,每个控制器支持8个转换通道,支持64个DMA请求源。4个DMA控制器分别为DMA0,SDMA0,DMA1,SDMA1,默认使用SDMA。
S5PV210支持两种DMA访问类型:① Memory-to-Memory内存到内存方式②Peripheral-to-memory内存到外设方式。相应的,DMA控制器也分为两类,共有3个DMA控制器
S3C2440DMA控制器初始化①初始化源地址;②初始化目的地址;③设置配置寄存器;④开启DMA。
①初始化源地址
存放源地址的寄存器为DMA INITIAL SOURCE (DISRC) REGISTER,共四个,对应着2440的4个通道源控制寄存器DMA INITIAL SOURCE CONTROL (DISRCC) REGISTER,用于配置源地址
LOC位用于选择源地址总线,即选择内存使用的总线,从2440数据手册可知,内存使用AHB总线;INC用于设置源地址是否需要递增。
②初始化目的地址
存放目的地址的寄存器为DMA INITIAL DESTINATION (DIDST) REGISTER,也有4个,对应着4个通道目的控制寄存器为DMA INITIAL DESTINATION CONTROL (DIDSTC) REGISTER,用于设置目的地址
CHK_INT在自动重载开启的状态起作用,在这里我们关闭了自动重载,因此该位不需要设置;LOC=1;INC=1
③设置配置寄存器
DMA控制寄存器DMA CONTROL (DCON) REGISTER用于设置DMA相关事项 [26:24]:选择请求源 [23]:选择是软件还是硬件触发 [22]:关闭自动重载 [19:0]:设置发送的数据量④开启DMA
开启与关闭DMA的寄存器为DMA MASK TRIGGER (DMASKTRIG) REGISTER 代码: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*)0x50000020void dma_init(){ //初始化源地址 DISRC0 = (unsigned int)buf; DISRCC0 = (0<<1)| (0<<0); //初始化目的地址 DIDST0 = UTXH0; DIDSTC0 = (1<<1)| (1<<0); DCON0 = (1<<24)| (1<<23)| (1<<22)| (12<<0); }void dma_start(){ DMASKTRIG0 = (1<<1);}S3C6410的DMA驱动程序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; //传输的大小 //开启channel0 DMA /* 流控制和传输类型:MTP 为 001 目标外设:DMA_UART0_1,源外设:DMA_MEM 通道有效: 1 */ DMACC0Configuration = (1<<6) | (1<<11) | (1<<14) | (1<<15); }void dma_start(){ DMACC0Configuration | = 1; }