最近帮客户调了一轮慷智AIM951/958的SerDes链路,从一片黑到画面稳定上屏,前后折腾了差不多一周。这中间踩了不少坑,也攒下了一套可以复用的话术和流程。今天把从寄存器配置到屏幕点亮的全流程拆开来讲,准备了一份可以直接抄作业的调试思路。不管你用的是哪家主控,只要走的是“摄像头/视频源 → 串行器 → 同轴线 → 解串器 → SoC → 屏幕”这条路,这套方法论基本都能用得上。
1. 项目背景与链路思路拆解:为什么SerDes是屏幕点亮的关键一环
1.1 SerDes是什么,AIM951和AIM958在链路里各干什么活
先解释一下名词。SerDes全称是Serializer/Deserializer,也就是串行器/解串器。它的核心工作就两件事:发送端把并行的MIPI信号转成一对高速串行差分信号,经过同轴线或者双绞线长距离传输;接收端再把串行信号恢复成MIPI CSI-2接口。对车载项目来说,这个转换的意义非常大,因为MIPI CSI-2在PCB上走线一般只能撑到十几厘米,超过这个距离信号质量就掉了,更别说摄像头装在车门、后视镜、车顶这些离主板好几米远的地方。
慷智AIM951和AIM958就是一对车规级SerDes芯片。AIM951是串行器,一般放在远端视频源那一侧,负责把摄像头的MIPI CSI-2数据打包成高速串行信号;AIM958是解串器,放在主控板这一侧,负责把线缆上收到的串行信号恢复成MIPI CSI-2,再交给SoC的CSI控制器。
打个比方,MIPI信号就像市内跑的小货车,灵活但跑不远;SerDes串行链路就像长途卡车,专为高架和高速设计,运力大、线路长。车上需要从远端把视频信号拉到中控屏幕的场景,用AIM951/958就是这个思路。
1.2 一条完整的视频链路:从镜头到屏幕
很多朋友一拿到这套芯片就急着写寄存器,我觉得先画清楚自己的数据流更重要。典型链路是这样的:
远端摄像头模组输出MIPI CSI-2,接到AIM951的并行侧,AIM951将数据串行化之后经过同轴线缆传到主控板上的AIM958,AIM958解串后恢复出MIPI CSI-2,接到SoC的CSI接口,SoC拿到图像数据后经过显示控制器送到LCD屏幕。
这个链路里,“屏幕点亮”的本质是完成两件事:第一,远端视频源的数据能完整地到达SoC;第二,SoC端能正确解析并显示这些数据。SerDes寄存器配置解决的只是第一件事,但很多时候第二件事的配置错误也会表现为“屏幕是黑的”,这就是为什么调试时要分清楚哪一段出了问题。
我这边用过的平台恰好是T113i这类车机SoC。T113i有自己的MIPI CSI接口和MIPI DSI接口,CSI用来收SerDes解串后的视频,DSI用来驱动屏幕,两者之间靠SoC内部的显示通路衔接。严格来说,T113i点亮屏幕需要把“CSI摄像头输入到显示回显”这条软件通路打通,而不只是让屏幕背光亮起来。理解这一点,就不会在调试时把背光问题和数据链路问题混在一起。
2. 调试前的装备与硬件准备:随手就能复用的检查清单
2.1 软硬件工具清单
SerDes调试和普通外设调试不太一样,涉及两个物理端点和一条传输线,排查问题必须同时盯住多个点。所以准备工具时不要心疼,前期装备越齐全,后面省的时间越多。
- 硬件:AIM951串行器模组、AIM958解串器板卡、摄像头模组、同轴线或双绞线线缆、开发板(T113i或其他带MIPI CSI的SoC板)、稳压电源、示波器(至少500MHz带宽,建议1GHz以上看信号质量)。
- 软件:i2c-tools工具包、逻辑分析仪上位机、I2C读写脚本(Python或Shell都行)、芯片寄存器手册(AIM951和AIM958各一份)、主控SoC的参考手册和驱动源码。
- 文档:拿到样片时一定要找原厂FAE要对应版本的寄存器手册。SerDes芯片版本更新很快,网上流传的零散配置不一定匹配你手里的芯片批次,这个坑我踩过,后面有一节专门讲。
工具这块很多人会忽略逻辑分析仪,总觉得示波器就够了。实际上I2C隧道是否打通、远端寄存器有没有写进去,逻辑分析仪能直接抓波形判断,比示波器看电压毛刺更直观。有条件的话两个都上,没条件至少保证I2C调试工具到位。
2.2 上电与硬件连接检查:先解决物理层
先看供电。AIM951这一侧如果用了Power over Coax(同轴供电),那远端模组不需要单独拉电源线,但主控板这边的AIM958供电能力要够,否则线缆一长电压跌落,摄像头发热后更容易出问题。如果是独立供电,也要确认上下电时序,远端摄像头模组和AIM951的供电顺序不稳定,会导致芯片锁死或者寄存器初始值错乱。
再看线缆连接。AIM951和AIM958之间是同轴线还是STP双绞线,取决于项目设计。不管哪种,连接器必须锁紧,线缆屏蔽层接地要可靠。很多“图像偶尔花屏”的case查到最后是Fakra头松了,或者屏蔽层压线没压好。
MIPI侧的方向一定要确认清楚。AIM951的输入端是MIPI CSI-2,AIM958的输出端也是MIPI CSI-2,中间的同轴串行链路是两个专用引脚。这个看起来不会错,但我见过有人把CSI输入输出接反,导致花了整整一天查寄存器。
最后一个容易忽略的是时钟。MIPI CSI-2需要参考时钟,SoC端的CSI控制器有没有正确输出或者接收时钟,直接决定链路能不能稳定。先确认时钟频率和极性,再谈寄存器配置。
3. 寄存器配置全流程:从读懂手册到命中关键位
3.1 先弄懂AIM951/958的I2C访问机制
AIM958在主控板上,直接挂在SoC的I2C总线上,这个访问比较简单。AIM951在远端,SoC没法直接访问它,必须通过AIM958的I2C隧道功能进行转发。
理解这一点非常重要,我见过不少人拿I2C工具直接去读AIM951的寄存器地址,结果总线上根本没有这个设备,自然读不到。正确的流程是:先访问AIM958,配置好隧道转发,让AIM958把对指定地址的读写请求通过SerDes链路转发给AIM951,AIM951收到后再响应。这个过程对外部I2C主控是透明的,但对调试人员来说,必须记得先使能转发。
具体操作上,一般是通过I2C写AIM958某个寄存器使能地址映射,然后在同一总线上用AIM951的从设备地址直接读写远端寄存器。AIM951和AIM958的默认I2C地址可能相同,也可能不同,这取决于芯片外部引脚配置和寄存器设置。如果地址冲突了,需要通过外部引脚或者初始配置错开。
调试时我习惯先用i2cdetect扫描一下挂在总线上的设备,确认能读到AIM958和摄像头模组再往下走。总线上一片空白的话,先查硬件连接和供电,别急着写配置。
3.2 初始化顺序:先视频再控制,还是先控制再视频
AIM951/958的寄存器很多,但初始化顺序有讲究,不是随便照着手册挑几个位改一改就行。我总结的推荐顺序如下:
- 复位AIM958和AIM951,确保芯片处于已知状态。
- 配置AIM958侧的PLL和I2C隧道相关寄存器。
- 配置AIM958的输出端MIPI CSI-2参数,包括lane数、时钟极性、连续时钟模式。
- 通过I2C隧道配置AIM951的输入侧MIPI CSI-2参数和PLL。
- 打开视频流使能位,让串行链路开始传输数据。
- 检查LOCK状态寄存器,确认解串器已经锁定远端信号。
- 启动SoC端摄像头应用或回显通路,屏幕上出现图像。
为什么要按这个顺序?因为SerDes链路是从解串器到串行器逐级建立连接的过程。AIM958需要先知道对端的时序和速率参数,才能正确锁定信号。如果先把AIM951开了,却发现AIM958还没配好,链路就会出现连续失锁,进一步导致I2C隧道也不稳定,后面的操作都要重来。
另外,I2C隧道是否稳定和视频链路是否锁定有关。链路没锁定时,远端I2C是没法正常访问的,所以先确保链路物理层建立,再做上层寄存器配置。
3.3 常见寄存器功能划分与配置示例
AIM951和AIM958的寄存器表按功能模块组织,不同批次芯片地址可能略有调整,所以我这里用功能宏名来表示,实际开发时替换成手册里的具体地址即可。
- 芯片ID/版本寄存器:用于确认I2C通信正常,一般只读。
- 复位控制寄存器:软件复位,配置前先复位一次。
- PLL配置寄存器:设定串行链路的传输速率,需要和远端匹配。
- CSI-2 lane数和数据速率寄存器:设定视频接口的模式,主控侧必须一致。
- 视频流使能寄存器:打开/关闭视频数据传输。
- GPIO和中断寄存器:用于输出LOCK状态或者接管外部信号。
- 转发/隧道配置寄存器:AIM958上用,使能远端寄存器访问。
这里给一个伪代码级别的初始化脚本,方向对了,细节按手册替换:
#!/bin/bash # AIM958 local side i2cset -y 2 0x40 0x01 0x01 # software reset AIM958 sleep 0.1 i2cset -y 2 0x40 0x10 0x00 # disable video stream before config i2cset -y 2 0x40 0x20 0x03 # MIPI CSI-2: 4 lanes, continuous clock i2cset -y 2 0x40 0x21 0x64 # set data rate / PLL parameter i2cset -y 2 0x40 0x30 0x01 # enable I2C tunnel / address mapping # Access AIM951 through AIM958 tunnel i2cset -y 2 0x44 0x01 0x01 # software reset AIM951 sleep 0.2 i2cset -y 2 0x44 0x10 0x00 # disable video stream i2cset -y 2 0x44 0x20 0x03 # MIPI CSI-2 input: 4 lanes i2cset -y 2 0x44 0x21 0x64 # set data rate / PLL parameter # Enable video stream i2cset -y 2 0x40 0x10 0x01 # enable AIM958 video stream i2cset -y 2 0x44 0x10 0x01 # enable AIM951 video stream再次强调,0x40和0x44只是示意地址,实际要以你的硬件原理图和芯片手册为准。但配置思路是一致的:先复位,再关流,然后配PLL和CSI参数,开隧道,最后使能视频流。
3.4 摄像头侧的I2C总线桥接
很多应用里,AIM951远端挂的不只是摄像头模组,摄像头的sensor寄存器也要通过I2C配置,比如曝光、增益、分辨率等。这时候AIM958要把主控的I2C请求转发给AIM951,再由AIM951挂载的I2C总线访问sensor。
这个“远程sensor寄存器读写”是调试中最容易困惑的地方。你需要配置AIM958的转发目标地址,让主控发出的sensor地址请求走到远端总线。此外,如果远端sensor的I2C地址和主控板上某个设备地址冲突,还需要通过地址重映射机制错开。
我自己的习惯是,在打通AIM951/958链路后,先读远端sensor的chip ID,如果能读到,说明I2C隧道和远端总线都正常,再往前推进视频配置。这样把问题拆成两段,排查范围会小很多。如果sensor ID读不到,优先查隧道配置,而不是反复折腾视频寄存器。
4. 屏幕点亮全流程实操:一次典型的调试过程
4.1 第一步:确认主控CSI控制器配置
以T113i平台为例,T113i的CSI控制器需要配置MIPI CSI-2的lane数、时钟极性和虚拟通道。AIM958输出的lane数必须和SoC端CSI控制器的lane数一致,否则SoC收不到完整数据。
不少项目的板子在硬件连接时只走了2 lane,但软件里配了4 lane,结果就是屏幕花屏或者直接黑屏。这个在设备树或者驱动初始化里一般都有对应字段,先确认一致再上电。
还需要确认CSI控制器的输入数据速率。AIM958输出端的数据速率是根据远端串行链路速率和lane数计算出来的,SoC端也要按这个速率配置,才能正常接收。实际操作中,我会先把SoC的CSI配置成和AIM958完全一致的参数,然后才去操作SerDes芯片。
T113i点亮屏幕还有一层,就是SoC内部的显示通路。CSI收到的是摄像头或视频源的图像,要显示到屏幕上,需要配置ISPOST、显示控制器等模块,让数据从CSI一路走到DSI接口。这一步调的就是SoC内部的软件通路,和SerDes芯片本身关系不大,但很多人会在这里卡住,误以为是SerDes没配好。
4.2 第二步:点亮AIM958并观察LOCK状态
上电后,先做最小化确认。用i2cdetect扫描SoC的I2C总线,找到AIM958的地址,然后读芯片ID寄存器,确认基本通信正常。再读PLL和LOCK状态寄存器,看看芯片是否进入工作状态。
这里说的LOCK状态是整个调试过程中的关键指标。AIM958在锁定远端AIM951发出的串行信号之后,LOCK引脚或LOCK状态位才会置位。如果LOCK一直为0,说明物理链路或者参数配置有问题,要么线缆没接好,要么PLL参数配错,要么AIM951那侧根本没发数据。
我调试时会在程序里循环读LOCK状态,同时用示波器看AIM958的MIPI输出引脚。如果LOCK跳成1,但CSI输出还是没有波形,那问题就在AIM958的CSI输出配置上;如果LOCK根本没置位,就先回到物理层和串行链路配置。
4.3 第三步:配置AIM951并打通I2C隧道
AIM958起来之后,重点转到AIM951。首先要确认I2C隧道已经打通,方法很简单:通过AIM958的隧道功能去读AIM951的芯片ID,能读到就说明链路两端能通信了,这时候再配置AIM951的CSI输入参数和PLL。
注意配置AIM951时,视频流使能位先不要打开,等所有参数都设好后再开。打开视频流之后,链路会开始传输连续的视频数据,如果这时候再去改PLL或者lane数配置,可能触发芯片重新锁定,出现几秒钟的黑屏或者花屏。
远端摄像头的sensor寄存器也可以在这个阶段一并验证。通过隧道读写sensor的chip ID,确认能访问到远端总线设备。如果sensor ID读不到但AIM951能读到,问题大概率在AIM951到sensor的I2C总线侧,查一下远端上拉电阻和供电。
4.4 第四步:图像上屏与常见现象判断
以上都正常后,启动SoC端软件通路,让屏幕显示远端视频源的图像。第一次点亮时不要期望画面直接完美,大概率会碰到以下几种情况:
- 全黑,但显示通路有出来,比如背光亮、UI正常,只是没有视频画面。
- 花屏,满屏噪点或者条纹。
- 图像有但不稳定,偶尔黑屏闪断。
- 色彩不对,偏色或者颜色翻转。
每一种情况的排查方向是不一样的。全黑优先查AIM958的CSI输出和SoC的CSI接收配置;花屏优先查lane数、数据速率不匹配;不稳定闪断优先查LOCK状态和物理层信号质量;偏色优先查MIPI的数据位序和SoC端pixel format配置。
这时候把手里的示波器用起来。用示波器量AIM958输出的MIPI data lane和clock lane,看有没有合理的差分波形。数据lane是高频翻转的,clock lane如果是连续时钟模式会有稳定的时钟波形,如果是非连续时钟模式,只在传输active数据时才有时钟。如果数据lane完全没波形,说明AIM958没输出数据;如果有波形但SoC收不到图像,问题就在SoC端软件通路。
5. 常见问题与排查技巧实录
5.1 I2C访问不通怎么办
这是第一步就会遇到的问题。I2C总线上扫描不到AIM958,或者能扫到958但读不到951。排查顺序:
| 现象 | 可能原因 | 排查方法 |
|---|---|---|
| 扫描不到958 | 供电、地址配置、I2C上拉 | 量电压、查硬件地址引脚、确认总线上拉电阻 |
| 能扫到958但读不到951 | I2C隧道未使能、链路未锁定 | 读958隧道状态寄存器、确认视频链路LOCK |
| 读到951但读不到sensor | 远端总线问题、地址映射 | 确认sensor地址、查远端上拉和供电 |
我实际操作中发现,最容易被忽视的是I2C总线上拉电阻。SerDes芯片配置时需要较快的I2C速率,上拉电阻太大导致波形上升沿太缓,就会出现时而能读时而不能读的现象。有条件的话用逻辑分析仪抓一下波形,直接看地址帧有没有ACK响应。
5.2 屏幕黑屏但链路已经锁定
链路LOCK已经置位,I2C通信也正常,但屏幕就是没有画面。这种case八成不在SerDes这边,而在SoC端。
先确认SoC有没有收到MIPI数据。可以在CSI驱动里打印中断状态寄存器,看有没有FIFO overrun或者帧同步错误。如果中断状态全0,说明SoC根本没收到数据,那就要回头查CSI配置和AIM958输出参数。
还要注意AIM958视频流使能位和SoC CSI启动顺序。有些板卡要求先启动SoC CSI接收,再使能SerDes视频流;有些则相反。这个差异来源于芯片具体实现,一般手册里会写。如果顺序反了,某些芯片会在建立链路的瞬间丢几个关键同步信号,导致一直等不到帧头。
5.3 图像花屏、闪断,物理层要重点查
花屏和闪断是SerDes调试里最磨人的问题。很多时候寄存器配置看起来全对,但图像就是带着雪花或横条纹。
这类问题我开始都会先看一眼物理层信号质量。和FPGA开发中接触的GT SerDes一样,AIM951/958的高速链路也存在预加重和均衡参数调整的余地。如果误码率高,可以尝试调整解串器的均衡档位或串行器的摆幅设置。这个参数不是越大越好,过大反而引入过冲,需要根据线缆长度实测。
线缆长度也是个变量。拿着标称能传输15米的设计,结果现场布线绕了远路,实际链路长度可能超过20米,这时需要适当加大对端均衡,或者降低传输速率。反过来,如果线缆很短还出现高频自激,也可能需要减小摆幅。
如果花屏表现为整帧随机噪点,大概率是链路误码造成的。可以先故意把视频流关掉,测试I2C隧道是否稳定;再用大量循环读写远端寄存器和预期值比较,确认误码率。隧道稳定但视频花屏,说明误码集中在高速差分信号上,调整物理层参数比改寄存器更有效。
5.4 LOCK状态偶发丢失,热启动后掉链子
项目做完之后偶发LOCK丢失,超过一半的根因在电源和地。摄像头模组在夜间开红外灯、补光灯时电流大,如果供电走线太长或者阻抗不够,压降会让SerDes芯片进入欠压保护。
还有一个经常踩的坑是SoC和SerDes的上电时序。T113i这类主控的I2C、GPIO在启动过程中有短暂高阻态,如果此时访问SerDes芯片,可能导致芯片进入异常状态。处理办法是确保SoC完成启动后再初始化SerDes,或者在硬件上加上电复位电路。
软件层面,我建议把LOCK状态做成周期性检测,发现失锁后自动重新初始化链路,而不是傻等。值班工程师接到投诉的时候可能只看得到“晚上偶尔黑一下”,没有自动恢复机制就要派人去现场复现,太痛苦。
6. 一点个人经验与建议
这套芯片调试下来,我最大的体会是想清楚再动手。拿到一个SerDes项目,第一件事不是找FAE要一堆初始化代码,而是先把数据流图画出来,把主控CSI、AIM958、AIM951、远端sensor四个节点之间的距离和接口关系搞清楚。任何一个节点的配置错配,都会表现为屏幕上的现象问题,而真正的故障点可能在完全意想不到的地方。
我现在的习惯是,所有寄存器配置全部做成脚本,并且添加注释说明每个寄存器的功能,不用一次性把所有功能都打开。视频流、I2C隧道、GPIO这些功能分开配,每配上一步就用i2cget读回确认,这样出了问题能快速定位在哪个功能模块。
另外,如果项目进度允许,尽量在电路板设计阶段就引出几组关键信号测试点,AIM958输出的MIPI差分对、LOCK状态引脚、I2C信号、同轴线输入端,有了这些测试点,后面量产阶段出了实际问题才能快速排查。没有测试点,调试时只能拿镊子戳芯片引脚,风险大效率低。
最后再分享一个小技巧:一旦屏幕点亮后,先别急着优化,把当前这套寄存器配置完整保存下来,包括初始化和异常恢复的逻辑。后续如果要换线缆长度或者换sensor,都是在这套稳定版本上做增量修改,而不是推翻重来。SerDes调试的坑踩一次就够了,把经验沉淀成配置模板,下次接新项目能省一半时间。