DMA驱动框架

框架入口源文件:dma.c

(可根据入口源文件,再按着框架到内核走一遍)

内核版本:linux_2.6.22.6    硬件平台:JZ2440

以下是驱动框架:

以下是驱动代码  dma.c :

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/irq.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/arch/regs-gpio.h>
#include <asm/hardware.h>
#include <linux/poll.h>
#include <linux/dma-mapping.h>

//源地址
static unsigned char *src;
static unsigned int src_phy;

//目的地址
static unsigned char* dest;
static unsigned int dest_phy;

//空间大小
#define  DMA_SIZE (1204*512)

//驱动类
static struct class *dma_class;

//主设备号
static int major ;

#define USE_DMA 1
#define NO_DMA 0

//DMA寄存器
static struct s3c_dma_reg
{
     unsigned long disrc;
     unsigned long disrcc;
     unsigned long didst;
     unsigned long didstc;
     unsigned long dcon;
     unsigned long dstat;
     unsigned long dcsrc;
     unsigned long dcdst;
     unsigned long dmaskting;
}*s3c_dma_regs;

//DMA地址
static unsigned long dma_addr0 = 0x4b000000;
static unsigned long dma_addr1 = 0x4b000040;
static unsigned long dma_addr2 = 0x4b000080;
static unsigned long dma_addr3 = 0x4b0000c0;

//为这个进程创建等待队列
static DECLARE_WAIT_QUEUE_HEAD(dma_wait_queue);

//进程队列标志位
static volatile int dma_wait_queue_condition=0;

static int s3c_dma_iotcl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long args)
{
   int i=0;
       memset(src, 0xAA, DMA_SIZE);
    memset(dest, 0x55, DMA_SIZE);

    switch(cmd)
   {
      case NO_DMA :
          {
          for(i=0;i<DMA_SIZE;i++) dest[i] = src[i];
          if(memcmp(src,dest,DMA_SIZE) == 0) printk("copy without DMA successfuly !\n");
          else printk("copy without DMA fialed !\n");
          break;
      }
      case USE_DMA :
          {
         // 设置DMA寄存器
          s3c_dma_regs->disrc = src_phy;
          s3c_dma_regs->disrcc = (0<<0)|(0<<0);
          s3c_dma_regs->didst = dest_phy;
          s3c_dma_regs->didstc =(0<<3)|(0<<1)|(0<<0);
          s3c_dma_regs->dcon = (1<<30)|(1<<29)|(0<<28)|(1<<27)|(0<<23)|(0<<20)|(DMA_SIZE<<0);
          s3c_dma_regs->dmaskting = (1<<1)|(1<<0);

         //休眠进程
          dma_wait_queue_condition = 0;      //状态标志位为假         休眠dma.c进程      。 进程可被信号中断休眠,返回非0值表示休眠被信号中断
          wait_event_interruptible(dma_wait_queue, dma_wait_queue_condition);  

          if(memcmp(src,dest,DMA_SIZE) == 0) printk(" copy with DMA successfuly !\n");
          else printk("copy with DMA failed !\n");
          break;
      }
     }
  return 0;

}

//字符设备操作函数
static struct file_operations dma_fops =
{
     .owner = THIS_MODULE,
     .ioctl = s3c_dma_iotcl,
};

//中断处理函数
static     int s3c_dma_irq(int irq, void *devid)
{
    dma_wait_queue_condition = 1;            //状态为真     唤醒dma.c进程
    wake_up_interruptible(&dma_wait_queue);
    return IRQ_HANDLED;
}

static int dma_init(void)
{
    //申请中断
    request_irq(IRQ_DMA3, s3c_dma_irq,0, "s3c_dma", 1);

    //申请源地址空间
     src = dma_alloc_writecombine(NULL,DMA_SIZE, &src_phy,GFP_KERNEL);
     //申请目的地址空间
     dest= dma_alloc_writecombine(NULL,DMA_SIZE, &dest_phy,GFP_KERNEL);

    //dma_reg映射
     s3c_dma_regs = ioremap(dma_addr3,sizeof(struct s3c_dma_reg));

    //注册字符设备
    major = register_chrdev(0, "s3c_dma",&dma_fops);

    //注册类 设备节点

    dma_class = class_create(THIS_MODULE,"s3c_dma_class");                //     /sys/class/s3c_dma_class
    class_device_create(dma_class,NULL,MKDEV(major,0),NULL, "s3c_dma");   //     /dev/s3c_dma

    return 0;
}

static void dma_exit(void)

{
   free_irq(IRQ_DMA3,1);
   dma_free_writecombine(NULL,DMA_SIZE, src,GFP_KERNEL);
   dma_free_writecombine(NULL,DMA_SIZE, dest,GFP_KERNEL);
   iounmap(s3c_dma_regs);
   unregister_chrdev(major, "s3c_dma");
   class_destroy(dma_class);
   class_device_destroy( dma_class,MKDEV(major,0));
}

module_init(dma_init);
module_exit(dma_exit);

MODULE_LICENSE("GPL");

以下是驱动测试文件:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <string.h>

#define USE_DMA 1
#define NO_DMA 0

int main(int argc ,char **argv)
{
    int fd=0;
    fd = open("/dev/s3c_dma", O_RDWR);
    if(fd<0)   printf("can‘t open \n");
    if(argc !=2) printf("please using like this : ./dma_test  <dma|no_dma>\n"); 

    if(argc ==2)
        {
         if(strcmp(argv[1],"dma")==0) while(1) ioctl(fd,USE_DMA);
         if(strcmp(argv[1],"no_dma")==0)while(1)  ioctl(fd,NO_DMA);
        }

  return 0;
}

