You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

190 lines
7.2 KiB

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