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");


  • 1
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Linux中的DMA(Direct Memory Access,直接内存访问)是一种数据传输方式,它允许外部设备(如网卡、声卡、磁盘控制器等)直接访问系统内存,而无需CPU的干预。这种方式能够提高数据传输的效率和速度。 在Linux系统中进行DMA测试可以通过以下步骤进行: 1. 确保系统已经加载了DMA控制器的驱动程序,可以使用命令`lsmod`来查看系统加载的模块,包括与DMA相关的模块。 2. 定义一个DMA缓冲区,在测试中可以使用内核提供的函数`dma_alloc_coherent()`来分配一块连续的内存空间。 3. 配置DMA控制器,包括设置传输模式、传输方向、数据缓冲区等。这可以通过调用DMA设备驱动程序提供的接口来完成。 4. 准备测试数据,可以通过编写测试代码来生成一些测试数据,然后将其写入DMA缓冲区中。 5. 启动DMA传输,执行DMA控制器的传输操作。这可以通过调用DMA设备驱动程序提供的接口来完成。 6. 验证传输结果,在传输完成后,可以检查DMA缓冲区中的数据是否正确,以确保传输的准确性。 7. 释放DMA资源,包括释放DMA缓冲区和关闭DMA控制器等。 通过以上步骤可以对Linux系统中的DMA进行测试,以验证DMA传输的正确性和稳定性。测试结果可以用来评估系统性能和调优。在测试过程中需要注意保证测试环境的稳定性和系统资源的充足性,以获得可靠的测试结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值