打印
[i.MX]

i.MX_6Quad_6Dual的DMA测试

[复制链接]
4257|11
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
精灵脚|  楼主 | 2014-8-6 21:48 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
AD, DMA, i.mx, TE, ST
项目想用EIM的DMA,有没有合适的参考?
我在linux3.0.35中找到了一个Dmatest.c程序,是个驱动,但运行时总是报错。
        dma_cap_set(DMA_MEMCPY, mask);
        for (;;) {
                chan = dma_request_channel(mask, filter, NULL);
                ......
        }
dmatest_init函数中,这段程序不能用DMA_MEMCPY吗?
另外,这个Dmatest.c程序实现了什么功能,是两块内存间DMA?

相关帖子

沙发
精灵脚|  楼主 | 2014-8-6 22:06 | 只看该作者
提示错误是:
damtest_init
dmaengine: failed to get dma0chan0: (-22)
dmaengine: failed to get dma1chan0: (-22)

我是在make menuconfig中,配置Device Drivers\DMA Engine support\DMA Test client,编译到内核中。内核启动时,就上面的错误。

使用特权

评论回复
板凳
FSL_TICS_A| | 2014-8-7 09:59 | 只看该作者
你好,楼主!
我会将你的问题转告给i.MX工程师,他稍后会回复你的

使用特权

评论回复
地板
FSL_TICS_Rita| | 2014-8-7 10:44 | 只看该作者
楼主你好,关于DMA的问题建议你到飞思卡尔官网创建一个技术服务SR请求,链接为:https://bbs.21ic.com/icview-684518-1-1.html

使用特权

评论回复
5
精灵脚|  楼主 | 2014-8-8 20:15 | 只看该作者
bsp中找到了个能运行的测试例子,驱动mxc_sdma_memcopy_test.c,应用mxc_sdma_test.c。

使用特权

评论回复
6
FSL_TICS_A| | 2014-8-11 09:35 | 只看该作者
精灵脚 发表于 2014-8-8 20:15
bsp中找到了个能运行的测试例子,驱动mxc_sdma_memcopy_test.c,应用mxc_sdma_test.c。 ...

你好,楼主!
如果问题解决,请结贴!

使用特权

评论回复
7
精灵脚|  楼主 | 2014-8-13 10:40 | 只看该作者
又不能结贴。。。。。。

使用特权

评论回复
8
FSL_TICS_Rita| | 2014-8-13 10:57 | 只看该作者
精灵脚 发表于 2014-8-13 10:40
又不能结贴。。。。。。

非常感谢楼主对我们工作的支持,欢迎有问题继续在本论坛中提问和讨论哈~~

使用特权

评论回复
9
ericvic| | 2014-8-22 14:52 | 只看该作者
本帖最后由 ericvic 于 2014-8-22 15:05 编辑

你好我现在imx53上遇到也是相关eim与dma的问题,是这样的,我的eim上挂了一个cpld,然后我想用dma来实现cpld与内存的通信,之前用的是ioremap实现的用cpu来处理内存跟cpld的通信,cpld在eim上的起始物理地址是0xf4000000(ioremap(0xf4000000,SIZE_4K)) ,关键是现在我用
dma的话,我该怎么设置以下是我根据mxc_sdma_memcopy_test.c修改的测试代码,一直不通,请问大神我该怎样修改,谢谢!!!!

#include <linux/module.h>
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/mman.h>
#include <linux/init.h>
#include <linux/dma-mapping.h>
#include <linux/fs.h>
#include <linux/version.h>
#include <linux/delay.h>
#include <mach/dma.h>

#include <linux/dmaengine.h>
#include <linux/device.h>

#include <linux/io.h>
#include <linux/delay.h>

static int gMajor; /* major number of device */
static struct class *dma_tm_class;
u32 *wbuf, *wbuf2, *wbuf3;
u32 *rbuf, *rbuf2, *rbuf3;
u32 *rxbuf,*txbuf;
struct dma_chan *dma_m2m_chan_rx,*dma_m2m_chan_tx;

struct completion dma_m2m_ok;

struct scatterlist sg_rx[1],sg_tx[1],sg[3], sg2[3];

