dma 测试程序

驱动程序:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/miscdevice.h>
#include <linux/irq.h>
#include <linux/delay.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/io.h>
#include <asm/uaccess.h>

#include <linux/pci.h>

//#include <linux/amba/pl330.h>
//#include <mach/dma.h>
//#include <plat/dma-ops.h>
 
#define BUF_SIZE        512
#define MEM_CPY_NO_DMA    _IOW('L', 0x1210, int)
#define MEM_CPY_DMA    _IOW('L', 0x1211, int)

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


void dma_callback_func(void* param)
{
    if(0 == memcmp(src, dst, BUF_SIZE))
        printk("MEM_CPY_DMA OK\n");
    else
        printk("MEM_CPY_DMA ERROR\n");
}

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


long my_dma_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
    int i = 0;

    memset(src, 0xAA, BUF_SIZE);
    memset(dst, 0xBB, BUF_SIZE);

    switch (cmd)
    {
        case MEM_CPY_NO_DMA:
            for(i = 0; i < BUF_SIZE; i++)
                dst[i] = src[i];

            if(0 == memcmp(src, dst, BUF_SIZE))
                printk("MEM_CPY_NO_DMA OK\n");
            else
                printk("MEM_CPY_DMA ERROR\n");

            break;

        case MEM_CPY_DMA:
        flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
        dev = chan->device;
            tx = dev->device_prep_dma_memcpy(chan, dma_dst, dma_src, BUF_SIZE, flags);
            if(!tx)
                printk("%s failed to prepare DMA memcpy\n", __func__);
             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("failed to do DMA tx_submit");
            }

            dma_async_issue_pending(chan);         // begin dma transfer
            break;

        default:
            break;
    }

    return 0;
}


int  my_dma_release(struct inode *inode, struct file *filp)
{
    return 0;
}
 
const struct file_operations my_dma_fops = {
    .open   = my_dma_open,
    .unlocked_ioctl = my_dma_ioctl,
    .release = my_dma_release,
};
 
struct miscdevice dma_misc = {
    .minor  = MISC_DYNAMIC_MINOR,
    .name   = "dma_m2m_test",
    .fops   = &my_dma_fops,
};

static void __exit my_dma_exit(void)
{
if(chan)    
{   
    dma_release_channel(chan);
    dma_free_coherent(chan->device->dev, BUF_SIZE, src, dma_src);
    dma_free_coherent(chan->device->dev, BUF_SIZE, dst, dma_dst);
}
    misc_deregister(&dma_misc);
}

//struct device    *pmydev;

static int __init my_dma_init(void)
{
    int ret = misc_register(&dma_misc);
    dma_cap_mask_t mask;

    if(ret < 0){
        printk("%s misc register failed !\n", __func__);
        return -EINVAL;
    }
 
    printk("%s misc register ok !\n", __func__);

//    dma_cap_mask_t mask;
    dma_cap_zero(mask);
    //dma_cap_set(DMA_MEMCPY, mask);                       // direction: m2m
    dma_cap_set(DMA_SLAVE, mask);                          // direction: m2m
    
    chan = dma_request_channel(mask, NULL, NULL);
    if(NULL == chan){
    msleep(100);
    chan = dma_request_channel(mask, NULL, NULL);  // request to dma channel
    }
 
    if(NULL == chan)
    {
        printk("chan request failed !\n");
    }
    else
    {    
        printk("chan OK!\n");
        if(chan->device && chan->device->dev)    
        printk("chan name %s \n",dev_name(chan->device->dev) );

        if(chan->dev)     
        printk("sys name %s  \n",dev_name(&(chan->dev->device)));
  
          if(chan->slave)                        
        printk("slave name %s \n",dev_name(chan->slave));

         // alloc 512 byte src memory and dst memory
        src = dma_alloc_coherent(chan->device->dev, BUF_SIZE, &dma_src, GFP_KERNEL);
        printk("src = %p, dma_src = %llu\n", src, dma_src);

        dst = dma_alloc_coherent(chan->device->dev, BUF_SIZE, &dma_dst, GFP_KERNEL);
        printk("dst = %p, dma_src = %llu\n", dst, dma_dst);

    }

    return 0;
}
module_init(my_dma_init);
module_exit(my_dma_exit);

MODULE_LICENSE("GPL");

app测试程序:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <fcntl.h>
 
 
#define DEV_NAME        "/dev/dma_m2m_test"
#define MEM_CPY_NO_DMA    _IOW('L', 0x1210, int)
#define MEM_CPY_DMA        _IOW('L', 0x1211, int)
 
int main(void)
{
    int fd = -1,
        ret = -1;
 
    fd = open(DEV_NAME, O_RDWR);
    if(fd < 0){
        printf("open fail !\n");
        exit(1);
    }
 
    ioctl(fd, MEM_CPY_NO_DMA, 0);
    sleep(1);
 
    ioctl(fd, MEM_CPY_DMA, 0);
    sleep(1);
 
    return 0;
}

makefile:

obj-m = dmatest.o
kernel_dir = /home/XX/kernel/

all:
    make -C $(kernel_dir) ARCH=arm64  M=${PWD} modules
    $(CROSS_COMPILE)gcc -o myapp  myapp.c
clean:
    make -C $(kernel_dir) ARCH=arm64  M=${PWD} clean    
 

执行情况:

root@rk3588-buildroot:/data/my-dmatest# insmod dmatest.ko
[   74.346086] my_dma_init misc register ok !
root@rk3588-buildroot:/data/my-dmatest# [   74.346144] chan OK!
[   74.346151] chan name fea10000.dma-controller
[   74.346157] sys name dma0chan2
[   74.346206] src = 00000000e159c068, dma_src = 2351104
[   74.346222] dst = 0000000066a0dfd3, dma_src = 2363392
 

root@rk3588-buildroot:/data/my-dmatest# ./myapp
[   82.427124] MEM_CPY_NO_DMA OK
[   83.427635] MEM_CPY_DMA OK

参考文档:

解读Linux内核DMA子系统驱动开发程序 - 知乎 (zhihu.com)

ps:参考文档在我的rk3588上编译不过,运行的时候也会出问题,已经修改了,

执行正常,验证通过

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值