]>
cloudbase.mooo.com Git - z180-stamp.git/blob - avr/cmd_mem.c
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"
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 dp_last_addr
;
38 static uint32_t dp_last_length
= 0x100;
39 static uint32_t mm_last_addr
;
41 static uint32_t base_address
= 0;
43 /*--------------------------------------------------------------------------*/
45 int z180_read_buf(uint8_t *buf
, uint32_t addr
, uint8_t count
)
47 if (!(z80_bus_cmd(Request
) & ZST_ACQUIRED
))
50 z80_read_block (buf
, addr
, count
);
55 /*--------------------------------------------------------------------------*/
62 command_ret_t
do_mem_md(cmd_tbl_t
*cmdtp
, int flag
, int argc
, char * const argv
[])
64 uint32_t addr
, length
;
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>");
76 /* We use the last specified parameters, unless new ones are
80 length
= dp_last_length
;
85 if ((flag
& CMD_FLAG_REPEAT
) == 0) {
86 /* Address is specified since argc > 1 */
87 addr
= strtoul(argv
[1], NULL
, 16);
90 /* If another parameter, it is the length to display. */
92 length
= strtoul(argv
[2], NULL
, 16);
95 /* Print the lines. */
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
;
103 dp_last_addr
= addr
+ length
;
104 dp_last_length
= length
;
106 return CMD_RET_SUCCESS
;
116 mod_mem(cmd_tbl_t
*cmdtp
, int incrflag
, int flag
, int argc
, char * const argv
[])
125 return CMD_RET_USAGE
;
127 /* We use the last specified parameters, unless new ones are
132 if ((flag
& CMD_FLAG_REPEAT
) == 0) {
133 /* New command specified.
136 /* Address is specified since argc > 1
138 addr
= strtoul(argv
[1], NULL
, 16);
139 addr
+= base_address
;
142 /* Print the address, followed by value. Then accept input for
143 * the next value. A non-converted value exits.
146 if (!(z80_bus_cmd(Request
) & ZST_ACQUIRED
)) {
147 my_puts_P(PSTR("Bus timeout\n"));
148 return CMD_RET_FAILURE
;
150 data
= z80_read(addr
);
151 z80_bus_cmd(Release
);
152 printf_P(PSTR("%05lx: %02x"), addr
, data
);
154 nbytes
= cli_readline(PSTR(" ? "), 0);
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.
160 addr
+= nbytes
? -1 : 1;
165 data
= strtoul(console_buffer
, &endp
, 16);
166 nbytes
= endp
- console_buffer
;
168 if (!(z80_bus_cmd(Request
) & ZST_ACQUIRED
)) {
169 my_puts_P(PSTR("Bus timeout\n"));
170 return CMD_RET_FAILURE
;
172 z80_write(addr
, data
);
173 z80_bus_cmd(Release
);
181 return CMD_RET_SUCCESS
;
185 command_ret_t
do_mem_mm(cmd_tbl_t
*cmdtp
, int flag
, int argc
, char * const argv
[])
187 return mod_mem (cmdtp
, 1, flag
, argc
, argv
);
189 command_ret_t
do_mem_nm(cmd_tbl_t
*cmdtp
, int flag
, int argc
, char * const argv
[])
191 return mod_mem (cmdtp
, 0, flag
, argc
, argv
);
194 command_ret_t
do_mem_mw(cmd_tbl_t
*cmdtp
, int flag
, int argc
, char * const argv
[])
197 uint32_t addr
, count
;
202 if ((argc
< 3) || (argc
> 4))
203 return CMD_RET_USAGE
;
205 /* Address is specified since argc > 1
207 addr
= strtoul(argv
[1], NULL
, 16);
208 addr
+= base_address
;
210 /* Get the value to write.
212 writeval
= (uint8_t) strtoul(argv
[2], NULL
, 16);
216 count
= strtoul(argv
[3], NULL
, 16);
221 if (!(z80_bus_cmd(Request
) & ZST_ACQUIRED
)) {
222 my_puts_P(PSTR("Bus timeout\n"));
223 return CMD_RET_FAILURE
;
225 z80_memset(addr
, writeval
, count
);
226 z80_bus_cmd(Release
);
228 return CMD_RET_SUCCESS
;
231 #ifdef CONFIG_MX_CYCLIC
232 command_ret_t
do_mem_mdc ( cmd_tbl_t
*cmdtp
, int flag
, int argc
, char * const argv
[])
241 return CMD_RET_USAGE
;
243 count
= strtoul(argv
[3], NULL
, 10);
245 clear_ctrlc(); /* forget any previous Control C */
248 if (argv
[0][1] == 'd')
249 do_mem_md (NULL
, 0, 3, argv
);
251 do_mem_mw (NULL
, 0, 3, argv
);
254 /* delay for <count> ms... */
257 /* check for ctrl-c to abort... */
258 if (had_ctrlc() || ctrlc()) {
259 my_puts_P(PSTR("Abort\n"));
260 return CMD_RET_SUCCESS
;
262 } while (get_timer(ts
) < count
);
265 return CMD_RET_SUCCESS
;
267 #endif /* CONFIG_MX_CYCLIC */
269 command_ret_t
do_mem_cmp(cmd_tbl_t
*cmdtp
, int flag
, int argc
, char * const argv
[])
271 uint32_t addr1
, addr2
, count
, ngood
;
272 command_ret_t rcode
= CMD_RET_SUCCESS
;
273 uint8_t byte1
, byte2
;
279 return CMD_RET_USAGE
;
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);
288 for (ngood
= 0; ngood
< count
; ++ngood
) {
289 if (!(z80_bus_cmd(Request
) & ZST_ACQUIRED
)) {
290 my_puts_P(PSTR("Bus timeout\n"));
291 rcode
= CMD_RET_FAILURE
;
294 byte1
= z80_read(addr1
);
295 byte2
= z80_read(addr2
);
296 z80_bus_cmd(Release
);
297 if (byte1
!= byte2
) {
298 printf_P(PSTR("byte at 0x%05lx (%#02x) != "
299 "byte at 0x%05lx (%#02x)\n"),
300 addr1
, byte1
, addr2
, byte2
);
301 rcode
= CMD_RET_FAILURE
;
307 /* check for ctrl-c to abort... */
309 my_puts_P(PSTR("Abort\n"));
310 return CMD_RET_SUCCESS
;
314 printf_P(PSTR("Total of %ld byte(s) (0x%lx) were the same\n"), ngood
, ngood
);
318 command_ret_t
do_mem_cp(cmd_tbl_t
*cmdtp
, int flag
, int argc
, char * const argv
[])
320 uint32_t src
, dest
, count
;
327 return CMD_RET_USAGE
;
329 src
= strtoul(argv
[1], NULL
, 16);
331 dest
= strtoul(argv
[2], NULL
, 16);
332 dest
+= base_address
;
333 count
= strtoul(argv
[3], NULL
, 16);
336 my_puts_P(PSTR("Zero length?\n"));
337 return CMD_RET_FAILURE
;
347 while (count
-- > 0) {
349 if (!(z80_bus_cmd(Request
) & ZST_ACQUIRED
)) {
350 my_puts_P(PSTR("Bus timeout\n"));
351 return CMD_RET_FAILURE
;
353 data
= z80_read(src
);
354 z80_write(dest
, data
);
355 z80_bus_cmd(Release
);
359 /* check for ctrl-c to abort... */
361 my_puts_P(PSTR("Abort\n"));
362 return CMD_RET_SUCCESS
;
365 return CMD_RET_SUCCESS
;
368 command_ret_t
do_mem_base(cmd_tbl_t
*cmdtp
, int flag
, int argc
,
375 /* Set new base address. */
376 base_address
= strtoul(argv
[1], NULL
, 16);
378 /* Print the current base address. */
379 printf_P(PSTR("Base Address: 0x%05lx\n"), base_address
);
380 return CMD_RET_SUCCESS
;
383 command_ret_t
do_mem_loop(cmd_tbl_t
*cmdtp
, int flag
, int argc
,
386 uint32_t addr
, length
;
392 return CMD_RET_USAGE
;
394 /* Address is always specified. */
395 addr
= strtoul(argv
[1], NULL
, 16);
397 /* Length is the number of bytes. */
398 length
= strtoul(argv
[2], NULL
, 16);
401 /* We want to optimize the loops to run as fast as possible.
402 * If we have only one object, just run infinite loops.
405 if (!(z80_bus_cmd(Request
) & ZST_ACQUIRED
)) {
406 my_puts_P(PSTR("Bus timeout\n"));
407 return CMD_RET_FAILURE
;
414 if (!(z80_bus_cmd(Request
) & ZST_ACQUIRED
)) {
415 my_puts_P(PSTR("Bus timeout\n"));
416 return CMD_RET_FAILURE
;
426 return CMD_RET_SUCCESS
;
429 command_ret_t
do_mem_loopw (cmd_tbl_t
*cmdtp
, int flag
, int argc
, char * const argv
[])
431 uint32_t addr
, length
;
438 return CMD_RET_USAGE
;
440 /* Address is always specified. */
441 addr
= strtoul(argv
[1], NULL
, 16);
443 /* Length is the number of bytes. */
444 length
= strtoul(argv
[2], NULL
, 16);
446 data
= strtoul(argv
[3], NULL
, 16);
449 * We want to optimize the loops to run as fast as possible.
450 * If we have only one object, just run infinite loops.
453 if (!(z80_bus_cmd(Request
) & ZST_ACQUIRED
)) {
454 my_puts_P(PSTR("Bus timeout\n"));
455 return CMD_RET_FAILURE
;
459 z80_write(addr
, data
);
462 if (!(z80_bus_cmd(Request
) & ZST_ACQUIRED
)) {
463 my_puts_P(PSTR("Bus timeout\n"));
464 return CMD_RET_FAILURE
;
471 z80_write(p
++, data
);
475 //#define CONFIG_SYS_ALT_MEMTEST
477 #ifdef CONFIG_CMD_MEMTEST
478 static uint32_t mem_test_alt(uint32_t start_addr
, uint32_t end_addr
)
484 uint32_t test_offset
;
486 uint8_t anti_pattern
;
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 */
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
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).
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
) {
528 printf_P(PSTR("FAILURE (data line): "
529 "expected %02x, actual %02x\n"),
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
) {
537 printf_P(PSTR("FAILURE (data line): "
538 "Is %02x, should be %02x\n"),
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.
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.
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
583 * Returns: 0 if the test succeeds, 1 if the test fails.
586 num_bytes
= (end_addr
- start_addr
) / sizeof(uint8_t);
591 // debug("## %s:%d: length = 0x%.5lx\n", __func__, __LINE__, num_bytes);
593 * Write the default pattern at each of the
594 * power-of-two offsets.
596 for (offset
= 1; offset
< num_bytes
; offset
<<= 1)
597 z80_write(addr
+offset
, pattern
);
600 * Check for address bits stuck high.
602 z80_write(start_addr
, anti_pattern
);
604 for (offset
= 1; offset
< num_bytes
; offset
<<= 1) {
605 temp
= z80_read(start_addr
+ offset
);
606 if (temp
!= pattern
) {
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
);
615 z80_write(start_addr
, pattern
);
618 * Check for addr bits stuck low or shorted.
620 for (test_offset
= 1; test_offset
< num_bytes
; test_offset
<<= 1) {
621 z80_write(start_addr
+ test_offset
, anti_pattern
);
623 for (offset
= 1; offset
< num_bytes
; offset
<<= 1) {
624 temp
= z80_read(start_addr
+ offset
);
625 if ((temp
!= pattern
) && (offset
!= test_offset
)) {
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
);
634 z80_write(start_addr
+ test_offset
, pattern
);
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.
650 * Returns: 0 if the test succeeds, 1 if the test fails.
655 * Fill memory with a known pattern.
657 for (pattern
= 1, addr
= start_addr
; addr
<= end_addr
; pattern
++, addr
++)
658 z80_write(addr
, pattern
);
661 * Check each location and invert it for the second pass.
663 for (pattern
= 1, addr
= start_addr
; addr
<= end_addr
; pattern
++, addr
++) {
664 temp
= z80_read(addr
);
665 if (temp
!= pattern
) {
666 printf_P(PSTR("FAILURE (read/write) @ 0x%.5lx:"
667 " expected 0x%.2x, actual 0x%.2x)\n"),
668 addr
, pattern
, temp
);
674 anti_pattern
= ~pattern
;
675 z80_write(addr
, anti_pattern
);
679 * Check each location for the inverted pattern and zero it.
681 for (pattern
= 1, addr
= start_addr
; addr
<= end_addr
; pattern
++, addr
++) {
682 anti_pattern
= ~pattern
;
683 temp
= z80_read(addr
);
684 if (temp
!= anti_pattern
) {
685 printf_P(PSTR("FAILURE (read/write) @ 0x%.5lx:"
686 " expected 0x%.2x, actual 0x%.2x)\n"),
687 start_addr
, anti_pattern
, temp
);
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.
703 command_ret_t
do_mem_mtest(cmd_tbl_t
*cmdtp
, int flag
, int argc
,
708 unsigned int iteration_limit
= 0;
709 unsigned int iteration
;
710 uint32_t errs
= 0; /* number of errors */
717 start
= strtoul(argv
[1], NULL
, 16);
720 end
= strtoul(argv
[2], NULL
, 16);
722 end
= CONFIG_SYS_RAMSIZE_MAX
- 1;
725 iteration_limit
= (unsigned int) strtoul(argv
[3], NULL
, 16);
727 printf_P(PSTR("Testing %05lx ... %05lx:\n"), start
, end
);
728 // debug("## %s:%d: start %#05lx end %#05lx\n", __func__, __LINE__, start, end);
730 clear_ctrlc(); /* forget any previous Control C */
733 !iteration_limit
|| iteration
< iteration_limit
;
736 printf_P(PSTR("Iteration: %6d\r"), iteration
+ 1);
739 if (!(z80_bus_cmd(Request
) & ZST_ACQUIRED
)) {
740 my_puts_P(PSTR("Bus timeout\n"));
741 return CMD_RET_FAILURE
;
743 errs
+= mem_test_alt(start
, end
);
744 z80_bus_cmd(Release
);
746 if (had_ctrlc() || ctrlc()) {
752 /* Memory test was aborted - write a newline to finish off */
754 ret
= CMD_RET_FAILURE
;
756 printf_P(PSTR("Tested %d iteration(s) with %lu errors.\n"),
758 ret
= errs
? CMD_RET_FAILURE
: CMD_RET_SUCCESS
;
763 #endif /* CONFIG_CMD_MEMTEST */