]>
cloudbase.mooo.com Git - z180-stamp.git/blob - avr/cmd_mem.c
2 * (C) Copyright 2014,2018 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)
17 #include <avr/interrupt.h>
19 #include "cli_readline.h"
20 #include "print-utils.h"
21 #include "con-utils.h"
22 #include "getopt-min.h"
26 #include "disas_z180.h"
30 #ifndef CONFIG_SYS_MEMTEST_SCRATCH
31 #define CONFIG_SYS_MEMTEST_SCRATCH 0
34 /* Display values from last command.
35 * Memory modify remembered values are different from display memory.
37 static uint32_t disas_last_addr
;
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 static ERRNUM
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 /*--------------------------------------------------------------------------*/
58 command_ret_t
do_mem_size(cmd_tbl_t
*cmdtp UNUSED
, uint_fast8_t flag UNUSED
, int argc UNUSED
, char * const argv
[] UNUSED
)
60 int32_t ramsize
= z80_memsize_detect();
63 cmd_error(CMD_RET_FAILURE
, (ERRNUM
) -ramsize
, PSTR("Couldn't access RAM"));
65 printf_P(PSTR("Detected RAM: Start %.5lx, End: %.5lx, Size: %.5lx (%ld dec)\n"),
66 0l, ramsize
? ramsize
-1 : 0l, ramsize
, ramsize
);
68 return CMD_RET_SUCCESS
;
72 * Disassemble code from memory
75 * disassemble address [# of lines]
78 command_ret_t
do_disas(cmd_tbl_t
*cmdtp
, uint_fast8_t flag
, int argc
, char * const argv
[])
82 /* We use the last specified parameters, unless new ones are
85 uint32_t addr
= disas_last_addr
;
87 int ret
= CMD_RET_SUCCESS
;
92 if ((flag
& CMD_FLAG_REPEAT
) == 0) {
93 /* Address is specified since argc > 1 */
94 addr
= eval_arg(argv
[1], NULL
);
97 /* If another parameter, it is the length (Number of lines) to display. */
99 length
= (int) eval_arg(argv
[2], NULL
);
102 z80_bus_request_or_exit();
103 clear_ctrlc(); /* forget any previous Control-C */
104 for (; length
> 0; --length
) {
105 addr
= dis_decode(addr
);
106 if (had_ctrlc() || ctrlc()) {
107 ret
= CMD_RET_FAILURE
;
111 z80_bus_cmd(Release
);
112 disas_last_addr
= addr
;
122 command_ret_t
do_mem_md(cmd_tbl_t
*cmdtp
, uint_fast8_t flag
, int argc
, char * const argv
[])
124 uint32_t addr
, length
;
129 printf_P(PSTR("flag: %d, argc: %d"), flag
, argc
);
130 for (int i
= 0; i
< argc
; i
++) {
131 printf_P(PSTR(", argv[%d]: %s"), i
, argv
[i
] ? argv
[i
] : "<NULL>");
136 /* We use the last specified parameters, unless new ones are
140 length
= dp_last_length
;
143 return CMD_RET_USAGE
;
145 if ((flag
& CMD_FLAG_REPEAT
) == 0) {
146 /* Address is specified since argc > 1 */
147 addr
= eval_arg(argv
[1], NULL
);
148 addr
+= base_address
;
150 /* If another parameter, it is the length to display. */
152 length
= eval_arg(argv
[2], NULL
);
155 /* Print the lines. */
156 ERRNUM ret
= dump_mem(addr
, addr
, length
, z180_read_buf
, NULL
);
158 cmd_error(CMD_RET_FAILURE
, ret
, NULL
);
160 if (ret
== ESUCCESS
) {
161 dp_last_addr
= addr
+ length
;
162 dp_last_length
= length
;
164 return CMD_RET_SUCCESS
;
174 mod_mem(cmd_tbl_t
*cmdtp
, int incrflag
, uint_fast8_t flag
, int argc
, char * const argv
[])
183 return CMD_RET_USAGE
;
185 /* We use the last specified parameters, unless new ones are
190 if ((flag
& CMD_FLAG_REPEAT
) == 0) {
191 /* New command specified.
194 /* Address is specified since argc > 1
196 addr
= eval_arg(argv
[1], NULL
);
197 addr
+= base_address
;
200 /* Print the address, followed by value. Then accept input for
201 * the next value. A non-converted value exits.
204 z80_bus_request_or_exit();
205 data
= z80_read(addr
);
206 z80_bus_cmd(Release
);
207 printf_P(PSTR("%05lx: %02x"), addr
, data
);
209 nbytes
= cli_readline(PSTR(" ? "), 0);
210 if (nbytes
== 0 || (nbytes
== 1 && console_buffer
[0] == '-')) {
211 /* <CR> pressed as only input, don't modify current
212 * location and move to next. "-" pressed will go back.
215 addr
+= nbytes
? -1 : 1;
220 data
= eval_arg(console_buffer
, &endp
);
221 nbytes
= endp
- console_buffer
;
223 z80_bus_request_or_exit();
224 z80_write(addr
, data
);
225 z80_bus_cmd(Release
);
230 } while (nbytes
> 0);
233 return CMD_RET_SUCCESS
;
237 command_ret_t
do_mem_mm(cmd_tbl_t
*cmdtp
, uint_fast8_t flag
, int argc
, char * const argv
[])
239 return mod_mem (cmdtp
, 1, flag
, argc
, argv
);
241 command_ret_t
do_mem_nm(cmd_tbl_t
*cmdtp
, uint_fast8_t flag
, int argc
, char * const argv
[])
243 return mod_mem (cmdtp
, 0, flag
, argc
, argv
);
246 command_ret_t
do_mem_mw(cmd_tbl_t
*cmdtp
, uint_fast8_t flag
, int argc
, char * const argv
[])
251 uint_fast8_t width
= 1;
253 (void) cmdtp
; (void) flag
;
256 while ((opt
= getopt(argc
, argv
, PSTR("bwl"))) != -1) {
268 return CMD_RET_USAGE
;
272 /* remaining arguments */
274 if ((argc
< 2) || (argc
> 3))
275 return CMD_RET_USAGE
;
277 /* Address and value are specified since (adjusted) argc >= 2 */
278 addr
= eval_arg(argv
[optind
++], NULL
);
279 addr
+= base_address
;
280 writeval
= eval_arg(argv
[optind
++], NULL
);
284 count
= eval_arg(argv
[optind
], NULL
);
286 z80_bus_request_or_exit();
288 z80_memset(addr
, writeval
, count
);
291 z80_write_block((const uint8_t *) &writeval
, addr
, width
);
295 z80_bus_cmd(Release
);
297 return CMD_RET_SUCCESS
;
300 #ifdef CONFIG_MX_CYCLIC
301 command_ret_t
do_mem_mdc ( cmd_tbl_t
*cmdtp
, uint_fast8_t flag
, int argc
, char * const argv
[])
309 if (argv
[0][1] != 'd') {
311 while ((opt
= getopt(argc
, argv
, PSTR("bwl"))) != -1)
313 return CMD_RET_USAGE
;
317 if (argc
-optind
!= 4)
318 return CMD_RET_USAGE
;
320 count
= eval_arg(argv
[optind
+ 3], NULL
);
322 clear_ctrlc(); /* forget any previous Control C */
325 if (argv
[0][1] == 'd')
326 do_mem_md (NULL
, 0, argc
-1, argv
); /* memory display */
328 do_mem_mw (NULL
, 0, argc
-1, argv
); /* memory write */
331 /* delay for <count> ms... */
334 /* check for ctrl-c to abort... */
335 if (had_ctrlc() || ctrlc()) {
336 my_puts_P(PSTR("Abort\n"));
337 return CMD_RET_SUCCESS
;
339 } while (get_timer(ts
) < count
);
342 return CMD_RET_SUCCESS
;
344 #endif /* CONFIG_MX_CYCLIC */
346 command_ret_t
do_mem_cmp(cmd_tbl_t
*cmdtp
, uint_fast8_t flag
, int argc
, char * const argv
[])
348 uint32_t addr1
, addr2
, count
, ngood
;
349 command_ret_t rcode
= CMD_RET_SUCCESS
;
350 uint8_t byte1
, byte2
;
356 return CMD_RET_USAGE
;
359 addr1
= eval_arg(argv
[1], NULL
);
360 addr1
+= base_address
;
361 addr2
= eval_arg(argv
[2], NULL
);
362 addr2
+= base_address
;
363 count
= eval_arg(argv
[3], NULL
);
365 for (ngood
= 0; ngood
< count
; ++ngood
) {
366 if (!(z80_bus_cmd(Request
) & ZST_ACQUIRED
)) {
367 my_puts_P(PSTR("Bus timeout\n"));
368 rcode
= CMD_RET_FAILURE
;
371 byte1
= z80_read(addr1
);
372 byte2
= z80_read(addr2
);
373 z80_bus_cmd(Release
);
374 if (byte1
!= byte2
) {
375 printf_P(PSTR("byte at 0x%05lx (%#02x) != "
376 "byte at 0x%05lx (%#02x)\n"),
377 addr1
, byte1
, addr2
, byte2
);
378 rcode
= CMD_RET_FAILURE
;
384 /* check for ctrl-c to abort... */
386 my_puts_P(PSTR("Abort\n"));
387 return CMD_RET_SUCCESS
;
391 printf_P(PSTR("Total of %ld byte(s) (0x%lx) were the same\n"), ngood
, ngood
);
395 command_ret_t
do_mem_cp(cmd_tbl_t
*cmdtp
, uint_fast8_t flag
, int argc
, char * const argv
[])
397 uint32_t src
, dest
, count
;
404 return CMD_RET_USAGE
;
406 src
= eval_arg(argv
[1], NULL
);
408 dest
= eval_arg(argv
[2], NULL
);
409 dest
+= base_address
;
410 count
= eval_arg(argv
[3], NULL
);
413 my_puts_P(PSTR("Zero length?\n"));
414 return CMD_RET_FAILURE
;
424 while (count
-- > 0) {
426 z80_bus_request_or_exit();
427 data
= z80_read(src
);
428 z80_write(dest
, data
);
429 z80_bus_cmd(Release
);
433 /* check for ctrl-c to abort... */
435 my_puts_P(PSTR("Abort\n"));
436 return CMD_RET_SUCCESS
;
439 return CMD_RET_SUCCESS
;
442 command_ret_t
do_mem_base(cmd_tbl_t
*cmdtp
, uint_fast8_t flag
, int argc
,
449 /* Set new base address. */
450 base_address
= eval_arg(argv
[1], NULL
);
452 /* Print the current base address. */
453 printf_P(PSTR("Base Address: 0x%05lx\n"), base_address
);
454 return CMD_RET_SUCCESS
;
457 command_ret_t
do_mem_loop(cmd_tbl_t
*cmdtp
, uint_fast8_t flag
, int argc
,
460 uint32_t addr
, length
;
466 return CMD_RET_USAGE
;
468 /* Address is always specified. */
469 addr
= eval_arg(argv
[1], NULL
);
471 /* Length is the number of bytes. */
472 length
= eval_arg(argv
[2], NULL
);
475 /* We want to optimize the loops to run as fast as possible.
476 * If we have only one object, just run infinite loops.
479 z80_bus_request_or_exit();
485 z80_bus_request_or_exit();
494 return CMD_RET_SUCCESS
;
497 command_ret_t
do_mem_loopw (cmd_tbl_t
*cmdtp
, uint_fast8_t flag
, int argc
, char * const argv
[])
499 uint32_t addr
, length
;
506 return CMD_RET_USAGE
;
508 /* Address is always specified. */
509 addr
= eval_arg(argv
[1], NULL
);
511 /* Length is the number of bytes. */
512 length
= eval_arg(argv
[2], NULL
);
514 data
= eval_arg(argv
[3], NULL
);
517 * We want to optimize the loops to run as fast as possible.
518 * If we have only one object, just run infinite loops.
521 z80_bus_request_or_exit();
524 z80_write(addr
, data
);
527 z80_bus_request_or_exit();
533 z80_write(p
++, data
);
537 //#define CONFIG_SYS_ALT_MEMTEST
539 #ifdef CONFIG_CMD_MEMTEST
540 static uint32_t mem_test_alt(uint32_t start_addr
, uint32_t end_addr
)
546 uint32_t test_offset
;
548 uint8_t anti_pattern
;
552 static const FLASH
uint8_t bitpattern
[] = {
553 0x01, /* single bit */
554 0x03, /* two adjacent bits */
555 0x07, /* three adjacent bits */
556 0x0F, /* four adjacent bits */
557 0x05, /* two non-adjacent bits */
558 0x15, /* three non-adjacent bits */
559 0x55, /* four non-adjacent bits */
560 0xaa, /* alternating 1/0 */
564 * Data line test: write a pattern to the first
565 * location, write the 1's complement to a 'parking'
566 * address (changes the state of the data bus so a
567 * floating bus doesn't give a false OK), and then
568 * read the value back. Note that we read it back
569 * into a variable because the next time we read it,
570 * it might be right (been there, tough to explain to
571 * the quality guys why it prints a failure when the
572 * "is" and "should be" are obviously the same in the
575 * Rather than exhaustively testing, we test some
576 * patterns by shifting '1' bits through a field of
577 * '0's and '0' bits through a field of '1's (i.e.
578 * pattern and ~pattern).
581 dummy
= start_addr
+1;
582 for (unsigned int j
= 0; j
< ARRAY_SIZE(bitpattern
); j
++) {
583 pattern
= bitpattern
[j
];
584 for (; pattern
!= 0; pattern
<<= 1) {
585 anti_pattern
= ~pattern
;
586 z80_write(addr
, pattern
);
587 z80_write(dummy
, anti_pattern
); /* clear the test data off the bus */
588 temp
= z80_read(addr
);
589 if (temp
!= pattern
) {
590 printf_P(PSTR("FAILURE (data line): "
591 "expected %02x, actual %02x\n"),
595 z80_write(addr
, anti_pattern
);
596 z80_write(dummy
, pattern
); /* clear the test data off the bus */
597 temp
= z80_read(addr
);
598 if (temp
!= anti_pattern
) {
599 printf_P(PSTR("FAILURE (data line): "
600 "Is %02x, should be %02x\n"),
614 * Based on code whose Original Author and Copyright
615 * information follows: Copyright (c) 1998 by Michael
616 * Barr. This software is placed into the public
617 * domain and may be used for any purpose. However,
618 * this notice must not be changed or removed and no
619 * warranty is either expressed or implied by its
620 * publication or distribution.
626 * Description: Test the address bus wiring in a
627 * memory region by performing a walking
628 * 1's test on the relevant bits of the
629 * address and checking for aliasing.
630 * This test will find single-bit
631 * address failures such as stuck-high,
632 * stuck-low, and shorted pins. The base
633 * address and size of the region are
634 * selected by the caller.
636 * Notes: For best results, the selected base
637 * address should have enough LSB 0's to
638 * guarantee single address bit changes.
639 * For example, to test a 64-Kbyte
640 * region, select a base address on a
641 * 64-Kbyte boundary. Also, select the
642 * region size as a power-of-two if at
645 * Returns: 0 if the test succeeds, 1 if the test fails.
648 num_bytes
= (end_addr
- start_addr
) / sizeof(uint8_t);
653 // debug("## %s:%d: length = 0x%.5lx\n", __func__, __LINE__, num_bytes);
655 * Write the default pattern at each of the
656 * power-of-two offsets.
658 for (offset
= 1; offset
< num_bytes
; offset
<<= 1)
659 z80_write(addr
+offset
, pattern
);
662 * Check for address bits stuck high.
664 z80_write(start_addr
, anti_pattern
);
666 for (offset
= 1; offset
< num_bytes
; offset
<<= 1) {
667 temp
= z80_read(start_addr
+ offset
);
668 if (temp
!= pattern
) {
669 printf_P(PSTR("FAILURE: Address bit stuck high @ 0x%.5lx:"
670 " expected 0x%.2x, actual 0x%.2x\n"),
671 start_addr
+ offset
, pattern
, temp
);
677 z80_write(start_addr
, pattern
);
680 * Check for addr bits stuck low or shorted.
682 for (test_offset
= 1; test_offset
< num_bytes
; test_offset
<<= 1) {
683 z80_write(start_addr
+ test_offset
, anti_pattern
);
685 for (offset
= 1; offset
< num_bytes
; offset
<<= 1) {
686 temp
= z80_read(start_addr
+ offset
);
687 if ((temp
!= pattern
) && (offset
!= test_offset
)) {
688 printf_P(PSTR("FAILURE: Address bit stuck low or shorted"
689 " @ 0x%.5lx: expected 0x%.2x, actual 0x%.2x\n"),
690 start_addr
+ offset
, pattern
, temp
);
696 z80_write(start_addr
+ test_offset
, pattern
);
703 * Description: Test the integrity of a physical
704 * memory device by performing an
705 * increment/decrement test over the
706 * entire region. In the process every
707 * storage bit in the device is tested
708 * as a zero and a one. The base address
709 * and the size of the region are
710 * selected by the caller.
712 * Returns: 0 if the test succeeds, 1 if the test fails.
717 * Fill memory with a known pattern.
719 for (pattern
= 1, addr
= start_addr
; addr
<= end_addr
; pattern
++, addr
++)
720 z80_write(addr
, pattern
);
723 * Check each location and invert it for the second pass.
725 for (pattern
= 1, addr
= start_addr
; addr
<= end_addr
; pattern
++, addr
++) {
726 temp
= z80_read(addr
);
727 if (temp
!= pattern
) {
728 printf_P(PSTR("FAILURE (read/write) @ 0x%.5lx:"
729 " expected 0x%.2x, actual 0x%.2x)\n"),
730 addr
, pattern
, temp
);
736 anti_pattern
= ~pattern
;
737 z80_write(addr
, anti_pattern
);
741 * Check each location for the inverted pattern and zero it.
743 for (pattern
= 1, addr
= start_addr
; addr
<= end_addr
; pattern
++, addr
++) {
744 anti_pattern
= ~pattern
;
745 temp
= z80_read(addr
);
746 if (temp
!= anti_pattern
) {
747 printf_P(PSTR("FAILURE (read/write) @ 0x%.5lx:"
748 " expected 0x%.2x, actual 0x%.2x)\n"),
749 start_addr
, anti_pattern
, temp
);
761 * Perform a memory test. A more complete alternative test can be
762 * configured using CONFIG_SYS_ALT_MEMTEST. The complete test loops until
763 * interrupted by ctrl-c or by a failure of one of the sub-tests.
765 command_ret_t
do_mem_mtest(cmd_tbl_t
*cmdtp
, uint_fast8_t flag
, int argc
,
770 unsigned int iteration_limit
= 0;
771 unsigned int iteration
;
772 uint32_t errs
= 0; /* number of errors */
779 start
= eval_arg(argv
[1], NULL
);
782 end
= eval_arg(argv
[2], NULL
);
784 end
= CONFIG_SYS_RAMSIZE_MAX
- 1;
787 iteration_limit
= (unsigned int) eval_arg(argv
[3], NULL
);
789 printf_P(PSTR("Testing %05lx ... %05lx:\n"), start
, end
);
790 // debug("## %s:%d: start %#05lx end %#05lx\n", __func__, __LINE__, start, end);
792 clear_ctrlc(); /* forget any previous Control C */
795 !iteration_limit
|| iteration
< iteration_limit
;
798 printf_P(PSTR("Iteration: %6d\r"), iteration
+ 1);
801 z80_bus_request_or_exit();
802 errs
+= mem_test_alt(start
, end
);
803 z80_bus_cmd(Release
);
805 if (had_ctrlc() || ctrlc()) {
811 /* Memory test was aborted - write a newline to finish off */
813 ret
= CMD_RET_FAILURE
;
815 printf_P(PSTR("Tested %d iteration(s) with %lu errors.\n"),
817 ret
= errs
? CMD_RET_FAILURE
: CMD_RET_SUCCESS
;
822 #endif /* CONFIG_CMD_MEMTEST */