DDR 内存子系统常见硬件错误记及软件诊断算法

来源:互联网 发布:sql范式知乎 编辑:程序博客网 时间:2024/05/29 16:07

在Uboot下,Denx针对常见内存故障实现了严格的DDR检测程序。下图分三个阶段分别描述了检测数据线,地址线和DDR物理存储器件的过程和方法。科学是严谨的,来不得半点侥幸, 而DDR子系统又是很容易出故障却很难debug的。Denx设计的这一套算法堪称DDR内存检测之“铁面无私包青天”!
Denx Memory Test Scheme.PNG

为什么先检测数据线?
因为数据线如果是断开的,一切无从谈起!第二步是检测地址线,只有数据线地址线都ok,检测内存的存储单元才有意义,这样的顺序也利于分割定位问题。1楼的testing sequence 框图将整个检测过程分成三大步,用三个虚线方框表示。

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

如何检测数据线的连接错误
Denx设计的数据线检测算法我认为还是很Tricky和精秒的,看了好大一会才看懂:(
举个例子: 如果是两根数据线,只需要写入并读出一个pattern=0b01 就能判断它们是否短路或断开。很明显,大部分的嵌入式平台不止两根数据线,我们以64位地址线为例,pattern = 0b101010101010101010.... 能检测出奇偶位之间的数据错误。如果这个错误被排除,每两根数据线组成一组(这是理解下一个pattern的关键),再用相同的办法,检测没相邻两组之间是否有短路,就得到第二个pattern,就是 0b110011001100...... 依次类推,以4根数据线为一组,8根线为一组,相继得到共6个pattern,分别是0xaaaaaaaaaaaaaaaa,0xcccccccccccccccc,0xf0f0f0f0f0f0f0f0,0xff00ff00ff00ff00,    0xffff0000ffff0000,0xffffffff00000000。只要相继写入并读出这6个pattern就能验证是否存在数据线交叉短路错误。

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

什么是floating buses 错误
floating buses会“欺骗”测试软件,如果测试软件写入并很快读出一个值的时候,写操作会跟数据线上的电容充电,总线会短暂的保持它的状态。当测试软件读操作时,总线会返回刚写入的值,即使实际上该数据线是断路的。

如何检测数据线的floating buses 错误
检测floating buses 错误的算法不复杂,在写和读回之间再插入一次对不同地址写入不同值的操作。例如, X 写入 X1位置, Y 写入Y1 位置,再从X1 位置读出X 值则表示floating buses 错误不存在。

 

地址线的错误
如果地址线存在错误,其症状是地址空间中的两个不同位置被映射到同一物理存储位置。更通俗地讲,就是写一个位置却“改变”了另一个位置。

地址线的错误检测
地址线的错误检测相对简单,其算法是:
首先,将地址的值作为内容写入该地址处,汇编的表示方法是 (addr) = addr。这样确保每一个位置的内容不同。
其次,依次将内存基地址的某一根地址线的值翻转(flip/toggle)得到某个地址,从该地址取值,如果该值和基地址的值相等,则表示某一位地址线有问题。
这个算法的特点是每次只检测一根地址线,方法简单有效。

存储单元的错误
以上数据线和地址线的检测都是检测布线或工厂生产的错误,而存储单元的检测则是真正对DDR内存芯片的检测。内存芯片的常见错误是bit-stuck,简而言之,就是让它是0,它偏为1,让它为1,它偏为0,我行我素,不听号令:(
检测方法也很简单,就是用不同的pattern去写尽可能所有的地址并读回比较。有一些常用的pattern如0x5555, 0xAAAA等,在此不再赘述。

几个简单的检测DDR故障的方法
上面的DDR检测算法,虽然全面,但是耗时比较长,常常需要好几个小时,在Uboot命令行下也有几个简单的命令可以检测常见内存故障,不需要重编译代码就能执行。
1> mtest addr lenth pattern
这个命令需要注意,DDR在Uboot启动后被映射到了0地址,但是uboot的代码和堆、栈空间0x10000000处开始,这些空间是不能被刷的,否则就挂死了。mtest的执行就在这段空间,只能说是大水冲了龙王庙.
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系统,上面的方法更适用于系统不稳定时定位错误。

原创粉丝点击