【发布时间】:2015-04-09 13:13:37
【问题描述】:
我正在为Altera Soc Developement Kit 编写驱动程序,并且需要支持两种模式的数据与 FPGA 之间的传输:
- FIFO 传输:写入(或读取)FPGA FIFO 时,目标(或源)地址不得由 DMA 控制器递增。
- 非 FIFO 传输:这些是正常(类似于 RAM)的传输,其中源地址和目标地址都需要为每个传输的字增加一个增量。
我使用的特定 DMA 控制器是 CoreLink DMA-330 DMA 控制器,它的 Linux 驱动程序是 pl330.c (drivers/dma/pl330.c)。这个 DMA 控制器确实提供了一种在“固定地址突发”和“递增地址突发”之间切换的机制(这些是我的“FIFO 传输”和“非 FIFO 传输”的同义词)。 pl330 驱动程序通过在 CCRn 寄存器中设置适当的位来指定它想要的行为
#define CC_SRCINC (1 << 0)
#define CC_DSTINC (1 << 14)
我的问题:我完全不清楚 pl330 的客户端(例如我的驱动程序)应该如何指定地址递增行为。
DMA engine client API 没有说明如何指定这一点,而 DMA engine provider API 只是声明:
指向 RAM 的地址通常递增(或递减) 每次转移后。如果是环形缓冲区,它们可能会循环 (DMA_CYCLIC)。指向设备寄存器的地址(例如 FIFO) 通常是固定的。
没有详细说明地址类型如何与提供者通信(在我的例子中是 pl300 驱动程序)。
它在 pl330_prep_slave_sg 方法中的作用:
if (direction == DMA_MEM_TO_DEV) {
desc->rqcfg.src_inc = 1;
desc->rqcfg.dst_inc = 0;
desc->req.rqtype = MEMTODEV;
fill_px(&desc->px,
addr, sg_dma_address(sg), sg_dma_len(sg));
} else {
desc->rqcfg.src_inc = 0;
desc->rqcfg.dst_inc = 1;
desc->req.rqtype = DEVTOMEM;
fill_px(&desc->px,
sg_dma_address(sg), addr, sg_dma_len(sg));
}
之后,驱动程序使用 desc->rqcfg.src_inc 和 desc->rqcfg.dst_inc 来指定地址增量行为。
这意味着以下内容:
- 指定方向 = DMA_MEM_TO_DEV 表示客户端希望将数据从 FIFO 拉入 RAM。并且推测 DMA_DEV_TO_MEM 意味着客户端希望将数据从 RAM 推送到 FIFO。
- Scatter-gather DMA 操作(至少对于 pl300)仅限于源端点或目标端点是 FIFO 的情况。如果我想从系统 RAM 到 FPGA(非 FIFO)内存进行分散收集操作怎么办?
我是否误解和/或忽略了什么? DMA 引擎是否已经提供(未记录的)机制来指定地址增量行为?
【问题讨论】:
标签: linux linux-kernel dma