|
- # 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
- }
|