DMA驱动的demo

想要了解u-dam-buf可以查看 https://github.com/ikwzm/udmabuf/tree/v3.2.5
其中有各种开源的版本,配合DMA芯片手册,可以在应用层操作。

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

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

#include <linux/dmaengine.h>
#include <linux/dma-mapping.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/miscdevice.h>
#include <linux/device.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/of_device.h>
#include <linux/async_tx.h>
#include <asm/uaccess.h>
#include <asm/delay.h>
#include <linux/uaccess.h> //copy_from_user  and copy_to_user

struct dma_chan *chan;
static char *txbuf;
static char *rxbuf;
dma_addr_t txaddr;
dma_addr_t rxaddr;
#define   MAX_SIZE  (24)
#define   DMA_SPACE_SIZE  (0x800000)
#define DEVICE_NAME "ax_dma"

static int dma_open(struct inode *inode, struct file *file)
{
    printk("dma_open\r\n");
    return 0;
}

static int dma_release(struct inode *indoe, struct file *file)
{
    printk("dma_release\r\n");
    return 0;
}

static void dma_callback(void *data)
{
	int i;
	char  *p = rxbuf;
	printk("dma complete\n");

	for (i = 0; i < MAX_SIZE; i++)
    {
        printk("0x%x ", *p++);
    }

	printk("\n");
}

static bool filter(struct dma_chan *chan, void *filter_param)
{
	printk("filter :%s\n", dma_chan_name(chan));
	return strcmp(dma_chan_name(chan), filter_param) == 0;
}


ssize_t dma_read(struct file *file, char __user *buff, size_t size, loff_t *loff)
{
    printk("size :%d\n",size);
    int err;
    err = copy_to_user(buff,rxbuf,size);
    if(err){
        printk("copy_to_user fail..\n");
        return -1;
    }
    return 1;
}

static struct file_operations ax_fops =
{
    .owner   = THIS_MODULE,
   // .open    = dma_open,
    .read    = dma_read,
  //  .release = dma_release,
};

static struct miscdevice dma_misc =
{
    .minor = MISC_DYNAMIC_MINOR,
    .name  = DEVICE_NAME,
    .fops  = &ax_fops,
};

static int __init memcpy_init(void)
{
	int i, ret;
	dma_cap_mask_t mask;
	struct dma_async_tx_descriptor *desc;
	char name[] = "dma2chan0";
	unsigned int *p;
    enum dma_ctrl_flags flags;


     ret = misc_register(&dma_misc);
    if(ret)
    {
        printk("misc_register failed!\n");
        return 0;
    }
    printk("drv register ok  %d\n",PAGE_SIZE);

	dma_cap_zero(mask);
	dma_cap_set(DMA_MEMCPY, mask);
	chan = dma_request_channel(mask, filter, name);
	if (!chan) {
		printk("dma_request_channel failure\n");
		return -ENODEV;
	}

	txbuf = dma_alloc_coherent(chan->device->dev, DMA_SPACE_SIZE, &txaddr, GFP_KERNEL);
	if (!txbuf) {
		printk("dma_alloc_coherent failure\n");
		dma_release_channel(chan);
		return -ENOMEM;
	}

	rxbuf = dma_alloc_coherent(chan->device->dev, DMA_SPACE_SIZE, &rxaddr, GFP_KERNEL);
	if (!rxbuf) {
		printk("dma_alloc_coherent failure\n");
		dma_free_coherent(chan->device->dev, DMA_SPACE_SIZE, txbuf, txaddr);
		dma_release_channel(chan);
		return -ENOMEM;
	}

	// for (i = 0, p = txbuf; i < (DMA_SPACE_SIZE-1); i++)
    // {
    //     *p++ = i;
    // }
    memset(txbuf, 0x5, DMA_SPACE_SIZE);
    memcpy(txbuf,"hellojsjkakdjdjjabcdwqn",23);

	// for (i = 0, p = txbuf; i < MAX_SIZE; i++)
    // {
    //     printk("%d ", *p++);
    // }
	// printk("\n");

	 memset(rxbuf, 0, DMA_SPACE_SIZE);
	// for (i = 0, p = rxbuf; i < MAX_SIZE; i++)
    // {
    //     printk("%d ", *p++);
    // }

	printk("\n");
    //flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;

	desc = chan->device->device_prep_dma_memcpy(chan, rxaddr, txaddr, DMA_SPACE_SIZE, DMA_CTRL_ACK | DMA_PREP_INTERRUPT);
	desc->callback = dma_callback;
	desc->callback_param = NULL;

	dmaengine_submit(desc);
	dma_async_issue_pending(chan);

	return 0;
}

static void __exit memcpy_exit(void)
{
	dma_free_coherent(chan->device->dev, PAGE_SIZE, txbuf, txaddr);
	dma_free_coherent(chan->device->dev, PAGE_SIZE, rxbuf, rxaddr);
	dma_release_channel(chan);
	misc_deregister(&dma_misc); 
}

module_init(memcpy_init);
module_exit(memcpy_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Kevin Jiang <jiangxg@farsight.com.cn>");
MODULE_DESCRIPTION("simple driver using dmaengine");

代码可以直接用

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值