Linux DMA API:指定地址增量行为?
我正在为FPGA编写驱动程序,需要支持两种数据传输模式:Linux DMA API:指定地址增量行为?,linux,linux-kernel,dma,Linux,Linux Kernel,Dma,我正在为FPGA编写驱动程序,需要支持两种数据传输模式: FIFO传输:写入(或读取)FPGA FIFO时,DMA控制器不得增加目标(或源)地址 非FIFO传输:这是正常的(类似RAM的)传输,其中源地址和目标地址都要求传输的每个字都有一个增量 我使用的特定DMA控制器是CoreLink DMA-330 DMA控制器,其Linux驱动程序是pl330.c(drivers/DMA/pl330.c)。该DMA控制器提供了一种在“固定地址突发”和“递增地址突发”之间切换的机制(它们与我的“FIFO传输
#define CC_SRCINC (1 << 0)
#define CC_DSTINC (1 << 14)
其中,驱动程序使用desc->rqcfg.src_inc和desc->rqcfg.dst_inc指定地址增量行为
这意味着:
- 指定direction=DMA_MEM_TO_DEV意味着客户端希望将数据从FIFO拉入RAM。大概DMA_DEV_TO_MEM意味着客户端希望将数据从RAM推送到FIFO中
- 分散-聚集DMA操作(至少适用于pl300)仅限于源或目标端点为FIFO的情况。如果我想从系统RAM到FPGA(非FIFO)内存执行分散-聚集操作,该怎么办
pd->device_prep_dma_memcpy = pl330_prep_dma_memcpy;
pd->device_prep_dma_cyclic = pl330_prep_dma_cyclic;
pd->device_prep_slave_sg = pl330_prep_slave_sg;
这意味着你有不同的方法,就像你在文档中读到的那样。我怀疑,通过device\u prep\u dma\u memcpy()
可以完成类似RAM的传输(在查看内核中的各种驱动程序后),我认为这是唯一允许您(间接地)进行dma传输的样式控制自动增量行为是在其相应的设备准备功能中具有枚举dma\u传输方向的行为
根据include/linux/dmaengine.h
另一个选项应该是使用和struct dma_interleaved_template
,它允许您直接指定增量行为。但对这种方法的支持是有限的(例如,在3.8内核中,只有i.MX DMA驱动程序支持它,甚至这种支持似乎也是有限的)
因此,我认为,在一段时间内,我们一直在处理device\u prep\u slave\u sg
案例以及所有与sg
相关的复杂性
这就是我目前正在做的(尽管它是用于访问Atmel SAM9 SOC上的某些EBI连接设备)
另一件需要考虑的是设备的总线宽度。code>memcopy
-根据源和目标地址和大小,variant可以执行不同的总线宽度传输。这可能与FIFO元素的大小不匹配。是的,我是通过阅读pl330驱动程序得到的。看起来我可以为这个特定的DMA控制器驱动程序指定地址增量行为(通过prep_DMA_memcpy()或prep_slave_sg()方法)。但这是所有DMA控制器驱动程序使用的约定吗?如果使用了新的DMA控制器驱动程序,我不希望我的DMA客户端驱动程序中断。您必须修复所有要使用的驱动程序。通用实现允许您使用有限的功能集。不同的DMA控制器行为不同,因此DMA信道的用户应该应对所有可能的情况。
pd->device_prep_dma_memcpy = pl330_prep_dma_memcpy;
pd->device_prep_dma_cyclic = pl330_prep_dma_cyclic;
pd->device_prep_slave_sg = pl330_prep_slave_sg;