以下是编译驱动的Makefile:

KERN_DIR = /work/systems/kernel/linux-2/linux-2.6.22.6

all:
    make -C $(KERN_DIR) M=`pwd` modules 

clean:
    make -C $(KERN_DIR) M=`pwd` modules clean
    rm -rf modules.order

obj-m    +=dma.o

原文地址:https://www.cnblogs.com/zsy12138/p/10392844.html

时间: 2024-10-16 18:32:21

DMA驱动框架的相关文章

Linux设备驱动框架设计

引子 Linux操作系统的一大优势就是支持数以万计的芯片设备,大大小小的芯片厂商工程师都在积极地向Linux kernel提交设备驱动代码.能让这个目标得以实现,这背后隐藏着一个看不见的技术优势:Linux内核提供了一套易于扩展和维护的设备驱动框架.Linux内核本身提供一套设备驱动模型,此模型提供了Linux内核对设备的一般性抽象描述,包括设备的电源管理.对象生命周期管理.用户空间呈现等等.在设备模型的帮助下,设备驱动开发工程师从设备的一般性抽象中解脱出来.但是每个设备的具体功能实现还需要大量

Linux USB驱动框架分析 【转】

转自:http://blog.chinaunix.net/uid-11848011-id-96188.html 初次接触与OS相关的设备驱动编写,感觉还挺有意思的,为了不至于忘掉看过的东西,笔记跟总结当然不可缺,更何况我决定为嵌入式卖命了.好,言归正传,我说一说这段时间的收获,跟大家分享一下Linux的驱动开发.但这次只先针对Linux的USB子系统作分析,因为周五研讨老板催货.当然,还会顺带提一下其他的驱动程序写法. 事实上,Linux的设备驱动都遵循一个惯例——表征驱动程序(用driver更

Linux USB驱动框架分析(2)【转】

转自:http://blog.chinaunix.net/uid-23046336-id-3243543.html 看了http://blog.chinaunix.net/uid-11848011-id-96188.html的驱动框架分析,感觉受益匪浅.对于一些内容,我自己查漏补缺. 首先我们按照顺序,看内核模块的注册以及释放函数如下: 点击(此处)折叠或打开 static int __init usb_skel_init(void) { int result; /* register this

基于Linux 3.0.8 Samsung FIMC(S5PV210) 的摄像头驱动框架解读

作者:咕唧咕唧liukun321 来自:http://blog.csdn.net/liukun321 FIMC这个名字应该是从S5P100开始出现的,在s5pv210里面的定义是摄像头接口,但是它同样具有图像数据颜色空间转换的作用.而exynos4412对它的定义看起来更清晰些,摄像头接口被定义为FIMC-LITE .颜色空间转换的硬件结构被定义为FIMC-IS.不多说了,我们先来看看Linux3.0.8 三星的BSP包中与fimc驱动相关的文件. 上面的源码文件组成了整个fimc的驱动框架.通

Linux驱动修炼之道-SPI驱动框架源码分析(上)【转】

转自:http://blog.csdn.net/lanmanck/article/details/6895318 SPI驱动架构,以前用过,不过没这个详细,跟各位一起分享: 来自:http://blog.csdn.net/woshixingaaa/article/details/6574215 SPI协议是一种同步的串行数据连接标准,由摩托罗拉公司命名,可工作于全双工模式.相关通讯设备可工作于m/s模式.主设备发起数据帧,允许多个从设备的存在.每个从设备 有独立的片选信号,SPI一般来说是四线串

Linux下USB驱动框架分析【转】

转自:http://blog.csdn.net/brucexu1978/article/details/17583407 版权声明:本文为博主原创文章,未经博主允许不得转载. http://www.cnblogs.com/general001/articles/2319552.html http://blog.csdn.net/uruita/article/details/7263290:MODULE_DEVICE_TABLE http://blog.chinaunix.net/uid-2590

声卡驱动框架

修改内核的s3c2410-wm8976.c文件,让其支持开发板的声卡 框架入口源文件:s3c2410-wm8976.c (可根据入口源文件,再按着框架到内核走一遍) 内核版本:linux_2.6.22.6 硬件平台:JZ2440 以下是驱动框架: 以下是驱动代码: #include <linux/module.h> #include <linux/device.h> #include <linux/init.h> #include <linux/types.h&g

Linux驱动框架之framebuffer驱动框架

1.什么是framebuffer? (1)framebuffer帧缓冲(一屏幕数据)(简称fb)是linux内核中虚拟出的一个设备,framebuffer向应用层提供一个统一标准接口的显示设备.帧缓冲(framebuffer) 是Linux为显示设备提供的一个接口,把显存抽象后的一种设备,他允许上层应用程序在图形模式下直接对显示缓冲区进行读写操作.这种操作是抽象的,统一的.用 户不必关心物理显存的位置.换页机制等等具体细节.这些都是由Framebuffer设备驱动来完成的. (2)从驱动来看,f

初解,Scala语言中基于Actor的并发编程的机制,并展示了在Spark中基于Scala语言的Actor而产生的消息驱动框架Akka的使用,

Scala深入浅出实战中级--进阶经典(第66讲:Scala并发编程实战初体验及其在Spark源码中应用解析)内容介绍和视频链接 2015-07-24 DT大数据梦工厂 从明天起,做一个勤奋的人 看视频.下视频,分享视频 DT大数据梦工厂-Scala深入浅出实战中级--进阶经典:第66讲:Scala并发编程实战初体验及其在Spark源码中的应用解析 本期视频通过代码实战详解了Java语言基于加锁的并发编程模型的弊端以及Scala语言中基于Actor的并发编程的机制,并展示了在Spark中基于Sc