/ S$ O9 o' Q( v- [2 J. i9 a由于前段时间工作上的事情比较杂乱, 导致第七罪姗姗来迟,既然是大结局,当然就应该让大家更加深刻的来理解I2C.。我们先来复习一下大家共有的对I2C的认知:
# ^, }! y/ R2 { U) P. I1 k
1. I2C的SCL(Clock)总是由Master来驱动;
2. I2C的SDA (Data)则不同,Master和Slave分别都驱动。
6 o {0 _$ k) x' P9 p+ o3 X0 a
) ]/ Y+ S& W, W
这两点想必读者都没有什么疑问,因为前面的六宗罪都已经说得比较多了,我们今天要说的是另外一种特殊情况,就是Slave也会去Drive。
9 l) ^9 b t- ]( |) l
先来看一个例子,我的一个项目发生过这样一件事情,CPU在访问板子上的另外一颗SENSOR时,一直Fail,我们非常仔细检查了时序,都是准确的。
) ]6 i7 `9 D2 a* v+ _
注意:这里我们发现是有一个知识盲点,导致一直找不到Root Cause。
* T2 S! D% y& n; _; }
3 j- `" v1 r2 c* {9 `
细心的工程师会在测量过程中发现, SCL上有下图这样的尖尖的毛刺,毛刺有矮的也有高的,于是我们认为SCL上这种尖毛刺会导致Slave的状态机误触发,跑飞了。
x7 A/ `* M, V* x! h& J
3 \" J9 ~" g& l% W& n整整一个星期我们都是这么认为的,尝试各种方法试图去消除这个毛刺。
- ?& ]- B4 h3 x) j* b
因为信号从主板通过连接器到子板,我们认为这里的SCL信号很容易受到外部的干扰,比如从空间耦合过来的噪声。
1 N5 B4 x+ {9 b0 R% ^
所以在信号上加电容、加匹配、降低上拉电阻等等,试图滤除毛刺。
! l( y- D4 I0 S5 v; e) \- w& S4 t
得到的效果是,即便我们滤除的毛刺有改善,可问题依然存在,只是稍有好转。
' m6 R0 C' B) G& j; t
! p* j: y. k0 Z$ A4 h' \& j
虽然说,现在拿着结果来讲故事听起来很轻松,其实那个过程真的很难受,我们接着往下看。
' h. e1 k* A& O& H) Z
8 u! ~2 N1 K' F! l1 V8 v- V5 ?; X% d2 A- W( B! I7 o+ H
俗话说三人行必有我师,有个聪明的工程师突然想到I2C有个Clock stretch的机制,来看这张图,我们看到Slave把SCL拉到低,这是什么情况呢?
+ A+ A" o H6 ]. H0 U! n$ m X/ D
先来叙述一下Clock Stretch:
1 V/ p! S0 G* S1 B M% M3 Q
1. 当Master是高速I2C设备,Slave是Low Speed设备时,Master输出的SCL的频率超出了Slave的承受范围,此时Slave跟不上Master的速度怎么办? Slave就要想办法告诉Master。
, o% V0 D1 G* c" D' r' [: G6 j
6 o; I9 T S% Y1 ~1 T
1 M* A& X$ G. Q! A0 B$ ~
% v9 r: c, T9 M5 q" t) [, B& F: {2 }
大家知道为什么这里会看到右边矮矮的Glitch吗?
8 r9 f+ J# q# t* G% ?: D0 |' ?4 {
因为Master此时是想驱动SCL高电平,而Slave却拖住SCL不让变为高电平,这个其实是一种想象,实际测试是看不到的,这里是为了方便大家理解。
$ V% R7 l M; U% Z; Q/ A8 {8 I
2. 我们再来看一张图,加深一下理解,Slave会强行把SCL拉低,拖住Master,这和之前我们对I2C的认知是完全相反的,此时Slave 是输出SCL信号,而Master则是检测SCL状态的输入信号。
, h+ r6 {6 |4 \5 X% n8 Z9 p
4 U# E9 f% o; ]) f5 f5 h* T8 W
正常情况下Master/Slave都是通过在SDA上的ACK信号来确认一笔操作的成功,如图:
但是如果Slave来不及怎么办?
9 N1 B0 L2 |( X2 x! ~; |8 X; D
(看下图)Slave直接把SCL信号拖住告知Master:兄弟我还没有准备好,你先等等我啊。
4 T1 ?' |+ q5 z
此时Master要做的事情就是乖乖等着,并且一直检测SCL的状态(输入信号),当Slave松开SCL信号,由于上拉电阻的存在,SCL自然变高,Master检测到SCL变高后,才开始检测ACK信号,然后继续下一步操作。
/ O$ k9 `$ {/ m7 f9 o# a7 D( Z2 g 说了那么多I2C stretch,想必大家应该理解了。
% l" p, S2 v; a& @7 L
回到最上面我们遇到的CPU和SENSOR之间的I2C问题,我们测量得到毛刺确实是罪魁祸首。
9 }- R6 m! {9 v* U
& k- |, }- K" x1 k4 v2 c3 m- b* @! \
因为此时CPU和SENSOR进入了Clock Stretch, Sensor拉低了SCL,而CPU Master不断地检测SCL的状态,期待高电平的到来,此时毛刺就误导了CPU,CPU看到尖的毛刺就认为Slave已经松开了SCL,就立刻开始下一步的动作,此时Slave很冤枉了,自己明明拉低了SCL让Master等着,可是这位兄弟怎么这么不听话呢?
& D! F F& v, ?( _& S
, G; J0 s# P8 z解决的方法很简单,CPU的I2C控制器在进入Clock Stretch时,检测SCL并且判断高电平时有一个De-Glitch的功能,我们之前没有打开,打开后就可以滤除Glitch这样的窄脉冲了。
- o9 A4 A8 D7 X$ r W' \7 V* m. ^
$ z! t8 s8 J8 s5 X; q/ t5 K( o
简单一点讲,就是当检测到一个SCL的高,用一个计数器继续连续计数,只有发现连续的40个高电平才认为是SCL真的拉高了,否则就认为是毛刺,不予理睬。
8 K. V+ b4 ~9 v( T# A. y聪明的人很多,我们再来说说最近碰到的另外一件关于Clock Stretching的事情。
q& H$ d$ s9 C* ^/ U/ D, W
紫色的线有一段半高, 其实原因也简单,就是因为此时Slave拉低SCL,但是Master不支持Clock Stretch,此时就发生了冲突。
r% f6 N5 [. ^
" d9 c' j4 r2 k+ R1 C+ j
Master不支持Clock Stretch,我们就需要通过软件的方式去模拟,此时有两件事需要实现:
$ H2 `5 P( r* ]+ k
1. Master要把SCL切换为输入,然后不停检测SCL的状态;
2. Master在检测SCL状态一定要做De-bounce或者De-Glitch的滤波。
9 _+ t3 s# i! [- X: V0 t$ k
看完了上面的叙述,想必大家都可以理解原因。可是这样会让软件工程师们很麻烦,那么应该怎样绕开Clock Stretch呢? 聪明的工程师总有自己的办法。
0 F9 X4 h$ \3 ^* `* q
我们和Slave芯片的Vendor确认,每次Slave在做ACK后,芯片需要最多5ms的Clock Stretch延时。
7 a' U! s& t) B7 Q& F- s+ C% P
% n5 K' |5 c1 ~( g& t5 S3 O
我们拿到这个数字后,软件工程师只要注意在Master每次得到ACK后,先等待5ms后再对Slave做下一笔操作。
4 S \+ U& r" X# R6 a; S3 p0 j
) }& z6 B- g6 `8 b4 B
在这个5ms期间Master完全不用关心 SCL信号上是高电平和低电平,因为5ms以后Slave肯定松开了SCL,也就是说SCL肯定是高电平了。
0 j5 a) A3 F; R" l) r9 C4 n
这种方法就避免Master的SCL信号切换为输入,还要不停地检测SCL的状态,最重要的是不需要做软件的De-bounce或者De-Glitch算法。
4 c5 W* |( ]' o( }+ `; f1 I
h6 y$ r+ b2 K
! e9 t4 o+ t6 `. a) \& x: Q
自此I2C的七宗罪就结束了,希望这七宗罪可以cover所有硬件设计过程中的I2C问题,到目前我还没有发现有其它超出这七个范围的问题。
排版编辑丨陆妹
7 s. O9 @# v) f+ n5 ^; N
注:本文为EDA365电子论坛原创文章,未经允许,不得转载。