最近几天我正在尝试开发主机和端点之间的数据传输,但我无法执行该实现。我已经尝试了如何使用一些调用(pci_read_long)
读取配置空间,它已成功读取vendor_id,device_id
等等数据
在配置空间BAR(基地址寄存器)中存储了存储器地址以及它取决于第0位的I / O地址。对于我的问题我正在读取10h地址寄存器,例如,让我们考虑一下值0XFE000000
我正在做的是清除最后四位,然后补充这些位,最后将1加到地址,然后结果表明地址的大小。
(FE000000)
写入特定地址位置pci_write_long
时,我都会遇到分段错误。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);
这是否是实现代码的正确方法?如果不正确可以提供任何相关信息或任何链接吗?
答案 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 - 立即访问该地址。