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)
imidc对日本独立服务器在搞特别促销,原价159美元的机器现在只需要88美元,而且给13个独立IPv4,30Mbps直连带宽,不限制流量。注意,本次促销只有一个链接,有2个不同的优惠码,你用不同的优惠码就对应着不同的配置,价格也不一样。88美元的机器,下单后默认不管就给512G SSD,要指定用HDD那就发工单,如果需要多加一个/28(13个)IPv4,每个月32美元...官方网站:https:...
想必我们有一些朋友应该陆续收到国内和国外的域名注册商关于域名即将涨价的信息。大概的意思是说从9月1日开始,.COM域名会涨价一点点,大约需要单个9.99美元左右一个。其实对于大部分用户来说也没多大的影响,毕竟如今什么都涨价,域名涨一点点也不要紧。如果是域名较多的话,确实增加续费成本和注册成本。今天整理看到Dynadot有发布新的八月份域名优惠活动,.COM首年注册依然是仅需48元,本次优惠活动截止...
HostKvm发布了夏季特别促销活动,针对香港国际/韩国机房VPS主机提供7折优惠码,其他机房全场8折,优惠后2GB内存套餐月付仅5.95美元起。这是一家成立于2013年的国外主机服务商,主要提供基于KVM架构的VPS主机,可选数据中心包括日本、新加坡、韩国、美国、中国香港等多个地区机房,均为国内直连或优化线路,延迟较低,适合建站或者远程办公等。下面分享几款香港VPS和韩国VPS的配置和价格信息。...