PCI总线协议的基础
注:看完之后,觉得还要详细研读一下spec。以前的理解可能不深刻。
PCI总线上动作最基本的机制是burst。一个burst由一个地址phase和一个或多个数据phase组成。Memory、io空间的访问也支持burst。总线上所有信号都是在clock的上升沿取样的,除了resetpin和中断pin。
一、基本的总线控制
PCI总线上所有的数据传输都是通过下面三个信号控制的:
FRAME#: 由master驱动,表示传输的开始和结束。
IRDY#: 由master驱动,表示master已经准备好传输或者接受数据
TRDY#: 由target驱动,表示targe已经准备好传输或者接受数据。
如果FRAME#和IRDY#处于deasserted状态,那么总线是处于Idle状态的。FRAME#被asserted之后的第一个clock是寻址phase,地址和总线命令从该clock edge开始传输。后续是一个或者多个 data phase,当然需要IRDY#和TRDY#同时被asserted,如果IRDY#和TRDY#中的任何一个被deasserted,则总线处于wait cycles。
数据源头在准备好数据之后,无条件的assert xRDY#信号(比如,IRDY#在write周期,TRDY#在Read周期)。而在接收端,如果,还没有准备好接受数据,则可以延迟xRDY#的assertion。
在结束传输的时候,不管是master还是targe,都不能随意的终止或者改变动作,除非此次数据传输已经完成了。比如,master asserted IRDY#之后,它不能随意的改变IRTY#和FRAME#的状态,而不考虑TRDY#。而target在assertedTRDY#之后,在当前data phase没有完成之前,都不能随意改变DEVEL#和TRDY#的状态。
二、寻址
PCI总线协议定义了三个地址空间:memory 地址空间、IO地址空间和配置空间。这里主要描述memory、io的地址空间的访问。
PCI设备内部的register是通过BAR寄存器来映射到memory或者io中的。PCI BIOS配置程序会在BAR中填写设备映射的memory、io空间的基地址。一般情况,推荐使用memory地址空间,因为IO空间是有限的。
PCI总线上的地址译码是分布式的,也就是说每个设备都要处理总线上的译码周期。但是只会有个一个对应的设备来响应地址译码,每个设备只负责响应自己的地址译码信号。PCI支持两种类型的地址译码:positive 和subtractive。一般来说positive方式译码会快一些,因为其寻址的地址是在Address windows中的,一比较就能知道是否在范围之内,类似于比较法。而subtractive译码则针对某个pci设备,此设备不被positive译码寻址到的,也就是类似于排除法的意思了。
AD总线上的AD[1:0]两个值是因地址空间而可变的。在IO地址空间中,所有32跟AD线都是用来提供全字节寻址的。AD[1:0]用来生成DEVSEL#,并且与BE#对应的。例如,如果BE0#被asserted,那么AD[1:0]将会是“00”,如果BE3#被asserted,那么AD[1:0]是“11”,表示byte3.如果访问中BE#没有被asserted,则AD[1:0]为“xx”。
如果设备发现寻址地址是自己的,那么会译码AD线,并asserted DEVSEL#。表示“好吧,我被发现”了。当然AD线所表示要收到目标设备的地址空间属性限制。例如,设备支持的地址空间是4字节对齐的,那么就不需要译码AD[1:0]。如果当前访问中BE#不是设备定义的对齐字节,则设备会以Target-Abort终止当前访问。
对于memory命令的传输,所有设备都需要确认AD[1:0]线。
三、TransactionOrdering
PCI总线的传输ordering需要完成如下三件事:第一,必须满足Producer-Consumer Model 的Write-resultsordering要求。第二,允许一些传输类型为Posted,以改善性能。第三,当Posting buffer被flushed时候,防止死锁的条件发生。(详细请查看PCI spec 相关章节,比较抽象)
这里涉及几个概念
1、 Posted 和NON-Posted 。
PCI总线属于多层次多bus的系统,以transaction经过bridge的方式区分,可以分成Posted传输和NON-Posted传输。Posted传输时指原始端总线动作完成的比目标端总线的完成早。类似于没有反馈的传输。中间环节的bridge必须接受这些transaction,并且有责任保证该transaction能够到达目的。Pci总线上下列允许posted:memory writes(Memory Write 和Memory Write and Invalidate)。
相对应NON-Posted 传输指目标端总线的动作完成比原始端的动作完成早,类似于原始端需要等待目标端的反馈。 Memory read(Memory Read,Memory Read Line、Memory Read Multiple),IO传输(IO Read 和IO Write),和配置传输(Configuration Read 和Configuration Write)都是NON-Posted。
2、 四点Ordering的规则。
由于Bridge可以实现投递memory write 传输以不同的方向通过bridge,并且涉及到一些Bridge随时有可能清空其posting buffers。如果不采取一些规范的话,可能会导致出现死锁的情况发生。
A、 对于多个Postedmemory write,必须保证原始端的order和在目标端完成的order要一致。
B、 Bridge中经过的某个方向的Writing传输流的顺序不会干涉Bridge中其他方向经过的Writing传输流
C、 当Read 传输完成之前,必须flush掉两个方向的Postedmemory write buffers。
D、 为了防止不出现死锁的现象,必须保证Post的传输优先级不能高于NON-Posted的优先级。
当Posted Write数据不被接受时产生的死锁。当有Write transaction 和Read transaction同时出现的时候,考虑到前面C点所说的规则,如果Write data在Read传输动作之前而优先完成的,那么总线就会出现死锁现象。