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

标签 c pci-e

过去几天开始,我尝试开发主机和端点之间的数据传输,但我无法实现该实现。我尝试了如何使用一些调用读取配置空间(pci_read_long),已成功读取vendor_id、device_id...等数据。

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

我的问题是:

  • 每当我使用此pci_write_long写入特定地址位置(FE000000)时,我都会面临段错误。
  • 为什么我在写作时遇到段错误?谁能请 帮我解决这个问题,计算内存大小是否正确(上述步骤)。
  • 关于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);

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

最佳答案

whenever I am writing to particular address location(FE000000) using this pci_write_long I am facing the segmentation fault.

pci_write_long() 用于访问端点配置空间。您尝试访问的地址是内存映射端点的内部寄存器,您可以简单地使用指针来完成此操作。只要您了解设备的内部寄存器结构,只需 mmap() 地址并像普通缓冲区一样访问它即可。 您可以看到第一次写入 0xFFFFFFFF 成功,因为您正在写入位于配置空间中的偏移量 0x10。下一次写入会导致段错误,您正在写入配置空间基址的偏移量 0xFE000000,这是无效的。 还有一点,如果您使用 ARM,该内存(即 0xFE000000)是否属于 PCIe Controller 内存范围?如果情况并非如此,那么您正在访问无效的内存。

why I am facing segmentation fault while writing ? can anyone please help me to resolve this issue and is it correct calculating the size of memory(above steps).

上面给出了崩溃原因。大小计算算法看起来是正确的。您只需将计算出的尺寸与 EP 数据表中提到的 BAR 尺寸进行匹配即可确定。

about bar : Is it represent the memory base address?

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

编辑 1 - 我可以看到您正在写入全 1 并尝试读取地址。您不首先字符串任何地址,该地址应该来自您的主机地址空间。我相信您对于 BAR 的使用存在一些误解,需要澄清。

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

关于c - 使用 PCIe 在主机和端点之间传输数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47390175/

相关文章:

c - 分隔文本文件

c - 学习C - 为什么这个方法不释放内存?

Linux PCIe 驱动程序 : What to use for private data structure?

c - uboot函数pci_hose_read_config_word()定义?

linux - 在 Linux 上重新扫描 PCIe 后未分配的 BAR 区域

c - 在 C 中不使用 strtok() 进行标记化

c - 我已经为 spoj 问题 "The Next Palindrome"编写了代码,但在我的提交中收到了错误的答案消息

c - 坚持退出 C 中的循环

Linux PCIe DMA 驱动程序 (Xilinx XDMA)

linux - 将 PCIe 驱动程序从 Linux 移植到 FreeBSD