1. 简介
linux下有现成的dw_dmac驱动,但是需要自己创建设备文件,分配IRQ和mem resources, 所以需要对配置进行测试
linux dma engine framework提供了dmatest.c测试文件,用于测试,但是怎么使用这个文件呢?首先一定要将该文件编译为ko文件,在测试时,insmod+参数 就可以启动这个函数
module 中使用参数主要有几个函数 :
module_param_string(name,string ,len,perm);
将变量name的内容拷贝到string中。(name代表我们在insmod时设置的参数 ,string是个内部参数),这样就可以给driver module传递参数
module_param(name,type,perm);
设置name的类型,将name export,这样可以在insmod时,改写这个参数值 、
dmatest.c的参数有:
parm:channel: | Bus ID of the channel to test (default: any) (string) |
parm:device: | Bus ID of the DMA Engine to test (default: any) (string) |
parm:iterations: | Iterations before stopping test (default: infinite) (uint) |
parm:max_channels: | Maximum number of channels to use (default: all) (uint) |
parm:pq_sources: | Number of p+q source buffers (default: 3) (uint) |
parm:test_buf_size: | Size of the memcpy test buffer (uint) |
parm:threads_per_chan: | Number of threads to start per channel (default: 1) (uint) |
parm:xor_sources: | Number of xor source buffers (default: 3) (uint) |
2. dmatest的使用方法:
1. 我的DMA是designWare的DMA, linux kernel版本为3.10, 驱动文件为linux/drivers/dma/dw_dmac.c
2. 根据dw_dmac.c中dma-spear1340,在linux/Document下面搜索,找到Document/devicetree/bindings/dma/snps-dma.txt,根据这个文件来配置这个DMA的devicetree
3. 修改dw_dma.c中的dw_probe->devm_clk_get()时,配置正确的clock
4. 为了简单,不给dmatest添加参数,将__run_threaded_test->dma_request_channel函数参数修改为(mask,NULL,NULL);
5. make menuconfig中配置dw_dmac和dmatest为模块
6. 启动linux, insmod dw_dmac.ko, 挂载debugfs, 最后insmod dmatest.ko,大功告成
3. dmaengine的使用
dma framework跑起来了,如何具体的使用dma驱动呢?
给个最简单的例子:
struct dma_chan *chan;
dma_addr_t dma_src;
dma_addr_t dma_dst;
char *src=dma_alloc_coherent(NULL,512,&dma_src,GFP_KERNEL);
char *dst=dma_alloc_coherent(NULL,512,&dma_dst,GFP_KERNEL);
int i=0;
for(i=0;i<512;i++){
*(src+i)='c';
}
dma_cap_mask_t mask;
dma_cap_zero(mask);
dma_cap_set(DMA_MEMCPY, mask);
chan = dma_request_channel(mask,NULL,NULL);
struct dma_device *dev;
struct dma_async_tx_descriptor *tx=NULL;
enum dma_ctrl_flags flags;
dma_cookie_t cookie;
flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT
| DMA_COMPL_SKIP_DEST_UNMAP | DMA_COMPL_SRC_UNMAP_SINGLE;
dev=chan->device;
tx=dev->device_prep_dma_memcpy(chan,dma_dst,
dma_src,512,flags);
if(!tx){
printk(KERN_INFO "Failed to prepare DMA memcpy:%d\n",__LINE__);
}
tx->callback=dac_dma_complete_func;
tx->callback_param=NULL;
cookie=tx->tx_submit(tx);
if(dma_submit_error(cookie)){
printk(KERN_INFO "Failed to do DMA tx_submit:%d\n",__LINE__);
}
dma_async_issue_pending(chan);
return 0;
dma_complete_func是dma传输完成后调用的回调函数
如需了解更多,请参考linux/Document/DMA-API-HOWTO.txt, DMA-API.txt 两个文档