[编辑]
我有一个带有 fpga (SoC) 的 arm64 板。
任务很简单:
- 可以将数据从/到“用户空间”区域(应用程序)传输到/从“内核空间”物理内存(设备内存 = fpga regs),有和没有 dma 支持使用(流式传输类型)。那个 dma 在板上(ZynqMP / GDMA)。
我将有几个设备 - 在 fpga 和外部,应该使用这种通信,但现在我只使用 fpga-ddr4 内存区域。
现在我看到了下一个逻辑流程:
- 一些初始化(dma 参数等);
- ioremap() 一个 fpga 设备区域;
- 制作一个缓冲区(通过 kzalloc() 或其他) - 这个缓冲区我应该通过 mmap fops 给美国;
- 从缓冲区制作一个分散列表(下面的伪代码);
- 使用 scatterlist 和 dmaengine 来传输数据;
// scatterlist init pseudo-code
struct scatterlist sgl[2];
struct scatterlist *sge;
int i, buf_n, err_code;
__u8 *buffer; // allocated earlier
sg_init_table(sgl, ARRAY_SIZE(sgl));
for_each_sg(sgl, sge, ARRAY_SIZE(sgl), i) {
struct page *pg = virt_to_page(buffer + i * PAGE_SIZE);
dma_addr_t dma_handle = dma_map_page(&pdev->dev, pg, 0, PAGE_SIZE, direction /* DMA_TO_DEVICE */);
if ((err_code = dma_mapping_error(&pdev->dev, dma_handle))) {
dev_err(&pdev->dev, "dma page mapping failed! (code: %i)\n", err_code);
break;
}
sg_set_page(sge, pg, PAGE_SIZE, 0);
}
dma_map_sg(&pdev->dev, sgl, ARRAY_SIZE(sgl), direction) // with appropriate check
现在我误解了下一个 - 目的地如何或在哪里控制?我的意思是,我已经在 RAM 中分配了缓冲区,从中创建了 scatterlist,并通过 dmaengine 函数的参数给出了这个列表以进行传输。但我没有设置/使用 ioremapped 设备内存区域来保存这个缓冲区数据!这个 dma 是否仅适用于适当的 RAM 内存区域,我应该将缓冲区复制到设备区域?或者,我应该使用 ioremap 区域作为缓冲区吗?是正确的流量吗?请解释一下我的错误?