1 # Algorithms by Michael Barr, released into public domain
2 # Ported to OpenOCD by Shane Volpe, additional fixes by Paul Fertser
4 set CPU_MAX_ADDRESS
0xFFFFFFFF
5 source [find bitsbytes.tcl
]
6 source [find
memory.tcl
]
8 proc runAllMemTests
{ baseAddress nBytes
} {
9 memTestDataBus
$baseAddress
10 memTestAddressBus
$baseAddress $nBytes
11 memTestDevice
$baseAddress $nBytes
14 #***********************************************************************************
16 # * Function: memTestDataBus()
18 # * Description: Test the data bus wiring in a memory region by
19 # * performing a walking 1's test at a fixed address
20 # * within that region. The address (and hence the
21 # * memory region) is selected by the caller.
23 # * http://www.netrino.com/Embedded-Systems/How-To/Memory-Test-Suite-C
26 # * Returns: Empty string if the test succeeds.
27 # * A non-zero result is the first pattern that failed.
29 #***********************************************************************************
30 proc memTestDataBus
{ address
} {
31 echo
"Running memTestDataBus"
33 for {set i
0} {$i < 32} {incr i
} {
35 set pattern
[expr {1 << $i}]
37 # Write pattern to memory
38 memwrite32
$address $pattern
40 # Read pattern from memory
41 set data
[memread32
$address]
43 if {$data != $pattern} {
44 echo
"FAILED DATABUS: Address: $address, Pattern: $pattern, Returned: $data"
50 #***********************************************************************************
52 # * Function: memTestAddressBus()
54 # * Description: Perform a walking 1's test on the relevant bits
55 # * of the address and check for aliasing. This test
56 # * will find single-bit address failures such as stuck
57 # * -high, stuck-low, and shorted pins. The base address
58 # * and size of the region are selected by the caller.
60 # * http://www.netrino.com/Embedded-Systems/How-To/Memory-Test-Suite-C
62 # * Notes: For best results, the selected base address should
63 # * have enough LSB 0's to guarantee single address bit
64 # * changes. For example, to test a 64-Kbyte region,
65 # * select a base address on a 64-Kbyte boundary. Also,
66 # * select the region size as a power-of-two--if at all
69 # * Returns: Empty string if the test succeeds.
70 # * A non-zero result is the first address at which an
71 # * aliasing problem was uncovered. By examining the
72 # * contents of memory, it may be possible to gather
73 # * additional information about the problem.
75 #***********************************************************************************
76 proc memTestAddressBus
{ baseAddress nBytes
} {
77 set addressMask
[expr {$nBytes - 1}]
78 set pattern
0xAAAAAAAA
79 set antipattern
0x55555555
81 echo
"Running memTestAddressBus"
83 echo
"addressMask: [convertToHex $addressMask]"
85 echo
"memTestAddressBus: Writing the default pattern at each of the power-of-two offsets..."
86 for {set offset
32} {[expr {$offset & $addressMask}] != 0} {set offset
[expr {$offset << 1}] } {
87 set addr
[expr {$baseAddress + $offset}]
88 memwrite32
$addr $pattern
91 echo
"memTestAddressBus: Checking for address bits stuck high..."
92 memwrite32
$baseAddress $antipattern
94 for {set offset
32} {[expr {$offset & $addressMask}] != 0} {set offset
[expr {$offset << 1}]} {
95 set addr
[expr {$baseAddress + $offset}]
96 set data
[memread32
$addr]
98 if {$data != $pattern} {
99 echo
"FAILED DATA_ADDR_BUS_SHIGH: Address: [convertToHex $addr], Pattern: [convertToHex $pattern], Returned: [convertToHex $data]"
104 echo
"memTestAddressBus: Checking for address bits stuck low or shorted..."
105 memwrite32
$baseAddress $pattern
106 for {set testOffset
32} {[expr {$testOffset & $addressMask}] != 0} {set testOffset
[expr {$testOffset << 1}] } {
107 set addr
[expr {$baseAddress + $testOffset}]
108 memwrite32
$addr $antipattern
110 set data
[memread32
$baseAddress]
111 if {$data != $pattern} {
112 echo
"FAILED DATA_ADDR_BUS_SLOW: Address: [convertToHex $addr], Pattern: [convertToHex $pattern], Returned: [convertToHex $data]"
116 for {set offset
32} {[expr {$offset & $addressMask}] != 0} {set offset
[expr {$offset << 1}]} {
117 set addr
[expr {$baseAddress + $offset}]
118 set data
[memread32
$baseAddress]
120 if {(($data != $pattern) && ($offset != $testOffset))} {
121 echo
"FAILED DATA_ADDR_BUS_SLOW2: Address: [convertToHex $addr], Pattern: [convertToHex $pattern], Returned: [convertToHex $data], offset: [convertToHex $offset], testOffset [convertToHex $testOffset]"
125 set addr
[expr {$baseAddress + $testOffset}]
126 memwrite32
$addr $pattern
130 #***********************************************************************************
132 # * Function: memTestDevice()
134 # * Description: Test the integrity of a physical memory device by
135 # * performing an increment/decrement test over the
136 # * entire region. In the process every storage bit
137 # * in the device is tested as zero and as one. The
138 # * base address and the size of the region are
139 # * selected by the caller.
141 # * http://www.netrino.com/Embedded-Systems/How-To/Memory-Test-Suite-C
144 # * Returns: Empty string if the test succeeds.
145 # * A non-zero result is the first address at which an
146 # * incorrect value was read back. By examining the
147 # * contents of memory, it may be possible to gather
148 # * additional information about the problem.
150 #***********************************************************************************
151 proc memTestDevice
{ baseAddress nBytes
} {
152 echo
"Running memTestDevice"
154 echo
"memTestDevice: Filling memory with a known pattern..."
155 for {set pattern
1; set offset
0} {$offset < $nBytes} {incr pattern
; incr offset
32} {
156 memwrite32
[expr {$baseAddress + $offset}] $pattern
159 echo
"memTestDevice: Checking each location and inverting it for the second pass..."
160 for {set pattern
1; set offset
0} {$offset < $nBytes} {incr pattern
; incr offset
32} {
161 set addr
[expr {$baseAddress + $offset}]
162 set data
[memread32
$addr]
164 if {$data != $pattern} {
165 echo
"FAILED memTestDevice_pattern: Address: [convertToHex $addr], Pattern: [convertToHex $pattern], Returned: [convertToHex $data], offset: [convertToHex $offset]"
169 set antiPattern
[expr {~
$pattern}]
170 memwrite32
[expr {$baseAddress + $offset}] $antiPattern
173 echo
"memTestDevice: Checking each location for the inverted pattern and zeroing it..."
174 for {set pattern
1; set offset
0} {$offset < $nBytes} {incr pattern
; incr offset
32} {
175 set antiPattern
[expr {~
$pattern & ((1<<32) - 1)}]
176 set addr
[expr {$baseAddress + $offset}]
177 set data
[memread32
$addr]
178 set dataHex
[convertToHex
$data]
179 set antiPatternHex
[convertToHex
$antiPattern]
180 if {$dataHex != $antiPatternHex} {
181 echo
"FAILED memTestDevice_antipattern: Address: [convertToHex $addr], antiPattern: $antiPatternHex, Returned: $dataHex, offset: $offset"
187 proc convertToHex
{ value
} {