linux下DMA驱动测试代码

DMA传输可以是内存到内存、内存到外设和外设到内存。这里的代码通过dma驱动实现了内存到内存的数据传输。

/*
Function description:When we call dmatest_read(),it will transmit src memory data
to dst memory,then print dst memory data by dma_callback_func(void) function.
*/
#include<linux/module.h>
#include<linux/init.h>
#include<linux/fs.h>
#include<linux/sched.h>

#include<linux/device.h>
#include<linux/string.h>
#include<linux/errno.h>

#include<linux/types.h>
#include<linux/slab.h>
#include<linux/dmaengine.h>
#include<linux/dma-mapping.h>

#include<asm/uaccess.h>

#define DEVICE_NAME "dma_test"
unsigned char dmatest_major;
static struct class *dmatest_class;

struct dma_chan *chan;
 //bus address
dma_addr_t dma_src;
dma_addr_t dma_dst;
//virtual address
char *src = NULL;
char *dst = NULL ;
struct dma_device *dev;
struct dma_async_tx_descriptor *tx = NULL;
enum dma_ctrl_flags flags;
dma_cookie_t cookie;

//When dma transfer finished,this function will be called.
void dma_callback_func(void)
{
	int i;
	for (i = 0; i < 512; i++){
		printk(KERN_INFO "%c",dst[i]);
	}
}

int dmatest_open(struct inode *inode, struct file *filp)
{
	return 0;
}

int dmatest_release(struct inode *inode, struct file *filp)
{
	return 0;
}

static ssize_t dmatest_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos)
{
	int ret = 0;
	//alloc a desc,and set dst_addr,src_addr,data_size.
	tx = dev->device_prep_dma_memcpy(chan, dma_dst, dma_src, 512, flags);
	if (!tx){
		printk(KERN_INFO "Failed to prepare DMA memcpy");
	}

	tx->callback = dma_callback_func;//set call back function
	tx->callback_param = NULL;
	cookie = tx->tx_submit(tx); //submit the desc
	if (dma_submit_error(cookie)){
		printk(KERN_INFO "Failed to do DMA tx_submit");
	}

	dma_async_issue_pending(chan);//begin dma transfer

	return ret;
}

static ssize_t dmatest_write(struct file *filp, const char __user *buf, size_t size, loff_t *ppos)
{
	int ret = 0;
	return ret;
}

static const struct file_operations dmatest_fops = {
	.owner = THIS_MODULE,
	.read = dmatest_read,
	.write = dmatest_write,
	.open = dmatest_open,
	.release = dmatest_release,
};

int dmatest_init(void)
{
	int i;
	dma_cap_mask_t mask;

	//the first parameter 0 means allocate major device number automatically
	dmatest_major = register_chrdev(0,DEVICE_NAME,&dmatest_fops);
	if (dmatest_major < 0)
		return dmatest_major;
	//create a dmatest class
	dmatest_class = class_create(THIS_MODULE,DEVICE_NAME);
	if (IS_ERR(dmatest_class))
		return -1;
	//create a dmatest device from this class
	device_create(dmatest_class,NULL,MKDEV(dmatest_major,0),NULL,DEVICE_NAME);

	//alloc 512B src memory and dst memory
	src = dma_alloc_coherent(NULL, 512, &dma_src, GFP_KERNEL);
	printk(KERN_INFO "src = 0x%x, dma_src = 0x%x\n",src, dma_src);

	dst = dma_alloc_coherent(NULL, 512, &dma_dst, GFP_KERNEL);
	printk(KERN_INFO "dst = 0x%x, dma_dst = 0x%x\n",dst, dma_dst);

	for (i = 0; i < 512; i++){
		*(src + i) = 'a';
	}

	dma_cap_zero(mask);
	dma_cap_set(DMA_MEMCPY, mask);//direction:memory to memory
	chan = dma_request_channel(mask,NULL,NULL); //request a dma channel
	printk(KERN_INFO "dma channel id = %d\n",chan->chan_id);

	flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
	dev = chan->device;

	return 0;
}

void dmatest_exit(void)
{
	unregister_chrdev(dmatest_major,DEVICE_NAME);//release major device number
	device_destroy(dmatest_class,MKDEV(dmatest_major,0));//destroy globalmem device
	class_destroy(dmatest_class);//destroy globalmem class

	//free memory and dma channel
	dma_free_coherent(NULL, 512, src, &dma_src);
	dma_free_coherent(NULL, 512, dst, &dma_dst);

	dma_release_channel(chan);
}

module_init(dmatest_init);
module_exit(dmatest_exit);

MODULE_LICENSE("GPL");
时间: 2024-08-06 16:02:33

