之前我们讲了对PCIe的一些基础概念作了一个宏观的介绍,了解了PCIe是一种封装分层协议(packet-based layered protocol),主要包括事务层(Transaction layer), 数据链路层(Data link layer)和物理层(Physical layer);
一:系统复位(Reset)
在PCIe Spec中,Reset总共分为两类:Conventional Reset和Function Level Reset
1:Convemtional Reset
从字面上来讲,Conventional Reset是传统的Reset方式,这一类Reset功能是在PCIe Spec2.0之前的Spec中定义的,所以称为传统的Reset,PCIe设备必须要支持这一类Reset
Conventional Reset 包含了三种Reset:cold reset,warm reset和hot reset
另外,还有一个概念:Cold reset和warm reset又被称为Fundamental reset,hot reset被称为Non-fundamental reset。
什么是Fundamental Reset呢?
这是PCIe最基本的复位方式,主要通过硬件实现,效果是重置整个设备,对每个状态机,所有硬件逻辑,端口状态和配置寄存器重新初始化。
Nots:但是,也会有例外的情况:在某些寄存器中的字段只有在全部电源(包括VCC电源和Vaux备用电源)切断的情况下才会被重置,PCIe Spec给这些估值的字段起了个外号“Sticky Bits”
一般来说,Funcdamental Reset是针对整个系统做Reset,但是有时候也可以针对某个单一设备进行重置。
在这里说明一下Funcdamental Reset中的Cold reset和warm reset:
-
Cold Reset: 设备的主电源VCC上电时,就会触发Cold Reset。
-
Warm Reset: 在VCC不断电的情况下,系统可以触发Warm Reset。比如,电源状态的变化就会触发Warm Reset. 不过,PCIe Spec并没有定义触发Warm Reset的具体方式,这部分可以有系统设计人员自行决定。
另外,在PCIe Spec中,规定了两种出发Fundamental Reset方式:
-
一是通过PERST#(PCIe Reset)信号控制。
-
二是在没哟PERST#信号的情况下,通过Power on/off的方式实现。
举个例子,看看PERST是如何生成的:
-
系统上电稳定后,有POWERGOOD信号产生(下图红色框所示)。
-
当系统的南桥芯片(也就是图中的IO控制器ICH)收到POWERGOOD信号后,就会产生PERST#信号(下图绿色部分),此时会引起Cold Reset。
-
如果系统可以通过非上电的方式触发PERST#信号,此时会引起Warm Reset。
明白了Fundamental Reset,那Non-Fundamental reset中Hot reset又是什么呢?
与Fundamental Reset相反,Hot Reset是一种软件控制的复位方式,PCIe设备出现错误时,通常情况下用软件的方式对设备重置,软件可以通过在Bridge control中设置Secondary Bus Reset bit来触发Hot Reset。
另外,在PCIe总线中,通过发送TS1序列,并且在TS1序列中设置Hot Reset bit来对下游设备进行Hot Reset(如下图红色框)
在这个过程中,发送端会持续发送TS1序列至2ms, 接收端在接到2个连续的TS1序列之后进行Hot Reset
同样,举一个例子说明一下Hot Reset:
-
系统通过软件对Switch A左边端口的Secondary Bus Reset bit置为1(下图红色框),触发了Hot Reset.
-
之后通过发送TS1序列对PCIe链路中的下游设备触发Hot Reset(下图黑色箭头).
2:Function Level Reset
在传统复位方式的基础上,PCIe sepc 2.0以后开始增加了新的复位方式FLR(Function Level Reset)前面讲到的传统复位方式(Cold Reset,Warm Reset,Hot Reset)均属于全局复位方式,而FLR的优势则是对局部复位。
在PCIe协议中,一个PCIe设备可能包含多个功能模块(Function)每个功能模块相互对立,公用一个PCIe link,其中,某个功能模块出问题时,虽然可以采用传统复位方式对整个PCIe设备复位,但是这个显然不友好,因为其他功能模块可能正在埋头苦干,这就好比如,在一个团体中,一个人犯错了,要团队所有人一起承担,这个肯定会影响团结。
所以,PCIe深得管理学的精髓,为了不影响团结,FLR允许只对其中出错的功能模块(Function)进行重置,其他功能模块正常工作。
不过,FLR复位方式对PCIe设备并不是必须的,在对PCIe设备使用FLR复位之前必须先检查是否支持FLR,这部分可以查看Device Capabilities Register是否将Function-Level Reset Capbility bit置起。
如果PCIe设备支持FLR,那么就可以通过设置Device Control Register中的Function-Level Reset bit触发FLR复位了;
触发FLR之后,PCIe链路中都有哪些变化呢?
我们前面提到了,FLR是一个局部复位方式,只对出问题的那个Function起作用,所以说,FLR只会改变当下Function 内部的状态和寄存器的内容,以下几个仿麦呢不会被影响:
-
执行FLR的Function所在的PCIe链路状态不会改变,因为其他Function也在共用整条PCIe链路;
-
Sticky Bits. 传统复位方式也无法改变Sticky bits, 除非完全断电。
-
HwInit Bits. HwInit bits是硬件初始化的内容,这些值由芯片的配置引脚决定,后者上电复位后从EEPROM中获取。Cold和Warm Reset可以复位这些寄存器,然后从EEPROM中从新获取数据,但是使用FLR方式不能复位这些寄存器。
-
与Link相关的寄存器。比如ASPM,Flow control等相应的寄存器。
另外,PCIe Spec规定,某一个Function的FLR必须在100ms之后完成,所以,PCIe Spec写了一封倡议书给要使用FLR复位方式的“人们”——软件:
为了创造一个温馨的FLR工作环境,请做到以下几点:
-
在FLR工作期间,请不要访问对应的Function;
-
清除所有的Command Register;
-
通过Polling Device Status Register中的Transaction Pending bit来确保之前请求的Compeletion报文已完成,或者确保后续不会再发送Compeletion报文。
-
触发FLR之后,请耐心等待至少100ms;
-
初始化Function的配置寄存器,让其正常工作。
在FLR执行过程中,如果收到TLP或者Compeletion都会被默默的丢弃,而不会向系统报错;
举个例子,看看FLR执行过程:
1:如下图,这个PCIe设备中有两个功能模块:Function 0 和 Function 5,此时,两个Fucntion依旧是互不干扰,认真工作,传输TLPs。
2:之后,Function 5出现了一些问题,需要做FLR,FLR之后,Function 5中之前的TLPs全部被清除。
3:Function 5做FLR,并不影响Fucntion 0 ,继续TLPs传输,如下图,3个TLPs正常传输完毕。