1 //=============================================================================
5 //=============================================================================
6 //####ECOSGPLCOPYRIGHTBEGIN####
7 // -------------------------------------------
8 // This file is part of eCos, the Embedded Configurable Operating System.
9 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
11 // eCos is free software; you can redistribute it and/or modify it under
12 // the terms of the GNU General Public License as published by the Free
13 // Software Foundation; either version 2 or (at your option) any later version.
15 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
16 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 // You should have received a copy of the GNU General Public License along
21 // with eCos; if not, write to the Free Software Foundation, Inc.,
22 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
24 // As a special exception, if other files instantiate templates or use macros
25 // or inline functions from this file, or you compile this file and link it
26 // with other works to produce a work based on this file, this file does not
27 // by itself cause the resulting work to be covered by the GNU General Public
28 // License. However the source code for this file must still be made available
29 // in accordance with section (3) of the GNU General Public License.
31 // This exception does not invalidate any other reasons why a work based on
32 // this file might be covered by the GNU General Public License.
34 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
35 // at http://sources.redhat.com/ecos/ecos-license/
36 // -------------------------------------------
37 //####ECOSGPLCOPYRIGHTEND####
38 //=============================================================================
39 //#####DESCRIPTIONBEGIN####
41 // Author(s): Scott Coulter, Jeff Frazier, Eric Breeden
42 // Contributors: Mark Salter
47 //####DESCRIPTIONEND####
49 //===========================================================================*/
51 /*************************************************************************
52 * Memtest.c - this file performs an address/address bar memory test.
54 * Modification History
55 * --------------------
56 * 01sep00 ejb Ported to StrongARM2
59 * 25jan02 Rewritten for RedBoot by Mark Salter
67 // Do walking one's test
70 onesTest(CYG_ADDRWORD *testAddr)
72 CYG_ADDRWORD theOne, dataRead;
73 int fail, loopCount = 0; // To keep track of when to print CR
77 // Loop for all bits in an address
78 for (theOne = 1, fail = 0; theOne && !fail; theOne <<= 1) {
80 testAddr[0] = theOne; // Write test data
81 testAddr[1] = ~0L; // Drive d0-dn hi
82 dataRead = *testAddr; // Read back data
84 diag_printf("%08x%s", dataRead, (++loopCount % 8) ? "" : "\n");
86 if (dataRead != theOne) // Verify data
87 return FAILED; // Signal failure
93 // Do 32-bit word address test
96 Addr32 (cyg_uint32 *start, cyg_uint32 *end, CYG_ADDRWORD *badAddr)
98 cyg_uint32 *currentAddr; /* Current address being tested */
101 for(currentAddr = start; currentAddr <= end; currentAddr++)
102 *currentAddr = (cyg_uint32)(CYG_ADDRWORD)currentAddr;
104 for (currentAddr = start; currentAddr <= end; currentAddr++) {
106 if (data != (cyg_uint32)(CYG_ADDRWORD)currentAddr) {
107 diag_printf ("\n\nBad Read, Address = %p, Data Read = 0x%08x\n\n",
109 *badAddr = (CYG_ADDRWORD)currentAddr;
117 // Do inverse long word address test
120 Bar32 (cyg_uint32 *start, cyg_uint32 *end, CYG_ADDRWORD *badAddr)
122 cyg_uint32 *currentAddr, data;
124 for(currentAddr = start; currentAddr <= end; currentAddr++)
125 *currentAddr = ~(CYG_ADDRWORD)currentAddr;
127 for (currentAddr = start; currentAddr <= end; currentAddr++) {
129 if (data != (~(CYG_ADDRWORD)currentAddr) & 0xffffffff) {
130 diag_printf ("\n\nBad Read, Address = %p, Data Read = 0x%08x\n\n",
132 *badAddr = (CYG_ADDRWORD)currentAddr;
139 // Do byte address test
142 Addr8 (cyg_uint8 *start, cyg_uint8 *end, CYG_ADDRWORD *badAddr)
144 cyg_uint8 *currentAddr; // Current address being tested
146 for (currentAddr = start; currentAddr <= end; currentAddr++)
147 *currentAddr = (cyg_uint8)(CYG_ADDRWORD)currentAddr;
149 for (currentAddr = start; currentAddr <= end; currentAddr++)
150 if (*currentAddr != (cyg_uint8)(CYG_ADDRWORD)currentAddr) {
151 *badAddr = (CYG_ADDRWORD)currentAddr;
157 // Do inverse byte address test
160 Bar8 (cyg_uint8 *start, cyg_uint8 *end, CYG_ADDRWORD *badAddr)
162 cyg_uint8 *currentAddr; // Current address being tested
164 for(currentAddr = start; currentAddr <= end; currentAddr++)
165 *currentAddr = ~(CYG_ADDRWORD)currentAddr;
167 for(currentAddr = start; currentAddr <= end; currentAddr++)
168 if (*currentAddr != (~(CYG_ADDRWORD)currentAddr & 0xff)) {
169 *badAddr = (CYG_ADDRWORD)currentAddr;
175 // This routine is called if one of the memory tests fails. It dumps
176 // the 8 32-bit words before and the 8 after the failure address
179 dumpMem (CYG_ADDRWORD badAddr)
185 // Print out first line of mem dump
186 diag_printf("\n%p: %08x %08x %08x %08x",
187 (char *)badAddr - 32,
188 *(cyg_uint32 *)(badAddr - 32),
189 *(cyg_uint32 *)(badAddr - 28),
190 *(cyg_uint32 *)(badAddr - 24),
191 *(cyg_uint32 *)(badAddr - 20));
193 diag_printf("\n%p: %08x %08x %08x %08x",
194 (char *)badAddr - 16,
195 *(cyg_uint32 *)(badAddr - 16),
196 *(cyg_uint32 *)(badAddr - 12),
197 *(cyg_uint32 *)(badAddr - 8),
198 *(cyg_uint32 *)(badAddr - 4));
200 // Print out contents of fault addr
201 diag_printf("\n%p: %08x",
202 (char *)badAddr, *(cyg_uint32 *)badAddr);
204 diag_printf("\n%p: %08x %08x %08x %08x",
206 *(cyg_uint32 *)(badAddr + 4),
207 *(cyg_uint32 *)(badAddr + 8),
208 *(cyg_uint32 *)(badAddr + 12),
209 *(cyg_uint32 *)(badAddr + 16));
211 diag_printf("\n%p: %08x %08x %08x %08x",
212 (char *)badAddr + 20,
213 *(cyg_uint32 *)(badAddr + 20),
214 *(cyg_uint32 *)(badAddr + 24),
215 *(cyg_uint32 *)(badAddr + 28),
216 *(cyg_uint32 *)(badAddr + 32));
219 diag_printf ("\n\nReading back data in 32bit chunks:\n");
220 for (addr = (cyg_uint32 *)(badAddr - 16), i = 0; i <= 8; i++, addr++)
221 diag_printf ("Address = %p, Data = 0x%08x\n", addr, *addr);
224 diag_printf ("Reading back data in 16bit chunks:\n");
225 for (saddr = (cyg_uint16 *)(badAddr - 16), i = 0; i <= 16; i++, saddr++)
226 diag_printf ("Address = %p, Data = 0x%08x\n", saddr, *saddr);
230 // Returns 1 if passed, 0 if failed.
233 memTest (CYG_ADDRWORD startAddr, CYG_ADDRWORD endAddr)
235 CYG_ADDRWORD badAddr; // Addr test failed at
237 diag_printf("\nWalking 1's test: ");
238 if (onesTest((CYG_ADDRWORD *)startAddr) == FAILED)
240 diag_printf("passed");
242 diag_printf("\n32-bit address test: ");
243 if (Addr32((cyg_uint32 *)startAddr, (cyg_uint32 *)endAddr, &badAddr) == FAILED)
245 diag_printf("passed");
247 diag_printf("\n32-bit address bar test: ");
248 if (Bar32((cyg_uint32 *)startAddr, (cyg_uint32 *)endAddr, &badAddr) == FAILED)
250 diag_printf("passed");
252 diag_printf("\n8-bit address test: ");
253 if (Addr8((cyg_uint8 *)startAddr, (cyg_uint8 *)endAddr, &badAddr) == FAILED)
255 diag_printf("passed");
257 diag_printf("\nByte address bar test: ");
258 if (Bar8((cyg_uint8 *)startAddr, (cyg_uint8 *)endAddr, &badAddr) == FAILED)
260 diag_printf("passed");
265 diag_printf("failed");
272 /* Do alternating inverse long word address test */
274 ABar32(cyg_uint32 *start, /* Starting address of test */
275 cyg_uint32 *end, /* Ending address */
276 CYG_ADDRWORD *badAddr) /* Failure address */
278 register cyg_uint32 *currentAddr; /* Current address being tested */
279 int fail = 0; /* Test hasn't failed yet */
282 /* In this test, the contents of each longword address toggles
283 between the Address and the Address BAR */
284 for(currentAddr = start; currentAddr <= end; currentAddr++) {
286 if ((CYG_ADDRWORD)currentAddr & 4) /* Address ending in 0x4 or 0xc */
287 *currentAddr = ~(cyg_uint32)(CYG_ADDRWORD)currentAddr;
289 else /* Address ending in 0x0 or 0x8 */
290 *currentAddr = (cyg_uint32)(CYG_ADDRWORD)currentAddr;
293 for (currentAddr = start; currentAddr <= end && !fail; currentAddr++) {
296 switch ((CYG_ADDRWORD)currentAddr & 0xf) {
299 if (data != (cyg_uint32)(CYG_ADDRWORD)currentAddr) {
301 diag_printf ("\nFailed at Address %p, Expected 0x%08X, Read 0x%08X\n",
302 currentAddr, (cyg_uint32)(CYG_ADDRWORD)currentAddr, data);
308 if (data != ~(cyg_uint32)(CYG_ADDRWORD)currentAddr) {
310 diag_printf ("\nFailed at Address %p, Expected 0x%08X, Read 0x%08X\n",
311 currentAddr, ~(cyg_uint32)(CYG_ADDRWORD)currentAddr, data);
317 diag_printf ("\nFailed at Address %p, Unaligned address\n", currentAddr);
323 *badAddr = (CYG_ADDRWORD)(--currentAddr);
332 * Returns 1 if passed, 0 if failed.
335 LoopMemTest (CYG_ADDRWORD startAddr, CYG_ADDRWORD endAddr)
337 CYG_ADDRWORD badAddr; /* Addr test failed at */
343 diag_printf("\n32-bit address test: ");
344 if (Addr32((cyg_uint32 *)startAddr, (cyg_uint32 *)endAddr, &badAddr) == FAILED)
346 diag_printf("passed");
348 diag_printf("\n32-bit address bar test: ");
349 if (Bar32((cyg_uint32 *)startAddr, (cyg_uint32 *)endAddr, &badAddr) == FAILED)
351 diag_printf("passed");
353 diag_printf("\nAlternating Long word, Long word address bar test: ");
354 if (ABar32((cyg_uint32 *)startAddr, (cyg_uint32 *)endAddr, &badAddr) == FAILED)
356 diag_printf("passed");
359 diag_printf("failed at Address %p\n", badAddr);
360 diag_printf("Performing Continuous Write/Read/!Write/Read...\n\n");
362 *(volatile int *)badAddr = badAddr;
363 junk = *(volatile int *)badAddr;
364 *(volatile int *)badAddr = ~badAddr;
365 junk = *(volatile int *)badAddr;
368 return 1; // not reached