]> cloudbase.mooo.com Git - z180-stamp.git/blame - avr/cmd_mem.c
z80_bus_request_or_exit()
[z180-stamp.git] / avr / cmd_mem.c
CommitLineData
72f58822 1/*
b35fcb2f 2 * (C) Copyright 2014,2018 Leo C. <erbl259-lmu@yahoo.de>
35edb766 3 *
72f58822
L
4 * (C) Copyright 2000
5 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
6 *
8ed66016 7 * SPDX-License-Identifier: GPL-2.0
72f58822
L
8 */
9
10/*
11 * Memory Functions
12 *
13 * Copied from FADS ROM, Dan Malek (dmalek@jlc.net)
14 */
15
16#include "common.h"
72f58822 17#include <ctype.h>
5480dc65 18#include <avr/interrupt.h>
72f58822 19
72f58822
L
20#include "command.h"
21#include "cli_readline.h"
8f23e84c 22#include "print-utils.h"
72f58822 23#include "con-utils.h"
32154e5a 24#include "getopt-min.h"
fcd2239e 25#include "eval_arg.h"
5480dc65 26#include "timer.h"
72f58822 27#include "z80-if.h"
5480dc65 28#include "debug.h"
72f58822 29
72f58822
L
30
31#ifndef CONFIG_SYS_MEMTEST_SCRATCH
32#define CONFIG_SYS_MEMTEST_SCRATCH 0
33#endif
34
72f58822
L
35/* Display values from last command.
36 * Memory modify remembered values are different from display memory.
37 */
38static uint32_t dp_last_addr;
39static uint32_t dp_last_length = 0x100;
40static uint32_t mm_last_addr;
41
42static uint32_t base_address = 0;
43
44/*--------------------------------------------------------------------------*/
45
b35fcb2f 46static ERRNUM z180_read_buf(uint8_t *buf, uint32_t addr, uint8_t count)
e39cd2a2 47{
d9d8de47 48 if (!(z80_bus_cmd(Request) & ZST_ACQUIRED))
b35fcb2f 49 return EBUSTO;
d9d8de47
L
50
51 z80_read_block (buf, addr, count);
52 z80_bus_cmd(Release);
b35fcb2f 53 return ESUCCESS;
72f58822
L
54}
55
72f58822
L
56/*--------------------------------------------------------------------------*/
57
58/* Memory Display
59 *
60 * Syntax:
61 * md {addr} {len}
62 */
fcf1d5b3 63command_ret_t do_mem_md(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
72f58822
L
64{
65 uint32_t addr, length;
6035a17b 66
72f58822
L
67 (void) cmdtp;
68
6035a17b 69#if 0
72f58822
L
70 printf_P(PSTR("flag: %d, argc: %d"), flag, argc);
71 for (int i = 0; i < argc; i++) {
72 printf_P(PSTR(", argv[%d]: %s"), i, argv[i] ? argv[i] : "<NULL>");
73 }
74 putchar('\n');
75#endif
76
77 /* We use the last specified parameters, unless new ones are
78 * entered.
79 */
80 addr = dp_last_addr;
81 length = dp_last_length;
82
83 if (argc < 2)
84 return CMD_RET_USAGE;
85
86 if ((flag & CMD_FLAG_REPEAT) == 0) {
87 /* Address is specified since argc > 1 */
fcd2239e 88 addr = eval_arg(argv[1], NULL);
72f58822
L
89 addr += base_address;
90
91 /* If another parameter, it is the length to display. */
92 if (argc > 2)
fcd2239e 93 length = eval_arg(argv[2], NULL);
72f58822
L
94 }
95
96 /* Print the lines. */
b35fcb2f
L
97 ERRNUM ret = dump_mem(addr, addr, length, z180_read_buf, NULL);
98 if (ret == EBUSTO)
99 cmd_error(CMD_RET_FAILURE, ret, NULL);
72f58822 100
b35fcb2f 101 if (ret == ESUCCESS) {
d9d8de47
L
102 dp_last_addr = addr + length;
103 dp_last_length = length;
104 }
d0581f88 105 return CMD_RET_SUCCESS;
72f58822
L
106}
107
d0581f88
L
108/* Modify memory.
109 *
110 * Syntax:
111 * mm {addr}
112 * nm {addr}
113 */
114static command_ret_t
fcf1d5b3 115mod_mem(cmd_tbl_t *cmdtp, int incrflag, uint_fast8_t flag, int argc, char * const argv[])
d0581f88
L
116{
117 uint32_t addr;
118 uint8_t data;
119 int nbytes;
120
121 (void) cmdtp;
122
123 if (argc != 2)
124 return CMD_RET_USAGE;
125
126 /* We use the last specified parameters, unless new ones are
127 * entered.
128 */
129 addr = mm_last_addr;
130
131 if ((flag & CMD_FLAG_REPEAT) == 0) {
132 /* New command specified.
133 */
134
135 /* Address is specified since argc > 1
136 */
fcd2239e 137 addr = eval_arg(argv[1], NULL);
d0581f88
L
138 addr += base_address;
139 }
140
141 /* Print the address, followed by value. Then accept input for
142 * the next value. A non-converted value exits.
143 */
144 do {
b35fcb2f 145 z80_bus_request_or_exit();
d0581f88 146 data = z80_read(addr);
d0581f88 147 z80_bus_cmd(Release);
ea6971b8 148 printf_P(PSTR("%05lx: %02x"), addr, data);
d0581f88 149
8ed66016 150 nbytes = cli_readline(PSTR(" ? "), 0);
d0581f88
L
151 if (nbytes == 0 || (nbytes == 1 && console_buffer[0] == '-')) {
152 /* <CR> pressed as only input, don't modify current
153 * location and move to next. "-" pressed will go back.
154 */
155 if (incrflag)
156 addr += nbytes ? -1 : 1;
157 nbytes = 1;
ad9bc17c
L
158
159 } else {
d0581f88 160 char *endp;
fcd2239e 161 data = eval_arg(console_buffer, &endp);
d0581f88
L
162 nbytes = endp - console_buffer;
163 if (nbytes) {
b35fcb2f 164 z80_bus_request_or_exit();
d0581f88
L
165 z80_write(addr, data);
166 z80_bus_cmd(Release);
167 if (incrflag)
168 addr++;
169 }
170 }
13e88ed5 171 } while (nbytes > 0);
d0581f88
L
172
173 mm_last_addr = addr;
174 return CMD_RET_SUCCESS;
175}
176
177
fcf1d5b3 178command_ret_t do_mem_mm(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
72f58822
L
179{
180 return mod_mem (cmdtp, 1, flag, argc, argv);
181}
fcf1d5b3 182command_ret_t do_mem_nm(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
72f58822
L
183{
184 return mod_mem (cmdtp, 0, flag, argc, argv);
185}
186
fcf1d5b3 187command_ret_t do_mem_mw(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
72f58822 188{
32154e5a
L
189 uint32_t writeval;
190 uint32_t addr;
191 uint32_t count = 1;
192 uint_fast8_t width = 1;
193
194 (void) cmdtp; (void) flag;
195
196 /* reset getopt() */
beafa6d6 197 optind = 0;
32154e5a
L
198
199 int opt;
200 while ((opt = getopt(argc, argv, PSTR("bwl"))) != -1) {
201 switch (opt) {
202 case 'b':
203 width = 1;
204 break;
205 case 'w':
206 width = 2;
207 break;
208 case 'l':
209 width = 4;
210 break;
211 default: /* '?' */
212 return CMD_RET_USAGE;
213 }
214 }
72f58822 215
32154e5a
L
216 /* remaining arguments */
217 argc -= optind;
218 if ((argc < 2) || (argc > 3))
72f58822
L
219 return CMD_RET_USAGE;
220
32154e5a 221 /* Address and value are specified since (adjusted) argc >= 2 */
fcd2239e 222 addr = eval_arg(argv[optind++], NULL);
72f58822 223 addr += base_address;
fcd2239e 224 writeval = eval_arg(argv[optind++], NULL);
72f58822
L
225
226 /* Count ? */
32154e5a 227 if (argc == 3)
fcd2239e 228 count = eval_arg(argv[optind], NULL);
72f58822 229
b35fcb2f 230 z80_bus_request_or_exit();
32154e5a
L
231 if (width == 1)
232 z80_memset(addr, writeval, count);
233 else {
234 while (count--) {
235 z80_write_block((const uint8_t *) &writeval, addr, width);
236 addr += width;
237 }
238 }
62f624d3 239 z80_bus_cmd(Release);
72f58822 240
d0581f88 241 return CMD_RET_SUCCESS;
72f58822
L
242}
243
244#ifdef CONFIG_MX_CYCLIC
fcf1d5b3 245command_ret_t do_mem_mdc ( cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
72f58822 246{
72f58822 247 uint32_t count;
5480dc65
L
248 uint32_t ts;
249
250 (void) cmdtp;
251 (void) flag;
72f58822 252
fcd2239e
L
253 optind = 0;
254 if (argv[0][1] != 'd') {
255 int opt;
256 while ((opt = getopt(argc, argv, PSTR("bwl"))) != -1)
257 if (opt == '?')
258 return CMD_RET_USAGE;
259 --optind;
260 }
261
fcd2239e 262 if (argc-optind != 4)
72f58822
L
263 return CMD_RET_USAGE;
264
fcd2239e 265 count = eval_arg(argv[optind + 3], NULL);
72f58822 266
5480dc65 267 clear_ctrlc(); /* forget any previous Control C */
72f58822 268 for (;;) {
72f58822 269
5480dc65 270 if (argv[0][1] == 'd')
fcd2239e 271 do_mem_md (NULL, 0, argc-1, argv); /* memory display */
5480dc65 272 else
fcd2239e 273 do_mem_mw (NULL, 0, argc-1, argv); /* memory write */
72f58822 274
72f58822
L
275
276 /* delay for <count> ms... */
5480dc65
L
277 ts = get_timer(0);
278 do {
279 /* check for ctrl-c to abort... */
280 if (had_ctrlc() || ctrlc()) {
281 my_puts_P(PSTR("Abort\n"));
282 return CMD_RET_SUCCESS;
283 }
284 } while (get_timer(ts) < count);
72f58822
L
285 }
286
d0581f88 287 return CMD_RET_SUCCESS;
72f58822
L
288}
289#endif /* CONFIG_MX_CYCLIC */
290
fcf1d5b3 291command_ret_t do_mem_cmp(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
72f58822
L
292{
293 uint32_t addr1, addr2, count, ngood;
d0581f88 294 command_ret_t rcode = CMD_RET_SUCCESS;
72f58822
L
295 uint8_t byte1, byte2;
296
297 (void) cmdtp;
298 (void) flag;
299
300 if (argc != 4)
301 return CMD_RET_USAGE;
302
303
fcd2239e 304 addr1 = eval_arg(argv[1], NULL);
72f58822 305 addr1 += base_address;
fcd2239e 306 addr2 = eval_arg(argv[2], NULL);
72f58822 307 addr2 += base_address;
fcd2239e 308 count = eval_arg(argv[3], NULL);
72f58822
L
309
310 for (ngood = 0; ngood < count; ++ngood) {
ea6971b8
L
311 if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) {
312 my_puts_P(PSTR("Bus timeout\n"));
313 rcode = CMD_RET_FAILURE;
314 break;
315 }
72f58822
L
316 byte1 = z80_read(addr1);
317 byte2 = z80_read(addr2);
62f624d3 318 z80_bus_cmd(Release);
72f58822 319 if (byte1 != byte2) {
6035a17b
L
320 printf_P(PSTR("byte at 0x%05lx (%#02x) != "
321 "byte at 0x%05lx (%#02x)\n"),
72f58822 322 addr1, byte1, addr2, byte2);
d0581f88 323 rcode = CMD_RET_FAILURE;
72f58822
L
324 break;
325 }
326 addr1++;
327 addr2++;
328
329 /* check for ctrl-c to abort... */
330 if (ctrlc()) {
69988dc1 331 my_puts_P(PSTR("Abort\n"));
d0581f88 332 return CMD_RET_SUCCESS;
72f58822
L
333 }
334 }
335
69988dc1 336 printf_P(PSTR("Total of %ld byte(s) (0x%lx) were the same\n"), ngood, ngood);
72f58822
L
337 return rcode;
338}
339
fcf1d5b3 340command_ret_t do_mem_cp(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
72f58822
L
341{
342 uint32_t src, dest, count;
343 int_fast8_t step;
344
345 (void) cmdtp;
346 (void) flag;
347
348 if (argc != 4)
349 return CMD_RET_USAGE;
350
fcd2239e 351 src = eval_arg(argv[1], NULL);
72f58822 352 src += base_address;
fcd2239e 353 dest = eval_arg(argv[2], NULL);
72f58822 354 dest += base_address;
fcd2239e 355 count = eval_arg(argv[3], NULL);
72f58822
L
356
357 if (count == 0) {
69988dc1 358 my_puts_P(PSTR("Zero length?\n"));
d0581f88 359 return CMD_RET_FAILURE;
72f58822 360 }
6035a17b 361
72f58822
L
362 if (dest > src) {
363 src += count - 1;
364 dest += count - 1;
365 step = -1;
366 } else
367 step = 1;
368
369 while (count-- > 0) {
370 uint8_t data;
b35fcb2f 371 z80_bus_request_or_exit();
72f58822
L
372 data = z80_read(src);
373 z80_write(dest, data);
62f624d3 374 z80_bus_cmd(Release);
72f58822
L
375 src += step;
376 dest += step;
377
378 /* check for ctrl-c to abort... */
379 if (ctrlc()) {
69988dc1 380 my_puts_P(PSTR("Abort\n"));
d0581f88 381 return CMD_RET_SUCCESS;
72f58822
L
382 }
383 }
d0581f88 384 return CMD_RET_SUCCESS;
72f58822
L
385}
386
fcf1d5b3 387command_ret_t do_mem_base(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc,
72f58822
L
388 char * const argv[])
389{
390 (void) cmdtp;
391 (void) flag;
392
393 if (argc > 1) {
394 /* Set new base address. */
fcd2239e 395 base_address = eval_arg(argv[1], NULL);
72f58822
L
396 }
397 /* Print the current base address. */
69988dc1 398 printf_P(PSTR("Base Address: 0x%05lx\n"), base_address);
d0581f88 399 return CMD_RET_SUCCESS;
72f58822
L
400}
401
fcf1d5b3 402command_ret_t do_mem_loop(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc,
72f58822
L
403 char * const argv[])
404{
405 uint32_t addr, length;
406
407 (void) cmdtp;
408 (void) flag;
409
410 if (argc < 3)
411 return CMD_RET_USAGE;
412
413 /* Address is always specified. */
fcd2239e 414 addr = eval_arg(argv[1], NULL);
72f58822
L
415
416 /* Length is the number of bytes. */
fcd2239e 417 length = eval_arg(argv[2], NULL);
72f58822
L
418
419
420 /* We want to optimize the loops to run as fast as possible.
421 * If we have only one object, just run infinite loops.
422 */
423 if (length == 1) {
b35fcb2f 424 z80_bus_request_or_exit();
5480dc65 425 cli();
72f58822
L
426 for (;;)
427 z80_read(addr);
72f58822
L
428 }
429
b35fcb2f 430 z80_bus_request_or_exit();
5480dc65 431 cli();
72f58822
L
432 for (;;) {
433 uint32_t i = length;
434 uint32_t p = addr;
435 while (i-- > 0)
436 z80_read(p++);
437 }
72f58822 438
d0581f88 439 return CMD_RET_SUCCESS;
72f58822
L
440}
441
fcf1d5b3 442command_ret_t do_mem_loopw (cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
72f58822
L
443{
444 uint32_t addr, length;
445 uint8_t data;
446
447 (void) cmdtp;
448 (void) flag;
449
450 if (argc < 4)
451 return CMD_RET_USAGE;
452
453 /* Address is always specified. */
fcd2239e 454 addr = eval_arg(argv[1], NULL);
72f58822
L
455
456 /* Length is the number of bytes. */
fcd2239e 457 length = eval_arg(argv[2], NULL);
72f58822 458
fcd2239e 459 data = eval_arg(argv[3], NULL);
72f58822 460
5480dc65
L
461 /*
462 * We want to optimize the loops to run as fast as possible.
72f58822
L
463 * If we have only one object, just run infinite loops.
464 */
465 if (length == 1) {
b35fcb2f 466 z80_bus_request_or_exit();
5480dc65 467 cli();
72f58822
L
468 for (;;)
469 z80_write(addr, data);
470 }
471
b35fcb2f 472 z80_bus_request_or_exit();
5480dc65 473 cli();
72f58822
L
474 for (;;) {
475 uint32_t i = length;
476 uint32_t p = addr;
477 while (i-- > 0)
478 z80_write(p++, data);
479 }
480}
5480dc65
L
481
482//#define CONFIG_SYS_ALT_MEMTEST
72f58822
L
483
484#ifdef CONFIG_CMD_MEMTEST
5480dc65 485static uint32_t mem_test_alt(uint32_t start_addr, uint32_t end_addr)
72f58822 486{
5480dc65
L
487 uint32_t addr;
488 uint32_t dummy;
72f58822 489 uint32_t errs = 0;
5480dc65
L
490 uint32_t offset;
491 uint32_t test_offset;
492 uint8_t pattern;
493 uint8_t anti_pattern;
494 uint8_t temp;
495 uint32_t num_bytes;
496
497 static const FLASH uint8_t bitpattern[] = {
498 0x01, /* single bit */
499 0x03, /* two adjacent bits */
500 0x07, /* three adjacent bits */
501 0x0F, /* four adjacent bits */
502 0x05, /* two non-adjacent bits */
503 0x15, /* three non-adjacent bits */
504 0x55, /* four non-adjacent bits */
505 0xaa, /* alternating 1/0 */
72f58822
L
506 };
507
72f58822
L
508 /*
509 * Data line test: write a pattern to the first
510 * location, write the 1's complement to a 'parking'
511 * address (changes the state of the data bus so a
512 * floating bus doesn't give a false OK), and then
513 * read the value back. Note that we read it back
514 * into a variable because the next time we read it,
515 * it might be right (been there, tough to explain to
516 * the quality guys why it prints a failure when the
517 * "is" and "should be" are obviously the same in the
518 * error message).
519 *
520 * Rather than exhaustively testing, we test some
521 * patterns by shifting '1' bits through a field of
522 * '0's and '0' bits through a field of '1's (i.e.
523 * pattern and ~pattern).
524 */
5480dc65
L
525 addr = start_addr;
526 dummy = start_addr+1;
527 for (unsigned int j = 0; j < ARRAY_SIZE(bitpattern); j++) {
528 pattern = bitpattern[j];
529 for (; pattern != 0; pattern <<= 1) {
530 anti_pattern = ~pattern;
531 z80_write(addr, pattern);
532 z80_write(dummy, anti_pattern); /* clear the test data off the bus */
533 temp = z80_read(addr);
534 if (temp != pattern) {
69988dc1 535 printf_P(PSTR("FAILURE (data line): "
5480dc65
L
536 "expected %02x, actual %02x\n"),
537 pattern, temp);
72f58822 538 errs++;
72f58822 539 }
5480dc65
L
540 z80_write(addr, anti_pattern);
541 z80_write(dummy, pattern); /* clear the test data off the bus */
542 temp = z80_read(addr);
543 if (temp != anti_pattern) {
69988dc1 544 printf_P(PSTR("FAILURE (data line): "
5480dc65
L
545 "Is %02x, should be %02x\n"),
546 temp, anti_pattern);
72f58822 547 errs++;
72f58822
L
548 }
549 }
5480dc65
L
550
551 if (ctrlc())
552 return -1;
72f58822
L
553 }
554
5480dc65
L
555 if (errs)
556 return errs;
557
72f58822
L
558 /*
559 * Based on code whose Original Author and Copyright
560 * information follows: Copyright (c) 1998 by Michael
561 * Barr. This software is placed into the public
562 * domain and may be used for any purpose. However,
563 * this notice must not be changed or removed and no
564 * warranty is either expressed or implied by its
565 * publication or distribution.
566 */
567
568 /*
569 * Address line test
570
571 * Description: Test the address bus wiring in a
572 * memory region by performing a walking
573 * 1's test on the relevant bits of the
574 * address and checking for aliasing.
575 * This test will find single-bit
576 * address failures such as stuck-high,
577 * stuck-low, and shorted pins. The base
578 * address and size of the region are
579 * selected by the caller.
580
581 * Notes: For best results, the selected base
582 * address should have enough LSB 0's to
583 * guarantee single address bit changes.
584 * For example, to test a 64-Kbyte
585 * region, select a base address on a
586 * 64-Kbyte boundary. Also, select the
587 * region size as a power-of-two if at
588 * all possible.
589 *
590 * Returns: 0 if the test succeeds, 1 if the test fails.
591 */
72f58822 592
5480dc65
L
593 num_bytes = (end_addr - start_addr) / sizeof(uint8_t);
594
595 pattern = 0xaa;
596 anti_pattern = 0x55;
597
598// debug("## %s:%d: length = 0x%.5lx\n", __func__, __LINE__, num_bytes);
72f58822
L
599 /*
600 * Write the default pattern at each of the
601 * power-of-two offsets.
602 */
5480dc65
L
603 for (offset = 1; offset < num_bytes; offset <<= 1)
604 z80_write(addr+offset, pattern);
72f58822
L
605
606 /*
607 * Check for address bits stuck high.
608 */
5480dc65 609 z80_write(start_addr, anti_pattern);
72f58822 610
5480dc65
L
611 for (offset = 1; offset < num_bytes; offset <<= 1) {
612 temp = z80_read(start_addr + offset);
72f58822 613 if (temp != pattern) {
5480dc65
L
614 printf_P(PSTR("FAILURE: Address bit stuck high @ 0x%.5lx:"
615 " expected 0x%.2x, actual 0x%.2x\n"),
616 start_addr + offset, pattern, temp);
72f58822
L
617 errs++;
618 if (ctrlc())
619 return -1;
620 }
621 }
5480dc65 622 z80_write(start_addr, pattern);
72f58822
L
623
624 /*
625 * Check for addr bits stuck low or shorted.
626 */
5480dc65
L
627 for (test_offset = 1; test_offset < num_bytes; test_offset <<= 1) {
628 z80_write(start_addr + test_offset, anti_pattern);
72f58822 629
5480dc65
L
630 for (offset = 1; offset < num_bytes; offset <<= 1) {
631 temp = z80_read(start_addr + offset);
72f58822 632 if ((temp != pattern) && (offset != test_offset)) {
5480dc65
L
633 printf_P(PSTR("FAILURE: Address bit stuck low or shorted"
634 " @ 0x%.5lx: expected 0x%.2x, actual 0x%.2x\n"),
635 start_addr + offset, pattern, temp);
72f58822
L
636 errs++;
637 if (ctrlc())
638 return -1;
639 }
640 }
5480dc65 641 z80_write(start_addr + test_offset, pattern);
72f58822
L
642 }
643
5480dc65
L
644 if (errs)
645 return errs;
646
72f58822
L
647 /*
648 * Description: Test the integrity of a physical
649 * memory device by performing an
650 * increment/decrement test over the
651 * entire region. In the process every
652 * storage bit in the device is tested
653 * as a zero and a one. The base address
654 * and the size of the region are
655 * selected by the caller.
656 *
657 * Returns: 0 if the test succeeds, 1 if the test fails.
658 */
5480dc65 659 num_bytes++;
72f58822
L
660
661 /*
662 * Fill memory with a known pattern.
663 */
5480dc65
L
664 for (pattern = 1, addr = start_addr; addr <= end_addr; pattern++, addr++)
665 z80_write(addr, pattern);
72f58822
L
666
667 /*
668 * Check each location and invert it for the second pass.
669 */
5480dc65
L
670 for (pattern = 1, addr = start_addr; addr <= end_addr; pattern++, addr++) {
671 temp = z80_read(addr);
72f58822 672 if (temp != pattern) {
5480dc65
L
673 printf_P(PSTR("FAILURE (read/write) @ 0x%.5lx:"
674 " expected 0x%.2x, actual 0x%.2x)\n"),
675 addr, pattern, temp);
72f58822
L
676 errs++;
677 if (ctrlc())
678 return -1;
679 }
680
681 anti_pattern = ~pattern;
5480dc65 682 z80_write(addr, anti_pattern);
72f58822
L
683 }
684
685 /*
686 * Check each location for the inverted pattern and zero it.
687 */
5480dc65 688 for (pattern = 1, addr = start_addr; addr <= end_addr; pattern++, addr++) {
72f58822 689 anti_pattern = ~pattern;
5480dc65 690 temp = z80_read(addr);
72f58822 691 if (temp != anti_pattern) {
5480dc65
L
692 printf_P(PSTR("FAILURE (read/write) @ 0x%.5lx:"
693 " expected 0x%.2x, actual 0x%.2x)\n"),
694 start_addr, anti_pattern, temp);
72f58822
L
695 errs++;
696 if (ctrlc())
697 return -1;
698 }
5480dc65 699 z80_write(addr, 0);
72f58822
L
700 }
701
5480dc65 702 return errs;
72f58822
L
703}
704
705/*
706 * Perform a memory test. A more complete alternative test can be
707 * configured using CONFIG_SYS_ALT_MEMTEST. The complete test loops until
708 * interrupted by ctrl-c or by a failure of one of the sub-tests.
709 */
fcf1d5b3 710command_ret_t do_mem_mtest(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc,
72f58822
L
711 char * const argv[])
712{
5480dc65
L
713 uint32_t start = 0;
714 uint32_t end;
715 unsigned int iteration_limit = 0;
716 unsigned int iteration;
717 uint32_t errs = 0; /* number of errors */
72f58822 718 int ret;
5480dc65
L
719
720 (void) cmdtp;
721 (void) flag;
72f58822
L
722
723 if (argc > 1)
fcd2239e 724 start = eval_arg(argv[1], NULL);
72f58822
L
725
726 if (argc > 2)
fcd2239e 727 end = eval_arg(argv[2], NULL);
72f58822 728 else
5480dc65 729 end = CONFIG_SYS_RAMSIZE_MAX - 1;
72f58822
L
730
731 if (argc > 3)
fcd2239e 732 iteration_limit = (unsigned int) eval_arg(argv[3], NULL);
72f58822 733
5480dc65
L
734 printf_P(PSTR("Testing %05lx ... %05lx:\n"), start, end);
735// debug("## %s:%d: start %#05lx end %#05lx\n", __func__, __LINE__, start, end);
72f58822 736
5480dc65 737 clear_ctrlc(); /* forget any previous Control C */
72f58822 738
72f58822
L
739 for (iteration = 0;
740 !iteration_limit || iteration < iteration_limit;
741 iteration++) {
72f58822 742
69988dc1 743 printf_P(PSTR("Iteration: %6d\r"), iteration + 1);
5480dc65
L
744// debug("\n");
745
b35fcb2f 746 z80_bus_request_or_exit();
5480dc65
L
747 errs += mem_test_alt(start, end);
748 z80_bus_cmd(Release);
749
750 if (had_ctrlc() || ctrlc()) {
72f58822 751 break;
5480dc65 752 }
72f58822
L
753 }
754
5480dc65 755 if (had_ctrlc()) {
72f58822 756 /* Memory test was aborted - write a newline to finish off */
5480dc65
L
757 putchar('\n');
758 ret = CMD_RET_FAILURE;
72f58822 759 } else {
69988dc1 760 printf_P(PSTR("Tested %d iteration(s) with %lu errors.\n"),
72f58822 761 iteration, errs);
5480dc65 762 ret = errs ? CMD_RET_FAILURE : CMD_RET_SUCCESS;
72f58822
L
763 }
764
5480dc65 765 return ret;
72f58822
L
766}
767#endif /* CONFIG_CMD_MEMTEST */