索尼IMX159传感器模组简单逆向手记(附:索尼CMOS传感器简易逆向指南)

前情提要:鄙人在小黄鱼上购得M43传感器的无人机云台一台(臻迪黄金眼云台(M43传感器云台)拆解),因为眼馋里面那传感器,于是想通过逆向工程来完成二次利用。

另外网上似乎没有太多关于索尼CMOS传感器的逆向指南,本着抛砖引玉的想法,就在这里简单的写一些关于索尼CMOS传感器的逆向指南。

基础知识

前面我一直在强调“CMOS传感器”,而非简单的“传感器”,是因为CCD传感器的逆向方法和CMOS传感器不完全相同。不过这两者逆向都有一个前提:就是必须要有一台能够正常工作的相机,这样才能采集信号。

CCD传感器是用户生成传感器读出时序,读出来的也都是模拟信号,虽然原始,但好处就是只需要示波器+万用表就能进行逆向(建议:逆向CCD时,示波器通道要多,最好是8通道甚至多台并联,不开玩笑)。通过测量/抓取引脚上的电压变化,推测传感器引脚定义/读出时序。纯苦力,但这个方法一点毛病没有,我逆向ICX453时就这样。

(逆向ICX453)

CMOS传感器就完全不同了,CMOS传感器读出时序由传感器本身管控(再加上用户给的同步/触发信号),用户侧能掌握的就是往里面的寄存器里写配置,然后传感器根据配置运转。所以逆向时,我们能够抓取的就是主控向传感器写配置的那个总线。然后去改相机参数(快门,ISO之类的),观察总线上的数据是否呈现某种规律。

例如,改变快门速度时,总是能观察到主控向一个相同的地址写不同值,那么这个寄存器大概率就是用来控制曝光的。

有了上面的基础知识,来看看索尼CMOS传感器都有啥特点。

索尼CMOS传感器特点

由于传感器市场的封闭性,以及考虑到潜在竞争,索尼对于定制传感器、新型号传感器、介于M43-全画幅面积的传感器,手册都是严格管控的。

所以下面内容这部分主要是根据本人使用有公开手册的索尼传感器时总结出来的,仅供参考。

物理特点

对于陶瓷封装的索尼CMOS传感器来说,大部分型号的图像输出接口都在封装某一侧集中出线,水平排开。传感器控制信号会集中在某个角落,剩下的都是电源相关引脚。

(IMX415引脚图)

信号特点

索尼CMOS传感器从用户侧看来还是比较友好的,主要的信号可以分为三组:

图像信号

一般是4~11对差分信号,可能使用的协议有subLVDS、SLVS-EC、MIPI DPHY、MIPI CPHY(CPHY不做讨论,这玩意感觉是非人类设计的)

同一传感器上,一般只有一种协议,有的会同时支持两种。

对于subLVDS接口,索尼一般使用统一的起始/结束码。有的型号可能会有IDLE态发送训练码(比如这次的IMX159,会发送0x208作为训练码),有的型号就不会在IDLE态发送训练码(本人用过的其他索尼subLVDS接口传感器)。不过没有IDLE态训练码也不要紧,在有效数据发送时,传感器是肯定会发送起始/结束码的。

(subLVDS接口起始/结束码)

对于MIPI DPHY接口,可以直接参考MIPI标准。貌似索尼的MIPI DPHY接口不会利用到LP信号,还是要通过自己的配置接口去配传感器。另外有的传感器支持2组4通道MIPI(例如IMX482),不过在这不做讨论。

对于SLVS-EC接口,本人并没实际使用过,不过根据The Landingfield博客,看起来就是很标准的内嵌时钟Serdes,使用K28.5作为同步码。同样的,所有配置都是走别的接口,图像接口只负责图像输出。

