]>
cloudbase.mooo.com Git - z180-stamp.git/blob - avr/cmd_mem.c
9adee72e7cace6501cf89341c083df8010b5970d
2 * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de>
5 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
7 * SPDX-License-Identifier: GPL-2.0
13 * Copied from FADS ROM, Dan Malek (dmalek@jlc.net)
19 #include <avr/interrupt.h>
22 #include "cli_readline.h"
23 #include "print-utils.h"
24 #include "con-utils.h"
25 #include "getopt-min.h"
31 #ifndef CONFIG_SYS_MEMTEST_SCRATCH
32 #define CONFIG_SYS_MEMTEST_SCRATCH 0
35 /* Display values from last command.
36 * Memory modify remembered values are different from display memory.
38 static uint32_t dp_last_addr
;
39 static uint32_t dp_last_length
= 0x100;
40 static uint32_t mm_last_addr
;
42 static uint32_t base_address
= 0;
44 /*--------------------------------------------------------------------------*/
46 int z180_read_buf(uint8_t *buf
, uint32_t addr
, uint8_t count
)
48 if (!(z80_bus_cmd(Request
) & ZST_ACQUIRED
))
51 z80_read_block (buf
, addr
, count
);
56 /*--------------------------------------------------------------------------*/
63 command_ret_t
do_mem_md(cmd_tbl_t
*cmdtp
, int flag
, int argc
, char * const argv
[])
65 uint32_t addr
, length
;
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>");
77 /* We use the last specified parameters, unless new ones are
81 length
= dp_last_length
;
86 if ((flag
& CMD_FLAG_REPEAT
) == 0) {
87 /* Address is specified since argc > 1 */
88 addr
= strtoul(argv
[1], NULL
, 16);
91 /* If another parameter, it is the length to display. */
93 length
= strtoul(argv
[2], NULL
, 16);
96 /* Print the lines. */
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
;
104 dp_last_addr
= addr
+ length
;
105 dp_last_length
= length
;
107 return CMD_RET_SUCCESS
;
117 mod_mem(cmd_tbl_t
*cmdtp
, int incrflag
, int flag
, int argc
, char * const argv
[])
126 return CMD_RET_USAGE
;
128 /* We use the last specified parameters, unless new ones are
133 if ((flag
& CMD_FLAG_REPEAT
) == 0) {
134 /* New command specified.
137 /* Address is specified since argc > 1
139 addr
= strtoul(argv
[1], NULL
, 16);
140 addr
+= base_address
;
143 /* Print the address, followed by value. Then accept input for
144 * the next value. A non-converted value exits.
147 if (!(z80_bus_cmd(Request
) & ZST_ACQUIRED
)) {
148 my_puts_P(PSTR("Bus timeout\n"));
149 return CMD_RET_FAILURE
;
151 data
= z80_read(addr
);
152 z80_bus_cmd(Release
);
153 printf_P(PSTR("%05lx: %02x"), addr
, data
);
155 nbytes
= cli_readline(PSTR(" ? "), 0);
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.
161 addr
+= nbytes
? -1 : 1;
166 data
= strtoul(console_buffer
, &endp
, 16);
167 nbytes
= endp
- console_buffer
;
169 if (!(z80_bus_cmd(Request
) & ZST_ACQUIRED
)) {
170 my_puts_P(PSTR("Bus timeout\n"));
171 return CMD_RET_FAILURE
;
173 z80_write(addr
, data
);
174 z80_bus_cmd(Release
);
182 return CMD_RET_SUCCESS
;
186 command_ret_t
do_mem_mm(cmd_tbl_t
*cmdtp
, int flag
, int argc
, char * const argv
[])
188 return mod_mem (cmdtp
, 1, flag
, argc
, argv
);
190 command_ret_t
do_mem_nm(cmd_tbl_t
*cmdtp
, int flag
, int argc
, char * const argv
[])
192 return mod_mem (cmdtp
, 0, flag
, argc
, argv
);
195 command_ret_t
do_mem_mw(cmd_tbl_t
*cmdtp
, int flag
, int argc
, char * const argv
[])
200 uint_fast8_t width
= 1;
202 (void) cmdtp
; (void) flag
;
208 while ((opt
= getopt(argc
, argv
, PSTR("bwl"))) != -1) {
220 return CMD_RET_USAGE
;
224 /* remaining arguments */
226 if ((argc
< 2) || (argc
> 3))
227 return CMD_RET_USAGE
;
229 /* Address and value are specified since (adjusted) argc >= 2 */
230 addr
= strtoul(argv
[optind
++], NULL
, 16);
231 addr
+= base_address
;
232 writeval
= strtoul(argv
[optind
++], NULL
, 16);
236 count
= strtoul(argv
[optind
], NULL
, 16);
238 if (!(z80_bus_cmd(Request
) & ZST_ACQUIRED
)) {
239 my_puts_P(PSTR("Bus timeout\n"));
240 return CMD_RET_FAILURE
;
244 z80_memset(addr
, writeval
, count
);
247 z80_write_block((const uint8_t *) &writeval
, addr
, width
);
251 z80_bus_cmd(Release
);
253 return CMD_RET_SUCCESS
;
256 #ifdef CONFIG_MX_CYCLIC
257 command_ret_t
do_mem_mdc ( cmd_tbl_t
*cmdtp
, int flag
, int argc
, char * const argv
[])
266 return CMD_RET_USAGE
;
268 count
= strtoul(argv
[3], NULL
, 10);
270 clear_ctrlc(); /* forget any previous Control C */
273 if (argv
[0][1] == 'd')
274 do_mem_md (NULL
, 0, 3, argv
);
276 do_mem_mw (NULL
, 0, 3, argv
);
279 /* delay for <count> ms... */
282 /* check for ctrl-c to abort... */
283 if (had_ctrlc() || ctrlc()) {
284 my_puts_P(PSTR("Abort\n"));
285 return CMD_RET_SUCCESS
;
287 } while (get_timer(ts
) < count
);
290 return CMD_RET_SUCCESS
;
292 #endif /* CONFIG_MX_CYCLIC */
294 command_ret_t
do_mem_cmp(cmd_tbl_t
*cmdtp
, int flag
, int argc
, char * const argv
[])
296 uint32_t addr1
, addr2
, count
, ngood
;
297 command_ret_t rcode
= CMD_RET_SUCCESS
;
298 uint8_t byte1
, byte2
;
304 return CMD_RET_USAGE
;
307 addr1
= strtoul(argv
[1], NULL
, 16);
308 addr1
+= base_address
;
309 addr2
= strtoul(argv
[2], NULL
, 16);
310 addr2
+= base_address
;
311 count
= strtoul(argv
[3], NULL
, 16);
313 for (ngood
= 0; ngood
< count
; ++ngood
) {
314 if (!(z80_bus_cmd(Request
) & ZST_ACQUIRED
)) {
315 my_puts_P(PSTR("Bus timeout\n"));
316 rcode
= CMD_RET_FAILURE
;
319 byte1
= z80_read(addr1
);
320 byte2
= z80_read(addr2
);
321 z80_bus_cmd(Release
);
322 if (byte1
!= byte2
) {
323 printf_P(PSTR("byte at 0x%05lx (%#02x) != "
324 "byte at 0x%05lx (%#02x)\n"),
325 addr1
, byte1
, addr2
, byte2
);
326 rcode
= CMD_RET_FAILURE
;
332 /* check for ctrl-c to abort... */
334 my_puts_P(PSTR("Abort\n"));
335 return CMD_RET_SUCCESS
;
339 printf_P(PSTR("Total of %ld byte(s) (0x%lx) were the same\n"), ngood
, ngood
);
343 command_ret_t
do_mem_cp(cmd_tbl_t
*cmdtp
, int flag
, int argc
, char * const argv
[])
345 uint32_t src
, dest
, count
;
352 return CMD_RET_USAGE
;
354 src
= strtoul(argv
[1], NULL
, 16);
356 dest
= strtoul(argv
[2], NULL
, 16);
357 dest
+= base_address
;
358 count
= strtoul(argv
[3], NULL
, 16);
361 my_puts_P(PSTR("Zero length?\n"));
362 return CMD_RET_FAILURE
;
372 while (count
-- > 0) {
374 if (!(z80_bus_cmd(Request
) & ZST_ACQUIRED
)) {
375 my_puts_P(PSTR("Bus timeout\n"));
376 return CMD_RET_FAILURE
;
378 data
= z80_read(src
);
379 z80_write(dest
, data
);
380 z80_bus_cmd(Release
);
384 /* check for ctrl-c to abort... */
386 my_puts_P(PSTR("Abort\n"));
387 return CMD_RET_SUCCESS
;
390 return CMD_RET_SUCCESS
;
393 command_ret_t
do_mem_base(cmd_tbl_t
*cmdtp
, int flag
, int argc
,
400 /* Set new base address. */
401 base_address
= strtoul(argv
[1], NULL
, 16);
403 /* Print the current base address. */
404 printf_P(PSTR("Base Address: 0x%05lx\n"), base_address
);
405 return CMD_RET_SUCCESS
;
408 command_ret_t
do_mem_loop(cmd_tbl_t
*cmdtp
, int flag
, int argc
,
411 uint32_t addr
, length
;
417 return CMD_RET_USAGE
;
419 /* Address is always specified. */
420 addr
= strtoul(argv
[1], NULL
, 16);
422 /* Length is the number of bytes. */
423 length
= strtoul(argv
[2], NULL
, 16);
426 /* We want to optimize the loops to run as fast as possible.
427 * If we have only one object, just run infinite loops.
430 if (!(z80_bus_cmd(Request
) & ZST_ACQUIRED
)) {
431 my_puts_P(PSTR("Bus timeout\n"));
432 return CMD_RET_FAILURE
;
439 if (!(z80_bus_cmd(Request
) & ZST_ACQUIRED
)) {
440 my_puts_P(PSTR("Bus timeout\n"));
441 return CMD_RET_FAILURE
;
451 return CMD_RET_SUCCESS
;
454 command_ret_t
do_mem_loopw (cmd_tbl_t
*cmdtp
, int flag
, int argc
, char * const argv
[])
456 uint32_t addr
, length
;
463 return CMD_RET_USAGE
;
465 /* Address is always specified. */
466 addr
= strtoul(argv
[1], NULL
, 16);
468 /* Length is the number of bytes. */
469 length
= strtoul(argv
[2], NULL
, 16);
471 data
= strtoul(argv
[3], NULL
, 16);
474 * We want to optimize the loops to run as fast as possible.
475 * If we have only one object, just run infinite loops.
478 if (!(z80_bus_cmd(Request
) & ZST_ACQUIRED
)) {
479 my_puts_P(PSTR("Bus timeout\n"));
480 return CMD_RET_FAILURE
;
484 z80_write(addr
, data
);
487 if (!(z80_bus_cmd(Request
) & ZST_ACQUIRED
)) {
488 my_puts_P(PSTR("Bus timeout\n"));
489 return CMD_RET_FAILURE
;
496 z80_write(p
++, data
);
500 //#define CONFIG_SYS_ALT_MEMTEST
502 #ifdef CONFIG_CMD_MEMTEST
503 static uint32_t mem_test_alt(uint32_t start_addr
, uint32_t end_addr
)
509 uint32_t test_offset
;
511 uint8_t anti_pattern
;
515 static const FLASH
uint8_t bitpattern
[] = {
516 0x01, /* single bit */
517 0x03, /* two adjacent bits */
518 0x07, /* three adjacent bits */
519 0x0F, /* four adjacent bits */
520 0x05, /* two non-adjacent bits */
521 0x15, /* three non-adjacent bits */
522 0x55, /* four non-adjacent bits */
523 0xaa, /* alternating 1/0 */
527 * Data line test: write a pattern to the first
528 * location, write the 1's complement to a 'parking'
529 * address (changes the state of the data bus so a
530 * floating bus doesn't give a false OK), and then
531 * read the value back. Note that we read it back
532 * into a variable because the next time we read it,
533 * it might be right (been there, tough to explain to
534 * the quality guys why it prints a failure when the
535 * "is" and "should be" are obviously the same in the
538 * Rather than exhaustively testing, we test some
539 * patterns by shifting '1' bits through a field of
540 * '0's and '0' bits through a field of '1's (i.e.
541 * pattern and ~pattern).
544 dummy
= start_addr
+1;
545 for (unsigned int j
= 0; j
< ARRAY_SIZE(bitpattern
); j
++) {
546 pattern
= bitpattern
[j
];
547 for (; pattern
!= 0; pattern
<<= 1) {
548 anti_pattern
= ~pattern
;
549 z80_write(addr
, pattern
);
550 z80_write(dummy
, anti_pattern
); /* clear the test data off the bus */
551 temp
= z80_read(addr
);
552 if (temp
!= pattern
) {
553 printf_P(PSTR("FAILURE (data line): "
554 "expected %02x, actual %02x\n"),
558 z80_write(addr
, anti_pattern
);
559 z80_write(dummy
, pattern
); /* clear the test data off the bus */
560 temp
= z80_read(addr
);
561 if (temp
!= anti_pattern
) {
562 printf_P(PSTR("FAILURE (data line): "
563 "Is %02x, should be %02x\n"),
577 * Based on code whose Original Author and Copyright
578 * information follows: Copyright (c) 1998 by Michael
579 * Barr. This software is placed into the public
580 * domain and may be used for any purpose. However,
581 * this notice must not be changed or removed and no
582 * warranty is either expressed or implied by its
583 * publication or distribution.
589 * Description: Test the address bus wiring in a
590 * memory region by performing a walking
591 * 1's test on the relevant bits of the
592 * address and checking for aliasing.
593 * This test will find single-bit
594 * address failures such as stuck-high,
595 * stuck-low, and shorted pins. The base
596 * address and size of the region are
597 * selected by the caller.
599 * Notes: For best results, the selected base
600 * address should have enough LSB 0's to
601 * guarantee single address bit changes.
602 * For example, to test a 64-Kbyte
603 * region, select a base address on a
604 * 64-Kbyte boundary. Also, select the
605 * region size as a power-of-two if at
608 * Returns: 0 if the test succeeds, 1 if the test fails.
611 num_bytes
= (end_addr
- start_addr
) / sizeof(uint8_t);
616 // debug("## %s:%d: length = 0x%.5lx\n", __func__, __LINE__, num_bytes);
618 * Write the default pattern at each of the
619 * power-of-two offsets.
621 for (offset
= 1; offset
< num_bytes
; offset
<<= 1)
622 z80_write(addr
+offset
, pattern
);
625 * Check for address bits stuck high.
627 z80_write(start_addr
, anti_pattern
);
629 for (offset
= 1; offset
< num_bytes
; offset
<<= 1) {
630 temp
= z80_read(start_addr
+ offset
);
631 if (temp
!= pattern
) {
632 printf_P(PSTR("FAILURE: Address bit stuck high @ 0x%.5lx:"
633 " expected 0x%.2x, actual 0x%.2x\n"),
634 start_addr
+ offset
, pattern
, temp
);
640 z80_write(start_addr
, pattern
);
643 * Check for addr bits stuck low or shorted.
645 for (test_offset
= 1; test_offset
< num_bytes
; test_offset
<<= 1) {
646 z80_write(start_addr
+ test_offset
, anti_pattern
);
648 for (offset
= 1; offset
< num_bytes
; offset
<<= 1) {
649 temp
= z80_read(start_addr
+ offset
);
650 if ((temp
!= pattern
) && (offset
!= test_offset
)) {
651 printf_P(PSTR("FAILURE: Address bit stuck low or shorted"
652 " @ 0x%.5lx: expected 0x%.2x, actual 0x%.2x\n"),
653 start_addr
+ offset
, pattern
, temp
);
659 z80_write(start_addr
+ test_offset
, pattern
);
666 * Description: Test the integrity of a physical
667 * memory device by performing an
668 * increment/decrement test over the
669 * entire region. In the process every
670 * storage bit in the device is tested
671 * as a zero and a one. The base address
672 * and the size of the region are
673 * selected by the caller.
675 * Returns: 0 if the test succeeds, 1 if the test fails.
680 * Fill memory with a known pattern.
682 for (pattern
= 1, addr
= start_addr
; addr
<= end_addr
; pattern
++, addr
++)
683 z80_write(addr
, pattern
);
686 * Check each location and invert it for the second pass.
688 for (pattern
= 1, addr
= start_addr
; addr
<= end_addr
; pattern
++, addr
++) {
689 temp
= z80_read(addr
);
690 if (temp
!= pattern
) {
691 printf_P(PSTR("FAILURE (read/write) @ 0x%.5lx:"
692 " expected 0x%.2x, actual 0x%.2x)\n"),
693 addr
, pattern
, temp
);
699 anti_pattern
= ~pattern
;
700 z80_write(addr
, anti_pattern
);
704 * Check each location for the inverted pattern and zero it.
706 for (pattern
= 1, addr
= start_addr
; addr
<= end_addr
; pattern
++, addr
++) {
707 anti_pattern
= ~pattern
;
708 temp
= z80_read(addr
);
709 if (temp
!= anti_pattern
) {
710 printf_P(PSTR("FAILURE (read/write) @ 0x%.5lx:"
711 " expected 0x%.2x, actual 0x%.2x)\n"),
712 start_addr
, anti_pattern
, temp
);
724 * Perform a memory test. A more complete alternative test can be
725 * configured using CONFIG_SYS_ALT_MEMTEST. The complete test loops until
726 * interrupted by ctrl-c or by a failure of one of the sub-tests.
728 command_ret_t
do_mem_mtest(cmd_tbl_t
*cmdtp
, int flag
, int argc
,
733 unsigned int iteration_limit
= 0;
734 unsigned int iteration
;
735 uint32_t errs
= 0; /* number of errors */
742 start
= strtoul(argv
[1], NULL
, 16);
745 end
= strtoul(argv
[2], NULL
, 16);
747 end
= CONFIG_SYS_RAMSIZE_MAX
- 1;
750 iteration_limit
= (unsigned int) strtoul(argv
[3], NULL
, 16);
752 printf_P(PSTR("Testing %05lx ... %05lx:\n"), start
, end
);
753 // debug("## %s:%d: start %#05lx end %#05lx\n", __func__, __LINE__, start, end);
755 clear_ctrlc(); /* forget any previous Control C */
758 !iteration_limit
|| iteration
< iteration_limit
;
761 printf_P(PSTR("Iteration: %6d\r"), iteration
+ 1);
764 if (!(z80_bus_cmd(Request
) & ZST_ACQUIRED
)) {
765 my_puts_P(PSTR("Bus timeout\n"));
766 return CMD_RET_FAILURE
;
768 errs
+= mem_test_alt(start
, end
);
769 z80_bus_cmd(Release
);
771 if (had_ctrlc() || ctrlc()) {
777 /* Memory test was aborted - write a newline to finish off */
779 ret
= CMD_RET_FAILURE
;
781 printf_P(PSTR("Tested %d iteration(s) with %lu errors.\n"),
783 ret
= errs
? CMD_RET_FAILURE
: CMD_RET_SUCCESS
;
788 #endif /* CONFIG_CMD_MEMTEST */