DMA驱动程序设计

来源:互联网 发布:詹姆斯2016赛季数据 编辑:程序博客网 时间:2024/06/07 12:47

通过串口发送数据的实质是:内存保存着字符串,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; }
0 0
原创粉丝点击