注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

小白的博客

嵌入式爱好者

 
 
 

日志

 
 

DMA程序  

2012-10-04 00:43:09|  分类: 韦东山视频第二轮 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
驱动程序:

#include <linux/fs.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/device.h>
#include <linux/gpio.h>
#include <linux/wait.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/dma-mapping.h>
#include <linux/cdev.h>

#include <asm/io.h>
#include <mach/regs-gpio.h>
#include <asm/uaccess.h>

#define DMA_TRANS 1
#define NO_DMA_TRANS 0
#define BUSIZE 1024*512

#define DMA0_REGS_BASE 0x4b000000
#define DMA1_REGS_BASE 0x4b000040
#define DMA2_REGS_BASE 0x4b000080
#define DMA3_REGS_BASE 0x4b0000c0

struct dma_regs {
volatile unsigned long disrc
volatile unsigned long disrcc
volatile unsigned long didst
volatile unsigned long didstc
volatile unsigned long dcon    ; 
volatile unsigned long dstat
volatile unsigned long dcsrc
volatile unsigned long dcdst
volatile unsigned long dmasktrig;
};

static int major;
static volatile int dma_finish = 0;
static dev_t dev;
static struct cdev dma_cdev;
static struct class *dma_class;
static struct dma_regs *dma_regs;

static char *sour;
static char *dest;
static u32 sour_phy;
static u32 dest_phy;

static DECLARE_WAIT_QUEUE_HEAD(dma_waitq);

//long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);

static long dma_ioctl(struct file *file, unsigned int cmd, unsigned long argc)
{
int i;
u32 x,y;
memset(sour, 0xAA, BUSIZE); 
memset(dest, 0x55, BUSIZE);
x=sour;
y=dest;
printk("sour = 0x%x\n",x);
printk("dest = 0x%x\n",y);
switch(cmd)
{
case DMA_TRANS    :
{
dma_finish = 0;
dma_regs->disrc = sour_phy;
dma_regs->disrcc = 0;
dma_regs->didst = dest_phy;
dma_regs->didstc = 0;
dma_regs->dcon = (1<<30)|(1<<29)|(1<<28)|(1<<27)|(1<<22)|(BUSIZE/4);
dma_regs->dmasktrig = (1<<1)|(1);
wait_event_interruptible(dma_waitq , dma_finish);
if(memcmp(sour , dest ,BUSIZE)==0)
{
printk("DMA_TRANS OK!\n");
}
else
{
printk("DMA_TRANS ERROR!\n");
return -1;
}
break;
}
case NO_DMA_TRANS :
{
for(i=0;i<BUSIZE;i++)
{
dest[i]=sour[i];
}
if(memcmp(sour , dest ,BUSIZE)==0)
{
printk("NO_DMA_TRANS OK!\n");
}
else
{
printk("NO_DMA_TRANS ERROR!\n");
return -1;
}
break;
}
}
return 0;
}

static irqreturn_t dma_finish_handler(int irq, void *dev_id)
{
dma_finish = 1;
wake_up_interruptible(&dma_waitq);
return IRQ_HANDLED;
}

static struct file_operations dma_operation ={
.owner          = THIS_MODULE,
.unlocked_ioctl = dma_ioctl,  //现在的内核里面ioctl函数已经不存在了,可以用unlocked_ioctl代替
};

static int dma_init(void)
{
sour = dma_alloc_writecombine(NULL , BUSIZE , &sour_phy , GFP_KERNEL);
if(sour<=0)
{
printk("alloc sour buffer fail\n");
return -1;
}
dest = dma_alloc_writecombine(NULL , BUSIZE , &dest_phy , GFP_KERNEL);
if(dest<=0)
{
printk("alloc dest buffer fail\n");
dma_free_writecombine(NULL , BUSIZE, sour ,sour_phy);
return -1;
}

dma_regs = ioremap(DMA3_REGS_BASE ,sizeof(struct dma_regs));
if(dma_regs<=0)
{
printk("ioremap dma_regs fail\n");
dma_free_writecombine(NULL , BUSIZE, dest ,dest_phy);
dma_free_writecombine(NULL , BUSIZE, sour ,sour_phy);
}

if(request_irq(IRQ_DMA3 , dma_finish_handler , 0, "dma_irq" ,NULL))
{
printk("request dma irq error\n");
dma_free_writecombine(NULL , BUSIZE, dest ,dest_phy);
dma_free_writecombine(NULL , BUSIZE, sour ,sour_phy);
iounmap(dma_regs);
return -EBUSY;
}

if(alloc_chrdev_region(&dev, 0,1,"NewDma"))
{
printk("alloc_chrdev_region error\n");
dma_free_writecombine(NULL , BUSIZE, dest ,dest_phy);
dma_free_writecombine(NULL , BUSIZE, sour ,sour_phy);
iounmap(dma_regs);
free_irq(IRQ_DMA3 ,NULL);
}
else
{
major = MAJOR(dev);
cdev_init(&dma_cdev ,&dma_operation);
cdev_add(&dma_cdev , dev ,1);
dma_class = class_create(THIS_MODULE , "dma");
device_create(dma_class, NULL, dev , NULL, "dma");
}

return 0;
}

static void dma_exit(void)
{
device_destroy(dma_class , dev);
class_destroy(dma_class);
cdev_del(&dma_cdev);
unregister_chrdev_region(dev ,1);
free_irq(IRQ_DMA3 ,NULL);
iounmap(dma_regs);
dma_free_writecombine(NULL , BUSIZE, dest ,dest_phy);
dma_free_writecombine(NULL , BUSIZE, sour ,sour_phy);
}

module_init(dma_init);
module_exit(dma_exit);
MODULE_LICENSE("GPL");

测试程序:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>

#define DMA_TRANS 1
#define NO_DMA_TRANS 0

static print_usage(char *name)
{
printf("Usage:%s dma|no_dma\n",name);
}

int main(int argc , char **argv)
{
int fd;
if(argc!=2)
{
print_usage(argv[0]);
return -1;
}
fd = open("/dev/dma" , O_RDWR);
if(fd<0)
{
printf("open /dev/dma error\n");
return -1;
}
if(strcmp(argv[1],"dma")==0)
{
while(1)
{
ioctl(fd , DMA_TRANS);
}
}
else if(strcmp(argv[1],"no_dma")==0)
{
while(1)
{
ioctl(fd , NO_DMA_TRANS);
}
}
else
{
printf("open /dev/dma error\n");
return -1;
}
return 0;
}

  评论这张
 
阅读(1255)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017