首页 > 解决方案 > 使用 DMA 内核模块从保留的内存中复制数据

问题描述

我们正在开发一个自定义模块,它将读取由 FPGA 写入的数据到保留的内存位置。一旦数据准备好,就会触发中断以警告模块它可以读取数据(读取部分在 tasklet 中完成)。

目前,我们正在使用 memremap 将物理地址映射到虚拟地址。之后,我们使用 memcpy 将缓冲区数据复制到内核中的缓冲区中。

主要问题是 memcpy 太慢(对于每像素 8 位的 1280*480 像素图像,我们无法每秒读取 60 帧)。似乎正确的方法是使用 DMA 引擎来加速复制。

尽管搜索了很长时间,但我找不到演示如何做到这一点的示例?我看到如果你保留了内存,你可以使用 dma_alloc_coherent 分配其中的一些。但是我想指定保留内存中物理缓冲区的偏移量(就像我在使用 memremap 时所做的那样)。

我目前拥有的是:

    dma_cap_mask_t              _dma_cap_mask;
    struct dma_chan             *_dma_channel;
    struct dma_slave_config     _dma_cfg;

    dma_cap_zero(_dma_cap_mask);
    dma_cap_set(DMA_MEMCPY, _dma_cap_mask);
    _dma_channel = dma_request_channel(_dma_cap_mask, NULL, NULL);
    if (!p3v4l2fg._dma_channel) {
        PRINT_ERROR("Cannot request DMA channel\n");
        ret = -ENODEV;
        goto failure;
    }

    _dma_cfg.direction = DMA_MEM_TO_MEM;
    _dma_cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_32_BYTES;

    dmaengine_slave_config(_dma_channel, &_dma_cfg);

据我了解,执行前面的代码可以让我拥有一个 DMA 通道,但是从那里开始,正如我上面解释的那样,我有点迷茫:|

如何替换下面的逻辑

void * data = buf->data;
vaddr = memremap(paddr, singleBufferSize, MEMREMAP_WB);
memcpy(data, vaddr, singleBufferImSize);

使用 DMA 传输?(paddr 是保留内存范围内的物理地址,singleBufferSize 是我必须复制的字节数)。

非常感谢你能给我的任何帮助!

你的,

皮尔

标签: modulekernelfpgadma

解决方案


推荐阅读