由于不可抗拒因素,原定性产品替换一颗器件,该器件的目的是防止外界EMI干扰, 位置处于处理器和SD卡之间,器件是为每个SD卡信号线连接100Ω电阻。
更换后,SD卡探测正常,从SD卡读写几十KB文件功能正常, 从SD卡数据500KB以上的文件永远无法读完,系统其他功能依旧正常,再次插拔SD卡不可识别,只能关机重启。
问题原因:新旧器件的寄生电容有差异,SD卡时钟信号畸形,处理器SD控制器
下面看看整个曲折排查过程
前天,报告故障时同事没有把事情给我描述清除,仅说“更换EMI器件后,从SD卡里执行系统更新时被卡住了,进度条走不完”。我到产线的确每次都能复现改描述问题。庆幸,容易复现以前都好办,可我的排查方向错了,被问题描述误导而去检查设备驱动是否存在问题,比如mmc驱动里某个核心死锁、等待信号量、while循环、状态机混乱。
纳闷着产品都量产好几年了,从SD卡执行系统更新功能我还特别关注过可靠性。生怕好好一台设备升级变砖。于是一下午在新、老器件上尝试对比差异。生产部门的示波器很难用,只用它初略对比信号高、低电平范围,没能捕获到实际频率响应特性,粗略观测到两设备插入SD卡后某几个信号线逻辑电平不一致,一个高电平、一个低电平,至于原因未知。
快下班时同事告知:“设备可以正常保存数据文件到SD卡。”。
What?有这么神奇?
设备业务数据每个文件只有200KB以内,我尝试着用dd命令在SD卡根目录创建若干不同大小文件,再telnet到设备上逐个 hexdump它们,发现500KB文件大小是个分水岭。
次日,对比新老器件的手册说明,两器件的差异仅仅在于寄生电容上,老器件寄生电容8.5pF,新器件36pF。其实这个时候动手算算时间响应系数、SD卡工作频率、在芯片手册时序特性就能确认故障点在这了,本产品的SDIO时钟频率48MHz。
SDIO这部分我不是太熟悉,尝试在群里请求帮助。
抱几台设备去实验室做对比实验,用着熟悉的示波器,操作起来游刃有余。
老器件的波形勉强还行,至少算是个正弦波,新器件的波形已经被寄生电容展宽成 斜三角波。初步怀疑布线质量差劲,波形抖动,访问大文件时时钟抖动累加影响处理器时序,状态机混乱。访问小文件时任务小巧。数个时钟偏差不足以引起单次读写任务执行。
是德科技的这款示波器默认没开放眼图功能,要使用眼图也行,1万RMB购买软件扩展功能lisence。我只能退而求其次使用它的 Mask(模板)功能 。这个功能原理和眼图类似,下文我还是用眼图来称呼它。Mask功能缺少眼图下移动标杆测量的能力, 不能测量“眼镜”开口大小,无法得知3dB位置,一拖动动屏幕任何参数,Mask数据都会丢失。
怎么让处理器保持读取数据内容呢?
让处理器反复地在SD卡上拷贝1MB文件就行了,记得末尾清除文件系统缓存,防止linux在内存里缓存SD卡文件。
while [ 1 ]
do
cp /mnt/sd/1MB.img /mnt/sd/unuse.img
echo 3 > /proc/sys/vm/drop_caches # 清除缓存
done
每个眼图都保持1min测试时长。
老器件的波形实际上也是存在抖动的,好在抖动不剧烈,抖动位置规则的分布在5个密集区域。
新器件的眼图我需要说明一下,文章开头描述“只要访问SD卡500KB以上的数据无响应,不再有时钟”。于是我对测试shell做了小修改,每次仅处理10KB的文件,接着让总线休息一下,避免shell执行太快SD控制器的来不及停止就继续执行。有了这个延时,所以新器件1min眼图效果和老器件是不能直接对比的,初略看他的抖动会比老器件的强。
老器件48MHz持续运行1min,约产生2880M个时钟。
新器件48MHz执行10KB,停歇1秒循环1min,约产生600K个时钟
所以1min里老器件工作量是新器件的4800倍=2880*10^6/600,约是老器件12.5ms=60s * 1000 / 4800的眼图效果
while [ 1 ]
do
cp /mnt/sd/10KB.img /mnt/sd/unuse.img
sleep 1 # 等待,否则同样会无响应
echo 3 > /proc/sys/vm/drop_caches # 清除缓存
done
人生苦短,姑且假设问题就是处在频率太高、寄生电容太大。尝试粗略修改处理器SDIO时钟频率,如果降低频率后能正常工作就可以定位故障点了。
大笔一挥,直接降低SDIO时钟为设置的一半,SDIO有这点好处,只要在SD卡的工作范围内,则可以在0-maxMHz范围内任意频率工作。
再次测试读写1MB文件,呕吼,两设备都正常执行。再次测量眼图,这回新器件的shell脚本可以和老器件的相同,不需要延时。可看出他们眼图1min效果是相同的。