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)
易探云产品限时秒杀&QQ音乐典藏活动正在进行中!购买易探云香港/美国云服务器送QQ音乐绿钻豪华版1年,价值180元,性价比超级高。目前,有四大核心福利产品推荐:福利一、香港云服务器1核1G2M,仅218元/年起(香港CN2线路,全球50ms以内);福利二、美国20G高防云服务器1核1G5M,仅336元/年起(美国BGP线路,自带20G防御);福利三、2G虚拟主机低至58.8元/年(更有免费...
LOCVPS(全球云)发布了新上韩国机房KVM架构主机信息,提供流量和带宽方式,适用全场8折优惠码,优惠码最低2G内存套餐月付仅44元起。这是一家成立较早的国人VPS服务商,目前提供洛杉矶MC、洛杉矶C3、和香港邦联、香港沙田电信、香港大埔、日本东京、日本大阪、新加坡、德国和荷兰等机房VPS主机,基于KVM或者XEN架构。下面分别列出几款韩国机房KVM主机配置信息。韩国KVM流量型套餐:KR-Pl...
imidc对日本独立服务器在搞特别促销,原价159美元的机器现在只需要88美元,而且给13个独立IPv4,30Mbps直连带宽,不限制流量。注意,本次促销只有一个链接,有2个不同的优惠码,你用不同的优惠码就对应着不同的配置,价格也不一样。88美元的机器,下单后默认不管就给512G SSD,要指定用HDD那就发工单,如果需要多加一个/28(13个)IPv4,每个月32美元...官方网站:https:...