博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
一般的,在s3c2440中,要想进行dma…
阅读量:4052 次
发布时间:2019-05-25

本文共 3407 字,大约阅读时间需要 11 分钟。

2010328

 2010-03-28 14:36:24 阅读125 评论0  字号: 订阅

 s3c2440dma操作的一般步骤 

一:

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

如果sourceS3C2410_DMASRC_HW(外设), 配置它的S3C2410_DMA_DISRCC,S3C2410_DMA_DISRC,S3C2410_DMA_DIDSTC

如果sourceS3C2410_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
关心的是总线地址。
关于总线地址与物理地址的区别,这里有很好的说明,感谢儒雅,现摘录如下:
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 driver's 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请求队列中的请求,传输剩下的数据。

 

本文来自CSDN博客,转载请标明出处:

 

你可能感兴趣的文章
AsyncTask、View.post(Runnable)、ViewTreeObserver三种方式总结frame animation自动启动
查看>>
Android中AsyncTask的简单用法
查看>>
概念区别
查看>>
final 的作用
查看>>
在Idea中使用Eclipse编译器
查看>>
Idea下安装Lombok插件
查看>>
zookeeper
查看>>
Idea导入的工程看不到src等代码
查看>>
技术栈
查看>>
Jenkins中shell-script执行报错sh: line 2: npm: command not found
查看>>
8.X版本的node打包时,gulp命令报错 require.extensions.hasownproperty
查看>>
Jenkins 启动命令
查看>>
Maven项目版本继承 – 我必须指定父版本?
查看>>
通过C++反射实现C++与任意脚本(lua、js等)的交互(二)
查看>>
利用清华镜像站解决pip超时问题
查看>>
微信小程序开发全线记录
查看>>
CCF 分蛋糕
查看>>
解决python2.7中UnicodeEncodeError
查看>>
小谈python 输出
查看>>
Django objects.all()、objects.get()与objects.filter()之间的区别介绍
查看>>