大侠好,欢迎来到FPGA技术江湖,江湖偌大,相见即是缘分。大侠可以关注FPGA技术江湖,在“闯荡江湖”、"行侠仗义"栏里获取其他感兴趣的资源,或者一起煮酒言欢。
最近有很多大侠在交流群里讨论PCI总线,PCI作为高速接口之一,在当下的FPGA产品设计研发中,地位举足轻重,应用广泛,今天给大侠带来PCI Express 系列连载,今天带来第十二篇,PCI设备的数据传递,包括PCI设备的正向译码与负向译码、处理器到PCI设备的数据传送、PCI设备的DMA操作、PCI桥的Combining、Merging和Collapsing。希望对各位大侠的学习有参考价值,话不多说,上货。
PCI设备的数据传递使用地址译码方式,当一个存储器读写总线事务到达PCI总线时,在这条总线上的所有PCI设备将进行地址译码,如果当前总线事务使用的地址在某个PCI设备的BAR空间中时,该PCI设备将使能DEVSEL#信号,认领这个总线事务。
如果PCI总线上的所有设备都不能通过地址译码,认领这个总线事务时,这条总线的“负向译码”设备将认领这个总线事务,如果在这条PCI总线上没有“负向译码”设备,该总线事务的发起者将使用Master Abort总线周期结束当前PCI总线事务。
PCI设备的正向译码与负向译码
如上文所示PCI设备使用“地址译码”方式接收存储器读写总线请求。在PCI总线中定义了两种“地址译码”方式,一个是正向译码,一个是负向译码。
我们仍以图3-2所示的处理器系统为例,说明数据传送使用的寻址方法。当HOST主桥通过存储器或者I/O读写总线事务访问其下所有PCI设备时,PCI总线0下的所有PCI设备都将对出现在地址周期中的PCI总线地址进行译码。如果这个地址在某个PCI设备的BAR空间中命中时,这个PCI设备将接收这个PCI总线请求。这个过程也被称为PCI总线的正向译码,这种方式也是大多数PCI设备所采用的译码方式。
但是在PCI总线上的某些设备,如PCI-to-(E)ISA桥并不使用正向译码接收来自PCI总线的请求,PCI-to-ISA桥在处理器系统中的位置如图1-1所示。PCI总线0上的总线事务在三个时钟周期后,没有得到任何PCI设备响应时(即总线请求的PCI总线地址不在这些设备的BAR空间中),PCI-to-ISA桥将被动地接收这个数据请求。这个过程被称为PCI总线的负向译码。可以进行负向译码的设备也被称为负向译码设备。
在PCI总线中,除了PCI-to-(E)ISA桥可以作为负向译码设备,PCI桥也可以作为负向译码设备,但是PCI桥并不是在任何时候都可以作为负向译码设备。在绝大多数情况下,PCI桥无论是处理“来自上游总线”,还是处理“来自下游总线”的总线事务时,都使用正向译码方式,但是在某些特殊应用中,PCI桥也可以作为负向译码设备。
如笔记本在连接Dock插座时,也使用了PCI桥。因为在大多数情况下,笔记本与Dock插座是分离使用的,而且Dock插座上连接的设备多为慢速设备,此时用于连接Dock插座的PCI桥使用负向译码。Dock插座在笔记本系统中的位置如图3-3所示。
当笔记本与Dock建立连接之后,如果处理器需要访问Dock中的外部设备时,Dock中的PCI桥将首先使用负向译码方式接收PCI总线事务,之后将这个PCI总线事务转发到Dock的PCI总线中,然后再访问相应的PCI设备。
在Dock中使用负向译码PCI桥的优点是,该桥管理的设备并不参与处理器系统对PCI总线的枚举过程。当笔记本插入到Dock之后,系统软件并不需要重新枚举Dock中的设备并为这些设备分配系统资源,而仅需要使用负向译码PCI桥管理好其下的设备即可,从而极大降低了Dock对系统软件的影响。
当HOST处理器访问Dock中的设备时,负向译码PCI桥,将首先接管这些存储器读写总线事务,然后发送到Dock设备中。值得注意的是,在许多笔记本的Dock实现中,并没有使用负向译码PCI桥,而使用PCI-to-ISA桥。
PCI总线规定使用负向译码的PCI桥,其Base Class Code寄存器为0x06,Sub Class Code寄存器为0x04,而Interface寄存器为0x01;使用正向译码方式的PCI桥的Interface寄存器为0x00。系统软件(E2PROM)在初始化Interface寄存器时务必注意这个细节。
综上所述,在PCI总线中有两种负向译码设备,PCI-to-E(ISA)桥和PCI桥。但是PCI桥并不是在任何时候都是负向译码设备,只有PCI桥连接Dock插座时,PCI桥的Primary Bus才使用负向译码方式。而这个PCI桥的Secondary Bus在接收Dock设备的请求时仍然使用正向译码方式。
PCI桥使用的正向译码方式与PCI设备使用的正向译码方式有所不同。如图3-4所示,当一个总线事务是从PCI桥的Primary Bus到Secondary Bus时,PCI桥使用的正向译码方式与PCI设备使用的方式类似。如果该总线事务使用的地址在PCI桥任意一个Memory Base窗口[1]命中时,该PCI桥将使用正向译码方式接收该总线事务,并根据实际情况决定是否将这个总线事务转发到Secondary Bus。
当一个总线事务是从PCI桥的Secondary Bus到Primary Bus时,如果该总线事务使用的地址没有在PCI桥所有的Memory Base窗口命中时,表明当前总线事务不是访问该PCI桥管理的PCI子树中的设备,因此PCI桥将接收当前总线事务,并根据实际情况决定是否将这个总线事务转发到Primary Bus。
以图3-2为例,当PCI设备11访问主存储器空间时,首先将存储器读写总线事务发送到PCI总线1上,而这个存储器地址显然不会在PCI总线1的任何PCI设备的BAR空间中,此时PCI桥1将认领这个PCI总线的数据请求,并将这个总线事务转发到PCI总线0上。最后HOST主桥将接收这个总线事务,并将PCI总线地址转换为存储器域的地址,与主存储器进行读写操作。
值得注意的是,PCI总线并没有规定HOST主桥使用正向还是负向译码方式接收这个存储器读写总线事务,但是绝大多数HOST主桥使用正向译码方式接收来自下游的存储器读写总线事务。在PowerPC处理器中,如果当前存储器读写总线事务使用的地址在Inbound窗口内时,HOST主桥将接收这个总线事务,并将其转换为存储器域的读写总线事务,与主存储器进行数据交换。
处理器到PCI设备的数据传送
下文以图3-2所示的处理器系统为例,说明处理器向PCI设备11进行存储器写的数据传送过程。处理器向PCI设备进行读过程与写过程略有区别,因为存储器写使用Posted方式,而存储器读使用Non-Posted方式,但是存储器读使用的地址译码方式与存储器写类似,因此本节对处理器向PCI设备进行存储器读的过程不做进一步介绍。
PCI设备11在PCI总线域的地址范围是0x7300-0000~0x73FF-FFFF。这段空间在存储器域中对应的地址范围是0xF300-0000~0xF3FF-FFFF。下文我们假设处理器使用存储器写指令,访问0xF300-0008这个存储器地址,其步骤如下。
(1) 存储器域将0xF300-0008这个地址发向HOST主桥,0xF000-0000~0xF7FF-FFFF这段地址已经由HOST主桥映射到PCI总线域地址空间,所以HOST主桥认为这是一个对PCI设备的访问。因此HOST主桥将首先接管这个存储器写请求。
(2) HOST主桥将存储器域的地址0xF300-0008转换为PCI总线域的地址0x7300-0008,并通过总线仲裁获得PCI总线0的使用权,启动PCI存储器写周期,并将这个存储器写总线事务发送到PCI总线0上。值得注意的是,这个存储器读写总线事务使用的地址为0x7300-0008,而不是0xF300-0008。
(3) PCI总线0的PCI桥1发现0x7300-0008在自己管理的地址范围内,于是接管这个存储器写请求,并通过总线仲裁逻辑获得PCI总线1的使用权,并将这个请求转发到PCI总线1上。
(4) PCI总线1的PCI设备11发现0x7300-0008在自己的BAR0寄存器中命中,于是接收这个PCI写请求,并完成存储器写总线事务。
PCI设备的DMA操作
下文以图3-2所示的处理器系统为例,说明PCI设备11向存储器进行DMA写的数据传送过程。PCI设备的DMA写使用Posted方式而DMA读使用Non-Posted方式。本节不介绍PCI设备进行DMA读的过程,而将这部分内容留给读者分析。
假定PCI设备11需要将一组数据,发送到0x1000-0000~0x1000-FFFF这段存储器域的地址空间中。由上文所述,存储器域的0x0000-0000~0x7FFF-FFFF这段存储器空间与PCI总线域的0x8000-0000~0xFFFF-FFFF这段PCI总线地址空间对应。
PCI设备11并不能直接操作0x1000-0000~0x1000-FFFF这段存储器域的地址空间,PCI设备11需要对PCI总线域的地址空间0x9000-0000~0x9000-FFFF进行写操作,因为PCI总线地址空间0x9000-0000~0x9000-FFFF已经被HOST主桥映射到0x1000-0000~0x1000-FFFF这段存储器域。这个DMA写具体的操作流程如下。
(1) 首先PCI设备11通过总线仲裁逻辑获得PCI总线1的使用权,之后将存储器写总线事务发送到PCI总线1上。值得注意的是,这个存储器写总线事务的目的地址是PCI总线域的地址空间0x9000-0000~0x9000-FFFF,这个地址是主存储器在PCI总线域的地址映像。
(2) PCI总线1上的设备将进行地址译码,确定这个写请求是不是发送到自己的BAR空间,在PCI总线1上的设备除了PCI设备11之外,还有PCI桥2和PCI桥1。
(3) 首先PCI桥1、2和PCI设备11对这个地址同时进行正向译码。PCI桥1发现这个PCI地址并不在自己管理的PCI总线地址范围之内,因为PCI桥片1所管理的PCI总线地址空间为0x7000-0000~0x73FF-FFFF。此时PCI桥1将接收这个存储器写总线事务,因为PCI桥1所管理的PCI总线地址范围并不包含当前存储器写总线事务的地址,所以其下所有PCI设备都不可能接收这个存储器写总线事务。
(4) PCI桥1发现自己并不能处理当前这个存储器写总线事务,则将这个存储器写总线事务转发到上游总线。PCI桥1首先通过总线仲裁逻辑获得PCI总线0的使用权后,然后将这个总线事务转发到PCI总线0。
(5) HOST主桥发现0x9000-0000~0x9000-FFFF这段PCI总线地址空间与存储器域的存储器地址空间0x1000-0000~0x1000-FFFF对应,于是将这段PCI总线地址空间转换成为存储器域的存储器地址空间,并完成对这段存储器的写操作。
(6) 存储器控制器将从HOST主桥接收数据,并将其写入到主存储器。
PCI设备间的数据传递与PCI设备到存储器的数据传送大体类似。我们以PCI设备11将数据传递到PCI设备42为例说明这个传递过程。我们假定PCI设备11将一组数据发送到PCI设备42的PCI总线地址0x7500-0000~0x7500-FFFF这段地址空间中。这个过程与PCI设备11将数据发送到存储器的第1~5步基本类似,只是第5、6步不同。PCI设备11将数据发送到PCI设备42的第5、6步如下所示。
(1) PCI总线0发现其下的设备PCI桥4能够处理来自PCI总线0的数据请求,则PCI桥4将接管这个PCI写请求,并通过总线仲裁逻辑获得PCI总线4的使用权,之后将这个存储器写请求发向PCI总线4。此时HOST主桥不会接收当前存储器写总线事务,因为0x7500-0000~0x7500-FFFF这段地址空间并不是HOST主桥管理的地址范围。
(2) PCI总线4的PCI设备42将接收这个存储器写请求,并完成这个PCI存储器写请求总线事务。
PCI总线树内的数据传送始终都在PCI总线域中进行,因此不存在不同域之间的地址转换,因此PCI设备11向PCI设备42进行数据传递时,并不会进行PCI总线地址空间到存储器地址空间的转换。
PCI桥的Combining、Merging和Collapsing
由上文所述,PCI设备间的数据传递有时将通过PCI桥。在某些情况下,PCI桥可以合并一些数据传递,以提高数据传递的效率。PCI桥可以采用Combining、Merging和Collapsing三种方式,优化数据通过PCI桥的效率。
1 Combining
PCI桥可以将接收到的多个存储器写总线事务合并为一个突发存储器写总线事务。PCI桥进行这种Combining操作时需要注意数据传送的“顺序”。当PCI桥接收到一组物理地址连续的存储器写访问时,如对PCI设备的某段空间的DW1、2和4进行存储器写访问时,PCI桥可以将这组访问转化为一个对DW1~4的突发存储器写访问,并使用字节使能信号C/BE[3:0]#进行控制,其过程如下所示。
PCI桥将在数据周期1中,置C/BE[3:0]#信号为有效表示传递数据DW1;在数据周期2中,置C/BE[3:0]#信号为有效表示传递数据DW2;在数据周期3中,置C/BE[3:0]#信号为无效表示在这个周期中所传递的数据无效,从而跳过DW3;并在数据周期4中,置C/BE[3:0]#信号为有效表示传递数据DW4。
目标设备将最终按照发送端的顺序,接收DW1、DW2和DW4,采用这种方法在不改变传送序的前提下,提高了数据的传送效率。值得注意的是,有些HOST主桥也提供这种Combining方式,合并多次数据访问。如果目标设备不支持突发传送方式,该设备可以使用Disconnect周期,终止突发传送,此时PCI桥/HOST主桥可以使用多个存储器写总线事务分别传送DW1、DW2和DW4,而不会影响数据传送。
如果PCI桥收到“乱序”的存储器写访问,如对PCI设备的某段空间的DW4、3和1进行存储器写访问时,PCI桥不能将这组访问转化为一个对DW1~4的突发存储器写访问,此时PCI桥必须使用三个存储器写总线事务转发这些存储器写访问。
2 Merge
PCI桥可以将收到的多个对同一个DW地址的Byte、Word进行的存储器写总线事务,合并为一个对这个DW地址的存储器写总线事务。PCI规范并没有要求这些对Byte、Word进行的存储器写在一个DW的边界之内,但是建议PCI桥仅处理这种情况。本节也仅介绍在这种情况下,PCI桥的处理过程。
PCI规范允许PCI桥进行Merge操作的存储器区域必须是可预读的,而可预读的存储器区域必须支持这种Merge操作。Merge操作可以不考虑访问顺序,可以将对Byte0、Byte1、Byte3的存储器访问合并为一个DW,也可以将对Byte3、Byte1、Byte0的存储器访问合并为一个DW。在这种情况下,PCI总线事务仅需屏蔽与Byte2相关的字节使能信号C/BE2#即可。
如果PCI设备对Byte1进行存储器写、然后再对Byte1、Byte2、Byte3进行存储器写时,PCI桥不能将这两组存储器写合并为一次对DW进行存储器写操作。但是PCI桥可以合并后一组存储器写,即首先对Byte1进行存储器写,然后合并后一组存储器写(Byte1、Byte2和Byte3)为一个DW写,并屏蔽相应的C/BE0#信号。Combining与Merge操作之间没有直接联系,PCI桥可以同时支持这两种方式,也可以支持任何一种方式。
3 Collapsing
Collapsing指PCI桥可以将对同一个地址进行的Byte、Word和DW存储器写总线事务合并为一个存储器写操作。使用PCI桥的Collapsing方式是,具有某些条件限制,在多数情况下,PCI桥不能使用Collapsing方式合并多个存储器写总线事务。
当PCI桥收到一个对“DW地址X”的Byte3进行的存储器写总线事务,之后又收到一个对“DW地址X”的Byte、Word或者DW存储器写总线事务时,而且后一个对DW地址X进行的存储器写仍然包含Byte3时,如果PCI桥支持Collapsing方式,就可以将这两个存储器写合并为一个存储器写。
PCI桥在绝大多数情况下不能支持这种方式,因为很少有PCI设备支持这种数据合并方式。通常情况下,对PCI设备的同一地址的两次写操作代表不同的含义,因此PCI桥不能使用Collapsing方式将这两次写操作合并。PCI规范仅是提出了Collapsing方式的概念,几乎没有PCI桥支持这种数据合并方式。
[1] PCI桥除了具有Memory Base窗口外,还有I/O Base窗口和Prefetchable Memory Base窗口。
PCI Express 系列连载篇(十二)就到这里结束,明天继续带来第十三篇,包括与Cache相关的PCI总线事务相关内容。各位大侠,明天见!
END
后续会持续更新,带来Vivado、 ISE、Quartus II 、candence等安装相关设计教程,学习资源、项目资源、好文推荐等,希望大侠持续关注。
大侠们,江湖偌大,继续闯荡,愿一切安好,有缘再见!