#define SDMA_BUF_SIZE  1024



static bool dma_m2m_filter(struct dma_chan *chan, void *param)
{
        if (!imx_dma_is_general_purpose(chan))
                {
        printk("I #################\n");
                return false;
        }
        chan->private = param;
        return true;
}
static void dma_m2m_callback(void *data)
{
        printk("in %s\n",__func__);
        complete(&dma_m2m_ok);
        return ;
}
static int imx_fpga_dma_init()
{

        dma_cap_mask_t dma_m2m_mask;
        struct imx_dma_data m2m_dma_data = {0};
        struct dma_slave_config dma_m2m_config;
        init_completion(&dma_m2m_ok);

        dma_cap_zero(dma_m2m_mask);
        dma_cap_set(DMA_SLAVE, dma_m2m_mask);
        m2m_dma_data.peripheral_type = IMX_DMATYPE_EXT;
        m2m_dma_data.priority = DMA_PRIO_HIGH;

        dma_m2m_chan_rx = dma_request_channel(dma_m2m_mask, dma_m2m_filter, &m2m_dma_data);
        dma_m2m_config.direction = DMA_FROM_DEVICE;
        dma_m2m_config.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
       dma_m2m_config.src_addr =0x74000000;
        dmaengine_slave_config(dma_m2m_chan_rx, &dma_m2m_config);
        rxbuf=kzalloc(SDMA_BUF_SIZE, GFP_DMA);
        /* tx*/
        dma_m2m_chan_tx = dma_request_channel(dma_m2m_mask, dma_m2m_filter, &m2m_dma_data);
        dma_m2m_config.direction = DMA_TO_DEVICE;
        dma_m2m_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
        dma_m2m_config.dst_addr =0x74000000;
        dmaengine_slave_config(dma_m2m_chan_tx, &dma_m2m_config);
        
        txbuf=kzalloc(SDMA_BUF_SIZE, GFP_DMA);

}
static int start_rx_dma()
{
        int ret;
        struct dma_async_tx_descriptor *desc;
        sg_init_table(sg_rx, 1);
        sg_set_buf(&sg_rx[0],rxbuf,SDMA_BUF_SIZE);
        ret = dma_map_sg(NULL, sg_rx, 1, DMA_FROM_DEVICE);
        if (ret == 0) {
                pr_err("DMA mapping error for RX.\n");
                return -EINVAL;
        }
        desc = dma_m2m_chan_rx->device->device_prep_slave_sg(dma_m2m_chan_rx,
                                sg_rx, 1, DMA_FROM_DEVICE, 0);
        if (!desc) {
                pr_err("We cannot prepare for the RX slave dma!\n");
                return -EINVAL;
        }
        desc->callback = dma_m2m_callback;
        dmaengine_submit(desc);

        dmaengine_submit(desc);
        dma_unmap_sg(NULL, sg_rx, 1, DMA_FROM_DEVICE);
        return 0;
}
static int start_tx_dma()
{
        int ret;
        struct dma_async_tx_descriptor *desc;
        memset(txbuf,0x33,SDMA_BUF_SIZE);
        sg_init_table(sg_tx, 1);
        sg_set_buf(&sg_tx[0],txbuf,SDMA_BUF_SIZE);
        ret = dma_map_sg(NULL, sg_tx, 1, DMA_TO_DEVICE);
        desc = dma_m2m_chan_tx->device->device_prep_slave_sg(dma_m2m_chan_tx,
                                sg_tx, 1, DMA_FROM_DEVICE, DMA_PREP_INTERRUPT| DMA_COMPL_SKIP_DEST_UNMAP);
        if (!desc) {
                pr_err("We cannot prepare for the tX slave dma!\n");
                return -EINVAL;
        }
        desc->callback = dma_m2m_callback;
        dmaengine_submit(desc);

        dmaengine_submit(desc);
        dma_unmap_sg(NULL, sg_tx, 1, DMA_TO_DEVICE);
        
        return 0;
}

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

