In U-boot, Denx (developer of U-boot) has conducted rigorous detection of common DDR memory failures, and the following figure depicts the three steps of the detection process: the detection of data lines, address lines, and DDR physical storage parts, mainly related to the process and methods of these three steps, For the DDR subsystem, it is very easy to fail and is difficult to debug detection, and Denx for the DDR memory fault design of the detection method is very rigorous, worthy of study.
The following are mainly related to the detection and processing ideas and problems:
1, why first detect the data line.
Because if the data line is disconnected, then nothing is to be talked about. Next is the detection of address lines, only the data and address lines are passed, the memory storage unit to detect the significance of the process is also conducive to segmentation positioning problems. The Testingsequence block diagram above divides the entire inspection process into three major steps, denoted by three dashed squares.
2, the connection error of the data cable
There may be two errors in the connection of the data cable, one being disconnected, and the other wiring or production causing a short circuit to each other.
3, how to detect the connection error of the data cable
Denx design of the data line detection algorithm is very tricky and fine seconds, the entire process is the following example: If it is two data lines, only need to write and read a pattern=0b01 (0b at the beginning of the binary number) to determine whether they are short-circuited or disconnected. Obviously, most of the embedded platform more than two data lines, we take 64-bit address line for example, pattern= 0b101010101010101010 .... Can detect data errors between odd and even bits. If this error is excluded, a group of two data lines is formed (this is the key to understanding the next pattern), and then the same method is used to detect if there is a short circuit between two adjacent groups, then the second pattern is 0b110011001100 ... And so on, to 4 data lines for a group, 8 lines for a group, successively obtained a total of 6 pattern, respectively, is 0xaaaaaaaaaaaaaaaa,0xcccccccccccccccc,0xf0f0f0f0f0f0f0f0, 0xff00ff00ff00ff00,0xffff0000ffff0000,0xffffffff00000000. As long as the 6 pattern is written and read sequentially, it is possible to verify the existence of a data line cross-short error.
4, how to detect the data cable and other signal lines on the board cross-circuit or circuit breaker
Take the 6 pattern of the inverse code, a total of 12 pattern can detect each bit can be written and read out 0 and 1.
5. What is floating buses error
Floatingbuses will "cheat" the test software, if the test software writes and quickly read a value, the write operation will be charged with the capacitance on the data line, the bus will keep its state for a short time. When testing the software read operation, the bus returns the value that was just written, even if the data line is actually open-circuit.
6, how to detect the floating buses error of the data cable
The algorithm for detecting floatingbuses errors is not complex, and the operation of writing different values to different addresses is inserted again between write and read back. For example, X writes the X1 position, Y writes the Y1 position, and then reads the x value from the X1 location to indicate that the floatingbuses error does not exist.
7, the Address line error
If there is an error in the address line, the symptom is that two different locations in the address space are mapped to the same physical storage location. More generally, it is writing a position but "changing" another position.
8. Error detection of Address line
Address line error detection is relatively simple, the algorithm is:
1), write the value of the address as content to the address, the Assembly is represented by (addr) =addr. The address value is written to the address corresponding to the space, so that the content of each location is different.
2), in turn, the value of the address line of the memory base site is flipped (flip/toggle) to get an address, from that address value, if the value and base address is equal, it indicates a problem with one address line.
This algorithm is characterized by the detection of only one address line at a time, the method is simple and effective.
9. Error in storage unit
The above data and address line detection is the detection of cabling or factory production errors, and storage unit detection is true to the DDR memory chip detection. Memory chip Common error is bit-stuck, in short, let it is 0, it is biased to 1, let it be 1, it is 0, the detection method is very simple, is to use different pattern to write as far as possible all the addresses and read back to the comparison. There are some commonly used pattern such as 0x5555, 0xAAAA and so on.
10, a few simple methods to detect the DDR failure
The above DDR detection algorithm, although comprehensive, but takes a long time, often take several hours, at the uboot command line there are several simple commands to detect common memory failures, as follows:
1), Mtest addr Lenth pattern
This command needs to note that the DDR is mapped to the 0 address after the Uboot is started, but the Uboot code and heap, stack space 0x10000000 start, these spaces can not be brushed, or dead.
2), copy nor Flash content into memory, such as Cp.b 0x20080000 0x7fc020000, then compare cmp.b 0x20080000 0x7fc0 20000.
3), download kernel image into memory, copy NOR Flash or TFTP, and then call Iminfo Load_addr detect CRC error.
The first method is to brush the free space of the DDR with a specific pattern, and the second and third methods can say that the randomness of the pattern is greater.
Of course, the most thorough detection method is a long time to run the Linux system, the above method is more suitable for system instability when the location error.
The specific code is implemented as follows:[HTML]Viewplain copy print? Static voidmove64 (unsigned long long *src, unsigned long long*dest) {*dest= *src;} const static Unsignedlong long patter N[] = {0xaaaaaaaaaaaaaaaaULL, 0xccccccccccccccccULL, 0xf0f0f0f0f0f0f0f0ull, 0xff00ff00ff00ff00ull, 0xffff0000ffff0000ull, 0xffffffff00000000ull, 0x00000000ffffffffull, 0x0000ffff0000ffffull, 0x00ff00ff00ff00ffULL, 0x0f0f0f0f0f0f0f0full, 0x3333333333333333ull, 0x5555555555555555ull}; Const unsigned Longlong otherpattern = 0x0123456789abcdefull; Static Intmemory_post_dataline (unsigned long long * pmem) {unsigned longlong temp64 = 0; int num_patterns= sizeof (pattern )/sizeof (pattern[0]); Inti unsigned int hi, Lo,pathi, Patlo; int ret= 0; for (i= 0;i<</FONT> Num_patterns; i++) {move64 (unsigned Longlong *) & (Pattern[i]), pmem++); Move64 ((unsigned longlong *) &otherpattern, pmem--); Move64 (PMEM,&TEMP64); #ifdefINJECT_DATA_ERRORS Temp64 ^=0x00008000; #endif if (temp64!=pattern[i]) {Pathi = (Pattern[i]>>& 0xFFFFFFFF; Patlo = pattern[i]& 0xFFFFFFFF; Hi = (temp64>>& 0xFFFFFFFF; Lo = temp64&0xffffffff; Post_log ("Memory (Dateline) error at x," "wrote xx, read xx!\n", Pmem, Pathi, Patlo, Hi,lo); RET =-1; }} Returnret; } Static Intmemory_post_addrline (ULONG *testaddr, ulong *base, ulongsize) {ulong*target; ulong*end; ulongreadback; ulong Xor int ret= 0; End = (ulong*) ((ULONG) base + size); XOR = 0; for (xor= sizeof (ULONG); XOR>0; Xor<</span><</span>=1){target = (ulong*) ((ULONG) testaddr ^ xor), if (target>=base) && (target<</FONT> End) {*testaddr= ~*target; readback =*target; #ifdefINJECT_ADDRESS_ERRORS if (xor==0x00008000) {readback =*testaddr;} #end If if (readback== *testaddr) {Post_log ("Memory address" error at x<</span>->x, ""XOR value x!\n", testaddr, Target,xor); RET =-1; }}} Returnret; } static Intmemory_post_test1 (unsigned long start, unsigned longsize, unsigned longval) {unsigned longi; ulong*mem = (ul Ong *) Start; Ulongreadback; int ret= 0; for (i = 0;i<</FONT> size/sizeof (ULONG); i++) {mem[i] =val; if (i%1024== 0) watchdog_reset ();} for (i = 0;i<</FONT> size/sizeof (ULONG) && ret== 0; i++) {readback = Mem[i], if (readback! = val) {post_log ("Memory Errorat x," "wrote X, read x!\n", mem + I, val,readback) ; RET =-1; Break } if (i%1024== 0) watchdog_reset (); } Returnret; } static Intmemory_post_test2 (unsigned long start, unsigned longsize) {unsigned longi; ulong*mem = (ULONG *) start; ulong Readback; int ret= 0; for (i = 0;i<</FONT> size/sizeof (ULONG); i++) {Mem[i] = 1<</SPAN><</SPAN> (i%);if (i%1024== 0) watchdog_reset (); } for (i = 0;i<</FONT> size/sizeof (ULONG) && ret== 0; i++) {readback = Mem[i]; if (readback! = (1<</SPAN><</SPAN> (i% 32))) {Post_log ("Memory Errorat x," "wrote X, read x!\n", mem + I, 1<</SPAN><</SPAN> (i%), readback);RET =-1; Break } if (i%1024== 0) watchdog_reset (); } Returnret; } static Intmemory_post_test3 (unsigned long start, unsigned longsize) {unsigned longi; ulong*mem = (ULONG *) start; ulong Readback; int ret= 0; for (i = 0;i<</FONT> size/sizeof (ULONG); i++) {mem[i] =i; if (i%1024== 0) watchdog_reset ();} for (i = 0;i<</FONT> size/sizeof (ULONG) && ret== 0; i++) {readback = Mem[i], if (readback! = i) {post_log ("Memory Errorat x," "wrote X, read x!\n", mem + I, i,readback); RET =-1; Break } if (i%1024== 0) watchdog_reset (); } Returnret; } static Intmemory_post_test4 (unsigned long start, unsigned longsize) {unsigned longi; ulong*mem = (ULONG *) start; ulong Readback; int ret= 0; for (i = 0;i<</FONT> size/sizeof (ULONG); i++) {mem[i] =~i; if (i%1024== 0) watchdog_reset ();} for (i = 0;i<</FONT> size/sizeof (ULONG) && ret== 0; i++) {readback = Mem[i]; if (readback! = ~i) {post_log ("Memory Errorat x," "wrote X, read x!\n", mem + I, ~i,readback); RET =-1; Break } if (i%1024== 0) watchdog_reset (); } Returnret; } static intmemory_post_tests (unsigned long start, unsi