您的位置 首页 开关

s3c2440的dma操作的一般过程

s3c2440的dma操作的一般步骤一般的,在s3c2440中,要想进行dma传输,需要一下七个步骤:一:ints3c2410_dma_request(unsignedintchan…

s3c2440dma操作的一般过程

一般的,在s3c2440中,要想进行dma传输,需求一下七个过程:

一:
int s3c2410_dma_request(unsigned int channel,
struct s3c2410_dma_client *client,
void *dev)

s3c2410_dma_client的界说为:
struct s3c2410_dma_client {
char *name;
};
以uda1314的驱动为例,驱动中界说了两个s3c2410_dma_client
static struct s3c2410_dma_client s3c2410iis_dma_out= {
.name = “I2SSDO”,
};

static struct s3c2410_dma_client s3c2410iis_dma_in = {
.name = “I2SSDI”,
};

二:
s3c2410_dma_config(dmach_t channel,int xferunit,int dcon)

s3c2410_dma_config(dmach_t channel,int xferunit,int dcon)
依据xferunit以及dcon设置通道的操控寄存器DCONx
xferunit为每次传输的数据巨细:0:byte 1:half word 2:word

三:

int s3c2410_dma_set_buffdone_fn(dmach_t channel, s3c2410_dma_cbfn_t rtn)

设置相应的dma通道完结一次dma传输后的回调函数,也便是s3c2410_dma_enqueue完结后会调用的函数
回调函数应具有一下格局:
typedef void (*s3c2410_dma_cbfn_t)(struct s3c2410_dma_chan *,
void *buf, int size,
enum s3c2410_dma_buffresult result);
buf能够传递一些有用的数据,在uda1314的驱动中,传递的是audio_buf_t结构体

四:
int s3c2410_dma_setflags(dmach_t channel, unsigned int flags)

在1314驱动中,
flags = S3C2410_DMAF_AUTOSTART;
s3c2410_dma_setflags(channel, flags);

五:

int s3c2410_dma_devconfig(int channel,
enum s3c2410_dmasrc source,
int hwcfg,
unsigned long devaddr)

参数含义:
* source: S3C2410_DMASRC_HW: source is hardware
* S3C2410_DMASRC_MEM: source is memory
*
* hwcfg: the value for xxxSTCn register,
* bit 0: 0=increment pointer, 1=leave pointer
* bit 1: 0=soucre is AHB, 1=soucre is APB
*
* devaddr: physical address of the source

假如source为S3C2410_DMASRC_HW(外设), 装备它的S3C2410_DMA_DISRCC,S3C2410_DMA_DISRC,S3C2410_DMA_DIDSTC
假如source为S3C2410_DMASRC_MEM(内存),装备它的S3C2410_DMA_DISRCC,S3C2410_DMA_DIDST,S3C2410_DMA_DIDSTC
由此可见,地址方面,只装备触及外设的地址
以uda1341的驱动为例,这几个值为
source = S3C2410_DMASRC_MEM;
hwcfg = 3;
devaddr = 0x55000010;

六:
void *dma_alloc_coherent(struct device *dev,size_t size,dma_addr_t *dma_handle,int flag)

运用此函数,恳求dmabuf,树立共同性映射
以uda1314的驱动为例,调应的实例为:
dmabuf = dma_alloc_coherent(NULL, dmasize, &dmaphys, GFP_KERNEL);(在audio_setup_buf函数中)
dmabuf为虚拟地址,dmaphys是总线地址,虚拟地址用来让驱动写buf用,dmaphys用来传给dma。
dma关怀的是总线地址。
关于总线地址与物理地址的差异,这里有很好的阐明http://hi.baidu.com/zengzhaonong/blog/item/eeb8003083276e9ba9018ee3.html,感谢儒雅,现摘抄如下:
1) 物理地址是与CPU相关的。在CPU的地址信号线上发生的便是物理地址。在程序指令中的虚拟地址经过段映射和页面映射后,就生成了物理地址,这个物理地址被放到CPU的地址线上。
2) 总线地址,望文生义,是与总线相关的,便是总线的地址线或在地址周期上发生的信号。外设运用的是总线地址。
3) 物理地址与总线地址之间的关系由体系的规划决议的。在x86平台上,物理地址与PCI总线地址是相同的。在其他平台上,惹祸会有某种转化,通常是线性的转化。

比方:CPU需求拜访物理地址是0xfa000的单元,那么在x86平台上,会发生一个PCI总线上对0xfa000地址的拜访。这个单元或者是内存中,或者是某个卡上的存储单元,乃至或许这个地址上没有对应的存储器。而在别的一个平台上,或许在PCI总线上发生的拜访是针对地址为0x1fa000的单元。
上述函数是树立共同性映射。运用dma_map_single函数能够树立共同性映射:
2.当只要一个缓冲区要被传输的时分,运用dma_map_single函数来映射它
dma_addr_t dma_map_single(struct device *dev,void *buffer,size_t size, enum dma_data_direction direction)
3.为page结构指针指向的缓冲区树立映射,单页流式映射:
dma_addr_t dma_map_page(struct device *dev,struct page *page ,unsigned long offset ,size_t size,enum dma_data_direction direction);
4.涣散/集合映射
int dma_map_sg(struct device *dev,struct scatterlist *sg,int nents,enum dma_alloc_coherent direction);
还不知道哪种情况下用流式映射,哪种用共同映射。关于s3c2440,其mmc驱动顶用到了涣散集合(流式)映射,声卡驱动中又用到了共同映射。

七:
int s3c2410_dma_enqueue(unsigned int channel, void *id,
dma_addr_t data, int size)

建议一次dma传输
参数含义:
* id the device drivers id information for this buffer
* data the physical address of the buffer data
* size the size of the buffer in bytes
将dma_alloc_coherent中得到的dmaphys传递给s3c2410_dma_enqueue. s3c2410_dma_enqueue提交一次dma恳求,当dma通道可用的时分经过s3c2410_dma_loadbuffer开端一次传输,传输完结后会发生irq中止。其dma的中止服务函数中会持续发动dma恳求行列中的恳求,传输剩余的数据。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/dianyuan/kaiguan/264914.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部