想要了解u-dam-buf可以查看 https://github/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>");
MODULE_DESCRIPTION("simple driver using dmaengine");
代码可以直接用
更多推荐
DMA驱动的demo
发布评论