首页 > 其他分享 >SC2440 DMA使用

SC2440 DMA使用

时间:2024-03-24 20:45:14浏览次数:31  
标签:DMA dma int SC2440 unsigned 使用 include s3c

DMA介绍可见:https://www.cnblogs.com/lethe1203/p/18092378 本节复习2440 DMA使用 参考资料:韦东山驱动第二期  

DMA字符驱动代码:

#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/irq.h>
#include <asm/arch/regs-gpio.h>
#include <asm/hardware.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/dma-mapping.h>

#define  S3C_DMA_SIZE   512*1024          //DMA传输长度   512KB

#define NORMAL_COPY     0                 //两个地址之间的正常拷贝
#define DMA_COPY        1                 //两个地址之间的DMA拷贝

/*函数声明*/
static DECLARE_WAIT_QUEUE_HEAD(s3c_dma_queue);          //声明等待队列
static int s3c_dma_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long flags);

  /*
   * 定义中断事件标志
   * 0:进入等待队列        1:退出等待队列
   */
     static int s3c_dma_even=0;


static unsigned char   *source_virt;            //源虚拟地址
static unsigned int     source_phys;            //源物理地址

static unsigned char *dest_virt;              //目的虚拟地址
static unsigned int   dest_phys;              //目的虚拟地址


/*DMA3寄存器*/
struct  S3c_dma3_regs{
    unsigned int disrc3    ;          //0x4b0000c0
    unsigned int disrcc3   ;                    
    unsigned int didst3    ;                    
    unsigned int didstc3   ;               
    unsigned int dcon3     ;                
    unsigned int dstat3    ; 
    unsigned int dcsrc3    ; 
    unsigned int dcdst3    ;        
    unsigned int dmasktrig3;        //0x4b0000e0
};


 static volatile struct S3c_dma3_regs   *s3c_dma3_regs;

/*字符设备操作*/
static struct file_operations  s3c_dma_fops={
        .owner  = THIS_MODULE,
        .ioctl     = s3c_dma_ioctl,
};

/*中断服务函数*/
static irqreturn_t  s3c_dma_irq (int irq, void *dev_id)   
{
    s3c_dma_even=1;                             //退出等待队列
    wake_up_interruptible(&s3c_dma_queue);      //唤醒 中断
    return IRQ_HANDLED;
}

/*ioctl函数*/
static int s3c_dma_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long flags)
{
    int i;
    memset(source_virt, 0xAA, S3C_DMA_SIZE);          
    memset(dest_virt, 0x55, S3C_DMA_SIZE);   
    
    switch(cmd)
    {
    case NORMAL_COPY:                           //正常拷贝
            
             for(i=0;i<S3C_DMA_SIZE;i++)
                 dest_virt[i] =  source_virt[i];

             if(memcmp(dest_virt, source_virt, S3C_DMA_SIZE)==0)
           {
         printk("NORMAL_COPY OK\n");
                return 0;
         }
         else
        {
         printk("NORMAL_COPY ERROR\n");
               return -EAGAIN;
        }             
            
    case DMA_COPY:                               //DMA拷贝

        s3c_dma_even=0;     //进入等待队列
        
        /*设置DMA寄存器,启动一次DMA传输 */
        /* 源的物理地址 */
        s3c_dma3_regs->disrc3      = source_phys;      
        /* 源位于AHB总线, 源地址递增 */  
        s3c_dma3_regs->disrcc3     = (0<<1) | (0<<0);
        /* 目的的物理地址 */
        s3c_dma3_regs->didst3      = dest_phys;      
        /* 目的位于AHB总线, 目的地址递增 */
        s3c_dma3_regs->didstc3     = (0<<2) | (0<<1) | (0<<0);     
        /* 使能中断,单个传输,软件触发, */
        s3c_dma3_regs->dcon3=(1<<30)|(1<<29)|(0<<28)|(1<<27)|(0<<23)|(0<<20)|(S3C_DMA_SIZE<<0);  
        //启动一次DMA传输
        s3c_dma3_regs->dmasktrig3  = (1<<1) | (1<<0);     
        
        wait_event_interruptible(s3c_dma_queue, s3c_dma_even);    //进入睡眠,等待DMA传输中断到来才退出
        
        if(memcmp(dest_virt, source_virt, S3C_DMA_SIZE)==0)
        {
         printk("DMA_COPY OK\n");
                return 0;
         }
        else
        {
       printk("DMA_COPY ERROR\n");
             return -EAGAIN;
           }  

            break;
    }
    return 0;
}


static unsigned int major;
static struct class *cls;
static int s3c_dma_init(void)
{
    /*1.1 注册DMA3 中断  */
    if(request_irq(IRQ_DMA3, s3c_dma_irq,NULL, "s3c_dma",1)) 
    {
        printk("Can't    request_irq   \"IRQ_DMA3\"!!!\n ");
        return -EBUSY;
    }
    
    /*1.2 分配两个DMA缓冲区(源、目的)*/
    source_virt=dma_alloc_writecombine(NULL,S3C_DMA_SIZE, &source_phys, GFP_KERNEL);
    if(source_virt==NULL)       
   {
        printk("Can't  dma_alloc   \n ");
        return -ENOMEM;
   }
    
    dest_virt=dma_alloc_writecombine(NULL,S3C_DMA_SIZE, &dest_phys, GFP_KERNEL);
    if(dest_virt==NULL)       
   {
        printk("Can't  dma_alloc   \n ");
        return -ENOMEM;
   }
    
    /*2.注册字符设备,并提供文件操作集合fops*/
    major=register_chrdev(0, "s3c_dma",&s3c_dma_fops);
    cls= class_create(THIS_MODULE, "s3c_dma");
    class_device_create(cls, NULL,MKDEV(major,0), NULL, "s3c_dma");

    s3c_dma3_regs=ioremap(0x4b0000c0, sizeof(struct S3c_dma3_regs));
    
    return 0;  
}

