tcl: add memory testing functions for board diagnostics 55/1455/4
authorPaul Fertser <fercerpav@gmail.com>
Fri, 21 Jun 2013 21:16:41 +0000 (01:16 +0400)
committerSpencer Oliver <spen@spen-soft.co.uk>
Tue, 29 Oct 2013 22:50:33 +0000 (22:50 +0000)
This is a tcl implementation of public domain tests by Michael Barr,
http://www.barrgroup.com/Embedded-Systems/How-To/Memory-Test-Suite-C

The initial porting is done by Shane Volpe and posted to the mailing
list:
http://www.mail-archive.com/openocd-development@lists.berlios.de/msg16676.html

This patch includes some cosmetic amendments plus hardcodes 32bit word
size (as the code depends on memread32/memwrite32 anyway) which fixes
original code's issue of testing only the first quarter of the
specified nBytes.

Change-Id: I5f3a66f1f16fc4082c7a5a6aba338430646ed21c
Signed-off-by: Paul Fertser <fercerpav@gmail.com>
Reviewed-on: http://openocd.zylin.com/1455
Tested-by: jenkins
Reviewed-by: Spencer Oliver <spen@spen-soft.co.uk>
Reviewed-by: Mathias K├╝ster <kesmtp@freenet.de>
doc/openocd.texi
tcl/tools/memtest.tcl [new file with mode: 0644]

index a2bcaf8507801886cc26dff1ed3688a5ba42a16a..c7776b1073344f1f35d6c5cfcd3ea279e804d5a6 100644 (file)
@@ -79,6 +79,7 @@ Free Documentation License''.
 * Architecture and Core Commands::   Architecture and Core Commands
 * JTAG Commands::                    JTAG Commands
 * Boundary Scan Commands::           Boundary Scan Commands
+* Utility Commands::                 Utility Commands
 * TFTP::                             TFTP
 * GDB and OpenOCD::                  Using GDB and OpenOCD
 * Tcl Scripting API::                Tcl Scripting API
@@ -7926,6 +7927,53 @@ If @emph{xsvfdump} shows a file is using those opcodes, it
 probably will not be usable with other XSVF tools.
 
 
+@node Utility Commands
+@chapter Utility Commands
+@cindex Utility Commands
+
+@section RAM testing
+@cindex RAM testing
+
+There is often a need to stress-test random access memory (RAM) for
+errors. OpenOCD comes with a Tcl implementation of well-known memory
+testing procedures allowing to detect all sorts of issues with
+electrical wiring, defective chips, PCB layout and other common
+hardware problems.
+
+To use them you usually need to initialise your RAM controller first,
+consult your SoC's documentation to get the recommended list of
+register operations and translate them to the corresponding
+@command{mww}/@command{mwb} commands.
+
+Load the memory testing functions with
+
+@example
+source [find tools/memtest.tcl]
+@end example
+
+to get access to the following facilities:
+
+@deffn Command {memTestDataBus} address
+Test the data bus wiring in a memory region by performing a walking
+1's test at a fixed address within that region.
+@end deffn
+
+@deffn Command {memTestAddressBus} baseaddress size
+Perform a walking 1's test on the relevant bits of the address and
+check for aliasing. This test will find single-bit address failures
+such as stuck-high, stuck-low, and shorted pins.
+@end deffn
+
+@deffn Command {memTestDevice} baseaddress size
+Test the integrity of a physical memory device by performing an
+increment/decrement test over the entire region. In the process every
+storage bit in the device is tested as zero and as one.
+@end deffn
+
+@deffn Command {runAllMemTests} baseaddress size
+Run all of the above tests over a specified memory region.
+@end deffn
+
 @node TFTP
 @chapter TFTP
 @cindex TFTP
