手机等平台上使用的Camera sensor通常是由类似I2C这样的总线进行寄存器控制,由CPU端的Controller提供所需的驱动时序,通常支持YUV和RGB等数据格式。有的Sensor需要由CPU进行图像处理工作,有的Sensor自己会集成图像处理芯片,完成一些基础的图像处理工作,还有些高像素的Sensor甚至自己完成JPEG的编码工作。因为硬件的多样性,我所遇到的问题可能和你的原因现象都不尽相同,分析内容仅供参考。+ u; U% U9 U& A3 y6 Q" d
+ b+ F) ]5 Z, l% G" y2 m* [
Sensor端I2C总线没有响应- 症状4 Y3 r$ A+ z+ n" I& ], p- \1 F* h5 S
) ?4 q2 s# c1 |) a0 ]& m
所有输入电压和时钟信号都正常,往I2C总线上写入读取寄存器数据的命令后,sensor没有响应,没有数据从I2C总线上输出。
0 ?: {. i' |9 Z; Z3 C! h
Y' a# u9 c1 ^3 |8 P7 K- 分析
( p0 E& q" Y* Y6 }3 F
/ u! Y: u2 C* g6 M3 N" @% C ; m+ u/ `8 @. P2 X% f) b3 q8 G7 y
因为测量发现一切输出信号都正常,所以往往都会怀疑Sensor硬件存在问题,不过99%的情况,实际的原因总是因为I2C总线的ID值没有设置对,导致设备不响应命令。据我的观察,每次一个新的工程师在调试Sensor的时候几乎都会遇上这个问题。
: N6 x6 i( o1 K/ n1 n 5 H! a5 N; L% m8 j M. _
之所以这么容易设置错误的原因,是因为通常Camera Sensor的Spec上所写的I2C ID号,还包含了最后一位读写方向位。而这一位在I2C总线的定义中,严格来说,不属于ID的一部分,所以Linux I2C的驱动API中的调用参数里的ID号,通常是不考虑这一位的,读写方向位会在具体的读写操作中,在寄存器中进行设置。
T; }5 C- q$ A" ^1 x1 g6 P
3 J) s" O" M+ P# j# d
o0 F: @) G! b1 R4 u 例如Spec上会写 读写寄存器操作 I2C ID 分别为 0x64和0x65,实际调用API时应该使用0x32作为该设备的I2C ID
) F- |: A4 Q$ U+ f4 S1 P图像中有不断变化的细密的水平条纹- 症状3 I2 G! j3 f. ~, Q9 I3 e: L3 B A6 m
, A0 }3 U; K+ c2 N, {: T ) Y9 X1 V! a4 z) f( \( G: u
与荧光灯的频闪造成的大面积的滚动水平条纹不同,表现出来的是一个像素高的水平条纹状躁点,位置不固定,数量比较多,而且随光线强弱有一定的变化0 u4 g2 B5 B4 g1 y4 B
+ b& W7 _* F6 X& m" b- 分析2 m0 p% r8 g5 H: C D7 H# y* s- t
; B+ i( v n) A
# M$ Z( ^8 z. }) m
因为设置某些sensor寄存器的时候,会影响到这些水平条纹的颜色,所以基本上排除是在数据传输过程中板子对数据造成的干扰,也排除接触不良的可能性,应该是数据在sensor内部已经存在这些水平条纹。3 t2 L' c( p2 b+ g9 w2 q+ q' G
此外相同的初始化序列,相同的sensor,在厂商的demo版上也没有发生这种情况,所以也基本排除软件的问题。
6 `+ `; a7 E; f/ M. d 最后,发现原先为了节省硬件成本,将sensor的两个电压相同的模拟电和数字电由同一芯片输出供给,导致两者之间互相干扰,影响了sensor的正常工作 H" i9 |/ ]/ K. ?
) g4 c3 {7 N1 x2 d. K6 Y( ~- 解决# d! p! q: W X, s1 M. r" t
4 B5 b8 }7 k' F( U( m8 p
1 E- l3 [: G7 c" c$ K
将模拟电和数字电分离单独供电* e! \8 N$ j$ Y, O# f
& Q8 G; H0 M t. C图像上有固定的锯齿状垂直条纹- 症状
9 m$ l5 q. i F; Q+ `" ]! o
/ ?) V" N2 {. K$ d/ E+ l 5 s) [5 k; W# N9 ]3 |. \6 l# r
图像上有明显的垂直条纹,全屏分布,非常细密,好像百叶窗一样。
g5 h9 V `3 |# p+ x
9 k% X- U4 g |8 U% }- 分析
( ?; k# h7 Y% ]) g* I6 [+ e( D3 d: d
4 ^* ^% Z7 f( m x6 Q
仔细看可以发觉该垂直条纹实际上是由于图像上相邻的两两像素互相错位造成的锯齿状条纹
. S c& h9 C( |
% y0 n Q4 m0 F/ [. { 仔细分析spec可以看到,由于sensor是按字节送出图像数据,在RGB565模式下,两个字节表示一个像素。而在我所使用的CPU的Camera控制器中,数据是按4个字节也就是一个字为单位处理的,由于CPU这端是按LSB方式处理数据的,所以在一个字内部,未经调整的话,两个像素的顺序是颠倒过来的。也就是最终由DMA将数据送到内存的连续buffer中时,像素的顺序是:像素2,像素1,像素4,像素3。。。
' e5 C8 K0 I! a; g* K8 ` 4 W- o* g) H8 d+ t/ o; \) ^
- 解决) S: z: J$ ?" [ _* }3 I, |6 |
% D6 S6 X( D9 |& A8 K0 U6 H; j+ i: L
! B A9 p- Y# ^
用程序调整像素顺序,为了减少附加计算对CPU的负担,可以将这一步操作合并在其它类似颜色转换或PACK模式转Planer模式等操作中。
9 M2 S; o; T9 k n0 s
! S$ s s" F' k- E大尺寸时容易出现图像错位- 症状
! J! l% H. d5 n+ h' |6 {2 X7 Z- b: ]* `7 J* |: Y b, x
( h' {. z' ?1 A) i/ I. J h
当sensor工作在最大分辨率的情况下时,图像容易出现上下错位的现象。
0 j& ]7 P+ Z5 W) u4 c6 K' n
/ d6 _1 C3 T. ?: n- 分析
3 S9 I4 F' S" s8 o* |
5 a. V. S5 ]* I* @
7 _. q3 I; H; k5 E+ Q% d, b9 \ 跟踪程序可以看到这时候CPU的Camera控制器的FIFO缓存发生了溢出现象,也就是说DMA来不及将FIFO中的数据传送到内存中,该例中sensor在最大分辨率的情况下,输出数据的时钟工作在24MHZ,理论上说,DMA应该是来得急传送数据的,但是可能因为内存带宽还会被其它设备如CPU占用,导致来不及写入内存,使得DMA没有最大负荷的工作,所以来不及将FIFO中的数据读出,导致部分数据丢失,图像错位。
1 T2 V% D+ o( @2 h ; I1 P" L( @# y1 F3 G. b: x
6 o U9 t5 j' }& r. P" C* s- 解决; J; M9 g/ X3 I4 Z
5 M5 W. d# X2 K( V 7 \: O. a/ \6 X
某些情况下,改变DMA传输的启动阙值可以解决该问题,但是有些情况是无效的) `, Q& c2 @) J3 C2 d5 _' |8 k) o
! A5 [- c0 q4 D% \- f( v" f 考虑到最高分辨率仅在拍照的时候使用,预览的时候并不使用该分辨率,所以,在不影响预览桢数的情况下,可以在拍照的一瞬间改变分辨率的同时,修改sensor的时钟频率,降低到一个不会导致FIFO溢出的频率" y1 M8 @% M% u, t
5 v/ n8 c( c Q/ O
另外,在截获最高分辨率的图像的同时,尽量不执行其它的内存相关操作。截获完图像马上切换回预览用的分辨率。通过这些办法,减少发生FIFO溢出的可能性。
[2 P4 l/ W, D 0 v3 b3 _4 \' u) `: _
读取到的数据显示出来的时候是花屏- 症状& O+ F5 w! m/ j% {; Q; z+ f" y, E3 a
: ~! r0 G: B* j
) X, v" Z2 X9 W: B W& S3 M
读取到的数据显示出来的时候是花屏,但是明显是随着所拍摄的对象的变化而变化的。
% W W& s. u9 ~+ } 5 @/ j1 J8 g; e) D: d
- 分析# H8 d Y. X! I: k: l
; {4 i* l+ f8 M$ H" c' o1 M7 V1 N * u; }, y1 z7 }- F0 U
具体来说,常见的情况包括:' [- H3 `9 @ n
显示的数据是完全的花屏,或者可以看出物体大致轮廓,但颜色完全不对,例如一片绿色。这种情况往往是因为图像数据格式不匹配,例如没有处理YUV2RGB,YUV的各个分量采样顺序与软件计算的取值顺序不匹配等。0 T5 o) V# K" s& y$ Q+ ~
# [# O5 W9 l" @% W8 p# | 如果花屏的具体表现是图像不断变换,没有规律,通常有可能是数据接收的触发边沿有误,导致没有正确的接收数据。+ I" R* Y0 x0 L( E
" U' ~ F! k1 |. h4 H g' ^ 另外有一次,花屏的时候,仔细观察花屏的图案,发现有部分错位重复的图案的迹象。因此分析可能是Sensor的物理layout,其长宽比例与LCD刚好相反,仔细查看Spec得到确认。7 g, O0 ~( C- p8 l+ Q/ O; q/ W
' i" X2 }4 M0 f' b! g4 M4 U
8 o) u. x9 f. D8 ]. s, \) i' a- 解决4 c+ g# i$ z( e. b: F$ ]
) R0 N5 Q* n+ g8 s) A, V/ a
* g5 l W- Y$ U) v 具体情况具体处理了。
: G4 n2 T' x; `' H9 c
2 ^7 f X5 o- p" U) x# o& G1 f3 w3 s: m1 w% b$ B
7 o/ t" k$ j( c% L J j/ x) W3 f- q) ?# t* L5 B
9 f, u$ D, T" ?; {( k1 m$ d; c |