使用PCIe在主机和端点之间传输数据

时间:2017-11-20 10:45:38

标签: c pci-e

最近几天我正在尝试开发主机和端点之间的数据传输,但我无法执行该实现。我已经尝试了如何使用一些调用(pci_read_long)读取配置空间,它已成功读取vendor_id,device_id等等数据

在配置空间BAR(基地址寄存器)中存储了存储器地址以及它取决于第0位的I / O地址。对于我的问题我正在读取10h地址寄存器,例如,让我们考虑一下值0XFE000000我正在做的是清除最后四位,然后补充这些位,最后将1加到地址,然后结果表明地址的大小。

我的问题是:

  • 每当我使用此(FE000000)写入特定地址位置pci_write_long时,我都会遇到分段错误。
  • 为什么我在写作时遇到分段错误?任何人都可以请 帮我解决这个问题,是否正确计算内存大小(以上步骤)。
  • about bar:它是否代表内存基地址?

来到我的代码:

int  c = pci_write_long(dev,0X10,0xFFFFFFFF);//write all 1's to that location

c = pci_read_long(dev,0x10); //reading the address
printf("c = %x\n",c);

for(i=0;i<4;i++)             //clearing the last four bits
        c = c & ~(1<<i);
printf("c = %x\n",c);

c = ~c;                    // 1's complement
c =c+1;                    //add the one to that address

printf("c = %x\n",c);          // size of the address

int  ch1 = pci_write_byte(dev,c,0xf);  // i am facing the segmentation fault here
printf("ch1 = %x\n",ch1);

ch1 = pci_read_byte(dev,c);         // again i am reading the the data current location 
printf("final read = %x\n",ch1);

这是否是实现代码的正确方法?如果不正确可以提供任何相关信息或任何链接吗?

1 个答案:

答案 0 :(得分:0)

  

每当我使用时写入特定的地址位置(FE000000)   这个pci_write_long我正面临分段错误。

pci_write_long()用于访问端点配置空间。您尝试访问的地址是内存映射的Endpoint的内部寄存器,您只需使用指针即可。只需mmap()地址并像普通缓冲区一样访问它,只要你知道设备的内部寄存器结构。 您可以看到第一次写入0xFFFFFFFF成功,因为您正在写入位于配置空间中的偏移量0x10。下一次写入导致分段错误,您正在从配置空间基址写入偏移0xFE000000,这是无效的。 还有一点,如果你在ARM上,这个内存,即0xFE000000与PCIe控制器内存范围有关吗?如果不是这种情况,那么您正在访问无效的内存。

  

为什么我在写作时遇到分段错误?任何人都可以请   帮我解决这个问题,是否正确计算大小   记忆(上述步骤)。

上面给出了崩溃的原因。尺寸计算算法看起来正确。您可以简单地将计算出的尺寸与EP数据表中提到的BAR尺寸进行匹配。

  

关于bar:它是否代表内存基地址?

它表示您的端点或设备的内部寄存器/内存映射到主机地址空间区域的位置。您可以使用主机中的相同地址访问设备的内部寄存器,就像访问本地内存缓冲区一样。如果你的架构有虚拟内存,那么只需mmap()访问之前的地址。

编辑1 - 我可以看到你正在写所有1并试图读取地址。您不是首先应该来自主机地址空间的任何地址字符串。我相信你需要通过BAR使用来解决一些误解。

1 - 获取BAR尺寸。 2 - 将主机地址写入您希望EP内部寄存器映射的BAR。 (对于ARM,地址应来自PCIe控制器的地址范围。检查电路板的手册)     - 通过在命令寄存器中写入0x3来启用存储器事务访问。 3 - 从您的c代码,执行该地址的mmap() 4 - 立即访问该地址。