linux驱动程序使用DMA从用户空间传输数据

时间:2014-10-23 15:29:21

标签: linux memory arm driver dma

您好我正在尝试通过AXI总线实现FPGA加速器与ARM处理器的集成。 FPGA加速器包括一个DMA,旨在移动输入数据(从存储器)和输出数据(到存储器)。一切都是作为裸机应用程序工作,但我在Linux下遇到问题。

这个想法是用户空间进程必须提供输入数据并且必须读取输出数据。为了解决这个问题,我正在编写一个设备驱动程序,但我仍然坚持从虚拟地址到物理地址的地址转换。当我给DMA输入和输出基地址时,我能够提供对我来说无用的虚拟,因为我不知道如何将它转换为物理的。结果,我从错误的内存位置读取和写入数据。我还认为与裸机的另一个不同之处在于,在裸机中,linux数据可以分段,而它们位于连续的内存区域。

您是否有任何建议或参考来解决这些问题? 感谢

1 个答案:

答案 0 :(得分:0)

首先,警告:不要尝试使用virt_to_phys,这是此问题的常见建议。 source code itself表示此函数(实际上是一个宏,但不在此处)不应该用于DMA或设备驱动程序。

您应该使用的是来自dma_alloc家庭的功能。最有可能的候选人是void *dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flag),它会为您做一些事情:

  • 分配size字节的固定内存(固定可防止操作系统将内存交换到磁盘)
  • dma_handle分配一个句柄,该句柄可以转换为无符号整数,并作为内存的物理地址提供给您的硬件
  • 返回一个可用于从驱动程序中访问内存的虚拟地址
  • 确保记忆是连续的

以下是一些其他资源,所有这些资源都在kernel.org上托管:

Dynamic DMA Mapping Using the Generic Device
DMA Mapping Guide
Guide to the virt_to_phys and phys_to_virt functions(请记住,在这种情况下不应使用它们 - 这仅供参考。)