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