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