linux下DMA驱动测试代码的相关文章

linux下libphenom的测试代码

使用说明:测试使用libphenom库的字符串追加函数,效率是strcat的60多倍.所以在进行大量的字符串累加的时候可以考虑使用libphenom库  依赖库: ck-0.4.5.tar.gz cmake-3.1.2.tar.gz libtap-1.12.0.tar.bz2 libphenom.tar.gz 头文件: #include <phenom/sysutil.h> #include <phenom/string.h> #include <phenom/stream.

Linux下spi驱动开发

转载至:http://www.embedu.org/Column/Column367.htm 作者:刘洪涛,华清远见嵌入式学院讲师. 一.概述 基于子系统去开发驱动程序已经是linux内核中普遍的做法了.前面写过基于I2C子系 统的驱动开发.本文介绍另外一种常用总线SPI的开发方法.SPI子系统的开发和I2C有很多的相似性,大家可以对比学习.本主题分为两个部分叙述,第一 部分介绍基于SPI子系统开发的理论框架:第二部分以华清远见教学平台FS_S5PC100上的M25P10芯片为例(内核版本2.6

linux下无线鼠标驱动执行流程

操作系统: debian 7.4(linux 3.2.54) 硬件: 一个无线鼠标.一个有线鼠标 从淘宝上花了15块钱买了个无线鼠标,很好奇它的驱动程序是如何执行的. 首先执行下面命令来捕获uevent事件: sudo udevadm monitor 然后插入和移除再插入无线鼠标的nano接收器(为了完整的查看信息才操作这么多次),可以在控制台下查看到下面的信息: $ sudo udevadm monitor monitor will print the received events for:

Linux下二进制包和源代码包的区分

主要提供三种格式的mysql包:rpm格式.二进制格式.源码格式:(tar打包,gz压缩) rpm格式: libjpeg-devel-6b-33.x86_64.rpm       #rpm格式很好区分, 二进制包: mysql-3.23.58-pc-linux-i686.tar.gz   #二进制格式的包名字很长,有版本号.适应平台.适应的硬件类型等,格式:mysql-<版本>-<OS>-tar.gz 源码包:    php-5.2.14.tar.gz              

arch linux下nvidia 驱动死机问题

好长一段时间了,自从某次arch滚动升级nvidia驱动后,就频繁的Xorg死掉.一直没能解决,只好换用nouveau.nouveau一般使用问题到不大,但是前几天nouveau升级后,也开始抽筋. 于是又尝试换回nvidia的专有驱动,死机情况依然未解.偶然在死机后,用ssh连接上后用dmesg抓到一个错误: NVRM: GPU at 0000:01:00.0 Has Fallen Off The Bus 一番搜索,找到这篇文章: http://www.cyberciti.biz/faq/de

怎样在Windows和Linux下写相同的代码

目前,Linux在国内受到了越来越多的业内人士和用户的青睐.相信在不久的将来,在国内为Linux开发 的应用软件将会有很大的增加(这不,金山正在招兵买马移植WPS呢).由于未来将会是Windows和Linux两强鼎立的格局,怎样能够使得开发的软件保持最大的可移植性就成了一个很重要的问题.小弟经过一段时间的摸索,找到了这个问题的圆满解答. 在Linux下,所有的开发工具和库都属于自由软件,可以免费获得并且功能强大.如果这些工具和库都有相应的Windows版,那么我们就能够在Windows和Linu

Linux下adb驱动问题Linux下使用手机USB调试模式连接ADB进行Android程序的调试

Linux 下adb 驱动问题 Linux下使用手机USB调试模式连接ADB进行Android程序的调试,配置驱动没有Windows来的直观. 具体步骤首先确认手机连接上电脑,lsusb查看下设备记录. [email protected]:~$ lsusb Bus 007 Device 009: ID 18d1:4e12 Bus 007 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 006 Device 001: ID 1d

(转)linux下编译驱动

参考: 1,linux下编译运行驱动 http://blog.csdn.net/zeroboundary/article/details/9294715 2,A Simple Driver for Linux OShttp://www.codeproject.com/Articles/112474/A-Simple-Driver-for-Linux-OS (转)linux下编译驱动

Linux下配置及测试PHP

1.拷贝PHP配置文件 cd /usr/local/php/etc cp php.ini /usr/local/php/lib/php.ini 2.修改apache配置文件 vi /usr/local/apache/conf/httpd.conf 添加对php的支持: LoadModule php5_module modules/libphp5.so AddType application/x-httpd-php .php(注意中间有个空格) 3.测试 1)编写一个php文件,如phpinfo.