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