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)
博鳌云是一家以海外互联网基础业务为主的高新技术企业,运营全球高品质数据中心业务。自2008年开始为用户提供服务,距今11年,在国人商家中来说非常老牌。致力于为中国用户提供域名注册(国外接口)、免费虚拟主机、香港虚拟主机、VPS云主机和香港、台湾、马来西亚等地服务器租用服务,各类网络应用解決方案等领域的专业网络数据服务。商家支持支付宝、微信、银行转账等付款方式。目前香港有一款特价独立服务器正在促销,...
georgedatacenter这次其实是两个促销,一是促销一款特价洛杉矶E3-1220 V5独服,性价比其实最高;另外还促销三款特价vps,georgedatacenter是一家成立于2019年的美国VPS商家,主营美国洛杉矶、芝加哥、达拉斯、新泽西、西雅图机房的VPS、邮件服务器和托管独立服务器业务。georgedatacenter的VPS采用KVM和VMware虚拟化,可以选择windows...
每每进入第四季度,我们就可以看到各大云服务商的促销力度是一年中最大的。一来是年底的促销节日活动比较多,二来是商家希望最后一个季度冲刺业绩。这不还没有到第四季度,我们看到有些商家已经蠢蠢欲动的开始筹备活动。比如素有低价VPS收割机之称的Virmach商家居然还没有到黑色星期五就有发布黑五促销活动。Virmach 商家有十多个数据中心,价格是便宜的,但是机器稳定性和速度肯定我们也是有数的,要不这么低的...