int sdma_release(struct inode * inode, struct file * filp)
{
        dma_release_channel(dma_m2m_chan_rx);
        dma_m2m_chan_rx = NULL;
        dma_release_channel(dma_m2m_chan_tx);
        dma_m2m_chan_tx = NULL;
/*        kfree(wbuf);
        kfree(wbuf2);
        kfree(wbuf3);
        kfree(rbuf);
        kfree(rbuf2);
        kfree(rbuf3);*/
        return 0;
}

ssize_t sdma_read (struct file *filp, char __user * buf, size_t count,
                                                                loff_t * offset)
{
        //start_rx_dma();
   
        return 0;
}



ssize_t sdma_write(struct file * filp, const char __user * buf, size_t count,
                                                                loff_t * offset)
{
        start_tx_dma();
      
        return 0;
}

struct file_operations dma_fops = {
        open:                sdma_open,
        release:        sdma_release,
        read:                sdma_read,
        write:                sdma_write,
};

int __init sdma_init_module(void)
{
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26))
        struct device *temp_class;
#else
        struct class_device *temp_class;
#endif
        int error;

        /* register a character device */
        error = register_chrdev(0, "sdma_test", &dma_fops);
        if (error < 0) {
                printk("SDMA test driver can't get major number\n");
                return error;
        }
        gMajor = error;
        printk("SDMA test major number = %d\n",gMajor);

        dma_tm_class = class_create(THIS_MODULE, "sdma_test");
        if (IS_ERR(dma_tm_class)) {
                printk(KERN_ERR "Error creating sdma test module class.\n");
                unregister_chrdev(gMajor, "sdma_test");
                return PTR_ERR(dma_tm_class);
        }

#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28))
        temp_class = device_create(dma_tm_class, NULL,
                                   MKDEV(gMajor, 0), NULL, "sdma_test");
#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26))
        temp_class = device_create(dma_tm_class, NULL,
                                   MKDEV(gMajor, 0), "sdma_test");
#else
        temp_class = class_device_create(dma_tm_class, NULL,
                                             MKDEV(gMajor, 0), NULL,
                                             "sdma_test");
#endif
        if (IS_ERR(temp_class)) {
                printk(KERN_ERR "Error creating sdma test class device.\n");
                class_destroy(dma_tm_class);
                unregister_chrdev(gMajor, "sdma_test");
                return -1;
        }

        printk("SDMA test Driver Module loaded\n");
        return 0;
}

static void sdma_cleanup_module(void)
{
        unregister_chrdev(gMajor, "sdma_test");
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26))
        device_destroy(dma_tm_class, MKDEV(gMajor, 0));
#else
        class_device_destroy(dma_tm_class, MKDEV(gMajor, 0));
#endif
        class_destroy(dma_tm_class);

        printk("SDMA test Driver Module Unloaded\n");
}


module_init(sdma_init_module);
module_exit(sdma_cleanup_module);

MODULE_AUTHOR("Freescale Semiconductor");
MODULE_DESCRIPTION("SDMA test driver");
MODULE_LICENSE("GPL");

使用特权

评论回复
10
ericvic| | 2014-8-22 14:54 | 只看该作者
本帖最后由 ericvic 于 2014-8-22 15:00 编辑

我测试memory-to-memory的测试程序是可以运行的,现在是因为cpld作为外部的io内存设备,用ioremap出来的地址,dma根本就无法识别,所以也就无法使用这种内存到内存的方式

使用特权

评论回复
11
shangzuwei| | 2014-8-23 18:54 | 只看该作者
ericvic 发表于 2014-8-22 14:54
我测试memory-to-memory的测试程序是可以运行的,现在是因为cpld作为外部的io内存设备,用ioremap出来的地 ...

楼上的   不知道 你问题解决没有   我现在也在用DMA  是想挂在spi上  可是callback函数就是一直都不进

使用特权

评论回复
12
精灵脚|  楼主 | 2014-8-26 12:21 | 只看该作者
ericvic 发表于 2014-8-22 14:52
你好我现在imx53上遇到也是相关eim与dma的问题,是这样的,我的eim上挂了一个cpld,然后我想用dma来实现cpl ...

直接用copy_to_user

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

5

主题

23

帖子

0

粉丝