aboutsummaryrefslogtreecommitdiff
path: root/AT91SAM7S256
diff options
context:
space:
mode:
authorTat-Chee Wan (USM)2011-01-18 15:52:21 +0800
committerTat-Chee Wan (USM)2011-01-18 15:52:21 +0800
commitce2436796136900553a308bf7b043cf3d4f2d170 (patch)
tree6c5ffc896504f23d9af1d484b4ad35d58e704988 /AT91SAM7S256
parent239dac94dc5debc30c194fb878dce8d804757007 (diff)
parentf9ebd55c1fb05abdc57ae119fe1fd876b5005ac2 (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.S13
-rw-r--r--AT91SAM7S256/armdebug/Debugger/debug_macros.h143
-rw-r--r--AT91SAM7S256/armdebug/Debugger/debug_stub.S355
-rw-r--r--AT91SAM7S256/armdebug/Debugger/debug_stub.h50
4 files changed, 437 insertions, 124 deletions
diff --git a/AT91SAM7S256/armdebug/Debugger/debug_comm.S b/AT91SAM7S256/armdebug/Debugger/debug_comm.S
index 15b9706..e801479 100644
--- a/AT91SAM7S256/armdebug/Debugger/debug_comm.S
+++ b/AT91SAM7S256/armdebug/Debugger/debug_comm.S
@@ -57,15 +57,6 @@ hex2char_lut:
/* Macros
*/
-/* _asciiz
- * Terminate string given string buffer pointer in \addrptr
- * reg is used as a scratch register (destroyed)
- *
- */
- .macro _asciiz reg, strptr
- mov \reg, #0 /* NULL character */
- strb \reg, [\strptr] /* Terminate ASCIIZ string */
- .endm
/* _hex2char_lut
* Internal routine to intialize the LUT address pointer
@@ -479,7 +470,7 @@ _copy_msg_from_usbbuf:
ldr r3, =debug_InUSBBuf
add r3, r3, #USB_GDBMSG_START
- _dbg_memcpy r2, r3, r4 /* r2 updated to point to next empty char slot in Rx buffer */
+ _dbg_memcpy r2, r3, r4, r0 /* r2 updated to point to next empty char slot in Rx buffer */
sub r4, r2, r5 /* r4: cummulative length of message */
/* Update debug_msgRxBuf_AppendPtr */
@@ -644,7 +635,7 @@ _copy_msg_to_usbbuf:
strb r0, [r3], #1 /* Message Length */
mov r2, r5 /* Copy to R2 for updating */
- _dbg_memcpy r3, r2, r4 /* This copies over the message fragment, r3, r2 updated */
+ _dbg_memcpy r3, r2, r4, r0 /* This copies over the message fragment, r3, r2 updated */
mov r5, r2 /* Updated Tx Append Pointer, keep in R5 for now */
/* Check USB bus status, transmit message if possible */
diff --git a/AT91SAM7S256/armdebug/Debugger/debug_macros.h b/AT91SAM7S256/armdebug/Debugger/debug_macros.h
index 324bcbf..652c62b 100644
--- a/AT91SAM7S256/armdebug/Debugger/debug_macros.h
+++ b/AT91SAM7S256/armdebug/Debugger/debug_macros.h
@@ -72,40 +72,51 @@
ldm \instrmask, {\instrreg, \instrmask, \codehandler}
.endm
+/* _asciiz
+ * Terminate string given string buffer pointer in \strptr
+ * scratchreg is used as a scratch register (destroyed)
+ *
+ */
+ .macro _asciiz strptr, scratchreg
+ mov \scratchreg, #0 /* ASCIIZ character */
+ strb \scratchreg, [\strptr] /* Terminate ASCII string */
+ .endm
/* _dbg_stpcpy
- * _dbg_stpcpy macro
- * On entry:
- * deststrptr: Destination string [Cannot be R0]
- * sourcestrptr: Source string [Cannot be R0]
- * On exit:
- * deststrptr: Pointer to NULL character in destination string
- * sourcestrptr: Pointer to NULL character slot in source string
- * R0: destroyed
+ * _dbg_stpcpy macro
+ * On entry:
+ * deststrptr: Destination string
+ * sourcestrptr: Source string
+ * scratchreg: scratch register for copying
+ * On exit:
+ * deststrptr: Pointer to ASCIIZ character in destination string
+ * sourcestrptr: Pointer to next character slot in source string (after ASCIIZ)
+ * scratchreg: destroyed
*/
- .macro _dbg_stpcpy deststrptr, sourcestrptr
-1: ldrb r0, [\sourcestrptr], #1
- strb r0, [\deststrptr], #1
- teq r0, #0
+ .macro _dbg_stpcpy deststrptr, sourcestrptr, scratchreg
+1: ldrb \scratchreg, [\sourcestrptr], #1
+ strb \scratchreg, [\deststrptr], #1
+ teq \scratchreg, #0
bne 1b
- sub \deststrptr, \deststrptr, #1 /* Adjust Destination string pointer to point at NULL character */
+ sub \deststrptr, \deststrptr, #1 /* Adjust Destination string pointer to point at ASCIIZ character */
.endm
/* _dbg_memcpy
* _dbg_stpcpy macro
* On entry:
- * deststrptr: Destination string [Cannot be R0]
- * sourcestrptr: Source string [Cannot be R0]
- * sizereg: Number of bytes to copy [Cannot be R0]
+ * deststrptr: Destination string
+ * sourcestrptr: Source string
+ * sizereg: Number of bytes to copy
+ * scratchreg: scratch register for copying
* On exit:
* deststrptr: Pointer to next character slot in destination string
* sourcestrptr: Pointer to next character slot in source string
* R0: destroyed
*/
- .macro _dbg_memcpy deststrptr, sourcestrptr, sizereg
-1: ldrb r0, [\sourcestrptr], #1
- strb r0, [\deststrptr], #1
+ .macro _dbg_memcpy deststrptr, sourcestrptr, sizereg, scratchreg
+1: ldrb \scratchreg, [\sourcestrptr], #1
+ strb \scratchreg, [\deststrptr], #1
subs \sizereg, \sizereg, #1
bne 1b
.endm
@@ -113,73 +124,87 @@
/* _dbg_outputMsgValidResponse
* Return Message with valid response ('+$')
* On exit:
- * R0: destroyed
- * R1: points to NULL character after the prefix
+ * R0: Pointer to Output Buffer next character slot location
+ * R1: destroyed
* R2: destroyed
*/
.macro _dbg_outputMsgValidResponse
- ldr r1, =debug_OutMsgBuf
- ldr r2, =debug_ValidResponsePrefix
- _dbg_stpcpy r1, r2
+ ldr r0, =debug_OutMsgBuf
+ ldr r1, =debug_ValidResponsePrefix
+ _dbg_stpcpy r0, r1, r2
.endm
/* _dbg_outputMsgStatusOk
- * Return Message with Ok ('+OK') status
+ * Return Message with Ok ('+$OK') status
* On exit:
- * R0: destroyed
+ * R0: Pointer to Output Buffer ASCIIZ location
* R1: destroyed
* R2: destroyed
*/
.macro _dbg_outputMsgStatusOk
- ldr r1, =debug_OutMsgBuf
- ldr r2, =debug_OkResponse
- _dbg_stpcpy r1, r2
+ ldr r0, =debug_OutMsgBuf
+ ldr r1, =debug_OkResponse /* ASCIIZ terminated */
+ _dbg_stpcpy r0, r1, r2
.endm
/* _dbg_outputMsgStatusErr
- * Return Message with Error ('-ENN') status
+ * Return Message with Error ('-$ENN') status
* On entry:
- * R0: register containing error value (byte)
+ * R0: error code
* On exit:
- * R0: destroyed
+ * R0: Pointer to Output Buffer ASCIIZ location
* R1: destroyed
* R2: destroyed
* R3: destroyed
*/
.macro _dbg_outputMsgStatusErr
- mov r3, r0
- ldr r1, =debug_OutMsgBuf
- ldr r2, =debug_ErrorResponsePrefix
- _dbg_stpcpy r1, r2
- mov r0, r3
- bl byte2ascii /* R1 points to NULL character after the prefix */
+ mov r3, r0
+ ldr r0, =debug_OutMsgBuf
+ ldr r1, =debug_ErrorResponsePrefix
+ _dbg_stpcpy r0, r1, r2
+ mov r1, r3
+ bl byte2ascii /* R0 points to buffer position after byte value */
+ _asciiz r0, r1
+ .endm
+
+/* _dbg_outputMsgStatusErrCode
+ * Return Message with Error ('-$ENN') status
+ * On exit:
+ * R0: Pointer to Output Buffer ASCIIZ location
+ * R1: destroyed
+ * R2: destroyed
+ */
+ .macro _dbg_outputMsgStatusErrCode errcode
+ ldr r0, =debug_OutMsgBuf
+ ldr r1, =debug_ErrorResponsePrefix
+ _dbg_stpcpy r0, r1, r2
+ mov r1, #\errcode
+ bl byte2ascii /* R0 points to buffer position after byte value */
+ _asciiz r0, r1
.endm
/* _dbg_outputMsgStatusSig
- * Return Message with Signal ('+SNN') status
- * On entry:
- * R0: register containing error value (byte)
+ * Return Message with Signal ('+$SNN') status
* On exit:
- * R0: destroyed
+ * R0: Pointer to Output Buffer ASCIIZ location
* R1: destroyed
* R2: destroyed
- * R3: destroyed
*/
- .macro _dbg_outputMsgStatusSig
- mov r3, r0
- ldr r1, =debug_OutMsgBuf
- ldr r2, =debug_SignalResponsePrefix
- _dbg_stpcpy r1, r2
- mov r0, r3
- bl byte2ascii /* R1 points to NULL character after the prefix */
+ .macro _dbg_outputMsgStatusSig statuscode
+ ldr r0, =debug_OutMsgBuf
+ ldr r1, =debug_SignalResponsePrefix
+ _dbg_stpcpy r0, r1, r2
+ mov r1, #\statuscode
+ bl byte2ascii /* R0 points to buffer position after byte value */
+ _asciiz r0, r1
.endm
/* _getdbgregisterfromindex
* Retrieve register contents from debugger stack given index
*
* On entry:
- * indexreg contains debugger stack index value (0-max entries)
+ * indexreg contains debugger stack index value (0-max index)
* On exit:
* indexreg: Breakpoint index (preserved)
* contentsreg: Register Contents for given index
@@ -189,6 +214,22 @@
ldr \contentsreg, [\contentsreg, \indexreg, lsl #2]
.endm
+/* _setdbgregisterfromindex
+ * Store register contents to debugger stack given index
+ *
+ * On entry:
+ * indexreg contains debugger stack index value (0-max index)
+ * contentsreg: Register Contents for given index
+ * addressreg: Scratch register for address pointer
+ * On exit:
+ * indexreg: Breakpoint index (preserved)
+ * contentsreg: Register Contents for given index
+ */
+ .macro _setdbgregisterfromindex indexreg, contentsreg, addressreg
+ ldr \addressreg, =__debugger_stack_bottom__
+ str \contentsreg, [\addressreg, \indexreg, lsl #2]
+ .endm
+
/* _index2bkptindex_addr
* Convert Breakpoint index to breakpoing entry address
diff --git a/AT91SAM7S256/armdebug/Debugger/debug_stub.S b/AT91SAM7S256/armdebug/Debugger/debug_stub.S
index 508b619..78a5472 100644
--- a/AT91SAM7S256/armdebug/Debugger/debug_stub.S
+++ b/AT91SAM7S256/armdebug/Debugger/debug_stub.S
@@ -126,6 +126,38 @@
#include "debug_stub.h"
#include "debug_macros.h"
+/* Macro definitions */
+
+/* _check_msgseparator
+ * Look for separator ','
+ * On entry:
+ * bufferptr: points to the parameter buffer [can't be R0]
+ * On exit:
+ * R0: destroyed
+ * bufferptr: points to the next character location in the parameter buffer
+ * Flags: Updated
+ */
+
+ .macro _check_msgseparator bufferptr
+ ldrb r0, [\bufferptr], #1 /* get separator */
+ cmp r0, #MSGBUF_SEPCHAR
+ .endm
+
+/* _check_msgassignment
+ * Look for assignment '='
+ * On entry:
+ * bufferptr: points to the parameter buffer [can't be R0]
+ * On exit:
+ * R0: destroyed
+ * bufferptr: points to the next character location in the parameter buffer
+ * Flags: Updated
+ */
+
+ .macro _check_msgassignment bufferptr
+ ldrb r0, [\bufferptr], #1 /* get separator */
+ cmp r0, #MSGBUF_SETCHAR
+ .endm
+
.bss
.align 4
debug_state:
@@ -160,17 +192,17 @@ debug_cmdIndexTable:
* R0: Input Message Parameter Buffer address pointer (points to contents after '$' and '<cmdchar>')
*/
debug_cmdJumpTable:
- .word _dbg__procGetRegs /* 'g' */
- .word _dbg__procSetRegs /* 'G' */
- .word _dbg__procGetOneReg /* 'p' */
- .word _dbg__procSetOneReg /* 'P' */
+ .word _dbg__cmd_GetAllRegs /* 'g' */
+ .word _dbg__cmd_SetAllRegs /* 'G' */
+ .word _dbg__cmd_GetOneReg /* 'p' */
+ .word _dbg__cmd_SetOneReg /* 'P' */
.word _dbg__nop /* 'm' */
.word _dbg__nop /* 'M' */
.word _dbg__nop /* 'c' */
.word _dbg__nop /* 's' */
.word _dbg__nop /* 'k' */
- .word _dbg__nop /* 'z' */
- .word _dbg__nop /* 'Z' */
+ .word _dbg__cmd_remove_breakpoint /* 'z' */
+ .word _dbg__cmd_insert_breakpoint /* 'Z' */
.word _dbg__nop /* '?' */
.word 0
@@ -482,7 +514,7 @@ dbg__bkpt_waitCMD:
bne _dbg__cmdError /* Shouldn't happen */
ldrb r0, [r4], #1 /* Look for command char */
bl _dbg__cmdChar2Index /* Index in R0 */
- ldr r1, =MSGBUF_CMDINDEX_OUTOFRANGE_VAL
+ mov r1, #CMDINDEX_OUTOFRANGE
teq r0, r1
moveq r0, #MSG_UNKNOWNCMD /* Out of range, Command character not recognized */
beq _dbg__cmdError /* Send response to GDB server */
@@ -515,7 +547,7 @@ _dbg__cmdChar2Index:
ldr r3, =debug_cmdIndexTable /* Convert command to index using r3 as Index Lookup Address Pointer */
1: ldrb r2, [r3, r0] /* Get table entry */
teq r2, #0
- moveq r0, #MSGBUF_CMDINDEX_OUTOFRANGE_VAL /* End of Index Table, Not found */
+ moveq r0, #CMDINDEX_OUTOFRANGE /* End of Index Table, Not found */
beq _exit_cmdIndexTable
teq r1, r2
addne r0, #1 /* Increment Index */
@@ -523,153 +555,322 @@ _dbg__cmdChar2Index:
_exit_cmdIndexTable:
bx lr
+/* __dbg__cmdParamLen
+ * Determines the length of the parameter buffer for a given command
+ * On entry:
+ * R0: parameter buffer pointer (contents after '$' and '<cmdchar>')
+ * On exit:
+ * R0: Address of parameter buffer (preserved)
+ * R1: length
+ */
+__dbg__cmdParamLen:
+ stmfd sp!, {r0,r2,lr} /* R2: scratch register */
+ mov r1, #0
+1: ldrb r2, [r0], #1
+ teq r2, #0
+ addne r1, r1, #1
+ bne 1b
+ ldmfd sp!, {r0,r2,pc}
+
+/* __dbg__procCmdOk
+ * Common subroutine exit stub to return Command Ok Status for Command Handlers
+ * DO NOT CALL THIS STUB DIRECTLY! It Assumes that the return address is in the stack.
+ *
+ */
+__dbg__procCmdOk:
+ _dbg_outputMsgStatusOk
+ bl dbg__putDebugMsg /* Send error response to the GDB server */
+ ldmfd sp!, {pc}
+
/* __dbg__procCmdParamError
* Common subroutine exit stub to handle Command Parameter Error for Command Handlers
* DO NOT CALL THIS STUB DIRECTLY! It Assumes that the return address is in the stack.
*
*/
-
__dbg__procCmdParamError:
- mov r0, #MSG_UNKNOWNPARAM
- _dbg_outputMsgStatusErr
+ _dbg_outputMsgStatusErrCode MSG_UNKNOWNPARAM
bl dbg__putDebugMsg /* Send error response to the GDB server */
ldmfd sp!, {pc}
+/* __dbg__procBreakpointAddrError
+ * Common subroutine exit stub to handle Breakpoint Address Error for Breakpoint Insert/Remove Handlers
+ * DO NOT CALL THIS STUB DIRECTLY! It Assumes that the return address is in the stack.
+ *
+ */
+__dbg__procBreakpointAddrError:
+ _dbg_outputMsgStatusErrCode MSG_UNKNOWNBRKPT
+ bl dbg__putDebugMsg /* Send error response to the GDB server */
+ ldmfd sp!, {pc}
+
+
-/* _dbg__procGetOneReg
+/* _dbg__cmd_GetOneReg
* Get One Register Value Command Handler
- * Valid register parameter is from '0' to 'F' for User Mode Registers R0-R15
- * CPSR register parameer is '!'
+ * Valid command parameter x is from '0' to 'F' for User Mode Registers R0-R15
+ * CPSR register is '!'
* On entry:
* r0: parameter buffer pointer (contents after '$' and '<cmdchar>')
+ * x
+ * On exit:
+ * r0, r1, r2, r3: destroyed
*
*/
-_dbg__procGetOneReg:
+_dbg__cmd_GetOneReg:
stmfd sp!, {lr}
- ldrb r2, [r0, #1] /* char after parameter value (Should be NULL character) */
- ldrb r0, [r0] /* Retrieve register index parameter to R0 */
- teq r2, #0 /* Check for NULL */
+ bl __dbg__cmdParamLen
+ teq r1, #CMD_REG_GETONE_PARAMLEN /* Check for correct length */
bne __dbg__procCmdParamError /* Unexpected input, report error */
+ ldrb r0, [r0] /* Load Register index parameter */
teq r0, #MSGBUF_CPSRREG /* Check for CPSR register indicator */
moveq r0, #DBGSTACK_USERCPSR_OFFSET /* Put offset from User Registers (-1) into index, so that after adjustment it points to CPSR slot */
- beq _dbg__procRegister /* Handle User CPSR */
+ beq _dbg__proc_getRegister /* Handle User CPSR */
bl char2hex /* Convert to Hex value (assume input is valid) */
cmp r0, #NIBBLE0 /* sanity check, (though it is not foolproof as input char in 0x0-0xF (ctrl-chars) will pass through) */
bhi __dbg__procCmdParamError /* Non-hex char, report error */
-_dbg__procRegister:
+_dbg__proc_getRegister:
mov r3, r0 /* Keep register index safe */
- _dbg_outputMsgValidResponse /* Setup R1 with address of output message buffer data pointer (after response prefix) */
- mov r0, r3 /* Restore register index value */
+ _dbg_outputMsgValidResponse /* R0: address of output message buffer data pointer (after response prefix) */
+ mov r1, r3 /* Move register index value to R1 */
bl _dbg_outputOneRegValue /* update output buffer */
+ _asciiz r0, r1
bl dbg__putDebugMsg /* Send response to the GDB server */
ldmfd sp!, {pc}
/* _dbg_outputOneRegValue
* Given Register Index (-1: CPSR, 0-F: R0-R15), output hex char to buffer
* On entry:
- * r0: register index (-1, 0-F)
- * r1: output message buffer pointer
+ * r0: output message buffer pointer
+ * r1: register index (-1, 0-F)
* On exit:
- * r0: output message buffer pointer
- * r1: updated (points to NULL character at end of Output Buffer)
+ * r0: updated (points to next character slot at end of Output Buffer)
+ * r1: original output message buffer pointer
* r2: destroyed
*/
_dbg_outputOneRegValue:
stmfd sp!, {lr}
- add r2, r0, #DBGSTACK_USERREG_INDEX /* Convert register index to Debug Stack index */
- _getdbgregisterfromindex r2, r0 /* Retrieve Register contents into R0 */
- ldr r0, [r0]
+ 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 */
ldmfd sp!, {pc}
-/* _dbg__procGetRegs
+/* _dbg__cmd_GetAllRegs
* Get All Register Values Command Handler
* Output Buffer returns register values in the order: User CPSR, R0, R1, R2, ..., R15
* On entry:
* r0: parameter buffer pointer (contents after '$' and '<cmdchar>')
+ * <NULL> (no parameters)
+ * On exit:
+ * r0, r1, r2, r3: destroyed
*/
-_dbg__procGetRegs:
+_dbg__cmd_GetAllRegs:
stmfd sp!, {lr}
- ldrb r0, [r0] /* Retrieve register index parameter to R0 */
- teq r0, #0 /* Check for NULL */
+ bl __dbg__cmdParamLen
+ teq r1, #CMD_REG_GETALL_PARAMLEN /* Check for correct length */
bne __dbg__procCmdParamError /* Unexpected input, report error */
_dbg_outputMsgValidResponse /* Setup R1 with address of output message buffer data pointer (after response prefix) */
mov r3, #DBGSTACK_USERCPSR_OFFSET /* Output User CPSR Value first */
-1: mov r0, r3
+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 */
+ _asciiz r0, r1
bl dbg__putDebugMsg /* Send response to the GDB server */
ldmfd sp!, {pc}
+/* _dbg__cmd_SetOneReg
+ * Set One Register Value Command Handler
+ * Valid command parameter x is from '0' to 'F' for User Mode Registers R0-R15
+ * CPSR register is '!'
+ * On entry:
+ * r0: parameter buffer pointer (contents after '$' and '<cmdchar>')
+ * x=rrrr
+ * On exit:
+ * r0, r1, r2, r3: destroyed
+ *
+ */
-_dbg__procSetOneReg:
-_dbg__procSetRegs:
- bx lr
+_dbg__cmd_SetOneReg:
+ stmfd sp!, {lr}
+ bl __dbg__cmdParamLen
+ teq r1, #CMD_REG_SETONE_PARAMLEN /* Check for correct length */
+ bne __dbg__procCmdParamError /* Unexpected input, report error */
+ mov r3, r0 /* Keep parameter buffer address in R3 */
+ ldrb r1, [r3], #1 /* Load Register index parameter */
+ _check_msgassignment r3
+ bne __dbg__procCmdParamError /* Can't find '=' */
+ mov r0, r1 /* Move register index to R0 for subsequent processing */
+ teq r0, #MSGBUF_CPSRREG /* Check for CPSR register indicator */
+ moveq r0, #DBGSTACK_USERCPSR_OFFSET /* Put offset from User Registers (-1) into index, so that after adjustment it points to CPSR slot */
+ beq _dbg__proc_setRegister /* Handle User CPSR */
+ bl char2hex /* Convert to Hex value (assume input is valid) */
+ cmp r0, #NIBBLE0 /* sanity check, (though it is not foolproof as input char in 0x0-0xF (ctrl-chars) will pass through) */
+ bhi __dbg__procCmdParamError /* Non-hex char, report error */
+
+_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
+ _setdbgregisterfromindex r2, r0, r3 /* Set Register contents in R0, using index in R2, and scratch register R3 */
+ b __dbg__procCmdOk
+
+/* _dbg__cmd_SetAllReg
+ * Set All Register Values Command Handler
+ * On entry:
+ * r0: parameter buffer pointer (contents after '$' and '<cmdchar>')
+ * rrrrRRRRrrrr... (17 registers)
+ * On exit:
+ * r0, r1, r2, r3: destroyed
+ *
+ */
+_dbg__cmd_SetAllRegs:
+/* FIXME: Assumes that the registers are in the sequence CPSR, R0, R1, ... R15 -- 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 */
+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 */
+ add r2, r2, #1 /* increment index */
+ 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
/* _dbg__nop
* NOP Command Handler (placeholder)
* On entry:
* r0: parameter buffer (contents after '$' and '<cmdchar>')
+ * On exit:
+ * r0, r1, r2, r3: destroyed
*/
_dbg__nop:
stmfd sp!, {lr}
- mov r0, #MSG_ERRIMPL /* Stub, not implemented yet */
- _dbg_outputMsgStatusErr
- bl dbg__putDebugMsg /* Send error response to the GDB server */
+ _dbg_outputMsgStatusErrCode MSG_ERRIMPL /* Stub, not implemented yet */
+ bl dbg__putDebugMsg /* Send error response to the GDB server */
ldmfd sp!, {pc}
-/* dbg__cmd_install_breakpoint
- * Configure Breakpoint
- * On entry:
- * r0: index of breakpoint to install
- * r1: instruction address to install
- */
-dbg__cmd_install_breakpoint:
- bl _dbg__install_one_breakpoint /* r0: index, r1: instruction address */
- b dbg__bkpt_waitCMD
-/* dbg__cmd_clear_breakpoint
- * Clear Breakpoint
+/* _dbg__proc_brkpt_params
+ * Process Breakpoint Parameters
+ * On entry:
+ * r0: parameter buffer pointer (contents after '$' and '<cmdchar>')
+ * t,AA..AA,k
+ * On exit:
+ * r0: non-zero = breakpoint address; 0 = parameter error
+ * r1: destroyed
+ * r2: destroyed
+ * r3: destroyed
+ */
+_dbg__proc_brkpt_params:
+ /* FIXME: Add support for watchpoints */
+ stmfd sp!, {lr}
+ mov r3, r0 /* Keep parameter buffer address in R3 */
+ ldrb r0, [r3], #1 /* get breakpoint type t */
+ bl char2hex
+ cmp r0, #CMD_BKPT_TYPE_BREAK_MEMORY
+ bne _dbg__proc_brkpt_params_error /* We only support memory breakpoints for now */
+ _check_msgseparator r3
+ bne _dbg__proc_brkpt_params_error /* Something wrong with the parameters */
+ mov r0, r3 /* Check Address */
+ bl ascii2word /* R0: value, R1: pointer to next char slot */
+ mov r3, r0 /* Keep breakpoint address in R3 */
+ _check_msgseparator r1
+ bne _dbg__proc_brkpt_params_error /* Something wrong with the parameters */
+ ldrb r0, [r1], #1 /* get breakpoint kind k */
+ bl char2hex
+ cmp r0, #CMD_BKPT_KIND_THUMB
+ orreq r3, r3, #1 /* Mark Thumb breakpoints */
+ beq _exit_dbg__proc_brkpt_params
+ cmp r0, #CMD_BKPT_KIND_ARM
+ beq _exit_dbg__proc_brkpt_params /* ARM breakpoint */
+
+_dbg__proc_brkpt_params_error:
+ mov r3, #0 /* Unrecognized breakpoint type */
+_exit_dbg__proc_brkpt_params:
+ mov r0, r3 /* return breakpoint address */
+ ldmfd sp!, {pc}
+
+/* _dbg__cmd_insert_breakpoint
+ * Add Breakpoint
+ * On entry:
+ * r0: parameter buffer pointer (contents after '$' and '<cmdchar>')
+ * t,AA..AA,k
+ * On exit:
+ * r0, r1, r2, r3: destroyed
+ */
+_dbg__cmd_insert_breakpoint:
+ stmfd sp!, {lr}
+ bl __dbg__cmdParamLen
+ teq r1, #CMD_BKPT_INSERT_PARAMLEN /* Check for correct length */
+ bne __dbg__procCmdParamError /* Unexpected input, report error */
+ bl _dbg__proc_brkpt_params /* R0: Breakpoint Address */
+ teq r0, #0
+ beq __dbg__procBreakpointAddrError /* Thumb2 instructions, or unknown kind */
+ mov r3, r0 /* Keep breakpoint address in R3 */
+ mov r0, #0 /* Empty Breakpoint entry */
+ bl _dbg_find_breakpoint_slot /* Look for an available breakpoint slot, return index in R0 */
+ cmp r0, #CMD_BKPT_NOTFOUND
+ beq __dbg__procBreakpointAddrError /* No empty slot! */
+ mov r1, r3 /* Move breakpoint address to R1 */
+ bl _dbg__install_one_breakpoint /* r0: index, r1: instruction address */
+ b __dbg__procCmdOk
+
+/* _dbg__cmd_remove_breakpoint
+ * Remove Breakpoint
* On entry:
- * r0: index of breakpoint to clear
+ * r0: parameter buffer pointer (contents after '$' and '<cmdchar>')
+ * t,AA..AA,k
+ * On exit:
+ * r0, r1, r2, r3: destroyed
*/
-dbg__cmd_clear_breakpoint:
+_dbg__cmd_remove_breakpoint:
+ stmfd sp!, {lr}
+ bl __dbg__cmdParamLen
+ teq r1, #CMD_BKPT_REMOVE_PARAMLEN /* Check for correct length */
+ bne __dbg__procCmdParamError /* Unexpected input, report error */
+ bl _dbg__proc_brkpt_params /* R0: Breakpoint Address */
+ teq r0, #0
+ beq __dbg__procBreakpointAddrError /* Thumb2 instructions, or unknown kind */
+ bl _dbg_find_breakpoint_slot /* Look for matching breakpoint slot, return index in R0 */
+ cmp r0, #CMD_BKPT_NOTFOUND
+ beq __dbg__procBreakpointAddrError /* Specified Breakpoint not found! */
_index2bkptindex_addr r0, r0 /* Calculate Breakpoint Entry Address */
- bl _dbg__clear_one_breakpoint
- b dbg__bkpt_waitCMD
+ bl _dbg__clear_one_breakpoint /* R0: address of breakpoint to clear */
+ b __dbg__procCmdOk
-/* dbg__cmd_run
+/* _dbg__cmd_run
* Continue execution of program
*/
-dbg__cmd_run:
+_dbg__cmd_run:
bl _dbg__activate_breakpoints
b __dbg__resume_execution
-/* dbg__cmd_step
+/* _dbg__cmd_step
* Single Step execution of program
*/
-dbg__cmd_step:
+_dbg__cmd_step:
bl _dbg_next_instruction_addr /* next instruction address returned in r1 */
bl _dbg__install_singlestep /* Setup Single Step */
bl _dbg__activate_singlestep
b __dbg__resume_execution
-/* dbg__cmd_cont
+/* _dbg__cmd_cont
* Continue execution of program.
* If this is a Normal Breakpoint, then we need to install an Autobreakpoint at next instruction address
* and resume from current (Breakpoint) exception address
* Else (it is a Manual Breakpoint)
* We need to resume from the next instruction address
*/
-dbg__cmd_cont:
+_dbg__cmd_cont:
/* FIXME: What happens if we call this when we did not stop at a Breakpoint previously? */
_dbg_getstate r0
ldr r1, =DBG_MANUAL_BKPT_ARM
@@ -1345,6 +1546,38 @@ _thumb_long_b_handler: /* Long BL or BLX (4 bytes) Note: b11 (H) indicates 1s
* Breakpoint Manipulation Routines
*
****************************************************************************/
+/* _dbg_find_breakpoint_slot
+ * Find the matching Breakpoint Slot.
+ * This is both used to find empty slots (pass R0=0x0000) or
+ * occupied slots (pass R0=<brkpt addr>)
+ *
+ * On Entry:
+ * R0: Breakpoint Address
+ * On Exit:
+ * R0: Matching Index (-1: not found)
+ *
+ * NOTE: This routine performs exact match, i.e., breakpoint address MUST be configured
+ * for ARM or Thumb (bit 0 clear/set) as appropriate
+ */
+
+_dbg_find_breakpoint_slot:
+ stmfd sp!, {r1,r2,r3, lr}
+ mov r1, #1 /* Only consider Breakpoints 1-7 */
+ ldr r3, =__breakpoints_num__
+1:
+ _index2bkptindex_addr r1, r2 /* Calculate Breakpoint Entry Address */
+ ldr r2, [r2] /* Get actual breakpoint entry (instruction address) */
+ cmp r0, r2
+ beq _found_breakpoint_slot
+ add r1, r1, #1 /* no match, check next */
+ cmp r1, r3
+ blo 1b /* continue checking only if we don't exceed __breakpoints_num__ */
+
+_notfound_breakpoint_slot:
+ mov r1, #CMD_BKPT_NOTFOUND
+_found_breakpoint_slot:
+ mov r0, r1 /* Return value in R0 */
+ ldmfd sp!, {r1,r2,r3, pc}
/* _dbg__clear_singlestep
* Clear the Single Step Breakpoint
diff --git a/AT91SAM7S256/armdebug/Debugger/debug_stub.h b/AT91SAM7S256/armdebug/Debugger/debug_stub.h
index 9cf4d0a..41044b2 100644
--- a/AT91SAM7S256/armdebug/Debugger/debug_stub.h
+++ b/AT91SAM7S256/armdebug/Debugger/debug_stub.h
@@ -60,10 +60,57 @@
#define MSGBUF_CPSRREG '!'
#define MSGBUF_SETCHAR '='
#define MSGBUF_CHKSUMCHAR '#'
+#define MSGBUF_SEPCHAR ','
#define MSGBUF_MSGERROR -1
-#define MSGBUF_CMDINDEX_OUTOFRANGE_VAL -1
+/*@}*/
+
+/** @name Debug Command Lookup Constants.
+ *
+ * Debug Command Lookup
+ */
+/*@{*/
+
+#define CMDINDEX_OUTOFRANGE -1
+/*@}*/
+
+/** @name Debug Register Command Constants.
+ *
+ * Debug Register Command
+ */
+/*@{*/
+#define CMD_REG_NUMREGS 17
+#define CMD_REG_GETONE_PARAMLEN 1
+#define CMD_REG_GETALL_PARAMLEN 0
+#define CMD_REG_SETONE_PARAMLEN 6
+#define CMD_REG_SETALL_PARAMLEN (CMD_REG_NUMREGS*4)
+
/*@}*/
+
+/** @name Debug Breakpoint Command Constants.
+ *
+ * Debug Breakpoint Command
+ */
+/*@{*/
+
+#define CMD_BKPT_INSERT_PARAMLEN 12
+#define CMD_BKPT_REMOVE_PARAMLEN 12
+
+
+#define CMD_BKPT_TYPE_BREAK_MEMORY 0
+#define CMD_BKPT_TYPE_BREAK_HARD 1 /* Not supported */
+#define CMD_BKPT_TYPE_WATCH_WRITE 2 /* Not supported (yet) */
+#define CMD_BKPT_TYPE_WATCH_READ 3 /* Not supported (yet) */
+#define CMD_BKPT_TYPE_WATCH_ACCESS 4 /* Not supported (yet) */
+
+#define CMD_BKPT_KIND_THUMB 2
+#define CMD_BKPT_KIND_THUMB2 3 /* Not supported */
+#define CMD_BKPT_KIND_ARM 4
+
+#define CMD_BKPT_NOTFOUND -1
+
+/*@}*/
+
/** @name Debug Stack Constants.
*
* Debug Stack Manipulation Values
@@ -159,6 +206,7 @@ ENUM_VAL(MSG_ERRCHKSUM) /**< Checksum Error. */
ENUM_VAL(MSG_ERRFORMAT) /**< Message Format Error. */
ENUM_VAL(MSG_UNKNOWNCMD) /**< Unrecognized Command Error. */
ENUM_VAL(MSG_UNKNOWNPARAM) /**< Unrecognized Parameter Error. */
+ENUM_VAL(MSG_UNKNOWNBRKPT) /**< Unrecognized Breakpoint Error. */
ENUM_END(dbg_msg_errno)