static void s3c_dma_exit(void)
{
    iounmap(s3c_dma3_regs);
    
    class_device_destroy(cls, MKDEV(major,0));
    class_destroy(cls);

    dma_free_writecombine(NULL, S3C_DMA_SIZE, dest_virt, dest_phys);
    dma_free_writecombine(NULL, S3C_DMA_SIZE, source_virt, source_phys);   

    free_irq(IRQ_DMA3, 1);

}
module_init(s3c_dma_init);
module_exit(s3c_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>

/* ./dma_test NORMAL
 * ./dma_test DMA
 */
#define NORMAL_COPY     0               //两个地址之间的正常拷贝
#define DMA_COPY        1              //两个地址之间的DMA拷贝

void print_usage(char *name)
{
    printf("Usage:\n");
    printf("%s <NORMAL | DMA>\n", name);
}

int main(int argc, char **argv)
{
    int fd,i=30;
    
     if (argc != 2)
    {
        print_usage(argv[0]);
        return -1;
    }

    fd = open("/dev/s3c_dma", O_RDWR);
    if (fd < 0)
    {
        printf("can't open /dev/s3c_dma\n");
        return -1;
    }

    if (strcmp(argv[1], "NORMAL") == 0)
    {
        while (i--)                //调用驱动的ioctl(),30次
        {
            ioctl(fd, NORMAL_COPY);
        }
    }
    else if (strcmp(argv[1], "DMA") == 0)
    {
        while (i--)                //调用驱动的ioctl(),30次        
        {
            ioctl(fd, DMA_COPY);
        }
    }
    else
    {
        print_usage(argv[0]);
        return -1;
    }
    return 0;     
}

 

   

标签:DMA,dma,int,SC2440,unsigned,使用,include,s3c
From: https://www.cnblogs.com/lethe1203/p/18092992

相关文章

  • python趣味编程-使用 Django 和 WebSockets 的 Python 简单实时聊天室网站
    在Python中使用Django的简单实时聊天室系统该项目名为“简单实时聊天室系统”。这是一个使用Python和DjangoFramework开发的基于Web的应用程序。该应用程序是一个供随机用户使用的简单聊天室。所有人都可以在一个聊天框或对话框中进行交流。聊天消息会自动更新到所......
  • python趣味编程-使用 Django 的 Python 大学考勤管理系统
    在Python中使用Django的大学考勤管理系统该项目的名称为《大学考勤管理系统》。这是一个使用DjangoFramework用Python开发的基于Web的应用程序。该项目帮助某些大学学院存储/记录和管理学生每堂课的出勤情况。使用该应用程序,他们可以轻松列出班级学生名单并记录每......
  • Linux 中的以太网管理,以及udhcpc介绍和使用步骤
    在Linux中,udhcpc是一个用于动态获取IP地址的工具,通常用于DHCP(DynamicHostConfigurationProtocol)网络配置。它是BusyBox工具集中的一部分,用于从DHCP服务器获取IP地址、网关、DNS服务器等网络配置信息。以下是udhcpc的基本介绍和使用流程:1.安装udhcpc:udhcpc通常是与BusyBo......
  • 使用AI技术(单张图片或文字)生产3D模型 —— Ai生成3D模型的时代来了
    地址:https://www.bilibili.com/video/BV1A2421P7pH/视频用到的工具voxcraft体验地址:https://voxcraft.ai/......
  • chroma使用指南官方文档&翻译
    ......
  • Chroma向量数据库使用案例
     转载自:https://blog.csdn.net/xzq_qzx_/article/details/136535125​​​​​基于ChromaDB与BGEToward-VectorModel的本地私有化向量检索之路安装基础环境包括Python安装、pip安装及镜像设置等网上提供很多资料,这里就不介绍了。安装chromaDB环境安装pipinstallchrom......
  • 切记:使用nvidia omniverse时一定要用2T的固态硬盘
    最近在用nvidiaomniverse时突然发现这样的一个问题,那就是这个软件实在是太太了,一个组件就4个多GB大小,如果安装几个组件后那么几十GB的硬盘就没有了,同时由于这个体积太大,因此再启动和使用的时候需要从硬盘上导入文件,这个过程是十分的痛苦的,由于我用的是机械硬盘,这个速度简直是惨不......
  • 在Java项目中使用Redis的五大数据结构应用场景与代码实现
    在Java项目中使用Redis的五大数据结构可以应用于以下场景:1、字符串(String):1、缓存数据:将经常访问的数据存储在Redis中,以减轻数据库的负载。2、计数器:记录用户的访问次数、点赞数等。3、分布式锁:在分布式环境下实现互斥访问,防止并发问题。2、列表(List):1、消息队列:将生产......
  • 使用 Suno 创作歌曲
    Suno是一款基于人工智能的音乐创作工具,可以帮助您轻松创作原创歌曲。它可以根据您的歌词生成旋律、和弦和伴奏,并提供多种风格和情绪供您选择。在本文中,我们将介绍如何使用Suno创作歌曲。我们将使用以下步骤:选择客制化方式准备歌词选择风格和情绪输入标题生成音乐准备......
  • WPF中阴影效果和模糊效果的使用【Xaml】
    原文:https://blog.csdn.net/qq_39847278/article/details/129707074前言WPF中的控件效果主要通过Effect来实现,而Effect有DropShadowEffect(投影效果)和BlurEffect(模糊效果)两个派生类,本文将主要介绍Effect的运用!一、DropShadowEffect1、DropShadowEffect各属性效果图 另外还有......