DMA操作驱动

发布者:清新风华最新更新时间:2016-04-01 来源: eefocus关键字: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/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"
 
#define MEM_CPY_NO_DMA  0
#define MEM_CPY_DMA     1
 
#define BUF_SIZE  (512*1024)
 
#define DMA0_BASE_ADDR  0x4B000000
#define DMA1_BASE_ADDR  0x4B000040
#define DMA2_BASE_ADDR  0x4B000080
#define DMA3_BASE_ADDR  0x4B0000C0
 
struct s3c_dma_regs {
        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 dmasktrig;
};
 
 
static int major = 0;
 
static char *src;
static u32 src_phys;
 
static char *dst;
static u32 dst_phys;
 
static struct class *cls;
 
static volatile struct s3c_dma_regs *dma_regs;
 
static DECLARE_WAIT_QUEUE_HEAD(dma_waitq);
// 中断事件标志, 中断服务程序将它置1,ioctl将它清0 //
static volatile int ev_dma = 0;
 
static int s3c_dma_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
        int i;
 
        memset(src, 0xAA, BUF_SIZE);
        memset(dst, 0x55, BUF_SIZE);
        switch (cmd)
        {
                case MEM_CPY_NO_DMA :
                {
                        for (i = 0; i < BUF_SIZE; i++)
                                dst[i] = src[i];
                        if (memcmp(src, dst, BUF_SIZE) == 0)
                        {
                                printk("MEM_CPY_NO_DMA OK\n");
                        }
                        else
                        {
                                printk("MEM_CPY_DMA ERROR\n");
                        }
                        break;
                }
 
                case MEM_CPY_DMA :
                {
                        ev_dma = 0;
                        // 把源,目的,长度告诉DMA //
                        dma_regs->disrc      = src_phys;                             // 源的物理地址 //
                        dma_regs->disrcc     = (0<<1) | (0<<0);                // 源位于AHB总线, 源地址递增 //
                        dma_regs->didst      = dst_phys;                            // 目的的物理地址 //
                        dma_regs->didstc     = (0<<2) | (0<<1) | (0<<0); // 目的位于AHB总线, 目的地址递增 //
                        dma_regs->dcon       = (1<<30)|(1<<29)|(0<<28)|(1<<27)|(0<<23)|(0<<20)|(BUF_SIZE<<0);                                                                               // 使能中断,单个传输,软件触发, //
 
                        // 启动DMA                               //
                        dma_regs->dmasktrig  = (1<<1) | (1<<0);
 
                        // 如何知道DMA什么时候完成? //
                        // 休眠                                       //
                        wait_event_interruptible(dma_waitq, ev_dma);
 
                        if (memcmp(src, dst, BUF_SIZE) == 0)
                        {
                                printk("MEM_CPY_DMA OK\n");
                        }
                        else
                        {
                                printk("MEM_CPY_DMA ERROR\n");
                        }
                        break;
                }
        }
 
        return 0;
}
 
static struct file_operations dma_fops = {
        .owner  = THIS_MODULE,
        .ioctl  = s3c_dma_ioctl,
};
 
static irqreturn_t s3c_dma_irq(int irq, void *devid)
{
        // 唤醒 //
        ev_dma = 1;
        wake_up_interruptible(&dma_waitq);   // 唤醒休眠的进程 //
        return IRQ_HANDLED;
}
 
static int s3c_dma_init(void)
{
        if (request_irq(IRQ_DMA3, s3c_dma_irq, 0, "s3c_dma", 1))
        {
                printk("can't request_irq for DMA\n");
                return -EBUSY;
        }
        // 分配SRC, DST对应的缓冲区 //
        src = dma_alloc_writecombine(NULL, BUF_SIZE, &src_phys, GFP_KERNEL);
        if (NULL == src)
        {
                printk("can't alloc buffer for src\n");
                free_irq(IRQ_DMA3, 1);
                return -ENOMEM;
        }
        dst = dma_alloc_writecombine(NULL, BUF_SIZE, &dst_phys, GFP_KERNEL);
        if (NULL == dst)
        {
                free_irq(IRQ_DMA3, 1);
                dma_free_writecombine(NULL, BUF_SIZE, src, src_phys);
                printk("can't alloc buffer for dst\n");
                return -ENOMEM;
        }
 
        major = register_chrdev(0, "s3c_dma", &dma_fops);
 
        // 为了自动创建设备节点 //
        cls = class_create(THIS_MODULE, "s3c_dma");
        class_device_create(cls, NULL, MKDEV(major, 0), NULL, "dma");
 
        dma_regs = ioremap(DMA3_BASE_ADDR, sizeof(struct s3c_dma_regs));
        return 0;
}
 
