我们项目的简要描述:我们在项目中使用CycloneV,FPGA将使用AXI总线将数据写入DDR,我们的应用程序需要使用以太网发送数据。我们使用iperf对以太网吞吐量进行基准测试,它可以达到约700Mbps的速度。当我们测试我们的应用程序吞吐量时,我们得到的结果只有400Mbps。我们在不使用/dev/mem
的情况下编写简单的服务器代码,然后使用dd
命令使用随机数据填充内存,应用程序读取要发送的文件。我们注意到吞吐量实际上接近于iperf基准测试。我们发现当我们在打开/dev/mem
期间删除O_SYNC时,吞吐量可以接近iperf的吞吐量。但现在的问题是,如果我们不使用O_SYNC,我们会得到间歇性的错误数据。
我们使用dma_alloc_coherent
分配连续内存:
p_ximageConfig->fpgamem_virt = dma_alloc_coherent(NULL, Dma_Size, &(p_ximageConfig->fpgamem_phys), GFP_KERNEL);
我们使用IOCTL将phys内存传递给用户空间到mmap:
uint32 DMAPHYSADDR = getDmaPhysAddr();
pImagePool = ((volatile unsigned char*)mmap( 0,MAPPED_SIZE_BUFFER, PROT_READ|PROT_WRITE, MAP_SHARED, _fdFpga, DMAPHYSADDR));
我们尝试了以下方法:
在我们的驱动程序中编写我们自己的mmap:如果我们不同步,我们间歇性地得到错误的数据。我们尝试的同步方法是 pgprot_noncached 和 pgprot_dmacoherent ,但它只能达到300Mbps。
我们尝试使用 dma_mmap_coherent :我们得到的结果大约是500Mbps。
是否有任何方法可以帮助我们实现接近iperf性能的性能?
答案 0 :(得分:1)
我不知道为什么iperf
如此之快,但mmap
设备内存是如何工作的。
让我们看看mmap_mem()
function,它由用户的mmap
电话调用。根据{{3}},如果指定O_SYNC
,则此函数将内存映射为非缓存,并且(可能)写回其他。因此,vma->vm_page_prot = __pgprot_modify(vma->vm_page_prot, L_PTE_MT_MASK, L_PTE_MT_WRITEBACK);
可以使其更快。
所以这里我们启用了一个内存区域的缓存。那么如何用FPGA同步内容呢?
一种方法是通过软件进行同步。 this line和dmac_map_area()
次呼叫相应地对应dmac_unmap_area()
和v7_dma_map_area()
。这些函数有三个参数:用户地址addr
,大小size
和DMA方向dir
。
当我们调用dmac_map_area(addr, size, DMA_TO_DEVICE)
时,CPU缓存的内容将写入内存。当CPU完成写入内存并且设备将从该位置读取时,这样做。
当我们调用dmac_unmap_area(addr, size, DMA_FROM_DEVICE)
时,CPU缓存的内容被标记为“无效”,当我们从该位置读取时,设备中的新内容被读取到CPU缓存。因此,当设备完成写入内存并且CPU将从该位置读取时,请执行此操作。
另一种方法是使用专用硬件。根据{{3}},Cyclone V具有加速器一致性端口(ACP),它使FPGA能够读取ARM的高速缓存内容。我认为这可能比软件更快,但因为我不知道如何使用ACP,请尝试谷歌搜索。