DDR内存子系统常见硬件错误及Uboot中检测流程在U-Boot中 Denx U-Boot的开发商针对常见的DDR内存故障进行了严格的检测处理下图描述了该检测处理过程的三个步骤检测数据线、地址线和DDR物理存储部件主要涉及这三个步骤的处理过程和方法对于DDR子系统是很容易
下面主要是相关的检测处理思路及问题
1、为什么先检测数据线
因为如果数据线是断开的那么一切无从谈起接下来是检测地址线只有数据线和地址线都通过检测内存的存储单元才
示。
2、数据线的连接错误
数据线的连接可能存在两种错误一种是被断开 另一种布线或生产造成互相短路。
3、如何检测数据线的连接错误
pattern=0b01 0b开头表示二进制数就能判断它们是否短路或断开。很明显大部分的嵌入式平台不止两根数据线我们
这是理解下一个pattern的关键 再用相同的办法检测每相邻两组之间是否有短路就得到第二个pattern就是0b110011001100. . . . . .依次类推 以4根数据线为一组 8根线为一组相继得到共6个pattern分别是
0x aaaaaaaaaaaaaaaa 0xcccccccccccccccc 0xf0f0f0f0f0f0f0f0
0xff 00 ff 00 ff 00ff 00 0xffff 0000ffff 0000 0xffffffff 00000000。只要相继写入并读出这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 、依次将内存基地址的某一根地址线的值翻转
值如果该值和基地这个算法的特点是每次只检测一根地址线方法简单有效。
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 、复制NORflash的内容到内存中如cp.b 0x200800000x7fc020000然后比较cmp.b 0x200800000x7fc020000。
3 、下载kernel image到内存中 copy NOR flash或tftp都行然后调用iminfo LOAD_ADDR检测CRC错误。
当然最彻底的检测方法当然是长时间跑Linux系统上面的方法更适用于系统不稳定时定位错误。
内存检测方法程序示例static voidmove64(unsigned long long *src, unsigned long long *dest){
*dest = *src;
}
/*
* This is 64 bit wide testpatterns Note that theyreside in ROM
* (which presumably works) and the tests write them to RAM which may
* notwork
*
* The "otherpattern" is written to drive the data bus to values other
* than the testpattern This is for detecting floating bus lines
*
*/const static unsigned long long pattern[] = {
0x aaaaaaaaaaaaaaaa ULL,
0x cccccccccccccccc ULL,
0xf0f0f0f0f0f0f0f0ULL,
0xff00ff00ff00ff00ULL,
0xffff0000ffff0000ULL,
0xffffffff00000000ULL,
0x00000000ffffffffULL,
0x0000ffff0000ffffULL,
0x00ff00ff00ff00ffULL,
0x0f0f0f0f0f0f0f0fULL,
0x 3333333333333333ULL,
0x 5555555555555555ULL
};const unsigned long long otherpattern = 0x0123456789abcdefULL;/*数据线检测*/static intmemory_post_dataline(unsigned long long * pmem)
{unsigned long long temp64 = 0;int num_patterns = sizeof(pattern)/sizeof(pattern[0]);int i;unsigned int hi, lo, pathi, patlo;int ret = 0;for ( i = 0; i < num_patterns; i++)
{move64((unsigned long long *)&(pattern[i]), pmem++);
/*
* Put a differentpattern on the data lines: otherwise they
*mayfloat long enough to read backwhatwe wrote
*/
/*预防floating buses错误*/move64((unsigned long long *)&otherpattern, pmem- -);move64(pmem, &temp64);
#ifdef INJECT_DATA_ERRORS temp64 ^= 0x00008000;
#endif if (temp64 != pattern[i])
{pathi = (pattern[i]>>32)& 0xffffffff;patlo = pattern[i]& 0xffffffff;hi = (temp64>>32)& 0xffffffff;lo = temp64& 0xffffffff;post_log ("Memory(date line) error at %08x, "
"wrote %08x%08x, read %08x%08x ! \n",pmem, pathi, patlo, hi, lo);ret = -1;
}
}return ret;
}
/*地址线检测*/static intmemory_post_addrline(ulong *testaddr, ulong *base, ulong size){ulong *target;ulong *end;ulong readback;ulongxor;int ret = 0;end = (ulong *)((ulong)base + size);/* pointer arith! */xor = 0;for(xor = sizeof(ulong); xor > 0; xor <<= 1)
{
/*对测试的地址的某一根地址线的值翻转*/target = (ulong *)((ulong)testaddr ^ xor);if((target >= base)&& (target < end))
{
/*由于target是testaddr某一根地址线的值翻转得来
故testaddr != target,下面赋值操作后
应有*testaddr != *target */
*testaddr = ~*target;readback = *target;
#ifdef INJECT_ADDRESS_ERRORS if(xor == 0x00008000)
{readback = *testaddr;
}
#endif
/*出现此种情况只有testaddr == target,即某根地址线翻转无效*/if(readback == *testaddr)
{post_log ("Memory(address line) error at %08x<->%08x, "
"XOR value %08x ! \n",testaddr, target, xor);ret = -1;
}
}
}return ret;
}static intmemory_post_test1 (unsigned long start,unsigned long size,unsigned long val)
{unsigned long i;ulong *mem= (ulong *) start;ulong readback;int ret = 0;for (i = 0; i < size /sizeof (ulong); i++) {mem[i] = val;if (i % 1024 == 0)
WATCHDOG_RESET ();
}for (i = 0; i < size /sizeof (ulong)&& ret == 0; i++) {readback =mem[i];if (readback != val) {post_log ("Memory error at %08x, "
"wrote %08x, read %08x ! \n",mem + i, val, readback);ret = -1;break;
}if (i % 1024 == 0)
WATCHDOG_RESET ();
}return ret;
}static intmemory_post_test2 (unsigned long start, unsigned long size){unsigned long i;ulong *mem= (ulong *) start;ulong readback;int ret = 0;for (i = 0; i < size /sizeof (ulong); i++) {mem[i] = 1 << (i % 32);if (i % 1024 == 0)
WATCHDOG_RESET ();
}for (i = 0; i < size /sizeof (ulong)&& ret == 0; i++) {readback =mem[i];if (readback != (1 << (i % 32))) {post_log ("Memory error at %08x, "
"wrote %08x, read %08x ! \n",mem + i, 1 << (i % 32), readback);ret = -1;break;
}if (i % 1024 == 0)
腾讯云轻量应用服务器又要免费升级配置了,之前已经免费升级过一次了(腾讯云轻量应用服务器套餐配置升级 轻量老用户专享免费升配!),这次在上次的基础上再次升级。也许这就是良心云吧,名不虚传。腾讯云怎么样?腾讯云好不好。腾讯云轻量应用服务器 Lighthouse 是一种易于使用和管理、适合承载轻量级业务负载的云服务器,能帮助个人和企业在云端快速构建网站、博客、电商、论坛等各类应用以及开发测试环境,并提供...
古德云(goodkvm)怎么样?古德云是一家成立于2020年的商家,原名(锤子云),古德云主要出售VPS服务器、独立服务器。古德云主打产品是香港cn2弹性云及美西cn2云服务器,采用的是kvm虚拟化构架,硬盘Raid10。目前,古德云香港沙田cn2机房及美国五星级机房云服务器,2核2G,40G系统盘+50G数据盘,仅35元/月起,性价比较高,可以入手!点击进入:古德云goodkvm官方网站地址古德...
ProfitServer怎么样?ProfitServer好不好。ProfitServer是一家成立于2003的主机商家,是ITC控股的一个部门,主要经营的产品域名、SSL证书、虚拟主机、VPS和独立服务器,机房有俄罗斯、新加坡、荷兰、美国、保加利亚,VPS采用的是KVM虚拟架构,硬盘采用纯SSD,而且最大的优势是不限制流量,大公司运营,机器比较稳定,数据中心众多。此次ProfitServer正在对...