目录
简介
PCIe 中有4种复位机制:Cold Reset(冷复位)、Warm Reset(暖复位)、Hot Reset(热复位)、FLR(Function Level Reset,功能级复位)。
前3种被称为 Conventional Reset(传统复位)。其中 Cold Reset、Warm Reset 基于边带信号 PERST#,又称为Fundamental Resets(基本复位)。Hot Reset 不使用边带信号 PERST#,又称为 Non-Fundamental Reset。
第4种 FLR 是PCIe 2.0新加入的Feature。
而 Conventional Reset 和 FLR 又都是 NVMe Reset 中的 Controller Reset 的触发方式。(详见另一文章 NVMe Reset)
详细描述
Reset相关术语关系图
Conventional Reset(常规复位)
Fundamental Reset(基本复位)
由硬件控制,会重启整个设备,包括重新初始化所有的状态机、所有的硬件逻辑、端口状态和配置寄存器;某些寄存器里属性为 Sticky 的 Field(字段)除外。
一般发生在整个系统重启的时候(比如重启电脑)。
触发方式(两种)
- 系统给设备发送 PERST# 信号,设备接收该信号后触发。前提是 PCIe 设备支持 PERST# 信号。
- 如 PCIe 设备不支持 PERST# 信号,上电时自动触发。选择不支持 PERST# 信号的 PCIe 设备,必须能自己触发。比如,侦测到 3.3 V 电压后就触发 Fundamental Reset;设备供电超出标准电压是,必须触发 Fundamental Reset。
Cold Reset(冷复位)
设备主电源断开后重上电导致的复位。
主电源 Vcc 通断,辅助电源 Vaux 一直在。所以该复位不会影响到 Sticky 的字段。
触发方式
一个系统上电时,主电源稳定后会有"Power Good"信号,这时 ICH(I/O控制器集线器)就会发 PERST# 信号给挂载的 PCIe SSD。
如果系统重启,Power Good 信号的变化会触发 PERST# 的 Assert 和 De-Assert,就可以实现 PCIe 设备的 Cold Reset。
Warm Reset(温复位)
Optional,是可选的。各厂商可自行选择是否添加此功能。
不断开主电源 Vcc 的情况下由系统触发导致的复位。PCIe 协议没有定义具体如何触发 Warm Reset,因此产生机制由系统设计者决定,比如改变系统的电源管理状态可能会触发设备的 Warm Reset。
触发方式
如果系统可以提供触发 Power Good 以外的触发 PERST# 的方法,就可以实现 Warm Reset。
Sticky 属性
在 Reset Link 后还能保存之前的错误状态,对 FW 以及上层应用来说很有用。对调试阶段很有帮助。
配套辅助电源(Vaux)保证 Sticky 的字段记录。如果主电源和辅助电源都关闭,Sticky 寄存器也会复位。(详见另一文章 PCIe Stick)
PERST# 信号
PCIe Express Reset 信号,一种边带信号。
PERST# 信号会发送给所有 PCIe 设备,设备可以选择用这个信号,也可以不理它。
关于“PERST# 信号是如何产生的?”请看前面章节:Cold Reset 和 Warm Reset 的触发方式。
Non-Fundamental Reset(非基本复位)
Hot Reset(热复位)
是一种 In-band 复位,不使用边带信号。
触发方式
通过 Assert TS1 的 Symbol 5 的 bit 0 实现,如下图。
PCIe 设备通过向其链路(Link)相邻的设备发送数个TS1 Ordered Set( Symbol 5 的 bit 0 置1)。这些 TS1OS在所有的通道(Lane)上同时发送,并持续 2ms 左右。
PCIe 设备接收到两个连续的带 Hot Reset的 TS1 后,经过 2ms 的超时后:
LTSSM 经过 Recovery and Hot Reset 状态,最终停在 Detect 状态(Link Training 的初始状态),并重新开始链路初始化训练;设备所有的状态机、硬件逻辑、端口状态和配置寄存器(Sticky 位除外)都回到最初值。
如果 Switch 的 Upstream 端口收到 Hot Reset,则会广播至所有的 Downstream 端口,并复位自己。
如果 PCIe 的 Downstream 端口收到 Hot Reset,则只需要复位其自己即可。
方式一 软件配置 Secondary Bus Reset
软件可以通过配置空间的 Bridge Control 寄存器中的 Secondary Bus Reset(二级总线复位)bit 先写0再写1,来产生热复位。
需要注意的是,如果软件设置的是 Switch 的 Upstream 端口的二级总线复位 bit,则该 Switch 会往其所有的Downstream 端口广播热复位信号。而 PCIe-to-PCI 桥则会将接收到的热复位信号转换为 PERST# 置位,发送给PCI 设备。
二级总线复位(Secondary Bus Reset)bit在配置空间的位置如下图所示:
方式二 软件链路禁用
PCIe 协议还允许软件禁止某个链路(Link),通过在下游设备的链路控制寄存器中设置 Link Disable bit,把设备禁用。通过在下游设备的链路控制寄存器中设置 Link Disable bit,把设备禁用。如果将某个链路禁止,则该链路所有的下游 PCIe 设备都将收到链路禁止信号。
Link Control Register寄存器位于PCI Express Capability的Offset PXCAP + 10h: PXLC – PCI Express Link Control。
当禁用时,下游组件会收到禁用信号并执行相应的操作,这也会导致它们进行热复位。
当设备的 Link Disable bit 被置上后,会进入 Recovery LTSSM 状态,即开始向 Root Complex 发送带Disable位设置的 TS1 消息(见下图 Symbol Number 5 中的 bit 1)。需要注意的是,只有在禁用链路后,才能对下游端口进行控制。因此,Link Disable 位被保留给上行端口,例如终端设备或交换机上行端口。
Root Complex 收到这样的 TS1 后,其物理层会发送 LinkUp = 0 的信号给到链路层,之后所有的 Lane 都会进入 Electrical Idle 状态。2ms 超时后,Root Complex 会进入 LTSSM Detect 状态,但是设备会保持在 Disabled LTSSM 状态,等待重启。
FLR(功能级复位)
Function Level Reset,允许软件指定某一 Function,仅复位该 Function,无需复位所有 Function。但如下寄存器不会受到影响:
- 带Sticky属性的寄存器。
- HwInit类型的寄存器。这些寄存器的值由芯片的配置引脚决定,后者上电复位后从EEPROM中获取。
- 一些特殊的配置寄存器。如Captured Power(捕获功率)、ASPM Control、Max_Payload_Size、Virtual Channel等。
- FLR不会改变设备的LTSSM状态。
然而,并不是所有的设备都支持FLR,需要检查 Device Capabilities Register 的 bit 28 进行确认。
触发方式
如果设备支持,软件可以通过 Device Control Register 的 bit 15 来触发 FLR。
操作要求
- 一个 Function 的重置需要在 100ms 内完成。
- 确保 FLR 期间不会访问被 FLR 的 Function。
- 把指令寄存器清空。
- 轮询 Device Status Register 的 bit 5(Transactions Pending,待处理事务)直到被清空。等到了 Completion Timeout,如果 Completion Timeout 没有使能,等 100ms。
- 初始化 FLR 后至少等 100ms。
- 重新配置 Function 并使能。
过程建议
- 不能保留之前的任何可以被读取的信息。如内部闪存需要被清零或改写。
- 回复要求 FLR 的 Cfg 请求,并开启 FLR。
- 对发进来的 TLP 可以回复 UC(Unexpected COmpletion,预期外完成)或者直接丢掉。
- FLR 应该在 100ms 内完成,但其后的初始化还需一些时间,初始化过程中如果收到 Cfg 请求,可以回复 CRS(Configuration Retry Status,配置重试状态)。
复位退出
- 从复位状态退出后,必须在 20ms 内开启 Link Training。
- 软件需要给链路充分的时间完成 Link Training 和初始化,至少要等上 100ms 才能开始发送 Cfg 请求。
- 如果软件等了 100ms 开始发 Cfg 请求,当设备未初始化完成,会回复 CRS。
- 这时 RC 可以选择重发 Cfg 或者上报 CPU 说设备还没准备好。
- 设备被允许最多有 1s 的时间做出正确响应,之后必须能够正常工作,否则系统和 RC 就可以认为设备挂了。
结语
最后友情提醒,无论是 IC designer 还是 Firmware R&D,无论是功能开发还是客诉问题处理,当过程中出现 PCIe Reset 相关事件时,请一定一定先检查:
- 该复位的寄存器是否都复位了?
- 不该复位的寄存器是否误复位了?
希望本文能帮助大家更快地解决问题。