static void s3c_dma_exit(void)
{
        iounmap(dma_regs);
        class_device_destroy(cls, MKDEV(major, 0));
        class_destroy(cls);
        unregister_chrdev(major, "s3c_dma");
        dma_free_writecombine(NULL, BUF_SIZE, src, src_phys);
        dma_free_writecombine(NULL, BUF_SIZE, dst, dst_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 nodma
// ./dma_test dma
//
#define MEM_CPY_NO_DMA  0
#define MEM_CPY_DMA     1
 
void print_usage(char *name)
{
        printf("Usage:\n");
        printf("%s \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("can't open /dev/dma\n");
                return -1;
        }
 
        if (strcmp(argv[1], "nodma") == 0)
        {
                while (1)
                {
                        ioctl(fd, MEM_CPY_NO_DMA);
                }
        }
        else if (strcmp(argv[1], "dma") == 0)
        {
                while (1)
                {
                        ioctl(fd, MEM_CPY_DMA);
                }
        }
        else
        {
                print_usage(argv[0]);
                return -1;
        }
        return 0;
}
 

关键字:DMA  操作驱动 引用地址:DMA操作驱动

上一篇:hotplug_uevent机制
下一篇:NOR FLASH驱动程序

推荐阅读最新更新时间:2024-03-16 14:48

STM32F0使用LL库实现DMA方式AD采集
在本次项目中,限于空间要求我们选用了STM32F030F4作为控制芯片。这款MCU不但封装紧凑,而且自带的Flash空间也非常有限,所以我们选择了LL库实现。在本文中我们将介绍基于LL库的ADC的DMA采集方式。 1、概述 这次我们使用DMA方式实现对AD的采集,在遗忘我们使用HAL库和标准库都做过,这次我们使用LL库来实现。接下来我们简单了解一下STM32F030F4中的ADC和DMA。 首先看一看ADC,STM32F030F4是12位的ADC。它有多达19个多路复用通道,允许它测量来自16个外部和2个内部源的信号。各种通道的A/D转换可采用单通道、连续通道、扫描通道或不连续通道进行。ADC的结果存储在左对齐或右对齐的1
[单片机]
STM32F10x DMA介绍以及 dma usart数据收发
DMA方式 1. DMA 介绍 Direct memory access (DMA) is used in order to provide high-speed data transfer between peripherals and memory and between memory and memory. Data can be quickly moved by DMA without any CPU action. This keeps CPU resources free for other operations. The DMA controller combines a powerful dual AHB
[单片机]
stm32专题十三:DMA(一)结构框图
DMA(data memory access)直接存储器访问,和串口USART、GPIO一样,也是一个外设。 把数据从一个地方搬到另一个地方,而不占用CPU。像串口发送数据,数据是一个一个的发。CPU首先把数据从内存(数组)拿到CPU内部的寄存器(CPU内部有一组暂存数据寄存器R1、R2、R3等),然后再发到串口的数据寄存器USART_DR,这些过程一直需要占用CPU。而当我们使用DMA时,如果CPU给DMA一个命令(把数据从内存发到串口),这时DMA就会实现这个功能,整个过程CPU是空闲的,可以去做其他事。比如,点亮一个LED,显示液晶屏LCD等。 DMA支持3种模式: Memory to Memory (这里的Me
[单片机]
stm32专题十三:<font color='red'>DMA</font>(一)结构框图
stm32f4中通过dma采集adc
环境: 主机:WIN8 开发环境:MDK5.13 MCU:STM32F407IGH 源代码: drv_power.h /********************************************************************* * 电源模块驱动层头文件 * (c)copyright 2015,jdh * All Right Reserved *新建日期:2014/10/20 by jdh *修改时间:2015/3/2 by jdh *****************************************************************
[单片机]
STM32F429串口IDLE中断+DMA接收串口数据
#define Rec_GPS_DATA_Unfinish 0; #define Rec_GPS_DATA_Finish 1; extern unsigned char GPS_DATA ; extern unsigned char Rec_GPS_DATA_Flag; int main(void)//主函数 { SysTick_Init(); NVIC_Configuration(); Debug_USART_Config(); macUART4_Config(); DMA_Config(); while(1) { if(Rec_GPS_DATA_Flag) {
[单片机]
ADSP2106x中DMA的应用
   摘 要: 直接内存存取(DMA)是DSP芯片中用于快速数据交换的重要技术,对AD公司的浮点系列芯片ADSP2106x中的DMA的应用进行了详细介绍,并给出实际应用中的一些例子。     关键词: DMA 浮点系列芯片ADSP2106x     1 DMA概述     直接内存存取(DMA)对计算机系统是非常重要的。它可以使CPU在运行指令的同时,系统能实现从外部存储器或设备中存取数据,也可以在CPU不参与的情况下,由专用的DMA设备存取数据。     对于浮点DSP芯片来讲,DMA的作用更是重要。众所周知,DSP芯片主要是面向实时的信号处理,其核心的运算部件具有很高的运算速度,常以MFLOPS(每秒百万次浮点
[缓冲存储]
STM32—无需中断来实现使用DMA接收串口数据
本节目标: 通过DMA,无需中断,接收不定时长的串口数据 描述: 当在串口多数据传输下,CPU会产生多次中断来接收串口数据,这样会大大地降低CPU效率,同时又需要CPU去做其它更重要的事情,我们应该如何来优化? 比如四轴飞行器,当在不停地获取姿态控制方向时,又要去接收串口数据. 答:使用DMA,无需CPU中断便能实现接收串口数据 1.DMA介绍 DMA,全称为: Direct Memory Access,即直接存储器访问, DMA 传输方式无需 CPU 直接控制传输,通过硬件为 RAM 与 I/O 设备开辟一条直接传送数据的通路,能使 CPU 的效率大为提高。 2在main()中调用串口配置函数,初始化串口后,然后使能UA
[单片机]
STM32—无需中断来实现使用<font color='red'>DMA</font>接收串口数据
VxWorks操作系统下实现ComPactPCI总线驱动
1 引言   VxWorks是美国Wind River公司专门为嵌入式处理器设计的一种模块化、高性能的实时多任务操作系统。这里提出一种VxWorks操作系统下CompactPCI总线驱动程序的设计及实现。该设计使用德国Kontron DT-64,采用Dual PentiLim 3 CPU,工作频率高达866 MHz,具有128 KB一级高速缓存和128 KB二级高速缓存。     2 BSP与VxWorks的关系   板级支持包BSP(board support packet)通常是针对具体的硬件平台,是用户所编写的启动代码和部分设备驱动程序的集合。在VxWorks操作系统中,BSP是介于底层硬件环境和VxWorks之
[工业控制]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved