This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

AM437x Linux下如何使用EDMA



Hi all,

我们集成了一颗FPGA到系统(通过GPMC总线),现在希望通过dma读取FPGA数据,遇到点问题,如下:

1. 我应该使用哪个DMA通道?

根据TRM 10.3.20, 一些通道已经绑定到特定的模块了,所以我只能使用那些没有被绑定的通道,比如通道4,对吗?

2. 如何正确地使用dma api:

bool fpga_dma_filter_fn(struct dma_chan *chan, void *param)
{
    int chan_id = *(unsigned int *)param;
    if (chan_id == chan->chan_id)
        return true;
 return false;
}

void dma_init()

{

   dma_cap_mask_t mask;

   dma_cap_zero(mask);

   dma_cap_set(DMA_SLAVE, mask);

   unsigned int id = 4;

   gFpgaDmaChan = dma_request_channel(mask, fpga_dma_filter_fn, &id);

}

int fpga_dma_read(dma_addr_t dst, unsigned int len)
{
    struct dma_slave_config config;
    struct dma_async_tx_descriptor *desc;
    unsigned long flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;

    config.direction = DMA_DEV_TO_MEM;
    config.dst_addr = dst;
    config.src_addr = FPGA_PHY_BASE + 6;  --> the source address
    config.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
    config.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
    config.dst_maxburst = 16;
    config.src_maxburst = 16;
    dmaengine_slave_config(gFpgaDmaChan, &config);

    desc = dmaengine_prep_slave_single(
        gFpgaDmaChan, dst, len, DMA_DEV_TO_MEM, flags);

    desc->callback = fpga_dma_callback;
    dmaengine_submit(desc);
    dma_async_issue_pending(gFpgaDmaChan);
    return 1;
}

void fpga_test()

{

        dma_addr_t dest;
        char *ptr = dma_alloc_coherent(NULL, 1024, &dest, GFP_DMA);
        memset(ptr, 0x11, 1024);
        fpga_dma_read(dest, 1024);
        mdelay(1000);
        for (int i=0;i<33;i++){
            printk("0x%x ", ptr[i]);
        }

}

我在调用fpga_test时候,发现dma仅仅拷贝了config.src_maxburst *  config.src_addr_width = 16 * 2 = 32 bytes,然后就停止了,ptr[32]及后面的数据仍为0x11,并且fpga_dma_callback也没有被调用到,是我哪里使用、配置的不对吗?

烦请大牛们帮帮忙啊,谢谢了!!!

  • 1. 所有通道都可以用,10.3.20是EDMA的触发事件。

    2. param参数是如何设置的?

  • 多谢回复!

    你说的这个参数是在drivers/dma/dma.c里面设置的吧?

    这个还没有看,这个EDMA看起来好复杂,我只是需要使用它而已,现在不清楚是不是使用的api什么的有问题?

    我看drivers/mtd/nand/omap2.c里面也差不多是这么使用dma api的。

    我测过过Memory To Memory的传输,是正常工作的。

    另外,我的Kernel是4.4.19的。

  • Hi,我打印了下param的设置:

    @@@@@@@ acnt: 2, bcnt: 16, opt: 0x4004, src: 0x4000006, a_b_cnt: 0x100002, dst: 0xbc000000, src_dst_bidx: 0x20000, link_bcntrld: 0xffffffff, src_dst_cidx: 0x200000, ccnt: 16

  • Hi,

    我配置了ITCCHEN,这样就可以正确传输了,搜索edma.c,发现只有在edma_prep_dma_memcpy里面才会去配置这个bit,而我们用的是自定义的FPGA,按说这个外设应该和SD卡之类的一样的配置,是不是因为我们自定义的外设没有trigger event?