链路全绿却黑屏:视频通路的“状态向量“调试法
> 系列第三篇。场景:FPGA DisplayPort 视频透传(输入端收 GPU,输出端接显示器,
> 中间过 DDR 帧缓冲)。链路层一切正常,屏幕就是不亮——这类问题怎么系统性地查。
## "全绿"骗了我们几次
视频链路调试最折磨人的阶段,不是链路训练失败——那至少有明确的错误码——而是
**一切指标正常但屏幕不亮**:两侧链路训练成功、时序参数正确、主流使能已置位,
显示器背光亮着,画面漆黑或者一屏雪花。
这个阶段我们被"全绿"骗了不止一次,后来沉淀出一个原则:**链路状态只证明"管子
通了",不证明"水在流"。** 要判断水流,必须给整条数据路径的每一段都找到一个
可观测量,拼成一个"状态向量",一次采集、整体判读。
## 我们的状态向量长什么样
以"GPU→接收核→DMA 写→DDR→DMA 读→图样发生器→发送核→显示器"这样一条典型
透传链为例,状态向量至少包含:
1. **两侧链路状态**:训练完成位、每 lane 的 CR/EQ/符号锁定(这只是"管子")
2. **接收侧视频状态**:时序参数寄存器(分辨率/总行场/像素时钟比值)、
视频有效标志——证明协议核确实在解出视频
3. **DMA 写通道状态寄存器**:特别是错误锁存位(行/帧几何不匹配类错误)——
这是我们抓到最多次凶手的地方
4. **帧缓冲内容取证**:直接从 DDR 采样几个字(调试口读内存),间隔几秒采两次
—— 内容在变=真有像素在写;内容凝固=写路径断了;全零=只有初始化数据
5. **DMA 读通道 + 视频时钟锁定 + 图样发生器配置**:证明显示那半边在正确消费
一次黑屏,把向量全采出来,凶手几乎立刻现形。举三个真实案例(细节脱敏):
**案例 A:显示器显示"内存里的陈года数据"。** 向量显示:读通道健康、写通道
零活动、DDR 内容凝固。追到接收协议核里有一个视频输出使能门——bring-up 阶段
为了安静把它关了,忘了打开。视频根本没流出协议核。教训:**协议核内部的
enable 树要画全**,一个被遗忘的门就能吃掉整条流。
**案例 B:换一次显示模式就永久黑屏。** 向量显示:DMA 写通道错误位锁存
(行几何错误全家桶),且**停机后错误位不自动清除**——后续所有"重启写通道"的
自愈尝试都对着陈旧错误空转。两个教训:几何参数(每行字节数)必须和流的实际
打包格式逐模式核对;**错误锁存位的清除条件要读手册**,"停止再启动"往往不够,
需要复位。
**案例 C:一切正常,画面每隔几像素错位。** 向量全绿,唯独 DDR 取证的内容
"模式不对"——同一行内数据周期与预期打包宽度不符。追到"每拍像素数"这个参数在
链路上五个地方出现(接收管线、时序结构、DMA 几何、内存布局、发送核),其中
一处被驱动内部逻辑按像素时钟自动改写,与其余四处失配。教训:**跨模块共享的
格式参数,要么单点定义处处引用,要么在切换点全链同步**——"我这里设过了"不算数。
## 关于"读寄存器的时机"
状态向量方法有个隐蔽的坑:**采样时机**。视频协议核的时序寄存器在管线复位、
模式切换的瞬间会读出垃圾(我们抓到过"色深字段读出不存在的值"这种鬼数据,
差点顺着它修出第二个 bug)。三条守则:
- 采样前先确认链路处于已训练稳定态
- 一次把整组寄存器读完存下来,再去做任何会扰动管线的操作
- 关键值做"隔 N 毫秒复读一致"的防抖确认
## 小结
"链路通"与"画面对"之间隔着一整条数据路径。与其黑屏时凭直觉猜,不如提前给
路径的每一段布好观测点,黑屏时一次采全、整体判读。我们把这套向量做成了固件
里的一个调试命令+一个 JTAG 脚本,后来每次黑屏的平均定位时间从"天"缩到了
"十分钟"。
(本系列下一篇:嵌入式调试的四个反直觉时刻)