diff --git a/tcl/tools/memtest.tcl b/tcl/tools/memtest.tcl
new file mode 100644 (file)
index 0000000..02f94d3
--- /dev/null
@@ -0,0 +1,189 @@
+# Algorithms by Michael Barr, released into public domain
+# Ported to OpenOCD by Shane Volpe, additional fixes by Paul Fertser
+
+set CPU_MAX_ADDRESS 0xFFFFFFFF
+source [find bitsbytes.tcl]
+source [find memory.tcl]
+
+proc runAllMemTests { baseAddress nBytes } {
+    memTestDataBus $baseAddress
+    memTestAddressBus $baseAddress $nBytes
+    memTestDevice $baseAddress $nBytes
+}
+
+#***********************************************************************************
+# *
+# * Function:    memTestDataBus()
+# *
+# * Description: Test the data bus wiring in a memory region by
+# *              performing a walking 1's test at a fixed address
+# *              within that region.  The address (and hence the
+# *              memory region) is selected by the caller.
+# *             Ported from:
+# *             http://www.netrino.com/Embedded-Systems/How-To/Memory-Test-Suite-C
+# * Notes:
+# *
+# * Returns:     Empty string if the test succeeds.
+# *              A non-zero result is the first pattern that failed.
+# *
+#***********************************************************************************
+proc memTestDataBus { address } {
+    echo "Running memTestDataBus"
+
+    for {set i 0} {$i < 32} {incr i} {
+       # Shift bit
+       set pattern [expr {1 << $i}]
+
+       # Write pattern to memory
+       memwrite32 $address $pattern
+
+       # Read pattern from memory
+       set data [memread32 $address]
+
+       if {$data != $pattern} {
+           echo "FAILED DATABUS: Address: $address, Pattern: $pattern, Returned: $data"
+           return $pattern
+       }
+    }
+}
+
+#***********************************************************************************
+# *
+# * Function:    memTestAddressBus()
+# *
+# * Description: Perform a walking 1's test on the relevant bits
+# *              of the address and check for aliasing.  This test
+# *              will find single-bit address failures such as stuck
+# *              -high, stuck-low, and shorted pins.  The base address
+# *              and size of the region are selected by the caller.
+# *             Ported from:
+# *             http://www.netrino.com/Embedded-Systems/How-To/Memory-Test-Suite-C
+# *
+# * Notes:       For best results, the selected base address should
+# *              have enough LSB 0's to guarantee single address bit
+# *              changes.  For example, to test a 64-Kbyte region,
+# *              select a base address on a 64-Kbyte boundary.  Also,
+# *              select the region size as a power-of-two--if at all
+# *              possible.
+# *
+# * Returns:     Empty string if the test succeeds.
+# *              A non-zero result is the first address at which an
+# *              aliasing problem was uncovered.  By examining the
+# *              contents of memory, it may be possible to gather
+# *              additional information about the problem.
+# *
+#***********************************************************************************
+proc memTestAddressBus { baseAddress nBytes } {
+    set addressMask [expr $nBytes - 1]
+    set pattern 0xAAAAAAAA
+    set antipattern 0x55555555
+
+    echo "Running memTestAddressBus"
+
+    echo "addressMask: [convertToHex $addressMask]"
+
+    echo "memTestAddressBus: Writing the default pattern at each of the power-of-two offsets..."
+    for {set offset 32} {[expr $offset & $addressMask] != 0} {set offset [expr $offset << 1] } {
+       set addr [expr $baseAddress + $offset]
+       memwrite32 $addr $pattern
+    }
+
+    echo "memTestAddressBus: Checking for address bits stuck high..."
+    memwrite32 $baseAddress $antipattern
+
+    for {set offset 32} {[expr $offset & $addressMask] != 0} {set offset [expr $offset << 1]} {
+       set addr [expr $baseAddress + $offset]
+       set data [memread32 $addr]
+
+       if {$data != $pattern} {
+           echo "FAILED DATA_ADDR_BUS_SHIGH: Address: [convertToHex $addr], Pattern: [convertToHex $pattern], Returned: [convertToHex $data]"
+           return $pattern
+       }
+    }
+
+    echo "memTestAddressBus: Checking for address bits stuck low or shorted..."
+    memwrite32 $baseAddress $pattern
+    for {set testOffset 32} {[expr $testOffset & $addressMask] != 0} {set testOffset [expr $testOffset << 1] } {
+       set addr [expr $baseAddress + $testOffset]
+       memwrite32 $addr $antipattern
+
+       set data [memread32 $baseAddress]
+       if {$data != $pattern} {
+           echo "FAILED DATA_ADDR_BUS_SLOW: Address: [convertToHex $addr], Pattern: [convertToHex $pattern], Returned: [convertToHex $data]"
+           return $pattern
+       }
+
+       for {set offset 32} {[expr $offset & $addressMask] != 0} {set offset [expr $offset << 1]} {
+           set addr [expr $baseAddress + $offset]
+           set data [memread32 $baseAddress]
+
+            if {(($data != $pattern) && ($offset != $testOffset))} {
+               echo "FAILED DATA_ADDR_BUS_SLOW2: Address: [convertToHex $addr], Pattern: [convertToHex $pattern], Returned: [convertToHex $data], offset: [convertToHex $offset], testOffset [convertToHex $testOffset]"
+               return $pattern
+           }
+        }
+       set addr [expr $baseAddress + $testOffset]
+       memwrite32 $addr $pattern
+    }
+}
+
+#***********************************************************************************
+# *
+# * Function:    memTestDevice()
+# *
+# * Description: Test the integrity of a physical memory device by
+# *              performing an increment/decrement test over the
+# *              entire region.  In the process every storage bit
+# *              in the device is tested as zero and as one.  The
+# *              base address and the size of the region are
+# *              selected by the caller.
+# *             Ported from:
+# *             http://www.netrino.com/Embedded-Systems/How-To/Memory-Test-Suite-C
+# * Notes:
+# *
+# * Returns:     Empty string if the test succeeds.
+# *              A non-zero result is the first address at which an
+# *              incorrect value was read back.  By examining the
+# *              contents of memory, it may be possible to gather
+# *              additional information about the problem.
+# *
+#***********************************************************************************
+proc memTestDevice { baseAddress nBytes } {
+    echo "Running memTestDevice"
+
+    echo "memTestDevice: Filling memory with a known pattern..."
+    for {set pattern 1; set offset 0} {$offset < $nBytes} {incr pattern; incr offset 32} {
+       memwrite32 [expr $baseAddress + $offset] $pattern
+    }
+
+    echo "memTestDevice: Checking each location and inverting it for the second pass..."
+    for {set pattern 1; set offset 0} {$offset < $nBytes} {incr pattern; incr offset 32} {
+       set addr [expr $baseAddress + $offset]
+       set data [memread32 $addr]
+
+       if {$data != $pattern} {
+           echo "FAILED memTestDevice_pattern: Address: [convertToHex $addr], Pattern: [convertToHex $pattern], Returned: [convertToHex $data], offset: [convertToHex $offset]"
+           return $pattern
+       }
+
+       set antiPattern [expr ~$pattern]
+       memwrite32 [expr $baseAddress + $offset] $antiPattern
+    }
+
+    echo "memTestDevice: Checking each location for the inverted pattern and zeroing it..."
+    for {set pattern 1; set offset 0} {$offset < $nBytes} {incr pattern; incr offset 32} {
+       set antiPattern [expr ~$pattern & ((1<<32) - 1)]
+       set addr [expr $baseAddress + $offset]
+       set data [memread32 $addr]
+       set dataHex [convertToHex $data]
+       set antiPatternHex [convertToHex $antiPattern]
+       if {[expr $dataHex != $antiPatternHex]} {
+           echo "FAILED memTestDevice_antipattern: Address: [convertToHex $addr], antiPattern: $antiPatternHex, Returned: $dataHex, offset: $offset"
+           return $pattern
+       }
+    }
+}
+
+proc convertToHex { value } {
+    format 0x%08x $value
+}

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)