aboutsummaryrefslogtreecommitdiff
path: root/AT91SAM7S256/armdebug/Debugger
diff options
context:
space:
mode:
authorTat-Chee Wan (USM)2011-06-20 09:36:09 +0800
committerTat-Chee Wan (USM)2011-06-20 09:36:09 +0800
commit17b2827aeff34b69ecb98305d9890f58acb99461 (patch)
treebc810177c03a7f91a62c4f3b10b4c5ffc4de2243 /AT91SAM7S256/armdebug/Debugger
parent724f0cab2008109102428c6a7393f1ec85281574 (diff)
parent4814854ff7149f3b9dae2d5f1bf49d2bdeeaed6d (diff)
Merge branch 'master' of ssh://svc.cs.usm.my/~/gitrepo-bare/armdebug
Diffstat (limited to 'AT91SAM7S256/armdebug/Debugger')
-rw-r--r--AT91SAM7S256/armdebug/Debugger/debug_comm.S481
-rw-r--r--AT91SAM7S256/armdebug/Debugger/debug_hexutils.S457
-rw-r--r--AT91SAM7S256/armdebug/Debugger/debug_internals.h3
-rw-r--r--AT91SAM7S256/armdebug/Debugger/debug_runlooptasks.S174
-rw-r--r--AT91SAM7S256/armdebug/Debugger/debug_stub.S199
-rw-r--r--AT91SAM7S256/armdebug/Debugger/debug_stub.h4
-rw-r--r--AT91SAM7S256/armdebug/Debugger/undef_handler.S4
7 files changed, 756 insertions, 566 deletions
diff --git a/AT91SAM7S256/armdebug/Debugger/debug_comm.S b/AT91SAM7S256/armdebug/Debugger/debug_comm.S
index 821d0c8..570fedc 100644
--- a/AT91SAM7S256/armdebug/Debugger/debug_comm.S
+++ b/AT91SAM7S256/armdebug/Debugger/debug_comm.S
@@ -22,6 +22,22 @@
#include "debug_internals.h"
#include "debug_comm.h"
+ /* Hexutils function references */
+ .extern hex2char
+ .extern char2hex
+ .extern byte2ascii
+ .extern halfword2ascii_be
+ .extern halfword2ascii_le
+ .extern word2ascii_be
+ .extern word2ascii_le
+ .extern ascii2hex_varlen_be
+ .extern ascii2byte
+ .extern ascii2halfword_be
+ .extern ascii2halfword_le
+ .extern ascii2word_be
+ .extern ascii2word_le
+
+
.bss
.align 4
@@ -46,10 +62,11 @@ debug_msgTxBuf_AppendPtr:
debug_segmentRxNum: /* Current Rx Segment Number */
.word 0x0
-/* Incoming Message Length and Comm Channel is now common to both NxOS and NXT Firmware */
debug_nxtMsgLength: /* NXT Firmware Received Message Length */
.word 0x0
+/* Comm Channel is now common to both NxOS and NXT Firmware */
+ .global debug_nxtCommChannel
debug_nxtCommChannel:
.word 0x0
@@ -61,443 +78,9 @@ debug_nxtCommChannel:
nxt_commcmd_header:
.byte NXT_GDBMSG_TELEGRAMTYPE, 0x00, 0x00 /* padded to 3 bytes */
-hex2char_lut:
- .ascii "0123456789ABCDEF"
-
-/* Macros
- */
-
-
-/* _hex2char_lut
- * Internal routine to intialize the LUT address pointer
- */
- .macro _hex2char_lut addrptr
- ldr \addrptr, =hex2char_lut
- .endm
-
-/* _hex2char_cont
- * Internal routine that assumes that the LUT has been loaded.
- * This macro accepts a byte sized hex value as a parameter register(7:0) and returns the
- * ASCII equivalent in in the same register(7:0)
- * The second parameter is the LUT address pointer register to use (assumed to be initialized)
- * WARNING: Assumes that the value in register is sanity checked before invoking macro
- */
- .macro _hex2char_cont reg, addrptr
- ldrb \reg, [\addrptr, \reg]
- .endm
-
-/* _hex2char
- * This macro accepts a byte sized hex value as a parameter register(7:0) and returns the
- * ASCII equivalent in in the same register(7:0)
- * The second parameter is the LUT address pointer register to use (register content is destroyed)
- * WARNING: Assumes that the value in register is sanity checked before invoking macro
- */
- .macro _hex2char reg, addrptr
- _hex2char_lut \addrptr
- _hex2char_cont \reg, \addrptr
- .endm
-
-/* _char2hex
- * This macro accepts an ASCII char as a parameter register(7:0) and returns the
- * equivalent byte sized hex value in in the same register(7:0)
- * WARNING: Assumes that the char in register is a valid hex char before invoking macro
- */
- .macro _char2hex reg
- cmp \reg, #'A' /* If Alpha */
- bichs \reg, \reg, #ASCII_LOWER2UPPER_MASK /* Convert to Uppercase */
- subhs \reg, \reg, #7 /* Adjustment to allow for subtraction with 0x30 */
- sub \reg, \reg, #0x30 /* get final hex value */
- .endm
-
-
.code 32
.text
.align 4
-
-
-/* Utility Routines
- * GDB requires command parameters to be specified as Big Endian values.
- * However, the read/write register command expect the register contents to be specified in target byte order.
- * Hence we need both versions of multibyte conversion routines for word sized values.
- */
-
-/* hex2char
- * This routine accepts a byte sized hex value in R0(7:0) and returns the
- * ASCII equivalent in R0(7:0)
- */
- .global hex2char
-
-hex2char:
- stmfd sp!, {r1,lr}
- and r0, #NIBBLE0 /* make sure that input is sane */
- _hex2char r0, r1
- ldmfd sp!, {r1,pc}
-
-/* char2hex
- * This routine accepts an ASCII character in R0(7:0) and returns the
- * equivalent byte sized hex value in R0(7:0).
- * It accepts lowercase and uppercase ASCII Hex char inputs.
- * Invalid inputs return -1 as the value
-* On entry:
- * R0: ASCII character
- * On exit:
- * R0: Hex value
- */
- .global char2hex
-
-char2hex:
- and r0, r0, #BYTE0 /* make sure that input is sane */
- cmp r0, #'0'
- blo char2hex_error
- cmp r0, #'9'
- bls perform_char2hex
- cmp r0, #'A'
- blo char2hex_error
- cmp r0, #'F'
- bls perform_char2hex
- cmp r0, #'a'
- blo char2hex_error
- cmp r0, #'f'
- bhi char2hex_error
- /* Validated Hex Char */
-perform_char2hex:
- _char2hex r0 /* Return hex value in R0 */
- bx lr
-
-char2hex_error:
- mov r0, #-1 /* Set Return value to Error value */
- bx lr
-
-/* byte2ascii_cont
- * (Shared routine, does not perform sanity checks)
- * On entry:
- * R0: ASCII buffer pointer
- * R1[7:0]: byte value
- * On exit:
- * R0: Address of next empty char slot in buffer
- * R1: Destroyed
- *
- * This routine accepts an ASCII buffer pointer in R0 and a byte value in R1,
- * and stores the ASCII equivalent byte value in the buffer pointed to by R0.
- * Note: On return, R0 points to next empty char slot in buffer
- */
-byte2ascii_cont:
- stmfd sp!, {r2,r3,r4, lr}
- lsl r2, r1, #24 /* Keep copy of input byte value R1[7:0], shifted to MSB R2[31:24] */
- mov r4, #2 /* Loop counter */
- _hex2char_lut r3 /* initialize LUT pointer */
-1: ror r2, r2, #28 /* Rotate MSNibble R2[31:28] into LSNibble position R2[3:0] */
- and r1, r2, #NIBBLE0 /* Mask out everything else, store Nibble in R1 */
- _hex2char_cont r1, r3 /* Convert nibble to ASCII char */
- strb r1, [r0], #1
- subs r4, r4, #1 /* decrement loop counter */
- bne 1b
- ldmfd sp!, {r2,r3,r4, pc}
-
-/* byte2ascii
- * On entry:
- * R0: ASCII buffer pointer
- * R1[7:0]: Byte value
- * On exit:
- * R0: Address of next empty char slot in buffer
- * R1: Original Address of Buffer
- *
- * This routine accepts an ASCII buffer pointer in R0 and a byte value in R1,
- * and stores the ASCII equivalent byte value in the buffer pointed to by R0.
- * Note: On return, R0 points to the next empty char slot in buffer
- */
- .global byte2ascii
-
-byte2ascii:
- stmfd sp!, {r0, lr} /* Keep ASCII buffer pointer */
- and r1, #BYTE0 /* sanitize input */
- bl byte2ascii_cont
- ldmfd sp!, {r1, pc} /* return original string pointer in R1 */
-
-/* halfword2ascii_be
- * Big Endian version of halfword2ascii conversion routine
- * On entry:
- * R0: ASCII buffer pointer
- * R1[15:0]: Halfword value
- * On exit:
- * R0: Address of next empty char slot in buffer
- * R1: Original Address of Buffer
- *
- * This routine accepts an ASCII buffer pointer in R0 and a halfword value in R1,
- * and stores the ASCII equivalent halfword value in the buffer pointed to by R0.
- * Note: On return, R0 points to the next empty char slot in buffer
- */
- .global halfword2ascii_be
-halfword2ascii_be:
- stmfd sp!, {r0,r2,r3, lr} /* Keep ASCII buffer pointer */
- mov r3, #2 /* Loop Counter */
- mov r2, r1, lsl #16 /* copy of input halfword value R1[15:0], shifted to MSH R2[31:16] */
- b _conv_byte2ascii_be /* goto Byte conversion loop */
-
-/* halfword2ascii_le
- * Little Endian version of halfword2ascii conversion routine
- * On entry:
- * R0: ASCII buffer pointer
- * R1[15:0]: Halfword value
- * On exit:
- * R0: Address of next empty char slot in buffer
- * R1: Original Address of Buffer
- *
- * This routine accepts an ASCII buffer pointer in R0 and a halfword value in R1,
- * and stores the ASCII equivalent halfword value in the buffer pointed to by R0.
- * Note: On return, R0 points to the next empty char slot in buffer
- */
- .global halfword2ascii_le
-halfword2ascii_le:
- stmfd sp!, {r0,r2,r3, lr} /* Keep ASCII buffer pointer */
- mov r3, #2 /* Loop Counter */
- b _conv_byte2ascii_le /* goto Byte conversion loop */
-
-
-/* word2ascii_be
- * Big Endian version of word2ascii conversion routine
- * On entry:
- * R0: ASCII buffer pointer
- * R1[31:0]: Word value
- * On exit:
- * R0: Address of next empty char slot in buffer
- * R1: Original Address of Buffer
- *
- * This routine accepts an ASCII buffer pointer in R0 and a word value in R1,
- * and stores the ASCII equivalent word value in the buffer pointed to by R0.
- * Note: On return, R0 points to the next empty char slot in buffer
- */
- .global word2ascii_be
-word2ascii_be:
- stmfd sp!, {r0,r2,r3, lr} /* Keep ASCII buffer pointer */
- mov r2, r1 /* copy of input word value R1[31:0] */
- mov r3, #4 /* Loop Counter */
-
- /* Fall through to byte coversion loop */
-
-
-/* Big Endian Multibyte Convert: Rotate then convert */
-_conv_byte2ascii_be:
- ror r2, r2, #24 /* Rotate MSB R2[31:24] into LSB position R2[7:0] */
- and r1, r2, #BYTE0 /* Copy byte value in R2[7:0] into R1 */
- bl byte2ascii_cont /* R0: next ASCII buffer location pointer, R1: destroyed */
- subs r3, r3, #1
- bne _conv_byte2ascii_be
- ldmfd sp!, {r1,r2,r3, pc}
-
-/* word2ascii_le
- * Little Endian version of word2ascii conversion routine
- * On entry:
- * R0: ASCII buffer pointer
- * R1[31:0]: Word value
- * On exit:
- * R0: Address of next empty char slot in buffer
- * R1: Original Address of Buffer
- *
- * This routine accepts an ASCII buffer pointer in R0 and a word value in R1,
- * and stores the ASCII equivalent word value in the buffer pointed to by R0.
- * Note: On return, R0 points to the next empty char slot in buffer
- */
- .global word2ascii_le
-word2ascii_le:
- stmfd sp!, {r0,r2,r3, lr} /* Keep ASCII buffer pointer */
- mov r2, r1 /* copy of input word value R1[31:0] */
- mov r3, #4 /* Loop Counter */
-
- /* Fall through to byte coversion loop */
-
-/* Little Endian Multibyte Convert: Convert then rotate */
-_conv_byte2ascii_le:
- and r1, r2, #BYTE0 /* Copy byte value in R2[7:0] into R1 */
- bl byte2ascii_cont /* R0: next ASCII buffer location pointer, R1: destroyed */
- ror r2, r2, #8 /* Rotate LSB+1 R2[15:8] into LSB position R2[7:0] */
- subs r3, r3, #1
- bne _conv_byte2ascii_le
- ldmfd sp!, {r1,r2,r3, pc}
-
-
-/* ascii2hex_varlen_be
- * Big Endian version of ascii2hex_varlen conversion routine
- * (There is no Little Endian Version)
- * On entry:
- * R0: ASCII buffer pointer
- * On exit:
- * R0: Hex value
- * R1: Address of next char slot in buffer
- *
- * This routine accepts an ASCII buffer pointer in R0,
- * and returns the hex value in R0 for up to 8 Hex characters.
- * Note: On return, R1 points to the ASCII buffer location after the hex value chars.
- */
- .global ascii2hex_varlen_be
-
-ascii2hex_varlen_be:
- stmfd sp!, {r2,r3, lr}
- mov r3, #CMD_REG_REGPARAMLEN /* Set max count to 8 (Max Register size) */
- mov r1, r0 /* Use R1 as ASCII buffer pointer */
- mov r2, #0 /* Initialize Cummulative Results */
-2: ldrb r0, [r1] /* Load ASCII char for Hex Value */
- bl char2hex /* on return, hex value in R0, -1 for error */
- cmp r0, #-1
- beq _exit_ascii2hex_varlen
- orr r2, r0, r2, lsl #4 /* combined byte value */
- subs r3, r3, #1 /* Decrement Counter */
- add r1, r1, #1 /* Go to next char slot */
- bne 2b
-_exit_ascii2hex_varlen:
- mov r0, r2 /* Return results in R0 */
- ldmfd sp!, {r2,r3, pc}
-
-
-/* ascii2byte
- * On entry:
- * R0: ASCII buffer pointer
- * On exit:
- * R0[7:0]: Byte value
- * R1: Address of next char slot in buffer
- *
- * This routine accepts an ASCII buffer pointer in R0,
- * and returns the byte value in R0[7:0].
- * Note: On return, R1 points to the ASCII buffer location after the current 2 chars.
- * WARNING: This routine assumes that the input buffer was sanitized and contains valid Hex chars,
- * otherwise it will return invalid results.
- */
- .global ascii2byte
-
-ascii2byte:
- stmfd sp!, {r2, lr}
- mov r1, r0 /* Use R1 as ASCII buffer pointer */
- ldrb r0, [r1], #1 /* Load ASCII char for MSN */
- bl char2hex /* on return, hex value in R0, -1 for error (ignored) */
- mov r2, r0, lsl #4 /* Intermediate Results register */
- ldrb r0, [r1], #1 /* Load ASCII char for LSN */
- bl char2hex /* on return, hex value in R0, -1 for error (ignored) */
- orr r0, r2, r0 /* combined byte value */
- ldmfd sp!, {r2, pc}
-
-/* ascii2halfword_be
- * Big Endian version of ascii2halfword conversion routine
- * On entry:
- * R0: ASCII buffer pointer
- * On exit:
- * R0[15:0]: Halfword value
- * R1: Address of next char slot in buffer
- *
- * This routine accepts an ASCII buffer pointer in R0,
- * and returns the Halfword value in R0[15:0].
- * Note: On return, R1 points to the ASCII buffer location after the current 4 chars.
- * WARNING: This routine assumes that the input buffer was sanitized and contains valid Hex chars,
- * otherwise it will return invalid results.
- */
- .global ascii2halfword_be
-
-ascii2halfword_be:
- stmfd sp!, {r2,r3, lr}
- mov r3, #2 /* Loop counter */
- b _conv_ascii2byte_be
-
-/* ascii2halfword_le
- * Little Endian version of ascii2halfword conversion routine
- * On entry:
- * R0: ASCII buffer pointer
- * On exit:
- * R0[15:0]: Halfword value
- * R1: Address of next char slot in buffer
- *
- * This routine accepts an ASCII buffer pointer in R0,
- * and returns the Halfword value in R0[15:0].
- * Note: On return, R1 points to the ASCII buffer location after the current 4 chars.
- * WARNING: This routine assumes that the input buffer was sanitized and contains valid Hex chars,
- * otherwise it will return invalid results.
- */
- .global ascii2halfword_le
-
-ascii2halfword_le:
- stmfd sp!, {r2,r3, lr}
- mov r3, #2 /* Loop counter */
- b _conv_ascii2byte_le
-
-
-/* ascii2word_be
- * Big Endian version of ascii2word conversion routine
- * On entry:
- * R0: ASCII buffer pointer
- * On exit:
- * R0[31:0]: Word value
- * R1: Address of next char slot in buffer
- *
- * This routine accepts an ASCII buffer pointer in R0,
- * and returns the word value in R0[31:0].
- * Note: On return, R1 points to the ASCII buffer location after the current 8 chars.
- * WARNING: This routine assumes that the input buffer was sanitized and contains valid Hex chars,
- * otherwise it will return invalid results.
- */
- .global ascii2word_be
-
-ascii2word_be:
- stmfd sp!, {r2,r3, lr}
- mov r3, #4 /* Loop counter */
-
- /* Fall through to byte coversion loop */
-
-_conv_ascii2byte_be:
- teq r0, #0
- beq _exit_conv_ascii2byte_be /* exit if NULL pointer in R0 */
- mov r2, #0 /* Initialize Cummulative value */
-2: bl ascii2byte
- orr r2, r0, r2, lsl #8 /* Merge current byte with cummulative value */
- mov r0, r1 /* Copy next char pointer to R0 for next byte */
- subs r3, r3, #1
- bne 2b
- mov r0, r2 /* Copy it to R0 as return value */
-
-_exit_conv_ascii2byte_be:
- ldmfd sp!, {r2,r3, pc} /* return hex value in R0 */
-
-/* ascii2word_le
- * Litle Endian version of ascii2word conversion routine
- * On entry:
- * R0: ASCII buffer pointer
- * On exit:
- * R0[31:0]: Word value
- * R1: Address of next char slot in buffer
- *
- * This routine accepts an ASCII buffer pointer in R0,
- * and returns the word value in R0[31:0].
- * Note: On return, R1 points to the ASCII buffer location after the current 8 chars.
- * WARNING: This routine assumes that the input buffer was sanitized and contains valid Hex chars,
- * otherwise it will return invalid results.
- */
- .global ascii2word_le
-
-ascii2word_le:
- stmfd sp!, {r2,r3, lr}
- mov r3, #4 /* Loop counter */
-
- /* Fall through to byte coversion loop */
-
-_conv_ascii2byte_le:
- teq r0, #0
- beq _exit_conv_ascii2byte_le /* exit if NULL pointer in R0 */
- push {r3} /* Need to keep couter for final value adjustment */
- mov r2, #0 /* Initialize Cummulative value */
-2: bl ascii2byte
- orr r2, r0, r2, ror #8 /* Merge current byte with cummulative value */
- mov r0, r1 /* Copy next char pointer to R0 for next byte */
- subs r3, r3, #1
- bne 2b
- /* Cummulative value done, need to rotate it into the correct position for return value */
- pop {r3} /* retrieve counter */
- rsb r3, r3, #5 /* 5 - count */
- lsl r3, r3, #3 /* [(5-count) x 8] bits to rotate */
- mov r0, r2, ror r3 /* Copy it to R0 as return value */
-
-_exit_conv_ascii2byte_le:
- ldmfd sp!, {r2,r3, pc} /* return hex value in R0 */
-
-
-
-
/* Debugger Communications Routines
* It does not make sense to pass information from the Debugger Module to the Comm. link one character
* at a time, especially if we're not using a native serial interface (e.g., EIA-232). Consequently
@@ -577,24 +160,26 @@ dbg__comm_init:
str r0, [r1, #NXTCOMMCHANNEL_OFFSET] /* Clear NXT Channel on INIT */
ldmfd sp!, {pc}
-_dbg__comm_readbuf_reset:
#ifdef __NXOS__
+_dbg__comm_readbuf_reset:
stmfd sp!, {lr}
ldr r0, =debug_InCommBuf
mov r1, #USB_BUFSIZE
- ldr r2, =nx_usb_read
+ ldr r2, =fantom_init
mov lr, pc
bx r2
+#if 0
ldr r1, =debug_nxtMsgLength
mov r0, #0
str r0, [r1] /* Clear NxOS Received Message Length */
+#endif
ldmfd sp!, {pc}
#else
+_dbg__comm_readbuf_reset:
ldr r1, =debug_nxtMsgLength
mov r0, #0
str r0, [r1] /* Clear NXT Received Message Length */
bx lr
-#endif
.global dbg__copyNxtDebugMsg
/* dbg__copyNxtDebugMsg
@@ -616,6 +201,7 @@ dbg__copyNxtDebugMsg:
*/
_dbg_memcpy r1, r0, r2, r3 /* r3: scratch register */
bx lr
+#endif
/* _dbg_reset_msgTxBuf_AppendPtr
* Internal variable to reset pointers.
@@ -638,7 +224,7 @@ _dbg_reset_msgTxBuf_AppendPtr:
_dbg__commHasMsg:
stmfd sp!, {lr}
#ifdef __NXOS__
- ldr r2, =nx_usb_data_read
+ ldr r2, =nx_usb_fantom_data_read
mov lr,pc
bx r2 /* Number of bytes read in R0 */
/* Note: The return value in R0 is the Comm Buffer Size, includes NXT Direct Command Header */
@@ -662,7 +248,8 @@ _dbg__commHasMsg:
b _exit_dbg__commHasMsg
invalid_CommMsg:
- mov r0, #0
+ bl _dbg__comm_readbuf_reset /* Next Comm telegram transaction */
+ mov r0, #0
_exit_dbg__commHasMsg:
ldmfd sp!, {pc}
@@ -837,9 +424,11 @@ _dbg__sendCommMsg:
mov r4, r0 /* Keep Comm Buffer length in R4 */
#ifdef __NXOS__
/* Check USB bus status, transmit message if possible */
- bl nx_usb_is_connected /* R0 = True if USB is ready */
- cmp r0, #TRUE
- bne _exit_dbg__sendCommMsg
+ bl nx_usb_is_connected /* R0 = TRUE (#1) if USB is ready */
+ teq r0, #0 /* FALSE == #0;
+ We can't check for True condition since values
+ used by C-Compiler & ARMDEBUG are different */
+ beq _dbg__sendCommMsgFailed
/* Actual transmission (blocking) */
ldr r0, =debug_OutCommBuf /* data pointer parameter */
@@ -847,9 +436,11 @@ _dbg__sendCommMsg:
bl nx_usb_write
1: bl nx_usb_data_written /* R0 = True if data has been sent */
- cmp r0, #TRUE
+ teq r0, #0 /* FALSE == #0;
+ We can't check for True condition since values
+ used by C-Compiler & ARMDEBUG are different */
/* FIXME: implement timeout */
- bne 1b /* Busy Wait Loop */
+ beq 1b /* Busy Wait Loop */
#else
ldr r0, =debug_nxtCommChannel
ldr r0, [r0] /* Get Channel Enum */
diff --git a/AT91SAM7S256/armdebug/Debugger/debug_hexutils.S b/AT91SAM7S256/armdebug/Debugger/debug_hexutils.S
new file mode 100644
index 0000000..d54445b
--- /dev/null
+++ b/AT91SAM7S256/armdebug/Debugger/debug_hexutils.S
@@ -0,0 +1,457 @@
+/** @file debug_hexutils.S
+ * @brief GDB hexadecimal conversion utility routines
+ *
+ */
+
+/* Copyright (C) 2007-2011 the NxOS developers
+ *
+ * Module Developed by: TC Wan <tcwan@cs.usm.my>
+ *
+ * See AUTHORS for a full list of the developers.
+ *
+ * See COPYING for redistribution license
+ *
+ */
+
+
+#define __ASSEMBLY__
+
+#include "debug_internals.h"
+
+.data
+.align 4
+
+hex2char_lut:
+ .ascii "0123456789ABCDEF"
+
+/* Macros
+ */
+
+
+/* _hex2char_lut
+ * Internal routine to intialize the LUT address pointer
+ */
+ .macro _hex2char_lut addrptr
+ ldr \addrptr, =hex2char_lut
+ .endm
+
+/* _hex2char_cont
+ * Internal routine that assumes that the LUT has been loaded.
+ * This macro accepts a byte sized hex value as a parameter register(7:0) and returns the
+ * ASCII equivalent in in the same register(7:0)
+ * The second parameter is the LUT address pointer register to use (assumed to be initialized)
+ * WARNING: Assumes that the value in register is sanity checked before invoking macro
+ */
+ .macro _hex2char_cont reg, addrptr
+ ldrb \reg, [\addrptr, \reg]
+ .endm
+
+/* _hex2char
+ * This macro accepts a byte sized hex value as a parameter register(7:0) and returns the
+ * ASCII equivalent in in the same register(7:0)
+ * The second parameter is the LUT address pointer register to use (register content is destroyed)
+ * WARNING: Assumes that the value in register is sanity checked before invoking macro
+ */
+ .macro _hex2char reg, addrptr
+ _hex2char_lut \addrptr
+ _hex2char_cont \reg, \addrptr
+ .endm
+
+/* _char2hex
+ * This macro accepts an ASCII char as a parameter register(7:0) and returns the
+ * equivalent byte sized hex value in in the same register(7:0)
+ * WARNING: Assumes that the char in register is a valid hex char before invoking macro
+ */
+ .macro _char2hex reg
+ cmp \reg, #'A' /* If Alpha */
+ bichs \reg, \reg, #ASCII_LOWER2UPPER_MASK /* Convert to Uppercase */
+ subhs \reg, \reg, #7 /* Adjustment to allow for subtraction with 0x30 */
+ sub \reg, \reg, #0x30 /* get final hex value */
+ .endm
+
+
+.code 32
+.text
+.align 4
+
+
+/* Utility Routines
+ * GDB requires command parameters to be specified as Big Endian values.
+ * However, the read/write register command expect the register contents to be specified in target byte order.
+ * Hence we need both versions of multibyte conversion routines for word sized values.
+ */
+
+/* hex2char
+ * This routine accepts a byte sized hex value in R0(7:0) and returns the
+ * ASCII equivalent in R0(7:0)
+ */
+ .global hex2char
+
+hex2char:
+ stmfd sp!, {r1,lr}
+ and r0, #NIBBLE0 /* make sure that input is sane */
+ _hex2char r0, r1
+ ldmfd sp!, {r1,pc}
+
+/* char2hex
+ * This routine accepts an ASCII character in R0(7:0) and returns the
+ * equivalent byte sized hex value in R0(7:0).
+ * It accepts lowercase and uppercase ASCII Hex char inputs.
+ * Invalid inputs return -1 as the value
+* On entry:
+ * R0: ASCII character
+ * On exit:
+ * R0: Hex value
+ */
+ .global char2hex
+
+char2hex:
+ and r0, r0, #BYTE0 /* make sure that input is sane */
+ cmp r0, #'0'
+ blo char2hex_error
+ cmp r0, #'9'
+ bls perform_char2hex
+ cmp r0, #'A'
+ blo char2hex_error
+ cmp r0, #'F'
+ bls perform_char2hex
+ cmp r0, #'a'
+ blo char2hex_error
+ cmp r0, #'f'
+ bhi char2hex_error
+ /* Validated Hex Char */
+perform_char2hex:
+ _char2hex r0 /* Return hex value in R0 */
+ bx lr
+
+char2hex_error:
+ mov r0, #-1 /* Set Return value to Error value */
+ bx lr
+
+/* byte2ascii_cont
+ * (Shared routine, does not perform sanity checks)
+ * On entry:
+ * R0: ASCII buffer pointer
+ * R1[7:0]: byte value
+ * On exit:
+ * R0: Address of next empty char slot in buffer
+ * R1: Destroyed
+ *
+ * This routine accepts an ASCII buffer pointer in R0 and a byte value in R1,
+ * and stores the ASCII equivalent byte value in the buffer pointed to by R0.
+ * Note: On return, R0 points to next empty char slot in buffer
+ */
+byte2ascii_cont:
+ stmfd sp!, {r2,r3,r4, lr}
+ lsl r2, r1, #24 /* Keep copy of input byte value R1[7:0], shifted to MSB R2[31:24] */
+ mov r4, #2 /* Loop counter */
+ _hex2char_lut r3 /* initialize LUT pointer */
+1: ror r2, r2, #28 /* Rotate MSNibble R2[31:28] into LSNibble position R2[3:0] */
+ and r1, r2, #NIBBLE0 /* Mask out everything else, store Nibble in R1 */
+ _hex2char_cont r1, r3 /* Convert nibble to ASCII char */
+ strb r1, [r0], #1
+ subs r4, r4, #1 /* decrement loop counter */
+ bne 1b
+ ldmfd sp!, {r2,r3,r4, pc}
+
+/* byte2ascii
+ * On entry:
+ * R0: ASCII buffer pointer
+ * R1[7:0]: Byte value
+ * On exit:
+ * R0: Address of next empty char slot in buffer
+ * R1: Original Address of Buffer
+ *
+ * This routine accepts an ASCII buffer pointer in R0 and a byte value in R1,
+ * and stores the ASCII equivalent byte value in the buffer pointed to by R0.
+ * Note: On return, R0 points to the next empty char slot in buffer
+ */
+ .global byte2ascii
+
+byte2ascii:
+ stmfd sp!, {r0, lr} /* Keep ASCII buffer pointer */
+ and r1, #BYTE0 /* sanitize input */
+ bl byte2ascii_cont
+ ldmfd sp!, {r1, pc} /* return original string pointer in R1 */
+
+/* halfword2ascii_be
+ * Big Endian version of halfword2ascii conversion routine
+ * On entry:
+ * R0: ASCII buffer pointer
+ * R1[15:0]: Halfword value
+ * On exit:
+ * R0: Address of next empty char slot in buffer
+ * R1: Original Address of Buffer
+ *
+ * This routine accepts an ASCII buffer pointer in R0 and a halfword value in R1,
+ * and stores the ASCII equivalent halfword value in the buffer pointed to by R0.
+ * Note: On return, R0 points to the next empty char slot in buffer
+ */
+ .global halfword2ascii_be
+halfword2ascii_be:
+ stmfd sp!, {r0,r2,r3, lr} /* Keep ASCII buffer pointer */
+ mov r3, #2 /* Loop Counter */
+ mov r2, r1, lsl #16 /* copy of input halfword value R1[15:0], shifted to MSH R2[31:16] */
+ b _conv_byte2ascii_be /* goto Byte conversion loop */
+
+/* halfword2ascii_le
+ * Little Endian version of halfword2ascii conversion routine
+ * On entry:
+ * R0: ASCII buffer pointer
+ * R1[15:0]: Halfword value
+ * On exit:
+ * R0: Address of next empty char slot in buffer
+ * R1: Original Address of Buffer
+ *
+ * This routine accepts an ASCII buffer pointer in R0 and a halfword value in R1,
+ * and stores the ASCII equivalent halfword value in the buffer pointed to by R0.
+ * Note: On return, R0 points to the next empty char slot in buffer
+ */
+ .global halfword2ascii_le
+halfword2ascii_le:
+ stmfd sp!, {r0,r2,r3, lr} /* Keep ASCII buffer pointer */
+ mov r3, #2 /* Loop Counter */
+ b _conv_byte2ascii_le /* goto Byte conversion loop */
+
+
+/* word2ascii_be
+ * Big Endian version of word2ascii conversion routine
+ * On entry:
+ * R0: ASCII buffer pointer
+ * R1[31:0]: Word value
+ * On exit:
+ * R0: Address of next empty char slot in buffer
+ * R1: Original Address of Buffer
+ *
+ * This routine accepts an ASCII buffer pointer in R0 and a word value in R1,
+ * and stores the ASCII equivalent word value in the buffer pointed to by R0.
+ * Note: On return, R0 points to the next empty char slot in buffer
+ */
+ .global word2ascii_be
+word2ascii_be:
+ stmfd sp!, {r0,r2,r3, lr} /* Keep ASCII buffer pointer */
+ mov r2, r1 /* copy of input word value R1[31:0] */
+ mov r3, #4 /* Loop Counter */
+
+ /* Fall through to byte coversion loop */
+
+
+/* Big Endian Multibyte Convert: Rotate then convert */
+_conv_byte2ascii_be:
+ ror r2, r2, #24 /* Rotate MSB R2[31:24] into LSB position R2[7:0] */
+ and r1, r2, #BYTE0 /* Copy byte value in R2[7:0] into R1 */
+ bl byte2ascii_cont /* R0: next ASCII buffer location pointer, R1: destroyed */
+ subs r3, r3, #1
+ bne _conv_byte2ascii_be
+ ldmfd sp!, {r1,r2,r3, pc}
+
+/* word2ascii_le
+ * Little Endian version of word2ascii conversion routine
+ * On entry:
+ * R0: ASCII buffer pointer
+ * R1[31:0]: Word value
+ * On exit:
+ * R0: Address of next empty char slot in buffer
+ * R1: Original Address of Buffer
+ *
+ * This routine accepts an ASCII buffer pointer in R0 and a word value in R1,
+ * and stores the ASCII equivalent word value in the buffer pointed to by R0.
+ * Note: On return, R0 points to the next empty char slot in buffer
+ */
+ .global word2ascii_le
+word2ascii_le:
+ stmfd sp!, {r0,r2,r3, lr} /* Keep ASCII buffer pointer */
+ mov r2, r1 /* copy of input word value R1[31:0] */
+ mov r3, #4 /* Loop Counter */
+
+ /* Fall through to byte coversion loop */
+
+/* Little Endian Multibyte Convert: Convert then rotate */
+_conv_byte2ascii_le:
+ and r1, r2, #BYTE0 /* Copy byte value in R2[7:0] into R1 */
+ bl byte2ascii_cont /* R0: next ASCII buffer location pointer, R1: destroyed */
+ ror r2, r2, #8 /* Rotate LSB+1 R2[15:8] into LSB position R2[7:0] */
+ subs r3, r3, #1
+ bne _conv_byte2ascii_le
+ ldmfd sp!, {r1,r2,r3, pc}
+
+
+/* ascii2hex_varlen_be
+ * Big Endian version of ascii2hex_varlen conversion routine
+ * (There is no Little Endian Version)
+ * On entry:
+ * R0: ASCII buffer pointer
+ * On exit:
+ * R0: Hex value
+ * R1: Address of next char slot in buffer
+ *
+ * This routine accepts an ASCII buffer pointer in R0,
+ * and returns the hex value in R0 for up to 8 Hex characters.
+ * Note: On return, R1 points to the ASCII buffer location after the hex value chars.
+ */
+ .global ascii2hex_varlen_be
+
+ascii2hex_varlen_be:
+ stmfd sp!, {r2,r3, lr}
+ mov r3, #CMD_REG_REGPARAMLEN /* Set max count to 8 (Max Register size) */
+ mov r1, r0 /* Use R1 as ASCII buffer pointer */
+ mov r2, #0 /* Initialize Cummulative Results */
+2: ldrb r0, [r1] /* Load ASCII char for Hex Value */
+ bl char2hex /* on return, hex value in R0, -1 for error */
+ cmp r0, #-1
+ beq _exit_ascii2hex_varlen
+ orr r2, r0, r2, lsl #4 /* combined byte value */
+ subs r3, r3, #1 /* Decrement Counter */
+ add r1, r1, #1 /* Go to next char slot */
+ bne 2b
+_exit_ascii2hex_varlen:
+ mov r0, r2 /* Return results in R0 */
+ ldmfd sp!, {r2,r3, pc}
+
+
+/* ascii2byte
+ * On entry:
+ * R0: ASCII buffer pointer
+ * On exit:
+ * R0[7:0]: Byte value
+ * R1: Address of next char slot in buffer
+ *
+ * This routine accepts an ASCII buffer pointer in R0,
+ * and returns the byte value in R0[7:0].
+ * Note: On return, R1 points to the ASCII buffer location after the current 2 chars.
+ * WARNING: This routine assumes that the input buffer was sanitized and contains valid Hex chars,
+ * otherwise it will return invalid results.
+ */
+ .global ascii2byte
+
+ascii2byte:
+ stmfd sp!, {r2, lr}
+ mov r1, r0 /* Use R1 as ASCII buffer pointer */
+ ldrb r0, [r1], #1 /* Load ASCII char for MSN */
+ bl char2hex /* on return, hex value in R0, -1 for error (ignored) */
+ mov r2, r0, lsl #4 /* Intermediate Results register */
+ ldrb r0, [r1], #1 /* Load ASCII char for LSN */
+ bl char2hex /* on return, hex value in R0, -1 for error (ignored) */
+ orr r0, r2, r0 /* combined byte value */
+ ldmfd sp!, {r2, pc}
+
+/* ascii2halfword_be
+ * Big Endian version of ascii2halfword conversion routine
+ * On entry:
+ * R0: ASCII buffer pointer
+ * On exit:
+ * R0[15:0]: Halfword value
+ * R1: Address of next char slot in buffer
+ *
+ * This routine accepts an ASCII buffer pointer in R0,
+ * and returns the Halfword value in R0[15:0].
+ * Note: On return, R1 points to the ASCII buffer location after the current 4 chars.
+ * WARNING: This routine assumes that the input buffer was sanitized and contains valid Hex chars,
+ * otherwise it will return invalid results.
+ */
+ .global ascii2halfword_be
+
+ascii2halfword_be:
+ stmfd sp!, {r2,r3, lr}
+ mov r3, #2 /* Loop counter */
+ b _conv_ascii2byte_be
+
+/* ascii2halfword_le
+ * Little Endian version of ascii2halfword conversion routine
+ * On entry:
+ * R0: ASCII buffer pointer
+ * On exit:
+ * R0[15:0]: Halfword value
+ * R1: Address of next char slot in buffer
+ *
+ * This routine accepts an ASCII buffer pointer in R0,
+ * and returns the Halfword value in R0[15:0].
+ * Note: On return, R1 points to the ASCII buffer location after the current 4 chars.
+ * WARNING: This routine assumes that the input buffer was sanitized and contains valid Hex chars,
+ * otherwise it will return invalid results.
+ */
+ .global ascii2halfword_le
+
+ascii2halfword_le:
+ stmfd sp!, {r2,r3, lr}
+ mov r3, #2 /* Loop counter */
+ b _conv_ascii2byte_le
+
+
+/* ascii2word_be
+ * Big Endian version of ascii2word conversion routine
+ * On entry:
+ * R0: ASCII buffer pointer
+ * On exit:
+ * R0[31:0]: Word value
+ * R1: Address of next char slot in buffer
+ *
+ * This routine accepts an ASCII buffer pointer in R0,
+ * and returns the word value in R0[31:0].
+ * Note: On return, R1 points to the ASCII buffer location after the current 8 chars.
+ * WARNING: This routine assumes that the input buffer was sanitized and contains valid Hex chars,
+ * otherwise it will return invalid results.
+ */
+ .global ascii2word_be
+
+ascii2word_be:
+ stmfd sp!, {r2,r3, lr}
+ mov r3, #4 /* Loop counter */
+
+ /* Fall through to byte coversion loop */
+
+_conv_ascii2byte_be:
+ teq r0, #0
+ beq _exit_conv_ascii2byte_be /* exit if NULL pointer in R0 */
+ mov r2, #0 /* Initialize Cummulative value */
+2: bl ascii2byte
+ orr r2, r0, r2, lsl #8 /* Merge current byte with cummulative value */
+ mov r0, r1 /* Copy next char pointer to R0 for next byte */
+ subs r3, r3, #1
+ bne 2b
+ mov r0, r2 /* Copy it to R0 as return value */
+
+_exit_conv_ascii2byte_be:
+ ldmfd sp!, {r2,r3, pc} /* return hex value in R0 */
+
+/* ascii2word_le
+ * Litle Endian version of ascii2word conversion routine
+ * On entry:
+ * R0: ASCII buffer pointer
+ * On exit:
+ * R0[31:0]: Word value
+ * R1: Address of next char slot in buffer
+ *
+ * This routine accepts an ASCII buffer pointer in R0,
+ * and returns the word value in R0[31:0].
+ * Note: On return, R1 points to the ASCII buffer location after the current 8 chars.
+ * WARNING: This routine assumes that the input buffer was sanitized and contains valid Hex chars,
+ * otherwise it will return invalid results.
+ */
+ .global ascii2word_le
+
+ascii2word_le:
+ stmfd sp!, {r2,r3, lr}
+ mov r3, #4 /* Loop counter */
+
+ /* Fall through to byte coversion loop */
+
+_conv_ascii2byte_le:
+ teq r0, #0
+ beq _exit_conv_ascii2byte_le /* exit if NULL pointer in R0 */
+ push {r3} /* Need to keep couter for final value adjustment */
+ mov r2, #0 /* Initialize Cummulative value */
+2: bl ascii2byte
+ orr r2, r0, r2, ror #8 /* Merge current byte with cummulative value */
+ mov r0, r1 /* Copy next char pointer to R0 for next byte */
+ subs r3, r3, #1
+ bne 2b
+ /* Cummulative value done, need to rotate it into the correct position for return value */
+ pop {r3} /* retrieve counter */
+ rsb r3, r3, #5 /* 5 - count */
+ lsl r3, r3, #3 /* [(5-count) x 8] bits to rotate */
+ mov r0, r2, ror r3 /* Copy it to R0 as return value */
+
+_exit_conv_ascii2byte_le:
+ ldmfd sp!, {r2,r3, pc} /* return hex value in R0 */
+
diff --git a/AT91SAM7S256/armdebug/Debugger/debug_internals.h b/AT91SAM7S256/armdebug/Debugger/debug_internals.h
index 82c0e38..c7f5d16 100644
--- a/AT91SAM7S256/armdebug/Debugger/debug_internals.h
+++ b/AT91SAM7S256/armdebug/Debugger/debug_internals.h
@@ -88,6 +88,9 @@
#define CMD_REG_SETONE_MINPARAMLEN (2 + CMD_REG_REGPARAMLEN)
#define CMD_REG_SETONE_MAXPARAMLEN (3 + CMD_REG_REGPARAMLEN)
#define CMD_REG_SETALL_PARAMLEN (CMD_REG_NUMREGS*CMD_REG_REGPARAMLEN)
+#define CMD_KILL_PARAMLEN 0
+#define CMD_DETACH_PARAMLEN 0
+
/*@}*/
/** @name Debug Memory Command Constants.
diff --git a/AT91SAM7S256/armdebug/Debugger/debug_runlooptasks.S b/AT91SAM7S256/armdebug/Debugger/debug_runlooptasks.S
index fd17412..48b7e5a 100644
--- a/AT91SAM7S256/armdebug/Debugger/debug_runlooptasks.S
+++ b/AT91SAM7S256/armdebug/Debugger/debug_runlooptasks.S
@@ -1,4 +1,4 @@
-/** @file debug_runloop.S
+/** @file debug_runlooptasks.S
* @brief GDB Server platform Run Loop
*
*/
@@ -13,6 +13,11 @@
*
*/
+/*
+ * This file contains platform specific code.
+ * This include ABORT Mode Debugger Run Loop operation,
+ * as well as Debugger Interfacing code to the platform code.
+ */
/*
* The Debugger has to implement a Run Loop in ABORT mode
@@ -48,11 +53,10 @@
* ^-------v v-------^
*
* The Platform will invoke dbg__bkpt_init() after hardware and system initialization,
- * before entering the Platform Run Loop. This switches processing over to the
- * Debugger Run Loop which will wait for the GDB command to Go/Step/Cont before
- * returning control to the Platform Run Loop.
+ * before entering the Platform Run Loop. This configures the Debugger, but does not
+ * invoke the Debugger Run Loop unless a Manual Breakpoint is found in the platform code.
*
- * Subsequently, Debugger Run Loop will be triggered by Breakpoints, or
+ * Subsequently, the Debugger Run Loop will be triggered by Breakpoints, or
* when the communications subsystem receives a GDB Command.
*
* The Debugger Run Loop is actually dbg__bkpt_waitCMD(), this file contains
@@ -65,17 +69,31 @@
*/
#define __ASSEMBLY__
- .global dbg__runloopTasks
+#include "debug_internals.h"
+#include "debug_macros.h"
+#include "debug_stub.h"
+ .code 32
+ .align 4
+ .global dbg__runloopTasks
+ .global dbg__reboot
#ifdef __NXOS__
-/* NxOS Run Loop */
+/****************************************************************************
+ *
+ * NxOS Run Loop
+ *
+ ****************************************************************************/
dbg__runloopTasks:
/* Currently, there's nothing that needs to be done in the NxOS Run Loop */
bx lr
#else
-/* NXT Firmware Run Loop */
+/****************************************************************************
+ *
+ * NXT Firmware Run Loop
+ *
+ ****************************************************************************/
.extern cCommCtrl
dbg__runloopTasks:
@@ -85,3 +103,143 @@ dbg__runloopTasks:
/* OSWatchdogWrite is a NULL function in the NXT Firmware?! */
pop {pc}
#endif
+
+#ifdef __NXOS__
+ .extern nx_core_reset
+/****************************************************************************
+ *
+ * NxOS Reboot Routine
+ *
+ ****************************************************************************/
+ dbg__reboot:
+ b nx_core_reset /* Reboot Brick, won't return */
+
+#else
+/****************************************************************************
+ *
+ * NXT Firmware Reboot Routine
+ *
+ ****************************************************************************/
+dbg__reboot:
+ bx lr
+#endif
+
+
+#ifdef __NXOS__
+/****************************************************************************
+ *
+ * GDB Debugger Invocation Routine for NxOS
+ *
+ ****************************************************************************/
+ .code 32
+ .align 4
+
+ .extern dbg__install_singlestep
+ .extern dbg__activate_singlestep
+ .extern irq_stack_frame_address
+ .global nxos__handleDebug
+/* nxos__handleDebug
+ * Prepare to switch to Debug Mode
+ * int nxos__handleDebug(comm_chan_t channel);
+ *
+ * This routine is called from NxOS Fantom library to setup
+ * Single Step Breakpoint in preparation for Debugger invocation if we're in
+ * normal execution mode.
+ *
+ * It returns to complete the IRQ handling normally, after which the single
+ * step breakpoint will be triggered, and the incoming GDB message will then
+ * be processed in the dbg__bkpt_waitCMD() loop.
+ *
+ * If we're in Debugger Mode already, then just return and let the
+ * dbg__bkpt_waitCMD() loop handle it normally.
+ *
+ * If we're operating in normal NxOS mode, return True (!0)
+ * If we're already in Debugger Mode, return False (0)
+ */
+nxos__handleDebug:
+ push {lr}
+ /* This routine is called from nx__irq_handler() via fantom_filter_packet().
+ * The operating mode should already have been configured by the IRQ interrupt handler.
+ *
+ * The IRQ Stack Frame Pointer will contains the LR and SPSR from the topmost interrupted task
+ * if it is non-zero (NxOS supports nested IRQs)
+ */
+
+ ldr r3, =debug_nxtCommChannel
+ str r0, [r3] /* Keep track of which communications link was used (USB/Bluetooth) */
+
+ /* Check our current operating mode */
+ mov r0, #FALSE /* Setup Default Return value (False) */
+ mrs r3, cpsr /* Copy CPSR to r3 */
+ and r3, r3, #CPSR_MODE /* Get current mode */
+ teq r3, #MODE_ABT /* Are we in Abort (Debug) mode? */
+ beq exit_nxos__handleDebug /* Yes, return False */
+
+ /* Retrieve ISR Return Address */
+ ldr r3, =irq_stack_frame_address
+ ldr r3, [r3] /* Get Interrupt Stack Pointer */
+ teq r3, #0
+ beq exit_nxos__handleDebug /* NULL Interrupt Stack Frame Pointer, exit (status: False) */
+
+nxos_switch2debug:
+ /* Since the Interrupt Stack Frame Pointer points to the top of the stack frame,
+ * we'll have to use Load Empty Ascending Stack (LDMEA == LDMDB) to access the variables
+ */
+ ldmdb r3, {r1,r2} /* R1: LR, R2: SPSR */
+ tst r2, #CPSR_THUMB /* Check for Thumb Mode */
+ orrne r1, r1, #1 /* Configure for Thumb Single Step Breakpoint */
+ bl dbg__install_singlestep /* Setup Single Step, next instruction address returned in r1 */
+ bl dbg__activate_singlestep
+ mov r0, #TRUE /* We're going to switch to Debug Mode (via Single Step Breakpoint) */
+
+exit_nxos__handleDebug:
+ pop {r1}
+ bx r1 /* In case we have Interworking from different caller mode */
+
+#else
+
+/****************************************************************************
+ *
+ * GDB Debugger Invocation Routine for NXT Firmware
+ *
+ ****************************************************************************/
+ .code 16
+ .align 2
+
+ .extern dbg__copyNxtDebugMsg
+ .global cCommHandleDebug
+ .thumb_func
+/* cCommHandleDebug
+ * Switch Mode to Debugger.
+ * Used by NXT Firmware only
+ *
+ * UWORD cCommHandleDebug(UBYTE *pInBuf, UBYTE CmdBit, UWORD MsgLength);
+ *
+ * This routine is called from cCommInterprete either in normal operation mode (SVC)
+ * or else when we're in debug mode (ABORT) which uses the cCommCtrl() routine to handle
+ * I/O with the Host.
+ *
+ * On entry, the message is copied from the NXT buffer into our own buffers.
+ *
+ * If this is accessed from normal operation mode, we need to switch mode to
+ * ABORT mode to handle the incoming message using a Manual Breakpoint instruction.
+ * When DEBUG is exited, the execution resumes from the instruction following the Breakpoint.
+ */
+cCommHandleDebug:
+/* Arg Registers are not preserved since this is invoked explicitly */
+ push {lr} /* store arg registers */
+ bl dbg__copyNxtDebugMsg /* setup Debugger Message Buffers, validate input, CPSR returned in R0 */
+ _dbg_getmode r0 /* Get Debug Mode */
+ cmp r0, #(TRUE & BYTE0) /* Confine it to Byte size */
+
+ /* If Debug Mode is TRUE, this means that we're already running the Debugger */
+ beq _cCommHandleDebug_cont
+ /* Else, we're in normal operation mode (SVC), or other mode (??!) and need to force a switch to Debug mode */
+ dbg__bkpt_thumb
+_cCommHandleDebug_cont:
+ mov r0, #0 /* FIXME: Return Status */
+ pop {r1} /* Can't Pop LR directly */
+ bx r1 /* Safe code: actually we should be able to Pop PC since the caller is Thumb Mode */
+
+ .ltorg
+#endif
diff --git a/AT91SAM7S256/armdebug/Debugger/debug_stub.S b/AT91SAM7S256/armdebug/Debugger/debug_stub.S
index 4e26da3..b987d7c 100644
--- a/AT91SAM7S256/armdebug/Debugger/debug_stub.S
+++ b/AT91SAM7S256/armdebug/Debugger/debug_stub.S
@@ -79,6 +79,8 @@
* MAA..AA,LLLL:bb..bb
* Write LLLL bytes at address AA.AA OK or ENN
*
+ * D Detach (equivalent to continue Ack Only
+ * at current address)
* c Resume at current address SNN ( signal NN)
* cAA..AA Continue at address AA..AA SNN
*
@@ -142,6 +144,21 @@
#include "debug_internals.h"
#include "debug_macros.h"
+ /* Hexutils function references */
+ .extern hex2char
+ .extern char2hex
+ .extern byte2ascii
+ .extern halfword2ascii_be
+ .extern halfword2ascii_le
+ .extern word2ascii_be
+ .extern word2ascii_le
+ .extern ascii2hex_varlen_be
+ .extern ascii2byte
+ .extern ascii2halfword_be
+ .extern ascii2halfword_le
+ .extern ascii2word_be
+ .extern ascii2word_le
+
/* Macro definitions */
/* _check_msgseparator
@@ -196,6 +213,12 @@ debug_InMsgBuf:
debug_OutMsgBuf:
.space MSGBUF_SIZE,0
+ /* Make Debugger State accessible from other modules */
+ .global debug_state
+ .global debug_mode
+ .global debug_bkpt_type
+ .global debug_curr_breakpoint
+
debug_state:
.byte 0x0 /* dbg_state_t variable */
debug_mode:
@@ -227,7 +250,7 @@ debug_OkResponse:
/* The CmdIndexTable and CmdJumpTable must be kept in sync */
debug_cmdIndexTable:
- .byte 'g','G','p','P','m','M','c','s','k','z','Z','?','q','Q',0
+ .byte 'g','G','p','P','m','M','D','c','s','k','z','Z','?','q','Q',0
/* Command Handlers
* On entry:
@@ -241,9 +264,15 @@ debug_cmdJumpTable:
.word _dbg__cmd_SetOneReg /* 'P' */
.word _dbg__cmd_ReadMem /* 'm' */
.word _dbg__cmd_WriteMem /* 'M' */
+ .word _dbg__cmd_Detach /* 'D' */
.word _dbg__cmd_Continue /* 'c' */
+#ifdef __NXOS__
+ .word _dbg__cmd_Step /* 's' */
+#else
+ /* NXT Firmware does not support Stepping */
.word _dbg__nop /* 's' */
- .word _dbg__nop /* 'k' */
+#endif
+ .word _dbg__cmd_Kill /* 'k' */
.word _dbg__cmd_RemoveBreakpoint /* 'z' */
.word _dbg__cmd_InsertBreakpoint /* 'Z' */
.word _dbg__cmd_Status /* '?' */
@@ -469,99 +498,6 @@ debug_armComplexCCTable:
/* FIXME: The Debugger Stack Frame is probably not 100% consistent with the order that
GDB expects in the g/G messages. CSPR is probably located above R15 */
-#ifdef __NXOS__
-/****************************************************************************
- *
- * GDB Debugger Invocation Routine for NxOS
- *
- ****************************************************************************/
- .code 32
- .align 4
- .global nxos__handleDebug
-/* nxos__handleDebug
- * Prepare to switch to Debug Mode
- * int nxos__handleDebug(unsigned char *msg, comm_chan_t channel, long len, void *isrRetAddr);
- *
- * This routine is called from NxOS Fantom library to setup
- * Single Step Breakpoint and copy Incoming Message to
- * Debugger Message Buffers in preparation for Debugger invocation.
- *
- * If we're operating in normal NxOS mode, return True (!0)
- * If we're already in Debugger Mode, return False (0)
- */
-nxos__handleDebug:
- push {r4, lr}
- /* When called, NxOS is in ISR servicing mode (MODE_IRQ) */
- /* R0-R3 has received message related parameters */
- mov r4, r3 /* Keep isrRetAddr in R4 */
- mrs r3, spsr /* Copy SPSR to r3 */
- and r3, r3, #CPSR_MODE /* Get previous mode */
- teq r3, #MODE_ABT /* Are we in Abort (Debug) mode? */
- moveq r0, #FALSE
- beq exit_nxos__handleDebug /* Yes, return False */
-
-_nxos_switch2debug:
- bl dbg__copyNxtDebugMsg /* setup Debugger Message Buffers, validate input, CPSR returned in R0 */
-
- /* Retrieve ISR Return Address */
- mrs r3, spsr /* Copy SPSR to r3 */
- tst r3, #CPSR_THUMB /* Check for Thumb Mode */
- sub r1, r4, #4 /* R3 (isrRetAddr) has PC + 4, need to setup Single Step Breakpoint at PC */
- orrne r1, r1, #1 /* Configure for Thumb Single Step Breakpoint */
- bl _dbg__install_singlestep /* Setup Single Step, next instruction address returned in r1 */
- bl _dbg__activate_singlestep
- mov r0, #TRUE /* We're going to switch to Debug Mode */
-exit_nxos__handleDebug:
- pop {r4, lr}
- mov r1, lr /* Safe code: Thumb mode can't access lr */
- bx r1 /* In case we have Interworking from different caller mode */
-#endif
-
-#ifndef __NXOS__
-/****************************************************************************
- *
- * GDB Debugger Invocation Routine for NXT Firmware
- *
- ****************************************************************************/
- .code 16
- .align 2
- .global cCommHandleDebug
- .thumb_func
-/* cCommHandleDebug
- * Switch Mode to Debugger.
- * Used by NXT Firmware only
- *
- * UWORD cCommHandleDebug(UBYTE *pInBuf, UBYTE CmdBit, UWORD MsgLength);
- *
- * This routine is called from cCommInterprete either in normal operation mode (SVC)
- * or else when we're in debug mode (ABORT) which uses the cCommCtrl() routine to handle
- * I/O with the Host.
- *
- * On entry, the message is copied from the NXT buffer into our own buffers.
- *
- * If this is accessed from normal operation mode, we need to switch mode to
- * ABORT mode to handle the incoming message using a Manual Breakpoint instruction.
- * When DEBUG is exited, the execution resumes from the instruction following the Breakpoint.
- */
-cCommHandleDebug:
-/* Arg Registers are not preserved since this is invoked explicitly */
- push {lr} /* store arg registers */
- bl dbg__copyNxtDebugMsg /* setup Debugger Message Buffers, validate input, CPSR returned in R0 */
- _dbg_getmode r0 /* Get Debug Mode */
- cmp r0, #(TRUE & BYTE0) /* Confine it to Byte size */
-
- /* If Debug Mode is TRUE, this means that we're already running the Debugger */
- beq _cCommHandleDebug_cont
- /* Else, we're in normal operation mode (SVC), or other mode (??!) and need to force a switch to Debug mode */
- dbg__bkpt_thumb
-_cCommHandleDebug_cont:
- mov r0, #0 /* FIXME: Return Status */
- pop {r1} /* Can't Pop LR directly */
- bx r1 /* Safe code: actually we should be able to Pop PC since the caller is Thumb Mode */
-
- .ltorg
-#endif
-
/****************************************************************************
*
* GDB Debugger Init and Breakpoint Handler Routines
@@ -607,7 +543,7 @@ _dbg__flush_icache:
*/
dbg__thumb_bkpt_handler:
/* On entry, r0 contains breakpoint index value */
- mov r4, #BKPT16_AUTO_BKPT
+ /* mov r4, #BKPT16_AUTO_BKPT Redundant?! */
and r4, r0, #BKPT16_AUTO_BKPT /* keep AUTO flag value in r4 */
bic r0, r0, #BKPT16_AUTO_BKPT /* mask out AUTO flag */
_dbg_setcurrbkpt_index r0 /* keep current breakpoint index in memory */
@@ -630,7 +566,7 @@ dbg__thumb_bkpt_handler:
*/
dbg__arm_bkpt_handler:
/* On entry, r0 contains breakpoint index value */
- mov r4, #BKPT32_AUTO_BKPT
+ /* mov r4, #BKPT32_AUTO_BKPT Redundant?! */
and r4, r0, #BKPT32_AUTO_BKPT /* keep AUTO flag value in r4 */
bic r0, r0, #BKPT32_AUTO_BKPT /* mask out AUTO flag */
_dbg_setcurrbkpt_index r0 /* keep current breakpoint index in memory */
@@ -648,8 +584,8 @@ dbg__arm_bkpt_handler:
/* b _process_normal_breakpoint */
_process_normal_breakpoint:
- bl _dbg__restore_breakpoints
- bl _dbg__restore_singlestep
+ bl _dbg__restore_breakpoints /* includes restoring single step */
+/* bl _dbg__restore_singlestep */
bl _dbg__clear_singlestep
bl _dbg__flush_icache
b dbg__bkpt_waitCMD
@@ -706,6 +642,8 @@ dbg__bkpt_offset_outofrange:
dbg__bkpt_waitCMD:
/* We enter this code section when a Breakpoint Triggers */
_dbg_setmode TRUE /* Debug Mode = True */
+ msr cpsr_c, #(MODE_ABT) /* Re-enable Interrupts */
+
_dbg_getstate r0
cmp r0, #DBG_CONFIGURED
blo dbg__bkpt_waitCMD_cont /* Not configured yet, don't send Breakpoint Signal Response */
@@ -1233,6 +1171,27 @@ _dbg__cmd_WriteMem:
bne 1b
b __dbg__procCmdOk
+/* _dbg__cmd_Detach
+ * Detach User Program Execution Command Handler
+ * Treat this as being equivalent to 'Continue' without any arguments
+ *
+ * On entry:
+ * r0: parameter buffer pointer (contents after '$' and '<cmdchar>')
+ * <NULL> (No Parameters)
+ * On exit:
+ * r0-r7: destroyed
+ * Note: This routine does not return to caller. Instead it switches
+ * operating mode to UNDEF and returns to previously active program
+ */
+_dbg__cmd_Detach:
+ stmfd sp!, {lr} /* In case unexpected parameters were received */
+ bl __dbg__cmdParamLen
+ teq r1, #CMD_DETACH_PARAMLEN /* Check for correct length */
+ bne __dbg__procCmdParamError /* Unexpected input, report error */
+
+ ldmfd sp!, {lr} /* Cleanup stack, since we won't return to the Debugger Run Loop */
+ b _dbg__cont_check_breakpoint_type /* Continue from current PC */
+
/* _dbg__cmd_Continue
* Continue User Program Execution Command Handler
* Setup breakpoints before resuming execution of program.
@@ -1281,7 +1240,7 @@ _dbg__cont_is_normal_breakpoint:
mov r2, #DBGSTACK_NEXTINSTR_INDEX /* The Next Instruction Pointer for Resume is in index 0 of the Debug Stack */
_setdbgregisterfromindex r2, r0, r1 /* Set Register contents in R0, using index in R2, and scratch register R1 */
bl _dbg_following_instruction_addr /* following instruction address returned in r1 */
- bl _dbg__install_singlestep /* Setup Single Step, next instruction address returned in r1 */
+ bl dbg__install_singlestep /* Setup Single Step, next instruction address returned in r1 */
_dbg_getcurrbkpt_index r0 /* load current breakpoint index in memory */
bl _dbg__activate_autobreakpoint /* pass next instruction address in r1 */
b _dbg__switch2undefmode_withAck
@@ -1294,7 +1253,7 @@ _dbg__cont_is_manual_bkpt_or_address_specified:
* Step User Program Execution Command Handler
* Setup breakpoints before resuming execution of program.
*
- * If Address is specified, update the next instruction address to specified address
+ * If Address is specified, update the next instruction address to specified address
*
* If this is a Normal Breakpoint, then we need to install a Step Breakpoint at next instruction address
* and resume from current (Breakpoint) exception address
@@ -1347,10 +1306,30 @@ _dbg__step_is_manual_bkpt:
_dbg__step_is_manual_bkpt_or_address_specified:
bl _dbg_following_instruction_addr /* following instruction address returned in r1 */
- bl _dbg__install_singlestep /* Setup Single Step, next instruction address returned in r1 */
- bl _dbg__activate_singlestep
+ bl dbg__install_singlestep /* Setup Single Step, next instruction address returned in r1 */
+ bl dbg__activate_singlestep
b _dbg__switch2undefmode_withAck
+/* _dbg__cmd_Kill
+ * Kill User Program Execution Command Handler
+ * Kill Program, this is accomplished by rebooting the Brick
+ *
+ * On entry:
+ * r0: parameter buffer pointer (contents after '$' and '<cmdchar>')
+ * <NULL> (No Parameters)
+ * On exit:
+ * r0-r7: destroyed
+ * Note: This routine does not return to caller. Instead it calls
+ * the relevant system routine to reboot the Brick
+ */
+_dbg__cmd_Kill:
+ stmfd sp!, {lr} /* In case unexpected parameters were received */
+ bl __dbg__cmdParamLen
+ teq r1, #CMD_KILL_PARAMLEN /* Check for correct length */
+ bne __dbg__procCmdParamError /* Unexpected input, report error */
+
+ bl __dbg__procAckOnly /* send Ack to keep GDB server happy */
+ b dbg__reboot /* Goodbye.... */
/* _dbg__proc_brkpt_params
* Process Breakpoint Parameters
@@ -2800,12 +2779,13 @@ _dbg__clear_breakpoints:
blo 3b
ldmfd sp!, {pc}
-/* _dbg__install_singlestep
+ .global dbg__install_singlestep
+/* dbg__install_singlestep
* Install the Single Step Breakpoint
* On entry:
* R1: Instruction Address (31 bits, b0 = THUMB flag)
*/
-_dbg__install_singlestep:
+dbg__install_singlestep:
mov r0, #0
/* b _dbg__install_one_breakpoint */
@@ -2866,10 +2846,11 @@ _dbg__restore_breakpoints:
ldr r5, =_dbg__restore_one_breakpoint
b __dbg__iterate_breakpoint_array
-/* _dbg__activate_singlestep
+ .global dbg__activate_singlestep
+/* dbg__activate_singlestep
* Activate the single step breakpoint to memory
*/
-_dbg__activate_singlestep:
+dbg__activate_singlestep:
mov r0, #0 /* single step breakpoint index */
_index2bkptindex_addr r0, r1 /* Calculate Single Step Breakpoint Entry Address */
ldm r1, {r1, r2} /* r1: Breakpoint Address, r2: Breakpoint Instruction */
@@ -2894,7 +2875,7 @@ _nx_is_arm_bp:
teq r2, r3 /* check that the two instructions are identical */
bne _dbg__breakpoint_invalid_arm
ldr r2, =BKPT32_INSTR /* ARM BKPT instruction */
- and r2, r2, r0 /* Merge Breakpoint index */
+ orr r2, r2, r0 /* Merge Breakpoint index */
str r2, [r1] /* Store it into memory location */
_dbg__breakpoint_invalid_arm:
bx lr
@@ -2904,7 +2885,7 @@ _nx_is_thumb_bp:
teq r2, r3 /* check that the two instructions are identical */
bne _dbg__breakpoint_invalid_thumb
ldr r2, =BKPT16_INSTR /* Thumb BKPT instruction */
- and r2, r2, r0 /* Merge Breakpoint index */
+ orr r2, r2, r0 /* Merge Breakpoint index */
strh r2, [r1] /* Store it into memory location */
_dbg__breakpoint_invalid_thumb:
bx lr
diff --git a/AT91SAM7S256/armdebug/Debugger/debug_stub.h b/AT91SAM7S256/armdebug/Debugger/debug_stub.h
index c5cbeee..a4cbdda 100644
--- a/AT91SAM7S256/armdebug/Debugger/debug_stub.h
+++ b/AT91SAM7S256/armdebug/Debugger/debug_stub.h
@@ -71,7 +71,7 @@ ENUM_END(comm_chan_t)
* !0 if mode switch will happen
* Used by NxOS only
*/
-FUNCDEF int nxos__handleDebug(unsigned char *msg, comm_chan_t channel, long len, void *isrRetAddr);
+FUNCDEF int nxos__handleDebug(comm_chan_t channel);
#endif
#ifndef __NXOS__
@@ -138,7 +138,7 @@ static inline void dbg_breakpoint_thumb(void) { asm volatile (".hword 0xBE7F" /*
.word (BKPT32_INSTR | BKPT32_MANUAL_BKPT)
.endm
-/* dbg__bkpt_arm
+/* dbg__bkpt_thumb
* GDB breakpoint() for Thumb mode
*/
.macro dbg__bkpt_thumb
diff --git a/AT91SAM7S256/armdebug/Debugger/undef_handler.S b/AT91SAM7S256/armdebug/Debugger/undef_handler.S
index f185fbd..11d3cbc 100644
--- a/AT91SAM7S256/armdebug/Debugger/undef_handler.S
+++ b/AT91SAM7S256/armdebug/Debugger/undef_handler.S
@@ -100,8 +100,8 @@ _is_arm:
ldr r2, =dbg__arm_bkpt_handler /* handle BKPT, BKPT index in r0 */
_exit_undef_handler:
and r0, r1, r0 /* Keep index value */
- msr cpsr_c, #(MODE_ABT) /* Configure Abort Mode */
- mov pc, r2 /* Invoke Debugger State (Supervisor Mode) */
+ msr cpsr_c, #(MODE_ABT | CPSR_FIQ | CPSR_IRQ) /* Switch to Abort Mode, Disable Interrupts */
+ mov pc, r2 /* Invoke Debugger */
.global resume_execution