summaryrefslogtreecommitdiff
path: root/AT91SAM7S256
diff options
context:
space:
mode:
authorTC Wan2011-03-23 16:27:58 +0800
committerTC Wan2011-03-23 16:27:58 +0800
commit2f91494901e933524a0c6c117c0fa4c984835589 (patch)
treed4e7d352aadf6b9758d7f7b319a772b7bf300298 /AT91SAM7S256
parent0f08888a613ec00fb681e6da71152f99c27476f8 (diff)
parent9eaeb4f0b79cfb0015afba33a1f044530fcb7652 (diff)
Merge branch 'master' of ssh://svc.cs.usm.my/~/gitrepo-bare/armdebug
Diffstat (limited to 'AT91SAM7S256')
-rw-r--r--AT91SAM7S256/armdebug/Debugger/debug_comm.S254
-rw-r--r--AT91SAM7S256/armdebug/Debugger/debug_macros.h14
-rw-r--r--AT91SAM7S256/armdebug/Debugger/debug_stub.S150
-rw-r--r--AT91SAM7S256/armdebug/Debugger/debug_stub.h24
-rw-r--r--AT91SAM7S256/armdebug/Debugger/undef_handler.S41
-rw-r--r--AT91SAM7S256/armdebug/Host/gdb-commands.txt6
-rwxr-xr-xAT91SAM7S256/armdebug/Host/nxt-gdb-server.py2
-rw-r--r--AT91SAM7S256/armdebug/SConstruct4
8 files changed, 434 insertions, 61 deletions
diff --git a/AT91SAM7S256/armdebug/Debugger/debug_comm.S b/AT91SAM7S256/armdebug/Debugger/debug_comm.S
index 75f835e..b6f9cf5 100644
--- a/AT91SAM7S256/armdebug/Debugger/debug_comm.S
+++ b/AT91SAM7S256/armdebug/Debugger/debug_comm.S
@@ -111,6 +111,9 @@ hex2char_lut:
/* 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
@@ -127,16 +130,30 @@ hex2char:
/* char2hex
* This routine accepts an ASCII character in R0(7:0) and returns the
- * equivalent byte sized hex value in R0(7:0)
+ * 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
*/
.global char2hex
char2hex:
- and r0, #BYTE0 /* make sure that input is sane */
- cmp r0, #'0'
+ and r1, r0, #BYTE0 /* make sure that input is sane */
+ mov r0, #-1 /* Initialize Return value to Error value */
+ cmp r1, #'0'
blo exit_char2hex
- cmp r0, #'F'
+ cmp r1, #'9'
+ bls perform_char2hex
+ cmp r1, #'A'
+ blo exit_char2hex
+ cmp r1, #'F'
+ bls perform_char2hex
+ cmp r1, #'a'
+ blo exit_char2hex
+ cmp r1, #'f'
bhi exit_char2hex
+ /* Validated Hex Char */
+perform_char2hex:
+ mov r0, r1 /* restore hex char */
_char2hex r0
exit_char2hex:
bx lr
@@ -187,7 +204,8 @@ byte2ascii:
bl byte2ascii_cont
ldmfd sp!, {r1, pc} /* return original string pointer in R1 */
-/* halfword2ascii
+/* halfword2ascii_be
+ * Big Endian version of halfword2ascii conversion routine
* On entry:
* R0: ASCII buffer pointer
* R1[15:0]: Halfword value
@@ -199,14 +217,35 @@ byte2ascii:
* 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
-halfword2ascii:
+ .global halfword2ascii_be
+halfword2ascii_be:
stmfd sp!, {r0,r2,r3, lr} /* Keep ASCII buffer pointer */
- mov r2, r1, lsl #16 /* copy of input halfword value R1[15:0], shifted to MSH R2[31:16] */
- mov r3, #2 /* Loop Counter */
- b _conv_byte2ascii /* goto Byte conversion loop */
+ 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 */
-/* word2ascii
+/* 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
@@ -218,22 +257,86 @@ halfword2ascii:
* 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
-word2ascii:
+ .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 */
-_conv_byte2ascii:
+
+/* 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
+ 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], #1 /* Load ASCII char for Hex Value */
+ bl char2hex /* on return, hex value in R0, -1 for error */
+ teq r0, #-1
+ beq _exit_ascii2hex_varlen
+ orr r2, r0, r2, lsl #4 /* combined byte value */
+ subs r3, r3, #1 /* Decrement Counter */
+ bne 2b
+_exit_ascii2hex_varlen:
+ mov r0, r2 /* Return results in R0 */
+ ldmfd sp!, {r2,r3, pc}
+
/* ascii2byte
* On entry:
@@ -251,11 +354,18 @@ _conv_byte2ascii:
.global ascii2byte
ascii2byte:
- stmfd sp!, {r2,r3, lr}
- mov r3, #2 /* Loop counter */
- b _conv_ascii2byte
-
-/* ascii2halfword
+ 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:
@@ -268,15 +378,37 @@ ascii2byte:
* WARNING: This routine assumes that the input buffer was sanitized and contains valid Hex chars,
* otherwise it will return invalid results.
*/
- .global ascii2halfword
+ .global ascii2halfword_be
-ascii2halfword:
+ascii2halfword_be:
stmfd sp!, {r2,r3, lr}
- mov r3, #4 /* Loop counter */
- b _conv_ascii2byte
+ 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
+
+/* ascii2word_be
+ * Big Endian version of ascii2word conversion routine
* On entry:
* R0: ASCII buffer pointer
* On exit:
@@ -289,28 +421,69 @@ ascii2halfword:
* WARNING: This routine assumes that the input buffer was sanitized and contains valid Hex chars,
* otherwise it will return invalid results.
*/
- .global ascii2word
+ .global ascii2word_be
-ascii2word:
+ascii2word_be:
stmfd sp!, {r2,r3, lr}
- mov r3, #8 /* Loop counter */
+ mov r3, #4 /* Loop counter */
/* Fall through to byte coversion loop */
-_conv_ascii2byte:
+_conv_ascii2byte_be:
teq r0, #0
- beq _exit_conv_ascii2byte /* exit if NULL pointer in R0 */
- mov r1, r0 /* Copy of ASCII buffer pointer */
- mov r2, #0 /* Initialize results */
-2: ldrb r0, [r1], #1 /* Load ASCII char */
- bl char2hex /* on return, hex value in R0 */
- orr r2, r0, r2, lsl #4 /* merge Nibble into results */
- subs r3, r3, #1
- bne 2b
- mov r0, r2 /* Copy it to R0 as return value */
-_exit_conv_ascii2byte:
+ 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 */
+
@@ -596,12 +769,13 @@ _hasMsg2Copy:
strb r1, [r5, r2] /* Zero out '#' char for checksum calc later */
/* Need to account for Packet Acknowledgement */
- ldrb r0, [r5]
+1: ldrb r0, [r5]
teq r0, #MSGBUF_NAKCHAR /* Look for '-' */
beq exit_dbg__getMsgError /* FIXME: We can't handle retransmission, flag message error */
teq r0, #MSGBUF_ACKCHAR /* Look for '+' */
addeq r5, r5, #1 /* Adjust Buffer Start Pointer (excl '+') */
subeq r4, r4, #1 /* Adjust Message Length */
+ beq 1b /* Skip all Packet Acknowledgements */
#ifdef CHECK_GDBSTARTCHAR
/* Checked in dbg__bkpt_waitCMD */
diff --git a/AT91SAM7S256/armdebug/Debugger/debug_macros.h b/AT91SAM7S256/armdebug/Debugger/debug_macros.h
index 3fcc78c..d6786d5 100644
--- a/AT91SAM7S256/armdebug/Debugger/debug_macros.h
+++ b/AT91SAM7S256/armdebug/Debugger/debug_macros.h
@@ -223,6 +223,20 @@
_asciiz r0, r1
.endm
+/* _regenum2index
+ * Convert register enum to debugger stack index
+ *
+ * On entry:
+ * indexenum: enum representing Register to access
+ * indexreg: register to be used to store the debugger stack index value (0-max index)
+ * On exit:
+ * indexreg contains debugger stack index value (0-max index)
+ */
+ .macro _regenum2index indexenum, indexreg
+ mov \indexreg, #indexenum
+ add \indexreg, \indexreg, #DBGSTACK_USERREG_INDEX /* Convert register index to Debug Stack index, keep in R1 */
+ .endm
+
/* _getdbgregisterfromindex
* Retrieve register contents from debugger stack given index
*
diff --git a/AT91SAM7S256/armdebug/Debugger/debug_stub.S b/AT91SAM7S256/armdebug/Debugger/debug_stub.S
index 796de04..47ad2c3 100644
--- a/AT91SAM7S256/armdebug/Debugger/debug_stub.S
+++ b/AT91SAM7S256/armdebug/Debugger/debug_stub.S
@@ -68,7 +68,7 @@
* GrrrrRRRR.. set the value of the CPU registers OK or ENN
* where register values are given as
* 32-bit hex values in the sequence:
- * User CPSR, R0, R1, ..., R15
+ * User R0, R1, ..., R15, CPSR
* px get the value of one register (x) hex data or ENN
* Px=rrrr set the value of one register (x) to OK or ENN
* 32-bit hex value rrrr.
@@ -124,8 +124,18 @@
*
* Note: ARMDEBUG can only implement Memory Breakpoints t=0. Hardware breakpoints requires a JTAG debugger.
* Currently, watchpoints are not implemented as they require hardware support as well (need verification).
+ *
+ * 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.
+ * The default target byte order is Little Endian for the AT91SAM7xxx processor in the NXT.
+ * If Big Endian target byte order is required, the __BIG_ENDIAN__ preprocessor label should be defined.
*/
+/* FIXME: The Hex value arguments passed by GDB does not have fixed lengths! Although the standard says
+ * there should be x digits, it does not follow this requirement. e.g., register index.
+ */
+
+
#define __ASSEMBLY__
#include "debug_stub.h"
#include "debug_macros.h"
@@ -210,7 +220,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','?',0
+ .byte 'g','G','p','P','m','M','c','s','k','z','Z','?','q','Q',0
/* Command Handlers
* On entry:
@@ -224,12 +234,14 @@ debug_cmdJumpTable:
.word _dbg__cmd_SetOneReg /* 'P' */
.word _dbg__cmd_ReadMem /* 'm' */
.word _dbg__cmd_WriteMem /* 'M' */
- .word _dbg__nop /* 'c' */
+ .word _dbg__cmd_Continue /* 'c' */
.word _dbg__nop /* 's' */
.word _dbg__nop /* 'k' */
.word _dbg__cmd_remove_breakpoint /* 'z' */
.word _dbg__cmd_insert_breakpoint /* 'Z' */
- .word _dbg__nop /* '?' */
+ .word _dbg__cmd_Status /* '?' */
+ .word _dbg__cmd_Query /* 'q' */
+ .word _dbg__nop /* 'Q' */
.word 0
/*
@@ -578,11 +590,18 @@ dbg__bkpt_offset_outofrange:
*
****************************************************************************/
dbg__bkpt_waitCMD:
+ /* We enter this code section when a Breakpoint Triggers */
_dbg_setmode TRUE /* Debug Mode = True */
+ _dbg_getstate r0
+ cmp r0, #DBG_CONFIGURED
+ blo dbg__bkpt_waitCMD_cont /* Not configured yet, don't send Breakpoint Signal Response */
+ bl _dbg__cmd_Status /* Send signal response to the GDB server */
+
dbg__bkpt_waitCMD_cont:
+ bl dbg__runloopTasks /* Execute housekeeping tasks while in ABRT mode */
bl dbg__getDebugMsg /* Read new message from Debugger, buflen in R0, 0 if none, -1 if error, msgbuf pointer in R1 */
cmp r0, #0
- beq _dbg__housekeeping /* No message yet, do housekeeping tasks */
+ beq dbg__bkpt_waitCMD_cont /* No message yet, do housekeeping tasks */
blt __dbg__procChecksumError /* Message invalid, checksum error? */
/* Message now has $<packet info>\0 */
mov r4, r1 /* Use R4 as buffer pointer */
@@ -594,29 +613,33 @@ dbg__bkpt_waitCMD_cont:
bl _dbg__cmdChar2Index /* Index in R0 */
mov r1, #CMDINDEX_OUTOFRANGE
teq r0, r1
+ bne _dbg__cmdExists /* Found valid command, execute it */
+_dbg_unknown_command:
+ bl _dbg__nop /* Command character not recognized, send empty response to GDB server */
+ b dbg__bkpt_waitCMD_cont
+
+#if 0
moveq r0, #MSG_UNKNOWNCMD /* Out of range, Command character not recognized */
beq _dbg__cmdError /* Send response to GDB server */
+#endif
_dbg__cmdExists:
mov r3, r0 /* put Command Handler Index in R3 */
mov r0, r4 /* R0 now contains Input Message Buffer Parameter Pointer (previously in R4) */
_dbg_jumpTableHandler debug_cmdJumpTable, r2, r3 /* Call Command Handler Routine, use R2 as jump address pointer */
- b _dbg__housekeeping
+ b dbg__bkpt_waitCMD_cont
__dbg__procChecksumError:
_dbg_outputRetransmitFlag
bl dbg__requestRetransmission /* Request message retransmission from GDB server */
cmp r0, #0
- beq _dbg__housekeeping /* Sending of retransmission request succeeded */
+ beq dbg__bkpt_waitCMD_cont /* Sending of retransmission request succeeded */
bl dbg__runloopTasks /* Service run loop tasks */
b __dbg__procChecksumError /* Retry retransmission */
_dbg__cmdError:
_dbg_outputMsgStatusErr
bl dbg__putDebugMsg /* Send error response to the GDB server */
-
-_dbg__housekeeping:
- bl dbg__runloopTasks /* Execute platform run loop tasks while in ABRT mode */
b dbg__bkpt_waitCMD_cont
/* _dbg__cmdChar2Index
@@ -724,6 +747,31 @@ __dbg__sendDebugMsgExit:
bl dbg__putDebugMsg /* Send error response to the GDB server */
ldmfd sp!, {pc}
+/* _dbg__cmd_Status
+ * Status Command Handler
+ * On entry:
+ * r0: parameter buffer (contents after '$' and '<cmdchar>')
+ * On exit:
+ * r0, r1, r2, r3: destroyed
+ */
+_dbg__cmd_Status:
+ stmfd sp!, {lr}
+ _dbg_outputMsgStatusSig 0x0 /* FIXME: Dummy Signal number */
+ b __dbg__sendDebugMsgExit
+
+/* _dbg__cmd_Query
+ * Query Command Handler
+ * On entry:
+ * r0: parameter buffer (contents after '$' and '<cmdchar>')
+ * [varied, see GDB General Packets query docs]
+ * http://sourceware.org/gdb/current/onlinedocs/gdb/General-Query-Packets.html
+ * On exit:
+ * r0, r1, r2, r3: destroyed
+ */
+_dbg__cmd_Query:
+ stmfd sp!, {lr}
+ _dbg_setstate DBG_CONFIGURED /* We have exchanged query messages with the GDB server */
+ b __dbg__procUnimplementedError /* FIXME: return an empty message to GDB (no modifiable settings) */
/* _dbg__cmd_GetOneReg
@@ -773,12 +821,16 @@ _dbg_outputOneRegValue:
stmfd sp!, {lr}
add r2, r1, #DBGSTACK_USERREG_INDEX /* Convert register index to Debug Stack index */
_getdbgregisterfromindex r2, r1 /* Retrieve Register contents into R1 */
- bl word2ascii /* Convert and put hex chars into Output Message Buffer */
+#ifdef __BIG_ENDIAN__
+ bl word2ascii_be /* Convert and put hex chars into Output Message Buffer */
+#else
+ bl word2ascii_le /* Convert and put hex chars into Output Message Buffer */
+#endif
ldmfd sp!, {pc}
/* _dbg__cmd_GetAllRegs
* Get All Register Values Command Handler
- * Output Buffer returns register values in the order: User CPSR, R0, R1, R2, ..., R15
+ * Output Buffer returns register values in the order: User R0, R1, R2, ..., R15, CPSR
* On entry:
* r0: parameter buffer pointer (contents after '$' and '<cmdchar>')
* <NULL> (no parameters)
@@ -792,13 +844,18 @@ _dbg__cmd_GetAllRegs:
bne __dbg__procCmdParamError /* Unexpected input, report error */
_dbg_outputMsgValidResponse /* R0: address of output message buffer data pointer (after response prefix) */
- mov r3, #DBGSTACK_USERCPSR_OFFSET /* Output User CPSR Value first */
+
+ /* We must return R0-R15, then CPSR */
+ mov r3, #DBGSTACK_USERREG_INDEX /* Output User Register Values first */
1: mov r1, r3
bl _dbg_outputOneRegValue /* update output buffer */
add r3, r3, #1 /* increment index */
cmp r3, #0xF
ble 1b /* process all the registers */
+ mov r1, #DBGSTACK_USERCPSR_OFFSET /* Output User CPSR Value lasat */
+ bl _dbg_outputOneRegValue /* update output buffer */
+
_asciiz r0, r1
bl dbg__putDebugMsg /* Send response to the GDB server */
ldmfd sp!, {pc}
@@ -835,7 +892,11 @@ _dbg__cmd_SetOneReg:
_dbg__proc_setRegister:
add r2, r0, #DBGSTACK_USERREG_INDEX /* Convert register index to Debug Stack index, keep in R2 */
mov r0, r3 /* Retrieve parameter buffer pointer */
- bl ascii2word
+#ifdef __BIG_ENDIAN__
+ bl ascii2word_be
+#else
+ bl ascii2word_le
+#endif
_setdbgregisterfromindex r2, r0, r3 /* Set Register contents in R0, using index in R2, and scratch register R3 */
b __dbg__procCmdOk
@@ -849,20 +910,26 @@ _dbg__proc_setRegister:
*
*/
_dbg__cmd_SetAllRegs:
-/* FIXME: Assumes that the registers are in the sequence CPSR, R0, R1, ... R15 -- May not be GDB ordering */
+/* FIXME: Assumes that the registers are in the sequence R0, R1, ... R15, CPSR -- May not be GDB ordering */
stmfd sp!, {lr}
bl __dbg__cmdParamLen /* R0: pointer to parameters in buffer */
teq r1, #CMD_REG_SETALL_PARAMLEN /* Check for correct length */
bne __dbg__procCmdParamError /* Unexpected input, report error */
- mov r2, #DBGSTACK_USERCPSR_INDEX /* R2: register index, starting with CPSR */
+ mov r2, #DBGSTACK_USERREG_INDEX /* R2: register index, starting with R0 */
1: bl ascii2word /* R0: value, R1: pointer to next char in buffer */
_setdbgregisterfromindex r2, r0, r3 /* Set Register contents in R0, using index in R2, and scratch register R3 */
+ mov r0, r1 /* setup R0 for next ascii2word call */
add r2, r2, #1 /* increment index */
+ cmp r2, #DBGSTACK_USERPC_INDEX
+ bls 1b
+
+_set_cpsr:
+ mov r2, #DBGSTACK_USERCPSR_INDEX /* R2: CPSR Index */
+ _setdbgregisterfromindex r2, r0, r3 /* Set Register contents in R0, using index in R2, and scratch register R3 */
ldrb r0, [r1]
teq r0, #0 /* Look for ASCIIZ character to terminate loop */
- mov r0, r1 /* setup R0 for next ascii2word call */
- bne 1b /* continue only if ASCIIZ not found */
- b __dbg__procCmdOk
+ beq __dbg__procCmdOk
+ bne __dbg__procCmdParamError /* Unexpected input, report error */
/* _dbg__nop
* NOP Command Handler (placeholder)
@@ -947,6 +1014,51 @@ _dbg__cmd_WriteMem:
bne 1b
b __dbg__procCmdOk
+/* _dbg__cmd_Continue
+ * Continue User Program Execution Command Handler
+ * On entry:
+ * r0: parameter buffer pointer (contents after '$' and '<cmdchar>')
+ * Optional: AA..AA
+ * On exit:
+ * r0, r1, r2: destroyed
+ * Note: This routine does not return to caller. Instead it switches
+ * operating mode to UNDEF and returns to previously active program
+ */
+_dbg__cmd_Continue:
+ bl __dbg__cmdParamLen
+ cmp r1, #CMD_REG_CONTINUE_PARAMLEN /* Check for correct parameter length */
+ beq _dbg__cmd_processContinue /* Continue from current PC */
+ cmp r1, #CMD_REG_CONTINUEFROM_PARAMLEN /* Check for correct parameter length */
+ bne __dbg__procCmdParamError /* Unexpected input, report error */
+ /* Continue from Specified Address */
+ bl ascii2word /* convert ASCII address location to Hex (in R0), R1 has address of next buffer char */
+ 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 */
+
+_dbg__cmd_processContinue:
+/* FIXME: Currently we assume that the trigger is a Manual Breakpoint, i.e., no need to
+ restore instructions to memory, and handle auto-breakpoints (needed to reenable the memory
+ breakpoint that was triggered) */
+
+@@@@@
+#if 0
+/* Not part of the GDB Remote Protocol spec. Messages are sent only when system halts, not when we resume */
+__dbg__sendOkBeforeResume:
+ _dbg_outputMsgStatusOk
+ bl dbg__putDebugMsg /* Send Ok response to the GDB server */
+ cmp r0, #0
+ beq _dbg__switch2undefmode /* Sending of retransmission request succeeded */
+ bl dbg__runloopTasks /* Service run loop tasks */
+ b __dbg__sendOkBeforeResume /* Retry retransmission */
+#endif
+
+_dbg__switch2undefmode:
+ msr cpsr_c, #(MODE_UND | CPSR_FIQ | CPSR_IRQ) /* Configure Undef Mode */
+ _dbg_setmode FALSE /* Debug Mode = False */
+ ldr lr, =resume_execution
+ mov pc, lr /* Exit via UNDEF mode */
+
+
/* _dbg__proc_brkpt_params
* Process Breakpoint Parameters
* On entry:
diff --git a/AT91SAM7S256/armdebug/Debugger/debug_stub.h b/AT91SAM7S256/armdebug/Debugger/debug_stub.h
index e39fc8e..7dc9aa8 100644
--- a/AT91SAM7S256/armdebug/Debugger/debug_stub.h
+++ b/AT91SAM7S256/armdebug/Debugger/debug_stub.h
@@ -87,6 +87,13 @@
#define CMD_REG_REGPARAMLEN 8 /* 32-bit ASCII Hex Value */
#define CMD_REG_SETONE_PARAMLEN (2 + CMD_REG_REGPARAMLEN)
#define CMD_REG_SETALL_PARAMLEN (CMD_REG_NUMREGS*CMD_REG_REGPARAMLEN)
+/*@}*/
+
+/** @name Debug Memory Command Constants.
+ *
+ * Debug Memory Command
+ */
+/*@{*/
#define CMD_NUMITEMS_PARAMLEN 4 /* 16-bit ASCII Hex Value */
#define CMD_MEM_READ_PARAMLEN (CMD_REG_REGPARAMLEN + CMD_NUMITEMS_PARAMLEN + 1) /* Address length is equivalent to reg param len */
#define CMD_MEM_WRITE_MINPARAMLEN (CMD_REG_REGPARAMLEN + CMD_NUMITEMS_PARAMLEN + 2) /* Address length is equivalent to reg param len */
@@ -97,6 +104,17 @@
#define CMD_MEM_MAXWRITEBYTES ((CMD_MEM_MAXINBUFLEN - CMD_MEM_WRITE_MINPARAMLEN)/2)
/*@}*/
+/** @name Debug Continue Command Constants.
+ *
+ * Debug Continue Command
+ */
+/*@{*/
+#define CMD_REG_CONTINUE_PARAMLEN 0
+#define CMD_REG_CONTINUEFROM_PARAMLEN CMD_REG_REGPARAMLEN /* Address length is equivalent to reg param len */
+/*@}*/
+
+
+
/** @name Debug Breakpoint Command Constants.
*
* Debug Breakpoint Command
@@ -126,9 +144,12 @@
* Debug Stack Manipulation Values
*/
/*@{*/
-#define DBGSTACK_USERCPSR_OFFSET (DBGSTACK_USERCPSR_INDEX-DBGSTACK_USERREG_INDEX) /* = -1, offset for calculating Debug Stack index */
+#define DBGSTACK_NEXTINSTR_INDEX 0 /* Next Instruction Address is at index 0 from bottom of Debug Stack */
#define DBGSTACK_USERCPSR_INDEX 1 /* User CPSR (SPSR_UNDEF) is at index 1 from bottom of Debug Stack */
#define DBGSTACK_USERREG_INDEX 2 /* R0 starts at index 2 from bottom of Debug Stack */
+#define DBGSTACK_USERSP_INDEX (DBGSTACK_USERREG_INDEX + 13) /* SP is R13 */
+#define DBGSTACK_USERPC_INDEX (DBGSTACK_USERREG_INDEX + 15) /* PC is R15 */
+#define DBGSTACK_USERCPSR_OFFSET (DBGSTACK_USERCPSR_INDEX-DBGSTACK_USERREG_INDEX) /* = -1, offset for calculating Debug Stack index */
/*@}*/
/** @name Bitmask Definitions.
@@ -208,6 +229,7 @@
ENUM_BEGIN
ENUM_VALASSIGN(DBG_RESET, 0) /**< Initial State. */
ENUM_VAL(DBG_INIT) /**< Debugger Initialized. */
+ENUM_VAL(DBG_CONFIGURED) /**< Debugger has been configured by GDB Server */
ENUM_VAL(DBG_MANUAL_BKPT_ARM) /**< Manual ARM Breakpoint. */
ENUM_VAL(DBG_NORMAL_BKPT_ARM) /**< Normal ARM Breakpoint (Single Step, Normal). */
ENUM_VAL(DBG_MANUAL_BKPT_THUMB) /**< Manual Thumb Breakpoint. */
diff --git a/AT91SAM7S256/armdebug/Debugger/undef_handler.S b/AT91SAM7S256/armdebug/Debugger/undef_handler.S
index f040219..5562738 100644
--- a/AT91SAM7S256/armdebug/Debugger/undef_handler.S
+++ b/AT91SAM7S256/armdebug/Debugger/undef_handler.S
@@ -101,4 +101,45 @@ _exit_undef_handler:
ldr lr, =dbg__arm_bkpt_handler /* handle BKPT, BKPT index in r0 */
mov pc, lr /* Invoke Debugger State (Supervisor Mode) */
+ .global resume_execution
+
+resume_execution:
+/*
+ * This routine is called by the Debugger prior to returning control to
+ * the executing program.
+ * It updates the SPSR_UNDEF with the Debug Stack value, and
+ * restores all registers R0-R14 to the previously active mode.
+ * Then, it uses the Next Instruction Address Pointer to return
+ * execution control to the previously executing program.
+ */
+/* On Entry, SP(undef) points to the Next Instruction Address.
+ * If the instruction which triggered the Breakpoint need to be
+ * reexecuted, it should be placed in the Next Instruction Address slot
+ * by ABORT mode before coming here
+ */
+ ldr lr, =__debugger_stack_bottom__ /* Use LR(undef) for Debug Stack Access */
+ add r1, lr, #(DBGSTACK_USERSP_INDEX*4) /* Use R1 for Previous Mode SP (R13) and LR (R14) access */
+ ldr r0, [lr, #(DBGSTACK_USERCPSR_INDEX*4)]! /* LR updated, Retrieve SPSR into R0 */
+ msr spsr, r0 /* Update SPSR for return to program being debugged */
+ and r0, r0, #CPSR_MODE /* Get previous mode */
+ teq r0, #MODE_USR
+ bne _restore_prev_mode_banked_regs /* Can't switch back if we're in User mode! */
+
+ /* Previous mode was User Mode */
+ ldmed lr, {r0-r14}^ /* We use LDMED since LR is pointing to USERCPSR not R0 */
+ b _really_resume_execution
+
+_restore_prev_mode_banked_regs:
+ /* FIXME: We don't handle FIQ properly! */
+ orr r0, #(CPSR_FIQ | CPSR_IRQ) /* Disable Interrupts */
+ msr cpsr_c, r0 /* Switch to previous mode */
+ ldmfd r1, {sp, lr} /* Restore Previous Mode's LR (R14), SP (R13) via R1 */
+ msr cpsr_c, #(MODE_UND | CPSR_FIQ | CPSR_IRQ) /* Revert to Undef Mode */
+ ldmed lr, {r0-r12} /* We use LDMED since LR is pointing to USERCPSR not R0 */
+
+_really_resume_execution:
+ ldmfd sp, {pc}^ /* Exit to Previous Mode using Next Instruction Address */
+
+
+
diff --git a/AT91SAM7S256/armdebug/Host/gdb-commands.txt b/AT91SAM7S256/armdebug/Host/gdb-commands.txt
index 9b52613..8e6f156 100644
--- a/AT91SAM7S256/armdebug/Host/gdb-commands.txt
+++ b/AT91SAM7S256/armdebug/Host/gdb-commands.txt
@@ -15,6 +15,12 @@ $pF#B6
# Display User CPSR
$p!#91
+# Query Status
+$?#3F
+
+# Query Thread
+$qC#B4
+
# Set R1 to 0xAA
$P1=000000AA#60
diff --git a/AT91SAM7S256/armdebug/Host/nxt-gdb-server.py b/AT91SAM7S256/armdebug/Host/nxt-gdb-server.py
index a72055f..4babdb9 100755
--- a/AT91SAM7S256/armdebug/Host/nxt-gdb-server.py
+++ b/AT91SAM7S256/armdebug/Host/nxt-gdb-server.py
@@ -152,7 +152,7 @@ class NXTGDBServer:
# Some pyusb are buggy, ignore some "errors".
if e.args != ('No error', ):
raise e
- if LIBUSB_RECEIVE_BLOCKING:
+ if s and LIBUSB_RECEIVE_BLOCKING:
data = self.reassemble (brick.sock)
else:
client.close ()
diff --git a/AT91SAM7S256/armdebug/SConstruct b/AT91SAM7S256/armdebug/SConstruct
index 4ca6207..898bb91 100644
--- a/AT91SAM7S256/armdebug/SConstruct
+++ b/AT91SAM7S256/armdebug/SConstruct
@@ -162,11 +162,15 @@ else:
myasflags.append('-Wa,-mcpu=arm7tdmi,-mfpu=softfpa')
mycflags.append('-g')
mycflags.append('-ggdb')
+# Big Endian Output (disabled by default)
+#mycflags.append('-D__BIG_ENDIAN__')
# Test build for NXT Firmware first
#mycflags.append('-D__NXOS__')
myasflags.append('-g')
myasflags.append('-ggdb')
+# Big Endian Output (disabled by default)
+#mycflags.append('-D__BIG_ENDIAN__')
# Test build for NXT Firmware first
#myasflags.append('-D__NXOS__')