带 PCIe 的 DMA 驱动程序,用于将信息从 FPGA 传输到 RAM
DMA driver with PCIe for transferring information from the FPGA to RAM
我想编写一个驱动程序和软件:
软件每二十秒请求一次数据,硬件将数据写入 DMA 缓冲区并在完成时引发中断。
遗憾的是我没有编写驱动程序的经验,我不能使用已经有驱动程序的Xilinx IP核。
我使用的 PCIe IP 核是 UltraScale+ Device Integrated Block for PCI Express (PCIe)。
我已经实现了一个简单的驱动程序,可以读取FPGA上的状态寄存器。
我按照以下步骤实施 DMA:
//Driver_Probe
pci_set_master(pdev);
drv_priv->virt_addr = kmalloc(2048, GFP_DMA);
if (!drv_priv->virt_addr)
{
dev_err(dev, "Failed to kmalloc");
err = -ENOMEM;
return err;
}
drv_priv->bus_addr = pci_map_single(pdev, drv_priv->virt_addr, 2048, PCI_DMA_FROMDEVICE);
if (!drv_priv->bus_addr)
{
dev_err(dev, "Failed to allocate DMA buffer");
err = -ENOMEM;
return err;
}
我还需要添加什么来实现这个驱动程序?
据说在文档中取消映射操作之前,无法读取缓冲区中的数据。
解映射后如何才能成功读取数据?
有完整的例子吗?我找到的参考资料对于新手来说太简短了。
如有任何帮助,我将不胜感激。
几年前我用 PCIe 编写了 a tutorial 将数据从 FPGA 传输到 CPU RAM,但它使用的是 CycloneV。
简而言之:
- 首先你必须分配一个一致的缓冲区:
/* Allocate and initialize shared control data */
dmas->dmabuff = dmam_alloc_coherent(&pdev->dev, BUFF_SIZE, &dmas->dma_handle, GFP_KERNEL);
if (!dmas->dmabuff){
printk("Error, can't alloc coherent\n");
goto err_return;
}
- 然后在你FPGA下的DMA控制器中写入缓冲区地址
writel((unsigned long)(dmas->dma_handle), &dmas->bar0[CRA_REG_A2P_ADDR_MAP_LO0/4]);
在本例中,dma地址配置寄存器位于CRA_REG_A2P_ADDR_MAP_LO0
中的BAR0下。
一旦FPGA中的PCIe核有了buffer地址,就可以read/write到CPU RAM。
这是一个旧教程,现在可能 Linux API 改变了一点。但是我想精神还是一样的。
我想编写一个驱动程序和软件:
软件每二十秒请求一次数据,硬件将数据写入 DMA 缓冲区并在完成时引发中断。
遗憾的是我没有编写驱动程序的经验,我不能使用已经有驱动程序的Xilinx IP核。
我使用的 PCIe IP 核是 UltraScale+ Device Integrated Block for PCI Express (PCIe)。
我已经实现了一个简单的驱动程序,可以读取FPGA上的状态寄存器。 我按照以下步骤实施 DMA:
//Driver_Probe
pci_set_master(pdev);
drv_priv->virt_addr = kmalloc(2048, GFP_DMA);
if (!drv_priv->virt_addr)
{
dev_err(dev, "Failed to kmalloc");
err = -ENOMEM;
return err;
}
drv_priv->bus_addr = pci_map_single(pdev, drv_priv->virt_addr, 2048, PCI_DMA_FROMDEVICE);
if (!drv_priv->bus_addr)
{
dev_err(dev, "Failed to allocate DMA buffer");
err = -ENOMEM;
return err;
}
我还需要添加什么来实现这个驱动程序?
据说在文档中取消映射操作之前,无法读取缓冲区中的数据。 解映射后如何才能成功读取数据?
有完整的例子吗?我找到的参考资料对于新手来说太简短了。
如有任何帮助,我将不胜感激。
几年前我用 PCIe 编写了 a tutorial 将数据从 FPGA 传输到 CPU RAM,但它使用的是 CycloneV。
简而言之:
- 首先你必须分配一个一致的缓冲区:
/* Allocate and initialize shared control data */
dmas->dmabuff = dmam_alloc_coherent(&pdev->dev, BUFF_SIZE, &dmas->dma_handle, GFP_KERNEL);
if (!dmas->dmabuff){
printk("Error, can't alloc coherent\n");
goto err_return;
}
- 然后在你FPGA下的DMA控制器中写入缓冲区地址
writel((unsigned long)(dmas->dma_handle), &dmas->bar0[CRA_REG_A2P_ADDR_MAP_LO0/4]);
在本例中,dma地址配置寄存器位于CRA_REG_A2P_ADDR_MAP_LO0
中的BAR0下。
一旦FPGA中的PCIe核有了buffer地址,就可以read/write到CPU RAM。
这是一个旧教程,现在可能 Linux API 改变了一点。但是我想精神还是一样的。