访问内部Xilinx FPGA Block RAM

时间:2011-05-21 16:45:02

标签: linux-device-driver fpga

我正在为Xilinx Virtex-6 X8 PCI Express Gen 2评估/开发套件SX315T FPGA编写器件驱动程序。我的操作系统是openSUSE 11.3 64位。 在此设备的文档中(Virtex-6 FPGA集成块形式PCI Express用户指南UG517(v5.0)2010年4月19日,第219页)说:

PIO设计是一个简单的仅限目标的应用程序,它与Endpoint for PCIe核心的交易(TRN)接口,作为客户构建自己设计的起点。包括以下功能:

•使用内部Xilinx FPGA模块的四个特定于事务的2 KB目标区域 RAM,提供8192字节的总目标空间

•支持单个DWORD有效负载读写PCI Express事务 支持完成TLP的32/64位地址存储空间和I / O空间

•利用核心的trn_rbar_hit_n [6:0]信号来区分TLP目的地 基地址寄存器

•提供针对32位,64位和128位TRN优化的单独实现 接口

在设备中可用BAR0和BAR2长度为128个字节。 我正在尝试访问内部Xilinx FPGA Block RAM,因为我在虚拟空间内核中映射BAR0。

struct pcie_dev {
    struct          pci_dev* dev; 
    struct          cdev chr_dev;
    atomic_t        dev_available;
    u32             IOBaseAddress;
    u32             IOLastAddress;
    void* __iomem   bar;
    void            *virt_addr;
    u32             length;
    unsigned long   sirqNum;
    void           *private_data; };

struct pcie_dev cur_pcie_dev;

    cur_pcie_dev.IOBaseAddress = pci_resource_start(dev, 0);
    cur_pcie_dev.IOLastAddress = pci_resource_end(dev, 0);
    cur_pcie_dev.length=pci_resource_len(dev,0); 
    cur_pcie_dev.bar=pci_iomap(dev, 0,cur_pcie_dev.length); 

IOBaseAddress是0xfbbfe000 IOLastAddress是0xfbbfe07f 长度= 128;

使用IOCTL我尝试写入/读取数据。

case IOCTL_INFO_DEVICE:
{
u32 *rcslave_mem = (u32 *)pCur_dev->bar;
u32 result = 0;

     u32 value = 0;
     int i;
     for (i = 0; i <2048 ; i++) {
             printk(KERN_DEBUG "Writing 0x%08x to 0x%p.\n",
                     (u32)value, (void *)rcslave_mem + i);
             iowrite32(value, rcslave_mem + i);
             value++;
     }
     /* read-back loop */
     value = 0;
     for (i = 0; i < 2048; i++) {
             result = ioread32(rcslave_mem + i);
                     printk(KERN_DEBUG "Wrote 0x%08x to 0x%p, but read back 0x%08x.\n",
                             (u32)value, (void *)rcslave_mem + i, (u32)result);

             value++;
     } 

但事实证明只能写入和读取32个值。根据我的理解,录制发生在BAR0(4字节* 32值= 128字节),但不在内部Xilinx内存中。我试图走另一条路。

    cur_pcie_dev.IOBaseAddress = pci_resource_start(dev, 0);
    cur_pcie_dev.IOLastAddress = pci_resource_end(dev, 0);
    cur_pcie_dev.length=pci_resource_len(dev,0);
    flags = pci_resource_flags(dev,0);

if (flags & IORESOURCE_MEM) {
  if (request_mem_region(cur_pcie_dev.IOBaseAddress,cur_pcie_dev.length, DEVICE_NAME)== NULL) {
                 return -EBUSY;}

   cur_pcie_dev.virt_addr=ioremap_nocache(cur_pcie_dev.IOBaseAddress,cur_pcie_dev.length);
     if (cur_pcie_dev.virt_addr == NULL) {
                printk(KERN_ERR "ERROR: BAR%u remapping FAILED\n",0);
                return -ENOMEM;
            }
            printk(KERN_INFO " Allocated I/O memory range %#lx-%#lx\n",      cur_pcie_dev.IOBaseAddress,(cur_pcie_dev.IOBaseAddress+cur_pcie_dev.length-1));
        } else {
            printk(KERN_ERR "ERROR: Invalid PCI region flags\n");
            return -EIO;
        }

然后

     address = ((unsigned int)pCur_dev->virt_addr+pd.Address);
     iowrite32(pd.Value,(unsigned int*) address); 

     address = ((unsigned int)pCur_dev->virt_addr+pd.Address);
     pd.Value = ioread32((unsigned int *)address); 

我使用求和虚拟地址和指定用户的地址。但结果是读/写操作也不正确。告诉我我做错了什么。

P.S.Sryry我的英语不好

1 个答案:

答案 0 :(得分:1)

您尝试访问主板的内部Block RAM的原因是什么?我认为如果在FPGA上使用Programmed I / O(PIO),设备驱动程序(您的设备是PCI Express接口)的正常行为就足够了。当您写入设备驱动程序时,数据将通过FPGA端下载的IP内核(以及相反的方式)传输到Block RAM。

在Xilinx的xapp1022(内存端点测试)包中查看Linux驱动程序。

P.S。:我知道这是一个老问题,你可以尽快找到答案:)