当前位置:文档之家› 内存测试三步法

内存测试三步法

DDR内存子系统常见硬件错误及Uboot中检测流程在U-Boot中,Denx(U-Boot的开发商)针对常见的DDR 内存故障进行了严格的检测处理,下图描述了该检测处理过程的三个步骤:检测数据线、地址线和DDR物理存储部件,主要涉及这三个步骤的处理过程和方法,对于DDR子系统,是很容易出故障并且是很难debug检测出来的,而Denx所针对DDR 内存故障设计的检测方法是非常严谨,值得学习研究的。

下面主要是相关的检测处理思路及问题:1、为什么先检测数据线?因为如果数据线是断开的,那么一切无从谈起!接下来是检测地址线,只有数据线和地址线都通过,检测内存的存储单元才有意义,这样的流程也利于分割定位问题。

上面testing sequence 框图将整个检测过程分成三大步,用三个虚线方框表示。

2、数据线的连接错误数据线的连接可能存在两种错误,一种是被断开,另一种布线或生产造成互相短路。

3、如何检测数据线的连接错误Denx 设计的数据线检测算法还是很Tricky和精秒的,整个处理流程如下例子:如果是两根数据线,只需要写入并读出一个pattern=0b01(0b开头表示二进制数)就能判断它们是否短路或断开。

很明显,大部分的嵌入式平台不止两根数据线,我们以64位地址线为例,pattern = 0b101010101010101010.... 能检测出奇偶位之间的数据错误。

如果这个错误被排除,每两根数据线组成一组(这是理解下一个pattern的关键),再用相同的办法,检测每相邻两组之间是否有短路,就得到第二个pattern,就是0b110011001100...... 依次类推,以4根数据线为一组,8根线为一组,相继得到共6个pattern,分别是0xaaaaaaaaaaaaaaaa,0xcccccccccccccccc,0xf0f0f0f0f0f0f0f0,0xff00ff00ff00ff00,0xffff0000ffff0000,0xffffffff00000000。

只要相继写入并读出这6个pattern就能验证是否存在数据线交叉短路错误。

4、如何检测数据线与板上其它信号线交叉短路或断路取以上6个pattern的反码,总共12个pattern就能检测到每一位都可以写入和读出0和1。

5、什么是floating buses错误floating buses会“欺骗”测试软件,如果测试软件写入并很快读出一个值的时候,写操作会给数据线上的电容充电,总线会短暂的保持它的状态。

当测试软件读操作时,总线会返回刚写入的值,即使实际上该数据线是断路的。

6、如何检测数据线的floating buses错误检测floating buses错误的算法不复杂,在写入和读回之间再插入一次对不同地址写入不同值的操作。

例如,X写入X1位置,Y 写入Y1位置,再从X1位置读出X值则表示floating buses错误不存在。

7、地址线的错误如果地址线存在错误,其症状是地址空间中的两个不同位置被映射到同一物理存储位置。

更通俗地讲,就是写一个位置却“改变”了另一个位置。

8、地址线的错误检测地址线的错误检测相对简单,其算法是:1)、将地址的值作为内容写入该地址处,汇编的表示方法是(addr) = addr。

即将地址值写到地址对应的空间里,这样确保每一个位置的内容不同。

2)、依次将内存基地址的某一根地址线的值翻转(flip/toggle)得到某个地址,从该地址取值,如果该值和基地址的值相等,则表示某一位地址线有问题。

这个算法的特点是每次只检测一根地址线,方法简单有效。

9、存储单元的错误以上数据线和地址线的检测都是检测布线或工厂生产的错误,而存储单元的检测则是真正对DDR内存芯片的检测。

内存芯片的常见错误是bit-stuck,简而言之,就是让它是0,它偏为1,让它为1,它偏为0,检测方法也很简单,就是用不同的pattern 去写尽可能所有的地址并读回比较。

有一些常用的pattern如0x5555, 0xAAAA等。

