PCIe是总线协议的一种,具体可见 http://zh.wikipedia.org/wiki/PCI_Express
本文主要根据多核Tilera的PCIe驱动程序,说明PCIe数据传输的初始化步骤及分配资源,并说明如何定位driver的故障。
有了PCIe,两个相同的芯片可以互相传输数据、流量等。PCIe规定,两个互联的芯片,必须有一个是root-complex设备,另一个是end-point设备;其对应关系可通过读取特定文件获得。
PCIe发展至今可以无障碍支持全双工模式。为简单起见,本文首先以单工模式为例。设一个设备上允许C2C_sender程序,另一个设备上允许C2C_receiver程序,这两个程序基于PCIe传输数据。
限于时间关系,不再一一绘制流程图,直接在之前做的PPT上截屏。
PCIe在初始化的过程中,做了多次地址映射,很明显,应用程序的虚拟地址空间需要映射到PCIe地址空间;同时PCIe的地址空间也要映射回应用程序的虚拟地址空间。
下面,以接收者的视角,看一下地址映射的具体关系:
通读PCIe的驱动代码之后可以看出,PCIe的传输原理很清晰,其实现过程有清晰的地址映射,这保证了发送者发送数据的起始地址和接受者接收数据的起始地址是一致的,反之也是。当然,PCIe驱动的复杂度并未完全在此体现出来。
有了如此清晰的驱动逻辑及流程,距离定位驱动故障的原因也就不远了。另一篇博客http://blog.csdn.net/mysee1989/article/details/39105687介绍了基于PCIe驱动的芯片互联设计。方案设计完成之后,两个芯片间总是只能连通很短的时间。让我们先看看此问题的前提:
条件之一:芯片互联程序(双工)只能连通很短时间,但是代码逻辑经过检查无问题,双线程无死锁;
条件之二:原厂提供的程序(单工)可一直连通。
条件之三:原厂提供的单工程序是静态连接的,其程序体积显著大于动态链接的程序。
条件之四:本人编译、执行原厂提供的例子(动态、静态),均只能连通很短的时间。和芯片互联程序问题一样。
于是可以得出结论:原厂提供的可用程序,其静态连接的PCIe库文件,和公司机器上的PCIe库文件不一致,后来结果的确如此,只是在猜测的情况下,不敢确定。
问题反馈发过去,迟迟没有回应。公司这边也在紧锣密鼓的“要求”我尽快定位故障。
在通读了芯片附带提供的PDF文档、驱动代码的同时,本人也读了不少这方面的论文。一位老师曾不经意间说:他有一段时间对数字信号的本质不太理解,就跑到图书馆找了10多本这方面的书籍,对比翻阅,直到理解。在遇到问题的时候,不妨多找几个相关知识的讲解来源,这是捷径。
在PCEe文档里有这样一段描述,DMA的寄存器有个G标志位,置为该标志,则DMA传输立即进行。因为是立即进行,那么该置位语句应该是所有的初始化代码之后。对比驱动代码,并非如此,该置位语句之后依然有两句代码是用来初始化PCIe资源。调整置位语句的位置,重现编译库文件,问题立即得到解决。将近5G/s的吞吐量保持稳定。
过程的繁琐的,迷茫的。结果是极好的。