PCIe ASPM低功耗状态与系统节能调试 - 第4节
L1状态简介:深度省电与延迟权衡
好,我们接着聊L1状态。说白了,L1才是真正意义上的“深度省电”。L0s虽然省电,但只是小打小闹。L1直接把链路推向休眠——不仅数据通道停了,参考时钟、主PLL、大部分模拟电路都可以关掉。
一句话总结:L0s治标,L1治本。省电幅度差一个数量级。
L1与L0s的本质差异
我最早接触L1状态,是在一个NVMe SSD项目里。当时功耗压不下去,只看L0s的省电数据,总觉得差不多了。实际一测才发现,空闲时间稍长一点,L0s根本不够用。必须上L1。
咱们看核心对比:
| 特征 | L0s | L1 |
|---|---|---|
| 省电深度 | 浅(减掉FLR) | 深(关掉PLL、大部分模拟) |
| 典型功耗占比 | L0的60%~80% | L0的5%~15% |
| Entry触发条件 | 空闲状态 + 已发送完所有TLP | 空闲状态 + 双方均允许 + 无待处理Flows |
| Exit延迟 | ~500ns(仅链路恢复) | 1μs~10μs(需重锁PLL) |
| 对链路影响 | 保持电气Idle | 电气Idle更深(甚至可断时钟) |
| 软件可见性 | 透明 | 需ASPM软件配合 |
我的一个小习惯:初次接触一个PCIe设计时,我会先看链路空闲分布。如果单次空闲 < 5μs,大概率L0s就够了;如果空闲经常 > 10μs,L1才是最优选择。
L1的省电机制——到底关了啥?
你想想看,L0s只是把发送器静默,但PLL、时钟树、接收器还在跑。L1呢?直接说拜拜。
- Main PLL关闭——这是最大省电来源。PLL一旦停掉,整个收发器的参考频率就断了。
- 大部分模拟电路偏置关闭——包括Rx的EQ、DC平衡、连续时钟恢复。
- 参考时钟可关断——如果平台支持CLKREQ#,Root端可以在L1时停掉REFCLK。
- Phy层状态机缩到最小——只留一个极小状态机监视唤醒信号。
我记得有人问:“L1省这么多电,代价是什么?”代价就是Exit延迟。L1离开时,PLL必须重新锁定。这个重锁时间,往往是整条链路上最慢的一步。
为什么会这么慢?因为PLL锁定需要时间,有些设计需要1μs~2μs才能稳下来。如果链路还涉及CLKREQ#恢复,再加几百纳秒。所以L1的Exit延迟,无论如何都比L0s长。
L1的状态机——Entry与Exit流程
嗯,这里要注意。L1的Entry不是你想进就能进。它需要Link两端都同意。我怎么理解这个机制呢?
链路两边各有各的能力寄存器(ASPM Control寄存器),软件必须把两边的L1 Enable位都置1。然后硬件会监视链路空闲条件。满足后,EP发一个PM_Enter_L1 DLLP,RC回一个PM_Enter_L1 Ack。接着双方才能同时沉入L1。
- Entry前提:双方ASPM均开启 + 所有Pending TLP完成 + 流控Credits归还。
- Entry握手:PM_Enter_L1 → PM_Enter_L1_Ack → 进入电气Idle。
- L1维持:Tx/Rx均关闭,除唤醒电路外无活动。
- Exit条件:任意一侧发送Electrical Idle Exit (EIE)信号。
- Exit恢复:PLL Re-lock → 链路Training → L0。
我曾经踩过的一个坑:一次项目中,EP端的PLL恢复时间比spec慢了20%。L1 Exit时,RC已经在L0等EP,但EP还在锁PLL。结果RC超时,直接报LTSSM错误。说白了,Exit时间必须卡死,不能有侥幸。
这个地方我想给你一个实际的参数参考:
| 参数 | 典型值 | 说明 |
|---|---|---|
| TL1_on | 100ns~400ns | 从进入电气Idle到确认为L1的时间窗 |
| TL1_off | 50ns~100ns | 从退出电气Idle到PLL开始工作 |
| DL1_on | 1μs~3μs | PLL重锁 + 链路恢复 |
| DL1_off_Target | 最坏情况 < 10μs | 整个L1 Exit的总时间目标 |
这些数值,不同芯片差别很大。我建议你用寄存器实测转换延迟,别信datasheet上的典型值。
L1 vs L0s:怎么选?
你手里有个设计,到底该用L0s、L1,还是都用?我个人的判断标准:
- 平均空闲 < 2μs:L0s就够了。L1的Entry/Exit开销反而得不偿失。
- 平均空闲 2μs ~ 10μs:先只开L0s,观察功耗。如果不够,再考虑L1。
- 平均空闲 > 10μs:L1是最佳选择。这类场景常见于NVMe、GPU空闲、网卡轻负载。
- 混合场景:同时开启L0s + L1。硬件会自动选择:短空闲走L0s,长空闲走L1。
但注意,同时开L0s和L1时,入口条件是叠加的。如果L0s还没退出,不可能直接跳L1。硬件会先退L0s再进L1。这个过渡我见过很多设计做不好,导致额外的延迟抖动。
我建议的做法:如果你同时开L0s和L1,给L1的Entry再加一个延迟定时器。比如空闲10μs后才允许进L1。这样避免频繁切换,减少状态机抖动。
L1的扩展:L1.1与L1.2
这里提一嘴,PCIe规范在L1基础上又加了两个子状态:L1.1和L1.2。区别在于,L1.1只关PLL,但REFCLK还在;L1.2连REFCLK都停了,省电更深。这两个子状态的Entry条件更严格,但省电效果更好。
不过,第一次学ASPM,先把L0s和L1搞透。L1.1和L1.2属于进阶内容,后面会单独讲。
本章知识结构图
下面这张图,帮你把L1在ASPM状态机中的位置、Entry/Exit流程、关键参数串起来。
图里你看,L0s和L1都是从L0走出。L1的进入条件更严格,但省电深度远优于L0s。退出时,L1要经历PLL重锁和链路恢复,延迟一下就上去了。所以,搞清楚你的系统空闲特征再选,别盲上L1。
核心结论:L0s适合短功耗优化,L1适合长功耗优化。两者不是替代关系,是互补关系。在一个成熟设计中,我通常建议同时开启,让硬件自己选——但一定要配上延迟定时器,防频繁切换。