From b66fd09e34c9a720acd5367eb7658456417a8c3b Mon Sep 17 00:00:00 2001 From: Tat-Chee Wan (USM) Date: Tue, 22 Mar 2011 16:50:25 +0800 Subject: continue command wip Work in Progress, for implementing continue command --- Debugger/debug_macros.h | 14 ++++++++++++++ Debugger/debug_stub.S | 30 +++++++++++++++++++++++++++++- Debugger/debug_stub.h | 21 ++++++++++++++++++++- 3 files changed, 63 insertions(+), 2 deletions(-) diff --git a/Debugger/debug_macros.h b/Debugger/debug_macros.h index 3fcc78c..d6786d5 100644 --- a/Debugger/debug_macros.h +++ b/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/Debugger/debug_stub.S b/Debugger/debug_stub.S index 796de04..b0d7fed 100644 --- a/Debugger/debug_stub.S +++ b/Debugger/debug_stub.S @@ -224,7 +224,7 @@ 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' */ @@ -947,6 +947,34 @@ _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 '') + * Optional: AA..AA + * On exit: + * r0, r1, r2, r3, r4: destroyed + */ +_dbg__cmd_Continue: + stmfd sp!, {lr} + 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 r1, #DBGSTACK_NEXTINSTR_INDEX /* The Next Instruction Pointer for Resume is in index 0 of the Debug Stack */ + _setdbgregisterfromindex r1, r0, r2 /* Set Register contents in R0, using index in R2, and scratch register R3 */ + +_dbg__cmd_processContinue: +@@@@@ + /* Switch mode to Previous Mode, reload all the registers (except for PC) */ + /* Switch back to ABORT, resume with PC and SPSR */ + b __dbg__procCmdOk + + + /* _dbg__proc_brkpt_params * Process Breakpoint Parameters * On entry: diff --git a/Debugger/debug_stub.h b/Debugger/debug_stub.h index e39fc8e..85ff22a 100644 --- a/Debugger/debug_stub.h +++ b/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,10 @@ * 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_USERCPSR_OFFSET (DBGSTACK_USERCPSR_INDEX-DBGSTACK_USERREG_INDEX) /* = -1, offset for calculating Debug Stack index */ /*@}*/ /** @name Bitmask Definitions. -- cgit v1.2.3 From fae838b025f11aca2c8835ec3b27f9d567a52226 Mon Sep 17 00:00:00 2001 From: Tat-Chee Wan (USM) Date: Tue, 22 Mar 2011 20:55:58 +0800 Subject: continue execution wip Work in Progress to implement GDB Continue Execution --- Debugger/debug_stub.S | 24 ++++++++++++++++++------ Debugger/debug_stub.h | 1 + Debugger/undef_handler.S | 41 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 6 deletions(-) diff --git a/Debugger/debug_stub.S b/Debugger/debug_stub.S index b0d7fed..ffb6062 100644 --- a/Debugger/debug_stub.S +++ b/Debugger/debug_stub.S @@ -964,15 +964,27 @@ _dbg__cmd_Continue: 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 r1, #DBGSTACK_NEXTINSTR_INDEX /* The Next Instruction Pointer for Resume is in index 0 of the Debug Stack */ - _setdbgregisterfromindex r1, r0, r2 /* Set Register contents in R0, using index in R2, and scratch register R3 */ + 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: -@@@@@ - /* Switch mode to Previous Mode, reload all the registers (except for PC) */ - /* Switch back to ABORT, resume with PC and SPSR */ - b __dbg__procCmdOk +/* 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) */ +@@@@@ +__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 */ + +_dbg__switch2undefmode: + msr cpsr_c, #(MODE_UND | CPSR_FIQ | CPSR_IRQ) /* Configure Undef Mode */ + ldr lr, =resume_execution + mov pc, lr /* Exit via UNDEF mode */ /* _dbg__proc_brkpt_params diff --git a/Debugger/debug_stub.h b/Debugger/debug_stub.h index 85ff22a..dd71a16 100644 --- a/Debugger/debug_stub.h +++ b/Debugger/debug_stub.h @@ -147,6 +147,7 @@ #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_USERCPSR_OFFSET (DBGSTACK_USERCPSR_INDEX-DBGSTACK_USERREG_INDEX) /* = -1, offset for calculating Debug Stack index */ /*@}*/ diff --git a/Debugger/undef_handler.S b/Debugger/undef_handler.S index f040219..8d33e13 100644 --- a/Debugger/undef_handler.S +++ b/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 r0, spsr /* 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 */ + + + -- cgit v1.2.3 From b3b6c06df795c736afa26debc17aca7890d56aef Mon Sep 17 00:00:00 2001 From: Tat-Chee Wan (USM) Date: Wed, 23 Mar 2011 07:17:13 +0800 Subject: do not push lr to stack in continue command handler --- Debugger/debug_stub.S | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Debugger/debug_stub.S b/Debugger/debug_stub.S index ffb6062..86a1187 100644 --- a/Debugger/debug_stub.S +++ b/Debugger/debug_stub.S @@ -953,10 +953,11 @@ _dbg__cmd_WriteMem: * r0: parameter buffer pointer (contents after '$' and '') * Optional: AA..AA * On exit: - * r0, r1, r2, r3, r4: destroyed + * 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: - stmfd sp!, {lr} bl __dbg__cmdParamLen cmp r1, #CMD_REG_CONTINUE_PARAMLEN /* Check for correct parameter length */ beq _dbg__cmd_processContinue /* Continue from current PC */ -- cgit v1.2.3 From 8e54782f9f6d30a119327c3852a427776e5ff84a Mon Sep 17 00:00:00 2001 From: Tat-Chee Wan (USM) Date: Wed, 23 Mar 2011 07:22:49 +0800 Subject: fix syntax error for msr spsr instruction --- Debugger/undef_handler.S | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Debugger/undef_handler.S b/Debugger/undef_handler.S index 8d33e13..5562738 100644 --- a/Debugger/undef_handler.S +++ b/Debugger/undef_handler.S @@ -120,7 +120,7 @@ resume_execution: 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 r0, spsr /* Update SPSR for return to program being debugged */ + 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! */ @@ -131,10 +131,10 @@ 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 */ + 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 */ + 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: -- cgit v1.2.3 From 808ab55ee475b1fdf587e8c2b8d57cd8e6e1eaf7 Mon Sep 17 00:00:00 2001 From: Tat-Chee Wan (USM) Date: Wed, 23 Mar 2011 07:50:17 +0800 Subject: cleanup breakpoint waitcmd loop --- Debugger/debug_stub.S | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/Debugger/debug_stub.S b/Debugger/debug_stub.S index 86a1187..02f58ff 100644 --- a/Debugger/debug_stub.S +++ b/Debugger/debug_stub.S @@ -578,11 +578,16 @@ dbg__bkpt_offset_outofrange: * ****************************************************************************/ dbg__bkpt_waitCMD: + /* We enter this code section when a Breakpoint Triggers */ _dbg_setmode TRUE /* Debug Mode = True */ + _dbg_outputMsgStatusSig 0x0 /* FIXME: Dummy Signal number */ + bl dbg__putDebugMsg /* 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 $\0 */ mov r4, r1 /* Use R4 as buffer pointer */ @@ -601,22 +606,19 @@ _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 @@ -974,6 +976,8 @@ _dbg__cmd_processContinue: breakpoint that was triggered) */ @@@@@ +#ifdef 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 */ @@ -981,6 +985,7 @@ __dbg__sendOkBeforeResume: 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 */ -- cgit v1.2.3 From 260f2f561dcb016d553e45338b46c0490e2980aa Mon Sep 17 00:00:00 2001 From: Tat-Chee Wan (USM) Date: Wed, 23 Mar 2011 07:52:25 +0800 Subject: fix if preprocessor syntax error --- Debugger/debug_stub.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Debugger/debug_stub.S b/Debugger/debug_stub.S index 02f58ff..0a70784 100644 --- a/Debugger/debug_stub.S +++ b/Debugger/debug_stub.S @@ -976,7 +976,7 @@ _dbg__cmd_processContinue: breakpoint that was triggered) */ @@@@@ -#ifdef 0 +#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 -- cgit v1.2.3 From 1fe10665ea04f53f336676e88712391b7e5331da Mon Sep 17 00:00:00 2001 From: Tat-Chee Wan (USM) Date: Wed, 23 Mar 2011 08:09:14 +0800 Subject: receive from nxt only when we actually sent something to it --- Host/nxt-gdb-server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Host/nxt-gdb-server.py b/Host/nxt-gdb-server.py index a72055f..4babdb9 100755 --- a/Host/nxt-gdb-server.py +++ b/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 () -- cgit v1.2.3 From 9c6c02f8557a1aa44c344024bd8e67af6816cd67 Mon Sep 17 00:00:00 2001 From: Tat-Chee Wan (USM) Date: Wed, 23 Mar 2011 09:00:29 +0800 Subject: fix char2hex to allow lower case ascii hex chars --- Debugger/debug_comm.S | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Debugger/debug_comm.S b/Debugger/debug_comm.S index 75f835e..c5738da 100644 --- a/Debugger/debug_comm.S +++ b/Debugger/debug_comm.S @@ -127,7 +127,10 @@ 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. + * WARNING: The checking is not exhaustive, invalid ASCII characters can + * still slip thorough. */ .global char2hex @@ -135,8 +138,10 @@ char2hex: and r0, #BYTE0 /* make sure that input is sane */ cmp r0, #'0' blo exit_char2hex - cmp r0, #'F' + cmp r0, #'f' bhi exit_char2hex + /* In range '0'..'f' */ +perform_char2hex: _char2hex r0 exit_char2hex: bx lr -- cgit v1.2.3 From cf0bf1c74c61c8bc4f3c74a9a92dc482be13d531 Mon Sep 17 00:00:00 2001 From: Tat-Chee Wan (USM) Date: Wed, 23 Mar 2011 09:00:52 +0800 Subject: changed response for unrecognized command to return empty gdb message --- Debugger/debug_stub.S | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Debugger/debug_stub.S b/Debugger/debug_stub.S index 0a70784..4156d54 100644 --- a/Debugger/debug_stub.S +++ b/Debugger/debug_stub.S @@ -599,8 +599,13 @@ dbg__bkpt_waitCMD_cont: bl _dbg__cmdChar2Index /* Index in R0 */ mov r1, #CMDINDEX_OUTOFRANGE teq r0, r1 + bl _dbg__nop + 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 */ -- cgit v1.2.3 From c5319c87759fe9734b6d1433fc2f96f27c0ad828 Mon Sep 17 00:00:00 2001 From: Tat-Chee Wan (USM) Date: Wed, 23 Mar 2011 09:38:14 +0800 Subject: more gdb request response cleanup --- Debugger/debug_stub.S | 38 ++++++++++++++++++++++++++++++++++---- Debugger/debug_stub.h | 1 + 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/Debugger/debug_stub.S b/Debugger/debug_stub.S index 4156d54..5d05a49 100644 --- a/Debugger/debug_stub.S +++ b/Debugger/debug_stub.S @@ -210,7 +210,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: @@ -229,7 +229,9 @@ debug_cmdJumpTable: .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 /* @@ -580,8 +582,10 @@ dbg__bkpt_offset_outofrange: dbg__bkpt_waitCMD: /* We enter this code section when a Breakpoint Triggers */ _dbg_setmode TRUE /* Debug Mode = True */ - _dbg_outputMsgStatusSig 0x0 /* FIXME: Dummy Signal number */ - bl dbg__putDebugMsg /* Send signal response to the GDB server */ + _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 */ @@ -731,6 +735,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 '') + * 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 '') + * [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 @@ -994,6 +1023,7 @@ __dbg__sendOkBeforeResume: _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 */ diff --git a/Debugger/debug_stub.h b/Debugger/debug_stub.h index dd71a16..b61735b 100644 --- a/Debugger/debug_stub.h +++ b/Debugger/debug_stub.h @@ -228,6 +228,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. */ -- cgit v1.2.3 From 17fed9ce97331172b39f16bc0c4cdbd0109c27a3 Mon Sep 17 00:00:00 2001 From: Tat-Chee Wan (USM) Date: Wed, 23 Mar 2011 10:01:09 +0800 Subject: added more test messages --- Host/gdb-commands.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Host/gdb-commands.txt b/Host/gdb-commands.txt index 9b52613..8e6f156 100644 --- a/Host/gdb-commands.txt +++ b/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 -- cgit v1.2.3 From df3a37772fea4f6f7854100857aa3c1d2766a085 Mon Sep 17 00:00:00 2001 From: Tat-Chee Wan (USM) Date: Wed, 23 Mar 2011 10:22:22 +0800 Subject: add missing conditional branch to command checking logic --- Debugger/debug_stub.S | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Debugger/debug_stub.S b/Debugger/debug_stub.S index 5d05a49..5c91975 100644 --- a/Debugger/debug_stub.S +++ b/Debugger/debug_stub.S @@ -603,7 +603,9 @@ dbg__bkpt_waitCMD_cont: bl _dbg__cmdChar2Index /* Index in R0 */ mov r1, #CMDINDEX_OUTOFRANGE teq r0, r1 - bl _dbg__nop + 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 -- cgit v1.2.3 From 557eb76616e65cd27c3a014796eafd09836b0996 Mon Sep 17 00:00:00 2001 From: Tat-Chee Wan (USM) Date: Wed, 23 Mar 2011 10:58:40 +0800 Subject: modify get and set all regs to handle r0-r15 followed by cpsr --- Debugger/debug_stub.S | 30 +++++++++++++++++++++++------- Debugger/debug_stub.h | 1 + 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/Debugger/debug_stub.S b/Debugger/debug_stub.S index 5c91975..7c54810 100644 --- a/Debugger/debug_stub.S +++ b/Debugger/debug_stub.S @@ -126,6 +126,11 @@ * Currently, watchpoints are not implemented as they require hardware support as well (need verification). */ +/* 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" @@ -816,7 +821,7 @@ _dbg_outputOneRegValue: /* _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 '') * (no parameters) @@ -830,13 +835,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} @@ -887,20 +897,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) diff --git a/Debugger/debug_stub.h b/Debugger/debug_stub.h index b61735b..7dc9aa8 100644 --- a/Debugger/debug_stub.h +++ b/Debugger/debug_stub.h @@ -148,6 +148,7 @@ #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 */ /*@}*/ -- cgit v1.2.3 From 2a91d2fc501a9d84753586a900a01be59b6da24d Mon Sep 17 00:00:00 2001 From: Tat-Chee Wan (USM) Date: Wed, 23 Mar 2011 11:32:44 +0800 Subject: changed output routines to use little endian as default --- Debugger/debug_comm.S | 15 +++++++++++++++ SConstruct | 4 ++++ 2 files changed, 19 insertions(+) diff --git a/Debugger/debug_comm.S b/Debugger/debug_comm.S index c5738da..54c16a6 100644 --- a/Debugger/debug_comm.S +++ b/Debugger/debug_comm.S @@ -207,7 +207,9 @@ byte2ascii: .global halfword2ascii halfword2ascii: stmfd sp!, {r0,r2,r3, lr} /* Keep ASCII buffer pointer */ +#ifdef __BIG_ENDIAN__ mov r2, r1, lsl #16 /* copy of input halfword value R1[15:0], shifted to MSH R2[31:16] */ +#endif mov r3, #2 /* Loop Counter */ b _conv_byte2ascii /* goto Byte conversion loop */ @@ -231,6 +233,8 @@ word2ascii: /* Fall through to byte coversion loop */ +#ifdef __BIG_ENDIAN__ +/* Rotate then convert */ _conv_byte2ascii: 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 */ @@ -239,6 +243,17 @@ _conv_byte2ascii: bne _conv_byte2ascii ldmfd sp!, {r1,r2,r3, pc} +#else /* __LITTLE_ENDIAN__ */ +/* Convert then rotate */ +_conv_byte2ascii: + 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 + ldmfd sp!, {r1,r2,r3, pc} + +#endif /* ascii2byte * On entry: diff --git a/SConstruct b/SConstruct index 4ca6207..898bb91 100644 --- a/SConstruct +++ b/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__') -- cgit v1.2.3 From bbdd5f023b53949d606379c606fe55ace998102e Mon Sep 17 00:00:00 2001 From: Tat-Chee Wan (USM) Date: Wed, 23 Mar 2011 13:37:07 +0800 Subject: work in progress --- Debugger/debug_comm.S | 175 ++++++++++++++++++++++++++++++++++++++++---------- Debugger/debug_stub.S | 19 +++++- 2 files changed, 158 insertions(+), 36 deletions(-) diff --git a/Debugger/debug_comm.S b/Debugger/debug_comm.S index 54c16a6..1a5dd07 100644 --- a/Debugger/debug_comm.S +++ b/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 @@ -192,7 +195,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 @@ -204,16 +208,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 */ -#ifdef __BIG_ENDIAN__ - mov r2, r1, lsl #16 /* copy of input halfword value R1[15:0], shifted to MSH R2[31:16] */ -#endif - 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 */ + +/* 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 +/* word2ascii_be + * Big Endian version of word2ascii conversion routine * On entry: * R0: ASCII buffer pointer * R1[31:0]: Word value @@ -225,36 +248,54 @@ 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 */ -#ifdef __BIG_ENDIAN__ -/* Rotate then convert */ -_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} -#else /* __LITTLE_ENDIAN__ */ -/* Convert then rotate */ -_conv_byte2ascii: +/* 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 + bne _conv_byte2ascii_le ldmfd sp!, {r1,r2,r3, pc} -#endif - /* ascii2byte * On entry: * R0: ASCII buffer pointer @@ -275,7 +316,8 @@ ascii2byte: mov r3, #2 /* Loop counter */ b _conv_ascii2byte -/* ascii2halfword +/* ascii2halfword_be + * Big Endian version of word2ascii conversion routine * On entry: * R0: ASCII buffer pointer * On exit: @@ -288,15 +330,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 word2ascii 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 word2ascii conversion routine * On entry: * R0: ASCII buffer pointer * On exit: @@ -309,28 +373,73 @@ 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 */ + beq _exit_conv_ascii2byte_be /* 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 */ + 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: +_exit_conv_ascii2byte_be: ldmfd sp!, {r2,r3, pc} /* return hex value in R0 */ +/* ascii2word_le + * Litle Endian version of word2ascii 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 */ + 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, rol #4 /* merge Nibble into results */ + ldrb r0, [r1], #1 /* Load ASCII char */ + bl char2hex /* on return, hex value in R0 */ +@@@@@ not correct! + + orr r2, r0, r2, rol #4 /* merge Nibble into results */ + subs r3, r3, #1 + rorne r2, r2, #16 /* Rotate R + bne 2b + mov r0, r2 /* Copy it to R0 as return value */ +_exit_conv_ascii2byte_le: + ldmfd sp!, {r2,r3, pc} /* return hex value in R0 */ + diff --git a/Debugger/debug_stub.S b/Debugger/debug_stub.S index 7c54810..47ad2c3 100644 --- a/Debugger/debug_stub.S +++ b/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,6 +124,11 @@ * * 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 @@ -816,7 +821,11 @@ _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 @@ -883,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 -- cgit v1.2.3 From 4063fdfc7bae2702e71db748934bc2a83fe73e8d Mon Sep 17 00:00:00 2001 From: TC Wan Date: Wed, 23 Mar 2011 15:36:48 +0800 Subject: rewrite multibyte ascii to hex conversion routines to take care of little endian issues --- Debugger/debug_comm.S | 95 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 64 insertions(+), 31 deletions(-) diff --git a/Debugger/debug_comm.S b/Debugger/debug_comm.S index 1a5dd07..5e0b090 100644 --- a/Debugger/debug_comm.S +++ b/Debugger/debug_comm.S @@ -296,6 +296,36 @@ _conv_byte2ascii_le: bne _conv_byte2ascii_le ldmfd sp!, {r1,r2,r3, pc} + +/* ascii2hex_varlen + * (Shared routine, does not perform sanity checks) + * On entry: + * R0: ASCII buffer pointer + * R1: Max number of Hex digits (0/8=32-bits) + * On exit: + * R0[7:0]: Hex 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 ascii2hex_varlen + +ascii2hex_varlen: + 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 */ + 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 */ + orr r0, r2, r0 /* combined byte value */ + ldmfd sp!, {r2, pc} + + /* ascii2byte * On entry: * R0: ASCII buffer pointer @@ -312,12 +342,18 @@ _conv_byte2ascii_le: .global ascii2byte ascii2byte: - stmfd sp!, {r2,r3, lr} - mov r3, #2 /* Loop counter */ - b _conv_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 */ + 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 */ + orr r0, r2, r0 /* combined byte value */ + ldmfd sp!, {r2, pc} /* ascii2halfword_be - * Big Endian version of word2ascii conversion routine + * Big Endian version of ascii2halfword conversion routine * On entry: * R0: ASCII buffer pointer * On exit: @@ -338,7 +374,7 @@ ascii2halfword_be: b _conv_ascii2byte_be /* ascii2halfword_le - * Little Endian version of word2ascii conversion routine + * Little Endian version of ascii2halfword conversion routine * On entry: * R0: ASCII buffer pointer * On exit: @@ -360,7 +396,7 @@ ascii2halfword_le: /* ascii2word_be - * Big Endian version of word2ascii conversion routine + * Big Endian version of ascii2word conversion routine * On entry: * R0: ASCII buffer pointer * On exit: @@ -384,22 +420,19 @@ ascii2word_be: _conv_ascii2byte_be: teq r0, #0 beq _exit_conv_ascii2byte_be /* 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 */ - 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 */ + 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 word2ascii conversion routine + * Litle Endian version of ascii2word conversion routine * On entry: * R0: ASCII buffer pointer * On exit: @@ -423,20 +456,19 @@ ascii2word_le: _conv_ascii2byte_le: teq r0, #0 beq _exit_conv_ascii2byte_le /* 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, rol #4 /* merge Nibble into results */ - ldrb r0, [r1], #1 /* Load ASCII char */ - bl char2hex /* on return, hex value in R0 */ -@@@@@ not correct! - - orr r2, r0, r2, rol #4 /* merge Nibble into results */ + 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 - rorne r2, r2, #16 /* Rotate R bne 2b - mov r0, r2 /* Copy it to R0 as return value */ + /* Cummulative value done, need to rotate it into the correct position for return value */ + pop {r3} /* retrieve counter */ + sub r3, r3, #1 /* count - 1 */ + lsl r3, r3, #3 /* [(count-1) x 8] bits to rotate */ + mov r0, r2, rol r3 /* Copy it to R0 as return value */ + _exit_conv_ascii2byte_le: ldmfd sp!, {r2,r3, pc} /* return hex value in R0 */ @@ -725,12 +757,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 */ -- cgit v1.2.3 From 05eb01dbbde30b017e120fc826e0fe5c6e36798b Mon Sep 17 00:00:00 2001 From: TC Wan Date: Wed, 23 Mar 2011 15:38:45 +0800 Subject: cannot use rol, covert to ror instead --- Debugger/debug_comm.S | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Debugger/debug_comm.S b/Debugger/debug_comm.S index 5e0b090..358cc76 100644 --- a/Debugger/debug_comm.S +++ b/Debugger/debug_comm.S @@ -465,9 +465,9 @@ _conv_ascii2byte_le: bne 2b /* Cummulative value done, need to rotate it into the correct position for return value */ pop {r3} /* retrieve counter */ - sub r3, r3, #1 /* count - 1 */ - lsl r3, r3, #3 /* [(count-1) x 8] bits to rotate */ - mov r0, r2, rol r3 /* Copy it to R0 as return value */ + 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 */ -- cgit v1.2.3 From 9eaeb4f0b79cfb0015afba33a1f044530fcb7652 Mon Sep 17 00:00:00 2001 From: TC Wan Date: Wed, 23 Mar 2011 16:27:04 +0800 Subject: variable length big endian hex value conversion routine for gdb param parsing --- Debugger/debug_comm.S | 64 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 38 insertions(+), 26 deletions(-) diff --git a/Debugger/debug_comm.S b/Debugger/debug_comm.S index 358cc76..b6f9cf5 100644 --- a/Debugger/debug_comm.S +++ b/Debugger/debug_comm.S @@ -132,19 +132,28 @@ hex2char: * 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. - * WARNING: The checking is not exhaustive, invalid ASCII characters can - * still slip thorough. + * 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 - /* In range '0'..'f' */ + /* Validated Hex Char */ perform_char2hex: + mov r0, r1 /* restore hex char */ _char2hex r0 exit_char2hex: bx lr @@ -297,33 +306,36 @@ _conv_byte2ascii_le: ldmfd sp!, {r1,r2,r3, pc} -/* ascii2hex_varlen - * (Shared routine, does not perform sanity checks) +/* ascii2hex_varlen_be + * Big Endian version of ascii2hex_varlen conversion routine + * (There is no Little Endian Version) * On entry: * R0: ASCII buffer pointer - * R1: Max number of Hex digits (0/8=32-bits) * On exit: - * R0[7:0]: Hex value + * R0: Hex 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. + * 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 + .global ascii2hex_varlen_be -ascii2hex_varlen: - stmfd sp!, {r2, lr} +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 */ - ldrb r0, [r1], #1 /* Load ASCII char for MSN */ - bl char2hex /* on return, hex value in R0 */ - 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 */ - orr r0, r2, r0 /* combined byte value */ - ldmfd sp!, {r2, pc} + 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 @@ -345,10 +357,10 @@ 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 */ + 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 */ + bl char2hex /* on return, hex value in R0, -1 for error (ignored) */ orr r0, r2, r0 /* combined byte value */ ldmfd sp!, {r2, pc} -- cgit v1.2.3