(图像来源:The Landingfield—Decoding the SLVS-EC protocol from IMX410BQT

时钟/控制信号

主要有参考时钟输入(INCK)、同步信号输入(XVS/XHS)、SPI/IIC输入输出(传感器配置接口)、传感器使能/复位(XCE/XCLR)、传感器主从机配置(XMASTER,有的型号没有这个,只支持从机操作,从机模式意味着用户需要向传感器提供同步信号)

参考时钟:

可能会使用27MHz、36MHz、54MHz、72Mhz、74.25MHz这几个频率。一个小窍门就是:传感器的PLL其实不会关心你输入的参考钟频率,它只知道要把频率乘以多少、除以多少(即:只有比例关系)。如果想让传感器降速运行,那么直接更换一个更慢的晶振即可,想超频?换一个更快的晶振。当然,别走极端给他换个32KHz/200MHz的晶振上去,这肯定是跑不了的。在合理范围内,是可以使用不同晶振来改变传感器运行速度的。

这么搞有啥用呢?其实一般没多大用处,但是The Landingfield博客在逆向IMX410时,就通过直接更换参考时钟频率,让SLVS-EC接口降速一半运行,成功使用Xilinx 7 Series的HRIO配合ISERDES接受SLVS-EC信号(数据速率约1300Mbps)。所以如果你要逆向SLVS-EC接口或者MIPI接口时,更换晶振是个有用的技巧。

(图像来源:The Landingfield—Decoding the SLVS-EC protocol from IMX410BQT

SPI/IIC配置接口:

索尼没在这上面玩花活,都是比较标准的,相关接口知识网上也都有。唯一需要注意的可能是大小端序问题?

(SPI接口配置传感器时使用小端序)

但是逆向的时候我们一般不会关心这个,反正数据抓出来是怎么样,就按照原样给它塞回传感器里,至于寄存器的具体意义就更无从得知了。

现代CMOS传感器在上电时,都要通过配置接口写入各种魔法数(Magic Number),用于配置PLL、内部计数器、读出模式之类的。

某些厂商的传感器,上电时需要将每个像素的校准信息逐个写入,整个配置表下来大概几个Mbit,十分的恐怖。另外还有很多配置必须要在FAE的协助下才能完成,因为那些隐藏寄存器该怎么写只有原厂懂。

就单说配置这一方面,索尼是做的最好最阳间的,使用公版传感器,多数时候仅靠手册就可以将传感器点亮。

同步信号XVS/XHS:

某些型号中,该组信号可以被配置为输入或者输出。配置为输出时,就是主机模式,传感器主动输出同步信号告知主机。配置为输入时,就是从机模式,主机需要向其中输入信号控制读出。一般情况下从机模式使用比较多(而且很多型号也只有从机模式),这里就以从机模式操作举例。

一般来说,XVS的下降沿会激活传感器的电子快门回到初始位置(或者将传感器进行全局重置,配合机械快门/闪光灯使用),然后检测到XHS下降沿时,就读出一行像素。因此XVS信号决定传感器读出帧率(当然也取决于传感器最高速度),XHS决定传感器读出行数。

(XVS/XHS简易示意图)

在subLVDS传感器上使用从机模式时,需要注意的是传感器的图像输出接口和XVS/XHS信号不是稳定对齐的,需要用户自己维护。。

什么意思呢?比如你在传感器上电时,对齐了LVDS接口,找到了正确的数据起点。你很满意,打算拍一张照片,所以让XVS和XHS信号开始发出,结果发现原本对齐的数据接口失去了同步,数据又重新变回不对齐状态了。

出现这种情况的原因主要是和FPGA的SERDES工作方式,图像传感器输出抖动有关。但简单来说,用户要保证XVS/XHS信号到达传感器的时间点、传感器图像数据到达FPGA的时间点,这两者要卡在合适的窗口期。不然LVDS对齐就会被破坏。不过一旦找到了正确的同步时间点,这个对齐关系就不容易被破坏了,除非被外界干扰。

最优解还是实现一套动态对齐系统,因为上面说的卡Timing方法属于是投机取巧。有些厂商的Sensor每一帧(甚至行之间)出数据的时间抖动很大,因此重新对齐不是可选项而是必须项,要不然是永远接收不到正确数据的。

现在也终于理解为什么IMX159会在IDLE态发送训练码了😡。后面的型号可能是优化了,能够保证帧之间输出时不会失去对齐。

供电引脚

索尼传感器的直接供电引脚一般分为三组:模拟电源、数字电源、通信接口电源。除此之外还有片上LDO,用户需要外接参考电阻和退耦电容给这些片上LDO使用。另外这只是基础款供电,比较群魔乱舞的,比如IMX571,就还得让用户提供各种偏置电压。

供电这边没什么坑一般,尽管索尼手册里推荐上电时序,但笔者目前用了这么多索尼传感器,都是一股脑全部上电,没有遇到问题。不过有些传感器厂家的逆天产品确实是要严格按照时序上电,不然会出现短路的情况。

索尼CMOS传感器逆向的简单方法

讲完了索尼传感器基础,现在该讲讲上面的知识能在逆向中发挥什么用处了。

首先我们要明确目标,一般来说,逆向传感器,是连带着传感器载板PCB一起逆向的,而不是传感器本身。而使用时,也是直接使用安装有传感器的PCB板,而不是拆下传感器,重新安装到自己的定制PCB上,主要原因有二:

首先,现代CMOS传感器引脚数量多,大部分是电源引脚和无连接引脚。电源引脚逆向风险大,如果逆向错误有可能就放烟花了。另外如果传感器电源轨太多(加上各种片内LDO),也很容易逆向错(漏掉LDO的外接退耦电容之类)。如果使用LGA封装,逆向起来更是痛苦。

其次,直接使用现成传感器载板,我们就只需要逆向2至3个主电源(剩下电源转换由板载的稳压器完成),时钟/控制信号,图像信号引脚即可。不仅省时省力,还免去了拆焊传感器的风险。

话说回来,逆向传感器模组时,我们也主要关注电源、图像信号、控制信号三者,下面是我在逆向IMX159时的几个主要步骤:

  1. 确定载板主电源电压,GND连接
  2. 确定传感器图像信号引脚
  3. 确定传感器控制信号引脚
  4. 抓取上电过程,运行过程中寄存器配置
  5. 抓取XVS/XHS同步信号
  6. 制作转接板,尝试使用FPGA驱动

IMX159模组逆向尝试

Step1:目测排线,初步推断模组接口定义

前面提到,我们主要关注电源线、图像信号线、控制信号线,根据其功能特点,一般三者都会在形态、位置上表现出比较明显的特征。

首先是电源线,为了提高过流能力,一般会使用比较粗的走线,亦或者多根相同的导线连接到一起,形态上很容易辨认。

然后是图像信号线,subLVDS、SLVS-EC、MIPI DPHY都使用的是差分信号,并且由于速度很高,它们在设计板子时会被“特别关照”,有自己的布线区域。

最后是控制信号线,一般都是低速单端信号,这些线没办法一眼看出来其功能,必须配合万用表通断挡,结合板子上各个芯片的型号和功能,必要时还得挂逻辑分析仪或者示波器才能推断出来是干什么的。

好了,有了以上的知识,下面是这个传感器模组的排线照片,你能看出来这些线都承担了什么功能吗?

从图中我们不难看出,排线上部分区域就是图像信号的走线,而且数一下,正好11对,正好是subLVDS接口10对数据+1对时钟的配置。

紧接着往下有三组比较宽大的走线,不难推断这些就是电源线。

中间和下面部分的单端走线就是控制信号线。从下往上第8条信号线还被两GND包裹,不难推断这个是传感器的时钟信号。至于剩下的信号功能,就需要进一步推测了。

Step2:结合板载芯片型号,反推控制线

板子背面有如下芯片(特别感谢帮我反推丝印的群友):

第一张:

最上方:LT3024 LDO

中间:RT9013 LDO

最下方从左到右:MPU6500 惯性传感器,SN74AVC4T774RSVR * 2 电平转换器

第二张:

最左侧:MP2005 LDO

借助这些芯片的数据手册,配合万用表通断档,我们可以标记出排线上剩余信号线的功能,有的是LDO的使能信号(估计是控制传感器上电时序),有的是MPU6500的通信引脚。

不过最让我兴奋的还是那两片SN74电平转换器,因为索尼CMOS传感器通信一般都使用1.8V电平,因此极有可能在电平转换器上捕捉到传感器的配置通信。另外转换器旁边预留了很多焊盘,可以很方便的飞线,接入示波器或者逻辑分析仪。

Step3:结合示波器,确定信号线的具体功能

剩下的就是苦力活了,把相机拼好,用示波器探测转换器旁边的焊盘,通过观察波形特征,得出对应信号类型,再用万用表通断档找出对应的接线。

XVS特征:低频,100Hz以内,和传感器的帧率同步。

XHS特征:中高频,百KHz左右。

通信线特征:突发波形,特征根据接口类型而定,典型的SPI或者IIC

时钟线:持续稳定的高频信号

下面就是对排线的最终逆向结果:

可以看到,尽管排线上预留了11对差分信号,但传感器只用到了9对,说明传感器是工作在8通道subLVDS模式下的,现在的问题就是找到LVDS通道的时钟对,以及对应的LVDS通道顺序。

索尼subLVDS时钟最高速度是300Mhz(满足600Mbps DDR传输),这一步是比较棘手的,如果你的示波器带宽不够高的话,可能就没办法测到了。

但我们也不需要直接测量时钟信号,我们可以通过测量数据线来反推时钟线在哪。因为数据线的基波频率一般在100Mhz左右,对于很多示波器,我们完全可以测量到数据线基波,而时钟线由于基波很高(300MHz),在示波器上表现出来的就约等于没有信号。

因此只要测量到了没信号的那一对差分线,基本上就可以确定是时钟信号了。

不过我的示波器经过破解,带宽能勉强摸到时钟线的基波频率,所以我选择直接测量时钟线在哪。测量结果如下:

随后可以确定,排线上的Pair4是时钟信号,剩下的都是数据。按照之前调试其他索尼传感器的经验,具体的数据速率有可能是594Mbps或者576Mbps(因为示波器时钟测量不是绝对精确)。

如果数据线速率也高到示波器测不出了,考虑下前面提到的换晶振降速方法。如果是SLVS-EC信号,则不用测量了,人家内嵌时钟。

细心的读者可能会发现,我没有测量LVDS极性和数据线顺序,这是因为无论FPGA还是视频专用SoC,他们都支持LVDS极性翻转和数据线顺序内部交换,只需要保证硬件上时钟线和数据线接入了专用的引脚(例如FPGA中,高速时钟一定接入MRCC/SRCC引脚),数据极性和顺序问题都是可以在软件里方便修正的。

更新

还是测量了一下LVDS数据线顺序,索尼CMOS传感器的图像数据线一般是按照顺序水平排列,时钟信号线夹在中间。Px = 排线上的Pair,Dx = 数据线编号,CK = 时钟线。

Step4:使用逻辑分析仪,抓取传感器配置通信,同步信号

从上面的分析中,发现IMX159使用的是SPI通信(SDI、SCLK、SENSOR CS),由于我只关心向传感器写入配置而不需要读配置,因此SDO引脚不使用。下面就该逻辑分析仪登场了,因为示波器不适合做这种长时间,高采样率的抓取。

首先十分感谢群友@哈伯,借我逻辑分析仪使用。

接好分析仪,打开相机电源,总线上马上出现了通信信号,放大观察确实是SPI通信:

因为网络上已经有人逆向出了该云台相机(注意是整个相机系统,非传感器本身)的串口通信命令(臻迪黄金眼无人机协议100相机控制协议

我通过串口向相机发送各种指令,包括录制视频、拍摄照片、改变模式等,逻辑分析仪抓取配置总线上的通信,得到以下几个文件:

得到了一系列传感器寄存器写入时序,这些理论上应该足够我把IMX159点亮了。

最后一个需要测量的就是XVS和XHS同步信号。通过这两个信号我们可以得知传感器每帧读出了多少行,每秒读出多少帧。以下是测量结果:

传感器以29.97FPS速度读出,每次读出2944行。

完事,下面就可以把这套原硬件抛了!

Step5:画个转接板,接入FPGA

根据前面的逆向结果,我快速绘制了一个FPC排线转BTB的4层PCB,BTB定义是我自己做的FPGA核心板(FPGA已经放到到立创开源上了:四层Artix7带DDR内存—FPGA摄像头开发板

转接板上有两路DCDC降压,将5V分别降到3.3V和1.8V,以及36MHz晶振,一个电平转换器(1.8->3.3,然后传感器板上又会从3.3->1.8,乐)。

剩下的信号线就直接接到BTB的差分对上(当然前提是符合前面提到的时钟/数据专用引脚),不需要做对间等长,FPGA里可以使用IDELAY修正。

最后把东西全部拼起来:

Step6:寄存器整理

在Step4中,采集了主控向传感器写入配置的过程,现在就派上用场了。在DSView软件中设置好SPI总线解码(小端序),导出一份通信数据表格:

需要注意的是,在通信过程中,有的时候会写入24bit数据,而有的时候会写入32bit数据:


总之,按照上面的规律,把写入操作转化为C语言程序。在编写过程中,可以发现一些规律:

首先是传感器初始化阶段,都是写入24bit数据/组,并且这些寄存器大多并不相同。

当相机进入工作状态时,用手在旁边晃一晃,会触发自动曝光调节,此时可以看到寄存器写入变成32bit/组,并且具有高度重复性:

不难猜测,这些寄存器应该就是快门速度、增益调节相关的。

Step7:FPGA侧程序编写

之前跟群友@Badboy02合作写了个简易的,适配LVDS接口传感器的调试平台,该平台的作用很简单:完成LVDS传感器的初始化配置,将图像读入DDR3缓存,通过串口上传得到的图像。

当然其中也包含了一些简单的ISP处理和HDMI输出,只不过本次逆向工程不会使用。

结构大概如下:

Step8:冒烟测试

插电,开机,首先检查一下ILA里是否有数据出来。如果有数据出来则证明传感器配置成功:

LVDS接口成功接收到了数据,并且成功搜索到了索尼使用的10bit行起始序列(3ff-000-000-200)和IDLE训练码(208)。

有两个数据通道对齐失败了(通道4、通道7),因为这只是个快速测试,我没有根据走线长度补偿相应的IDELAY值,有的数据相比其他数据线提前1个bit或者2个bit到达了FPGA。

在未来会将延迟补偿这一过程也自动化完成,目前只实现了对齐自动化。动态对齐也得安排上。

触发一次快门,检查传感器总读出行数以及每行像素数量:

一共读出2716行有效行,每行600*8 = 4800个像素。因此总分辨率为4800*2716 ≈ 13MP,比例约16:9。

乍一看,和IMX159标称的16MP差了一些,是因为目前传感器处于4K视频模式,因此存在裁切也不奇怪。

Step9:出图测试

不过我已经等不及了,赶紧把图片端上来罢。测试方法很简单,无镜头,用一张小纸片遮住传感器部分区域,然后直接读出图像。

需要指出的是,前面提到的通道不对齐问题我暂时还没时间修正,所以总是有两个LVDS通道的像素是错误的。但不影响大局,就直接来看结果吧:

中心的扇形形状就是我放上去的纸片,因此可以确定传感器工作正常。

下面图片使用绿光灯直接照射进入传感器:

根据拜尔阵列特点,在一个四像素区块内,应该会出现两个明亮像素(绿色滤镜),和两个比较暗的像素(红蓝滤镜)。

同样的,由于两个通道的错位造成部分像素错误,但可以看到期望的像素阵列。

更新

经过一些调试,现在可以拍出“大部分正常的照片了”,为什么说是大部分正常呢?

嗯,很神秘的,同一张照片里出现了不同的曝光,乐。再调查调查是咋回事吧。

总结以及后续计划

通过逆向,对IMX159模块的初始化以及工作方式有了初步了解,也初步采集到了图像。后面可能进行的额外工作有:

  1. 实现LVDS接口的自动延迟补偿训练
  2. 测试传感器的其他模式(例如4:3全像素拍照模式)
  3. 做成一台完整的能拍照的相机(?画饼.jpg)

一转眼就要开学了,后面这些东西能做多少是多少吧。逆向的主要资料(排线定义图片,SPI通信过程)上传到了Github,需要的可以自取。:

https://github.com/BellssGit/Sony_IMX159_Module_Reverse_Engineering

发表回复