summaryrefslogtreecommitdiffstats
path: root/arch/mips/include/asm/pbl_nmon.h
diff options
context:
space:
mode:
authorAntony Pavlov <antonynpavlov@gmail.com>2013-06-24 23:10:10 +0400
committerSascha Hauer <s.hauer@pengutronix.de>2013-06-25 21:36:04 +0200
commit15001b1f95635a25f08e3b1e2463da280a5409a3 (patch)
treeb2dfd64a159dca10194a43557dacbd521bfd1084 /arch/mips/include/asm/pbl_nmon.h
parente6acb3f4b2d0e9ec5ac50f3f1f4c6173dddd39a0 (diff)
downloadbarebox-15001b1f95635a25f08e3b1e2463da280a5409a3.tar.gz
barebox-15001b1f95635a25f08e3b1e2463da280a5409a3.tar.xz
MIPS: pbl: add nmon MIPS nano-monitor
nmon is a tiny monitor (<1200 bytes) program for the MIPS processors. It can operate with NO working RAM at all! It uses only the processor registers and NS16550-compatible UART port for operation, so it can be used for a memory controller setup code debugging. With no changes nmon should work on different MIPS processors as it uses only common MIPS-I instructions. nmon is inspired by mmon, MIPS VR4300 Mini-monitor. mmon is copyrighted 1996, 2003 by Eric Smith. Also Alexander Voropay must be noted for his work on qemu & YAMON mmon adaptations made in 2006 and 2007. See http://www.brouhaha.com/~eric/software/mmon/ for mmon details. The mmon's features missed in nmon: * batch memory dumps; * byte and 16-bit half-words dumps and stores; * fill memory; * load S-records (this function make sense only if RAM works properly). nmon has only 4 commands: q - quit to barebox d <addr> - read 32-bit word from <addr> address w <addr> <val> - write 32-bit word <val> to <addr> g <addr> - jump to <addr> Addresses and data must be given in hexadecimal. Everything (including hex digits 'a'..'f') must be in lower case. EXAMPLE: change value of word with address 0xa0000000 nmon> d a0000000 00000000 nmon> w a0000000 12345678 nmon> d a0000000 12345678 nmon> There is no error checking of any kind. If you give an invalid address you will probably get an exception which will hang the board and you will have to press the reset button. You can interrupt current command (e.g. you have made error in input <addr> value) by pressing the <ESC> key. Signed-off-by: Antony Pavlov <antonynpavlov@gmail.com> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'arch/mips/include/asm/pbl_nmon.h')
-rw-r--r--arch/mips/include/asm/pbl_nmon.h270
1 files changed, 270 insertions, 0 deletions
diff --git a/arch/mips/include/asm/pbl_nmon.h b/arch/mips/include/asm/pbl_nmon.h
new file mode 100644
index 0000000000..e7baa4c5a9
--- /dev/null
+++ b/arch/mips/include/asm/pbl_nmon.h
@@ -0,0 +1,270 @@
+/*
+ * nano-monitor for MIPS CPU
+ *
+ * Copyright (C) 2013 Antony Pavlov <antonynpavlov@gmail.com>
+ *
+ * This file is part of barebox.
+ * See file CREDITS for list of people who contributed to this project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <board/debug_ll.h>
+#include <asm/debug_ll_ns16550.h>
+
+#define CODE_ESC 0x1b
+
+/*
+ * Delay slot warning!
+ *
+ * NMON was made with code portability in mind.
+ * So it uses '.set reorder' directives allowing
+ * assembler to insert necessary 'nop' instructions
+ * into delay slots (after branch instruction) and
+ * into load delay slot (after memory load instruction
+ * on very old R2000/R3000 processors).
+ */
+
+ .macro nmon_outs msg
+ .set push
+ .set reorder
+
+ ADR a1, \msg, t1
+
+ bal _nmon_outs
+
+ .set pop
+ .endm
+
+
+ .macro mips_nmon
+ .set push
+ .set reorder
+
+#ifdef CONFIG_NMON
+#ifdef CONFIG_NMON_USER_START
+
+#if CONFIG_NMON_USER_START_DELAY < 1
+#error CONFIG_NMON_USER_START_DELAY must be >= 1!
+#endif
+
+ nmon_outs msg_nmon_press_any_key
+
+ li s0, CONFIG_NMON_USER_START_DELAY
+ move s1, s0
+
+1:
+ li a0, '.'
+ bal _nmon_outc_a0
+ addi s1, s1, -1
+ bnez s1, 1b
+
+ move s1, s0
+
+nmon_wait_user:
+ pbl_sleep s2, CONFIG_NMON_1S_DELAY
+
+ nmon_outs msg_bsp
+
+ debug_ll_ns16550_check_char
+
+ bnez v0, 3f
+
+ addi s1, s1, -1
+ bnez s1, nmon_wait_user
+
+ nmon_outs msg_skipping_nmon
+
+ b nmon_exit
+
+msg_nmon_press_any_key:
+ .asciz "\r\npress any key to start nmon\r\n"
+
+ .align 4
+3:
+ /* get received char from ns16550's buffer */
+ debug_ll_ns16550_getc
+#endif /* CONFIG_NMON_USER_START */
+
+nmon_main_help:
+#ifdef CONFIG_NMON_HELP
+ nmon_outs msg_nmon_help
+#endif /* CONFIG_NMON_HELP */
+
+nmon_main:
+ nmon_outs msg_prompt
+
+ debug_ll_ns16550_getc
+
+ /* prepare a0 for debug_ll_ns16550_outc_a0 */
+ move a0, v0
+
+ li v1, 'q'
+ bne v0, v1, 3f
+
+ bal _nmon_outc_a0
+
+ b nmon_exit
+
+3:
+ li v1, 'd'
+ beq v0, v1, nmon_cmd_d
+
+ li v1, 'w'
+ beq v0, v1, nmon_cmd_w
+
+ li v1, 'g'
+ beq v0, v1, nmon_cmd_g
+
+ b nmon_main_help
+
+nmon_cmd_d:
+ bal _nmon_outc_a0
+
+ li a0, ' '
+ bal _nmon_outc_a0
+
+ bal _nmon_gethexw
+
+ nmon_outs msg_nl
+
+ lw a0, (v0)
+ debug_ll_ns16550_outhexw
+
+ b nmon_main
+
+nmon_cmd_w:
+ bal _nmon_outc_a0
+
+ li a0, ' '
+ bal _nmon_outc_a0
+ bal _nmon_gethexw
+ move s0, v0
+
+ li a0, ' '
+ bal _nmon_outc_a0
+ bal _nmon_gethexw
+
+ sw v0, (s0)
+ b nmon_main
+
+nmon_cmd_g:
+ bal _nmon_outc_a0
+
+ li a0, ' '
+ bal _nmon_outc_a0
+
+ bal _nmon_gethexw
+
+ nmon_outs msg_nl
+
+ jal v0
+ b nmon_main
+
+_nmon_outc_a0:
+ debug_ll_ns16550_outc_a0
+ jr ra
+
+_nmon_outs:
+ lbu a0, 0(a1)
+ addi a1, a1, 1
+ beqz a0, _nmon_jr_ra_exit
+
+ debug_ll_ns16550_outc_a0
+
+ b _nmon_outs
+
+_nmon_gethexw:
+
+ li t3, 8
+ li t2, 0
+
+_get_hex_digit:
+ debug_ll_ns16550_getc
+
+ li v1, CODE_ESC
+ beq v0, v1, nmon_main
+
+ li v1, '0'
+ bge v0, v1, 0f
+ b _get_hex_digit
+
+0:
+ li v1, '9'
+ ble v0, v1, 9f
+
+ li v1, 'f'
+ ble v0, v1, 1f
+ b _get_hex_digit
+
+1:
+ li v1, 'a'
+ bge v0, v1, 8f
+
+ b _get_hex_digit
+
+8: /* v0 \in {'a', 'b' ... 'f'} */
+ sub a3, v0, v1
+ addi a3, 0xa
+ b 0f
+
+9: /* v0 \in {'0', '1' ... '9'} */
+ li a3, '0'
+ sub a3, v0, a3
+
+0: move a0, v0
+ debug_ll_ns16550_outc_a0
+
+ sll t2, t2, 4
+ or t2, t2, a3
+ sub t3, t3, 1
+
+ beqz t3, 0f
+
+ b _get_hex_digit
+
+0:
+ move v0, t2
+
+_nmon_jr_ra_exit:
+ jr ra
+
+msg_prompt:
+ .asciz "\r\nnmon> "
+
+msg_nl:
+ .asciz "\r\n"
+
+msg_bsp:
+ .asciz "\b \b"
+
+msg_skipping_nmon:
+ .asciz "skipping nmon..."
+
+#ifdef CONFIG_NMON_HELP
+msg_nmon_help:
+ .ascii "\r\n\r\nnmon commands:\r\n"
+ .ascii " q - quit\r\n"
+ .ascii " d <addr> - read 32-bit word from <addr>\r\n"
+ .ascii " w <addr> <val> - write 32-bit word to <addr>\r\n"
+ .ascii " g <addr> - jump to <addr>\r\n"
+ .asciz " use <ESC> key to interrupt current command\r\n"
+#endif /* CONFIG_NMON_HELP */
+
+ .align 4
+
+nmon_exit:
+
+ nmon_outs msg_nl
+
+#endif /* CONFIG_NMON */
+ .set pop
+ .endm