10、几个简单的检测DDR故障的方法上面的DDR检测算法,虽然全面,但是耗时比较长,常常需要好几个小时,在Uboot命令行下也有几个简单的命令可以检测常见内存故障,如下所示:1)、mtest addr lenth pattern这个命令需要注意,DDR在Uboot启动后被映射到了0地址,但是uboot的代码和堆、栈空间0x10000000处开始,这些空间是不能被刷的,否则就挂死了。

2)、复制NOR flash的内容到内存中,如cp.b 0x20080000 0x7fc0 20000,然后比较cmp.b 0x20080000 0x7fc0 20000。

3)、下载kernel image到内存中,copy NOR flash 或tftp 都行,然后调用iminfo LOAD_ADDR 检测CRC错误。

第一种方法是用特定的pattern去刷DDR的空闲空间,第二种和第三种方法可以说Pattern的随机性更大一些。

当然最彻底的检测方法当然是长时间跑Linux系统,上面的方法更适用于系统不稳定时定位错误。

内存检测方法程序示例s t a t i c v o i d m o v e64(u n s i g n e d l o n g l o n g*s r c,u n s i g n e d l o n g l o n g*d e s t){*d e s t=*s r c;}/**T h i s i s64b i t w i d e t e s t p a t t e r n s.N o t e t h a t t h e y r e s i d e i n R O M*(w h i c h p r e s u m a b l y w o r k s)a n d t h e t e s t s w r i t e t h e m t o R A M w h i c h m a y*n o t w o r k.**T h e"o t h e r p a t t e r n"i s w r i t t e n t o d r i v e t h e d a t a b u s t o v a l u e s o t h e r*t h a n t h e t e s t p a t t e r n.T h i s i s f o r d e t e c t i n g f l o a t i n g b u s l i n e s.**/c o n s t s t a t i c u n s i g n ed l o n g l o n g p a t te r n[]={0x a a a a a a a a a a a a a a a a U L L,0x c c c c c c c c c c c c c c c c U L L,0x f0f0f0f0f0f0f0f0U L L,0x f f00f f00f f00f f00U L L,0x f f f f0000f f f f0000U L L,0x f f f f f f f f00000000U L L,0x00000000f f f f f f f f U L L,0x0000f f f f0000f f f f U L L,0x00f f00f f00f f00f f U L L,0x0f0f0f0f0f0f0f0f U L L,0x3333333333333333U L L,0x5555555555555555U L L};c o n s t u n s i g n ed l o n g l o n g o t he r p a t t e r n=0x0123456789a b c d ef U L L;/*数据线检测*/s t a t i c i n t m e m o r y_p o s t_d a t a l i n e(u n s i g n e d l o n g l o n g*p m e m){u n s i g n e d l o n g l o n g t e m p64=0;i n t n u m_p a t t e r n s=s i z e o f(p a t t e r n)/s i z e o f(p a t t e r n[0]);i n t i;u n s i g n e d i n t h i,l o,p a t h i,p a t l o;i n t r e t=0;f o r(i=0;i<n u m_p a t t e r n s;i++){m o v e64((u n s i g n e d l o n g l o n g*)&(p a t t e r n[i]),p m e m++);/**P u t a d i f f e r e n t p a t t e r n o n t h e d a t a l i n e s:o t h e r w i s e t h e y*m a y f l o a t l o n g e n o u g h t o r e a d b a c k w h a t w e w r o t e.*//*预防f l o a t i n g b u s e s错误*/m o v e64((u n s i g n e d l o n g l o n g*)&o t h e r p a t t e r n,p m e m--);m o v e64(p m e m,&t e m p64);#i f d e f I N J E C T_D A T A_E R R O R St e m p64^=0x00008000;#e n d i fi f(t e m p64!=p a t t e r n[i]){p a t h i=(p a t t e r n[i]>>32)&0x f f f f f f f f;p a t l o=p a t t e r n[i]&0x f f f f f f f f;h i=(t e m p64>>32)&0x f f f f f f f f;l o=t e m p64&0x f f f f f f f f;p o s t_l o g("M e m o r y(d a t e l i n e)e r r o r a t%08x,""w r o t e%08x%08x,r e a d%08x%08x!\n",p m e m,p a t h i,p a t l o,h i,l o);r e t=-1;}}r e t u r n r e t;}/*地址线检测*/s t a t i c i n t m e m o r y_p o s t_a d d r l i n e(u l o n g*t e s t a d d r,u l o n g*b a s e,u l o n g s i z e){u l o n g*t a r g e t;u l o n g*e n d;u l o n g r e a d b a c k;u l o n g x o r;i n t r e t=0;e n d=(u l o n g*)((u l o n g)b a s e+s i z e);/*p o i n t e r a r i t h!*/x o r=0;f o r(x o r=s i z e o f(u l o n g);x o r>0;x o r<<=1){/*对测试的地址的某一根地址线的值翻转*/t a r g e t=(u l o n g*)((u l o n g)t e s t a d d r^x o r);i f((t a r g e t>=b a s e)&&(t a r g e t<e n d)){/*由于t a r g e t是t e s t a d d r某一根地址线的值翻转得来故t e s t a d d r!=t a r g e t,下面赋值操作后应有*t e s t a d d r!=*t a r g e t*/*t e s t a d d r=~*t a r g e t;r e a d b a c k=*t a r g e t;#i f d e f I N J E C T_A D D R E S S_E R R O R Si f(x o r==0x00008000){r e a d b a c k=*t e s t a d d r;}#e n d i f/*出现此种情况只有t e s t a d d r==t a r g e t,即某根地址线翻转无效*/i f(r e a d b a c k==*t e s t a d d r){p o s t_l o g("M e m o r y(a d d r e s s l i n e)e r r o r a t%08x<->%08x," "X O R v a l u e%08x!\n",t e s t a d d r,t a r g e t,x o r);r e t=-1;}}}r e t u r n r e t;}s t a t i c i n t m e m o r y_p o s t_t e s t1(u n s i g n e d l o n g s t a r t, u n s i g n e d l o n g s i z e,u n s i g n e d l o n g v a l){u n s i g n e d l o n g i;u l o n g*m e m=(u l o n g*)s t a r t;u l o n g r e a d b a c k;i n t r e t=0;f o r(i=0;i<s i z e/s i z e o f(u l o n g);i++){m e m[i]=v a l;i f(i%1024==0)W A T C H D O G_R E S E T();}f o r(i=0;i<s i z e/s i z e o f(u l o n g)&&r e t==0;i++){r e a d b a c k=m e m[i];i f(r e a d b a c k!=v a l){p o s t_l o g("M e m o r y e r r o r a t%08x,""w r o t e%08x,r e a d%08x!\n",m e m+i,v a l,r e a d b a c k);r e t=-1;b r e a k;}i f(i%1024==0)W A T C H D O G_R E S E T();}r e t u r n r e t;}s t a t i c i n t m e m o r y_p o s t_t e s t2(u n s i g n e d l o n g s t a r t,u n s i g n e d l o n g s i z e) {u n s i g n e d l o n g i;u l o n g*m e m=(u l o n g*)s t a r t;u l o n g r e a d b a c k;i n t r e t=0;f o r(i=0;i<s i z e/s i z e o f(u l o n g);i++){m e m[i]=1<<(i%32);i f(i%1024==0)W A T C H D O G_R E S E T();}f o r(i=0;i<s i z e/s i z e o f(u l o n g)&&r e t==0;i++){r e a d b a c k=m e m[i];i f(r e a d b a c k!=(1<<(i%32))){p o s t_l o g("M e m o r y e r r o r a t%08x,""w r o t e%08x,r e a d%08x!\n",m e m+i,1<<(i%32),r e a d b a c k);r e t=-1;b r e a k;}i f(i%1024==0)W A T C H D O G_R E S E T();}r e t u r n r e t;}s t a t i c i n t m e m o r y_p o s t_t e s t3(u n s i g n e d l o n g s t a r t,u n s i g n e d l o n g s i z e) {u n s i g n e d l o n g i;u l o n g*m e m=(u l o n g*)s t a r t;u l o n g r e a d b a c k;i n t r e t=0;f o r(i=0;i<s i z e/s i z e o f(u l o n g);i++){m e m[i]=i;i f(i%1024==0)W A T C H D O G_R E S E T();}f o r(i=0;i<s i z e/s i z e o f(u l o n g)&&r e t==0;i++){r e a d b a c k=m e m[i];i f(r e a d b a c k!=i){p o s t_l o g("M e m o r y e r r o r a t%08x,""w r o t e%08x,r e a d%08x!\n",m e m+i,i,r e a d b a c k);r e t=-1;b r e a k;}i f(i%1024==0)W A T C H D O G_R E S E T();}r e t u r n r e t;}s t a t i c i n t m e m o r y_p o s t_t e s t4(u n s i g n e d l o n g s t a r t,u n s i g n e d l o n g s i z e) {u n s i g n e d l o n g i;u l o n g*m e m=(u l o n g*)s t a r t;u l o n g r e a d b a c k;i n t r e t=0;f o r(i=0;i<s i z e/s i z e o f(u l o n g);i++){m e m[i]=~i;i f(i%1024==0)W A T C H D O G_R E S E T();}f o r(i=0;i<s i z e/s i z e o f(u l o n g)&&r e t==0;i++){r e a d b a c k=m e m[i];i f(r e a d b a c k!=~i){p o s t_l o g("M e m o r y e r r o r a t%08x,""w r o t e%08x,r e a d%08x!\n",m e m+i,~i,r e a d b a c k);r e t=-1;b r e a k;}i f(i%1024==0)W A T C H D O G_R E S E T();}r e t u r n r e t;}s t a t i c i n t m e m o r y_p o s t_t e s t s(u n s i g n e d l o n g s t a r t,u n s i g n e d l o n g s i z e) {i n t r e t=0;i f(r e t==0)r e t=m e m o r y_p o s t_d a t a l i n e((u n s i g n e d l o n g l o n g*)s t a r t);W A T C H D O G_R E S E T();i f(r e t==0)r e t=m e m o r y_p o s t_a d d r l i n e((u l o n g*)s t a r t,(u l o n g*)s t a r t,s i z e);W A T C H D O G_R E S E T();i f(r e t==0)r e t=m e m o r y_p o s t_a d d r l i n e((u l o n g*)(s t a r t+s i z e-8), (u l o n g*)s t a r t,s i z e);W A T C H D O G_R E S E T();i f(r e t==0)r e t=m e m o r y_p o s t_t e s t1(s t a r t,s i z e,0x00000000);W A T C H D O G_R E S E T();i f(r e t==0)r e t=m e m o r y_p o s t_t e s t1(s t a r t,s i z e,0x f f f f f f f f);W A T C H D O G_R E S E T();i f(r e t==0)r e t=m e m o r y_p o s t_t e s t1(s t a r t,s i z e,0x55555555);W A T C H D O G_R E S E T();i f(r e t==0)r e t=m e m o r y_p o s t_t e s t1(s t a r t,s i z e,0x a a a a a a a a);W A T C H D O G_R E S E T();i f(r e t==0)r e t=m e m o r y_p o s t_t e s t2(s t a r t,s i z e);W A T C H D O G_R E S E T();i f(r e t==0)r e t=m e m o r y_p o s t_t e s t3(s t a r t,s i z e);W A T C H D O G_R E S E T();i f(r e t==0)r e t=m e m o r y_p o s t_t e s t4(s t a r t,s i z e);W A T C H D O G_R E S E T();r e t u r n r e t;}。

相关主题