summaryrefslogtreecommitdiff
path: root/AT91SAM7S256
diff options
context:
space:
mode:
Diffstat (limited to 'AT91SAM7S256')
-rw-r--r--AT91SAM7S256/Debugger/_c_arm_macros.h149
-rw-r--r--AT91SAM7S256/Debugger/debug_comm.S286
-rw-r--r--AT91SAM7S256/Debugger/debug_stub.S1332
-rw-r--r--AT91SAM7S256/Debugger/debug_stub.h149
-rw-r--r--AT91SAM7S256/Debugger/types.h46
5 files changed, 1962 insertions, 0 deletions
diff --git a/AT91SAM7S256/Debugger/_c_arm_macros.h b/AT91SAM7S256/Debugger/_c_arm_macros.h
new file mode 100644
index 0000000..f356a25
--- /dev/null
+++ b/AT91SAM7S256/Debugger/_c_arm_macros.h
@@ -0,0 +1,149 @@
+/** @file _c_arm_macros.h
+ * @brief Define macros to support shared C and ASM headers
+ *
+ */
+
+/* Copyright (C) 2007,2009 the NxOS developers
+ * Thanks to Bartli (forum post @ embdev.net ARM programming with GCC/GNU tools forum)
+ *
+ * See AUTHORS for a full list of the developers.
+ *
+ * Redistribution of this file is permitted under
+ * the terms of the GNU Public License (GPL) version 2.
+ */
+
+#ifndef __NXOS_BASE_C_ARM_MACROS__
+#define __NXOS_BASE_C_ARM_MACROS__
+
+#ifdef __ASSEMBLY__
+
+#define NULL 0x0 /* Stick the definition here instead of making types.h messy */
+#define FALSE 0
+#define TRUE ~FALSE
+
+#define TYPEDEF @
+#define FUNCDEF @
+
+ .set last_enum_value, 0
+ .macro enum_val name
+ .equiv \name, last_enum_value
+ .set last_enum_value, last_enum_value + 1
+ .endm
+
+#define ENUM_BEGIN .set last_enum_value, 0
+
+#define ENUM_VAL(name) enum_val name
+#define ENUM_VALASSIGN(name, value) \
+ .set last_enum_value, value ;\
+ enum_val name
+#define ENUM_END(enum_name)
+
+/** Macro to define driver ioctl table
+ * First five table entries are predefined
+ * 0: init
+ * 1: shutdown
+ * 2: sleep
+ * 3: wakeup
+ * 4: poll
+ *
+ */
+#define DRIVER_IOCTL(driver) \
+/* Dummy sleep and wakeup routines for now */ ;\
+ .set driver ## _sleep, NULL ;\
+ .set driver ## _wakeup, NULL ;\
+ .set driver ## _poll, NULL ;\
+.data ;\
+ .align 4 ;\
+ .global driver ## _ioctl ;\
+driver ## _ioctl: ;\
+ .word driver ## _init ;\
+ .word driver ## _shutdown ;\
+ .word driver ## _sleep ;\
+ .word driver ## _wakeup ;\
+ .word driver ## _poll ;\
+ .set num_ ## driver ## _cmds, 5
+
+/** Macro to define additional driver ioctl commands
+ * Be careful to follow the sequence defined for the CMD enums
+ * The first CMD should have an enum value of 5
+ *
+ */
+#define DRIVER_CMD(driver, cmd) \
+ .word driver ## _ ## cmd ;\
+ .set num_ ## driver ## _cmds, num_ ## driver ## _cmds + 1
+
+/** Macro to define driver state
+ * MUST BE DEFINED AFTER DRIVER_IOCTL section
+ * @param driver name of driver
+ * @param driverenum enum value of driver (in [31:25])
+ *
+ * The number of commands for driver (in [24:17]) -- derived from num_driver_cmds
+ *
+ * Format of driver_state table:
+ * driver signature (driverenum << 24 | numcommands << 16)
+ * driver parameters (per device instance)
+ */
+#define DRIVER_STATE(driver, driverenum) \
+.bss ;\
+ .global driver ## _state ;\
+driver ## _state: ;\
+ .set driver ## _signature, (driverenum << 24) | (num_ ## driver ## _cmds << 16) ;\
+ .word NULL /* driver_signature */
+
+
+/** Macro to define actual driver routine in .S
+ * On entry:
+ * r0 - address of driver_state
+ * r1-r3 - parameters (variable)
+ * r12 - number of parameters (IPC scratch register)
+ * Stack - parameters (variable)
+ */
+#define DRIVER_ROUTINE(driver, cmd) \
+ .global driver ## _ ## cmd ## ;\
+driver ## _ ## cmd ## :
+
+#else
+/** Macro to control typedef generation
+ *
+ */
+#define TYPEDEF typedef
+
+/** Macro to control extern generation
+ *
+ */
+#ifndef FUNCDEF
+#define FUNCDEF extern
+#endif
+
+/** Macro to control typedef enum generation
+ *
+ */
+#define ENUM_BEGIN typedef enum {
+
+/** Macro to specify enum instance (auto value assignment)
+ *
+ */
+#define ENUM_VAL(name) name,
+
+/** Macro to control enum specification and value assignment
+*
+*/
+#define ENUM_VALASSIGN(name, value) name = value,
+
+/** Macro to control enum named type generation
+ *
+ */
+#define ENUM_END(enum_name) } enum_name;
+
+#endif
+
+ENUM_BEGIN
+ENUM_VAL(INIT) /**< Driver Init Routine. */
+ENUM_VAL(SHUTDOWN) /**< Driver Shutdown Routine. */
+ENUM_VAL(SLEEP) /**< Driver Sleep Routine. */
+ENUM_VAL(WAKEUP) /**< Driver Wakeup Routine. */
+ENUM_VAL(POLL) /**< Driver Poll Routine. */
+ENUM_END(nx_driver_default_cmd)
+
+
+#endif /* __NXOS_BASE_C_ARM_MACROS__ */
diff --git a/AT91SAM7S256/Debugger/debug_comm.S b/AT91SAM7S256/Debugger/debug_comm.S
new file mode 100644
index 0000000..d6eaaa8
--- /dev/null
+++ b/AT91SAM7S256/Debugger/debug_comm.S
@@ -0,0 +1,286 @@
+
+/* Copyright (C) 2007-2010 the NxOS developers
+ *
+ * Module Developed by: TC Wan <tcwan@cs.usm.my>
+ *
+ * See AUTHORS for a full list of the developers.
+ *
+ * Redistribution of this file is permitted under
+ * the terms of the GNU Public License (GPL) version 2.
+ */
+
+#define __ASSEMBLY__
+#include "debug_stub.h"
+
+.data
+.align 4
+
+hex2char_lut:
+ .ascii "0123456789ABCDEF"
+
+/* 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
+ */
+ .macro _hex2char_lut addrptr
+ ldr \addrptr, =hex2char_lut
+ .endm
+
+/* _hex2char_cont
+ * Internal routine that assumes that the LUT has been loaded.
+ * This macro accepts a byte sized hex value as a parameter register(7:0) and returns the
+ * ASCII equivalent in in the same register(7:0)
+ * The second parameter is the LUT address pointer register to use (assumed to be initialized)
+ * WARNING: Assumes that the value in register is sanity checked before invoking macro
+ */
+ .macro _hex2char_cont reg, addrptr
+ ldrb \reg, [\addrptr, \reg]
+ .endm
+
+/* _hex2char
+ * This macro accepts a byte sized hex value as a parameter register(7:0) and returns the
+ * ASCII equivalent in in the same register(7:0)
+ * The second parameter is the LUT address pointer register to use (register content is destroyed)
+ * WARNING: Assumes that the value in register is sanity checked before invoking macro
+ */
+ .macro _hex2char reg, addrptr
+ _hex2char_lut \addrptr
+ _hex2char_cont \reg, \addrptr
+ .endm
+
+/* _char2hex
+ * This macro accepts an ASCII char as a parameter register(7:0) and returns the
+ * equivalent byte sized hex value in in the same register(7:0)
+ * WARNING: Assumes that the char in register is a valid hex char before invoking macro
+ */
+ .macro _char2hex reg
+ cmp \reg, #'A' /* If Alpha */
+ bichs \reg, \reg, #ASCII_LOWER2UPPER_MASK /* Convert to Uppercase */
+ subhs \reg, \reg, #7 /* Adjustment to allow for subtraction with 0x30 */
+ sub \reg, \reg, #0x30 /* get final hex value */
+ .endm
+
+
+.code 32
+.text
+.align 4
+
+
+/* Utility Routines
+ */
+
+/* hex2char
+ * This routine accepts a byte sized hex value in R0(7:0) and returns the
+ * ASCII equivalent in R0(7:0)
+ */
+ .global hex2char
+
+hex2char:
+ stmfd sp!, {r1,lr}
+ and r0, #0x000F /* make sure that input is sane */
+ _hex2char r0, r1
+ ldmfd sp!, {r1,pc}
+
+/* char2hex
+ * This routine accepts an ASCII character in R0(7:0) and returns the
+ * equivalent byte sized hex value in R0(7:0)
+ */
+ .global char2hex
+
+char2hex:
+ and r0, #0x00FF /* make sure that input is sane */
+ cmp r0, #'0'
+ blo exit_char2hex
+ cmp r0, #'F'
+ bhi exit_char2hex
+ _char2hex r0
+exit_char2hex:
+ bx lr
+
+/* byte2ascii_cont
+ * This routine accepts a byte value in R0(7:0), and a ASCII buffer pointer in R1,
+ * and stores the ASCII equivalent byte value in the buffer pointed to by R1.
+ * Note: On return, R1 points to next empty char slot in buffer (i.e., R1 is modified)
+ * and R0 is destroyed.
+ */
+byte2ascii_cont:
+ stmfd sp!, {r2,r3,r4, lr}
+ mov r2, r0, lsl #24 /* Keep copy of input byte value R0(7:0), shifted to MSB R2(31:24) */
+ mov r4, #2 /* Loop counter */
+ _hex2char_lut r3 /* initialize LUT pointer */
+1: mov r0, r2, ror #28 /* Rotate MSNibble R2(31:28) into LSNibble position R0(3:0) */
+ and r0, r0, #NIBBLE0 /* Mask out everything else */
+ _hex2char_cont r0, r3 /* Convert nibble to ASCII char */
+ strb r0, [r1], #1
+ subs r4, r4, #1 /* decrement loop counter */
+ bne 1b
+ ldmfd sp!, {r2,r3,r4, pc}
+
+/* byte2ascii
+ * This routine accepts a byte value in R0(7:0), and a ASCII buffer pointer in R1,
+ * and stores the ASCII equivalent byte value in the buffer pointed to by R1.
+ * Note: On return, R1 points to the end of the ASCIIZ string (i.e. NULL character)
+ */
+ .global byte2ascii
+
+byte2ascii:
+ stmfd sp!, {r1, lr} /* Keep ASCII buffer pointer */
+ and r0, #BYTE0 /* sanitize input */
+ bl byte2ascii_cont
+ _asciiz r0, r1
+ ldmfd sp!, {r0, pc} /* return string pointer in R0 */
+
+/* halfword2ascii
+ * This routine accepts a halfword value in R0(15:0), and a ASCII buffer pointer in R1,
+ * and returns the ASCIIZ equivalent byte value in the buffer pointed to by R0.
+ * Note: On return, R1 points to the end of the ASCIIZ string (i.e. NULL character)
+ */
+ .global halfword2ascii
+halfword2ascii:
+ stmfd sp!, {r1,r2,r3, lr} /* Keep ASCII buffer pointer */
+ mov r2, r0, lsl #16 /* copy of input halfword value R0(15:0), shifted to MSH R2(31:16) */
+ mov r3, #2 /* Loop Counter */
+ b _conv_byte2ascii /* goto Byte conversion loop */
+
+/* word2ascii
+ * This routine accepts a word value in R0(31:0), and a ASCII buffer pointer in R1,
+ * and returns the ASCIIZ equivalent byte value in the buffer pointed to by R0.
+ * Note: On return, R1 points to the end of the ASCIIZ string (i.e. NULL character)
+ */
+ .global word2ascii
+word2ascii:
+ stmfd sp!, {r1,r2,r3, lr} /* Keep ASCII buffer pointer */
+ mov r2, r0 /* copy of input word value R0(31:0) */
+ mov r3, #4 /* Loop Counter */
+
+ /* Fall through to byte coversion loop */
+
+_conv_byte2ascii:
+ mov r0, r2, ror #24 /* Rotate MSB R2(31:24) into LSB position R0(7:0) */
+ and r0, #BYTE0 /* Mask out everything else */
+ bl byte2ascii_cont
+ subs r3, r3, #1
+ bne _conv_byte2ascii
+ _asciiz r0, r1
+ ldmfd sp!, {r0,r2,r3, pc}
+
+
+/* ascii2byte
+ * This routine accepts an ASCII buffer pointer in R0,
+ * and returns the byte value in R0(7:0).
+ * Note: On return, R1 points to the ASCII buffer location after the current 2 chars.
+ * WARNING: This routine assumes that the input buffer was sanitized and contains valid Hex chars,
+ * otherwise it will return invalid results.
+ */
+ .global ascii2byte
+
+ascii2byte:
+ stmfd sp!, {r2,r3, lr}
+ mov r3, #2 /* Loop counter */
+ b _conv_ascii2byte
+
+/* ascii2halfword
+ * This routine accepts an ASCII buffer pointer in R0,
+ * and returns the word 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
+
+ascii2halfword:
+ stmfd sp!, {r2,r3, lr}
+ mov r3, #4 /* Loop counter */
+ b _conv_ascii2byte
+
+
+/* ascii2word
+ * 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
+
+ascii2word:
+ stmfd sp!, {r2,r3, lr}
+ mov r3, #8 /* Loop counter */
+
+ /* Fall through to byte coversion loop */
+
+_conv_ascii2byte:
+ teq r0, #0
+ beq _exit_conv_ascii2byte /* exit if NULL pointer in R0 */
+ mov r0, r1 /* 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:
+ ldmfd sp!, {r2,r3, pc} /* return hex value in R0 */
+
+
+
+
+/* Debugger Communications Routines
+ * It does not make sense to pass information from the Debugger Module to the Comm. link one character
+ * at a time, especially if we're not using a native serial interface (e.g., EIA-232). Consequently
+ * a Message interface has been defined. This can still call getChar() and putChar() subroutines
+ * if so desired, but it'll be a purely internal matter.
+ *
+ */
+ .global dbg__hasDebugMsg
+/* dbg__hasDebugMsg
+ * Checks for pending Debugger Message (Non-Blocking).
+ * On exit:
+ * r0: Boolean (0: no pending message, 1: has pending message)
+ */
+dbg__hasDebugMsg:
+ bx lr
+
+ .global dbg__getDebugMsg
+/* dbg__getDebugMsg
+ * Returns Debugger Message to calling routine after verifying and removing checksum (Blocking).
+ * On entry:
+ * r0: address of message buffer
+ * r1: maximum size of message buffer (incl NULL character)
+ * On exit:
+ * r0: address of message buffer with NULL terminated message, excluding '#<checksum>'
+ * (NULL if message error)
+ *
+ */
+dbg__getDebugMsg:
+ bx lr
+
+ .global dbg__putDebugMsg
+/* dbg__putDebugMsg
+ * Sends Debugger Message from calling routine after appending checksum (Blocking) .
+ * On entry:
+ * r0: address of message buffer with NULL terminated message, without '#<checksum>'
+ * On exit:
+ * r0: status (0: success, -1: error)
+ */
+dbg__putDebugMsg:
+ bx lr
+
+
+/* Private functions (if needed) */
+_dbg__getChar:
+_dbg__putChar:
+ bx lr
diff --git a/AT91SAM7S256/Debugger/debug_stub.S b/AT91SAM7S256/Debugger/debug_stub.S
new file mode 100644
index 0000000..3aa2cb7
--- /dev/null
+++ b/AT91SAM7S256/Debugger/debug_stub.S
@@ -0,0 +1,1332 @@
+
+/* Copyright (C) 2007-2010 the NxOS developers
+ *
+ * Module Developed by: TC Wan <tcwan@cs.usm.my>
+ *
+ * See AUTHORS for a full list of the developers.
+ *
+ * Redistribution of this file is permitted under
+ * the terms of the GNU Public License (GPL) version 2.
+ */
+
+ /* GDB sparc-stub.c comments header included below to document GDB Server Remote protocol */
+ /* This header has been modified to include additional commands not documented in the header stub */
+
+ /****************************************************************************
+
+ THIS SOFTWARE IS NOT COPYRIGHTED
+
+ HP offers the following for use in the public domain. HP makes no
+ warranty with regard to the software or it's performance and the
+ user accepts the software "AS IS" with all faults.
+
+ HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
+ TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+****************************************************************************/
+
+/****************************************************************************
+ * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
+ *
+ * Module name: remcom.c $
+ * Revision: 1.34 $
+ * Date: 91/03/09 12:29:49 $
+ * Contributor: Lake Stevens Instrument Division$
+ *
+ * Description: low level support for gdb debugger. $
+ *
+ * Considerations: only works on target hardware $
+ *
+ * Written by: Glenn Engel $
+ * ModuleState: Experimental $
+ *
+ * NOTES: See Below $
+ *
+ * Modified for SPARC by Stu Grossman, Cygnus Support.
+ *
+ * This code has been extensively tested on the Fujitsu SPARClite demo board.
+ *
+ * To enable debugger support, two things need to happen. One, a
+ * call to set_debug_traps() is necessary in order to allow any breakpoints
+ * or error conditions to be properly intercepted and reported to gdb.
+ * Two, a breakpoint needs to be generated to begin communication. This
+ * is most easily accomplished by a call to breakpoint(). Breakpoint()
+ * simulates a breakpoint by executing a trap #1.
+ *
+ *************
+ *
+ * The following gdb commands are supported:
+ *
+ * command function Return value
+ *
+ * g return the value of the CPU registers hex data or ENN
+ * GrrrrRRRR.. set the value of the CPU registers OK or ENN
+ * where register values are given as
+ * 32-bit hex values from R0 to R15
+ * 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.
+ *
+ * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN
+ * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN
+ *
+ * c Resume at current address SNN ( signal NN)
+ * cAA..AA Continue at address AA..AA SNN
+ *
+ * s Step one instruction SNN
+ * sAA..AA Step one instruction from AA..AA SNN
+ *
+ * k kill
+ *
+ * ? What was the last sigval ? SNN (signal NN)
+ *
+ * All commands and responses are sent with a packet which includes a
+ * checksum. A packet consists of
+ *
+ * $<packet info>#<checksum>.
+ *
+ * where
+ * <packet info> :: <characters representing the command or response>
+ * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>>
+ *
+ * When a packet is received, it is first acknowledged with either '+' or '-'.
+ * '+' indicates a successful transfer. '-' indicates a failed transfer.
+ *
+ * Example:
+ *
+ * Host: Reply:
+ * $m0,10#2a +$00010203040506070809101112131415#42
+ *
+ ****************************************************************************/
+ /* Modified GDB Server Remote Protocol definition from GDB's sparc-stub.c Comment Header included above */
+
+
+/* FIXME: What about setting/clearing Breakpoints? */
+
+#define __ASSEMBLY__
+#include "debug_stub.h"
+
+.bss
+.align 4
+debug_state:
+ .word 0x0
+debug_curr_breakpoint:
+ .word 0x0
+debug_InMsgBuf:
+ .space MSGBUF_SIZE,0
+debug_OutMsgBuf:
+ .space MSGBUF_SIZE,0
+
+.data
+.align 4
+debug_ValidResponsePrefix:
+ .byte '+','$',0
+
+debug_ErrorResponsePrefix:
+ .byte '-','$','E',0
+
+debug_SignalResponsePrefix:
+ .byte '+','$','S',0
+
+debug_OkResponse:
+ .byte '+','$','O','K',0
+
+/* The CmdIndexTable and CmdJumpTable must be kept in sync */
+debug_cmdIndexTable:
+ .byte 'g','G','p','P','m','M','c','s','k','?',0
+
+/* Command Handlers expect the address pointer to the parameter buffer (contents after '$' and '<cmdchar>') in R0
+ * and the Output Message Buffer Address in R1
+ */
+debug_cmdJumpTable:
+ .word _dbg__procGetRegs /* 'g' */
+ .word _dbg__procSetRegs /* 'G' */
+ .word _dbg__procGetOneReg /* 'p' */
+ .word _dbg__procSetOneReg /* 'P' */
+ .word _dbg__nop /* 'm' */
+ .word _dbg__nop /* 'M' */
+ .word _dbg__nop /* 'c' */
+ .word _dbg__nop /* 's' */
+ .word _dbg__nop /* 'k' */
+ .word _dbg__nop /* '?' */
+ .word 0
+
+
+.code 32
+.text
+.align 4
+ .extern __breakpoints_num__
+ .extern dbg__hasDebugMsg /* Check for message from the communications link */
+ .extern dbg__getDebugMsg /* Read a message from the communications link */
+ .extern dbg__putDebugMsg /* Write a message to the communications link */
+
+/* _dbg_jumpTableHandler
+ * Call Jump Table Routine based on Index
+ * On entry:
+ * jumptableaddr is the address (constant) of the Jump Table
+ * jumpreg is the register used to perform the indirect jump
+ * indexreg contains jump table index value
+ */
+ .macro _dbg_jumpTableHandler jumptableaddr, jumpreg, indexreg
+
+ ldr \jumpreg, =\jumptableaddr
+ ldr \jumpreg, [\jumpreg, \indexreg, lsl #2]
+ mov lr, pc
+ bx \jumpreg /* Call Command Handler Routine */
+ .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
+ * R0: destroyed
+ */
+ .macro _dbg_stpcpy deststrptr, sourcestrptr
+1: ldrb r0, [\sourcestrptr], #1
+ strb r0, [\deststrptr], #1
+ teq r0, #0
+ bne 1b
+ sub \deststrptr, \deststrptr, #1 /* Adjust Destination string pointer to point at NULL character */
+ .endm
+
+/* _dbg_outputMsgValidResponse
+ * Return Message with valid response ('+$')
+ * On exit:
+ * R0: destroyed
+ * R1: points to NULL character after the prefix
+ * R2: destroyed
+ */
+ .macro _dbg_outputMsgValidResponse
+ ldr r1, =debug_OutMsgBuf
+ ldr r2, =debug_ValidResponsePrefix
+ _dbg_stpcpy r1, r2
+ .endm
+
+
+/* _dbg_outputMsgStatusOk
+ * Return Message with Ok ('+OK') status
+ * On exit:
+ * R0: destroyed
+ * R1: destroyed
+ * R2: destroyed
+ */
+ .macro _dbg_outputMsgStatusOk
+ ldr r1, =debug_OutMsgBuf
+ ldr r2, =debug_OkResponse
+ _dbg_stpcpy r1, r2
+ .endm
+
+/* _dbg_outputMsgStatusErr
+ * Return Message with Error ('-ENN') status
+ * On entry:
+ * R0: register containing error value (byte)
+ * On exit:
+ * R0: destroyed
+ * 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 */
+ .endm
+
+/* _dbg_outputMsgStatusSig
+ * Return Message with Signal ('+SNN') status
+ * On entry:
+ * R0: register containing error value (byte)
+ * On exit:
+ * R0: destroyed
+ * 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 */
+ .endm
+
+
+/* _index2bkptindex_addr
+ * Convert Breakpoint index to breakpoing entry address
+ *
+ * On entry:
+ * indexreg contains breakpoint index value
+ * On exit:
+ * indexreg: Breakpoint index (preserved)
+ * addrreg: Breakpoint Entry Address
+ */
+ .macro _index2bkptindex_addr indexreg, addrreg
+ ldr \addrreg, =__breakpoints_start__
+ add \addrreg, \addrreg, \indexreg, lsl #3 /* Calculate Breakpoint Entry Address */
+ .endm
+
+/* _dbg_getstate
+ * Get Debugger State
+ * On exit:
+ * reg: Debugger State enum
+ */
+ .macro _dbg_getstate reg
+ ldr \reg, =debug_state
+ ldr \reg, [\reg]
+ .endm
+
+/* _dbg_setstate
+ * Set Debugger State to given value
+ * On exit:
+ * r0, r1: destroyed
+ */
+ .macro _dbg_setstate state
+ ldr r0, =\state
+ ldr r1, =debug_state
+ str r0, [r1]
+ .endm
+
+/* _dbg_getcurrbkpt_index
+ * Get current breakpoint index
+ * On exit:
+ * reg: Breakpoint index
+ */
+ .macro _dbg_getcurrbkpt_index reg
+ ldr \reg, =debug_curr_breakpoint
+ ldr \reg, [\reg]
+ .endm
+
+/* _dbg_setcurrbkpt_index
+ * Set current breakpoint index
+ * On exit:
+ * r1: destroyed
+ */
+ .macro _dbg_setcurrbkpt_index reg
+ ldr r1, =debug_curr_breakpoint
+ str \reg, [r1]
+ .endm
+
+/* _dbg_getabortedinstr_addr
+ * Get aborted instruction address
+ * On exit:
+ * reg: aborted instruction address
+ */
+ .macro _dbg_getabortedinstr_addr reg
+ ldr \reg, =__debugger_stack_bottom__
+ ldr \reg, [\reg]
+ .endm
+
+/* _dbg_setabortedinstr_addr
+ * Set aborted instruction address
+ * On exit:
+ * r1: destroyed
+ */
+ .macro _dbg_setabortedinstr_addr reg
+ ldr r1, =__debugger_stack_bottom__
+ str \reg, [r1]
+ .endm
+
+
+
+/* The Debugger Interface can handle a total of (n-1) Breakpoint States and 1 Single Stepping State,
+ * where n is a power of 2. The value of n is given by __breakpoints_num__ defined in the linker file.
+ *
+ * In addition, a Debugger Stack contains the User Mode Register Stack Frame + SPSR = Bkpt Instr Addr.
+ * These are currently stored in the .stack area in RAM, so there is no fixed address
+ * location that is used for this purpose.
+ *
+ * The Breakpoint feature assumes that the program is executed in RAM. It is not possible
+ * to set breakpoints for programs executed from Flash in the AT91SAM7S which lacks a hardware
+ * Debug interface.
+ *
+ * Each Breakpoint State i is a struct comprising the Breakpoint Address + Memory Contents
+ * stored in 8 bytes as:
+ * [High Memory Address]
+ * ADDR [i*8+4]: Memory Contents (32 bits)
+ * ADDR [i*8]: Breakpoint Address (31 bits, b0 = THUMB flag [not implemented yet])
+ * [Low Memory Address]
+ *
+ * A Non-zero Breakpoint Address means that the breakpoint is active, whereas the memory contents
+ * contains the instruction which resided at that address initially (now replaced by a BKPT <index>
+ * instruction).
+ * Note: Currently it is not possible to resume execution of a program with breakpoints enabled
+ * after a RESET, since the RESET will clear all contents of the stack, destroying the instruction
+ * contained in a given breakpoint.
+ * Fortunately the NXT will also need to reload the program into RAM so this is not expected to be
+ * an issue.
+ *
+ * The Memory Map for the Debugger State is as follows:
+ *
+ * [High Memory Address] __breakpoints_end__
+ * Breakpoint 07 State
+ * Breakpoint 06 State
+ * ...
+ * Breakpoint 02 State
+ * Breakpoint 01 State
+ * Single Step State __debugger_stack__ / __breakpoints_start__
+ * User Mode R15
+ * User Mode R14
+ * ...
+ * User Mode R02
+ * User Mode R01
+ * User Mode R00
+ * User Mode CPSR (UNDEF SPSR)
+ * Bkpt Instr Addr __debugger_stack_bottom__
+ * [Low Memory Address]
+ *
+ * Each Breakpoint State will initially be zeroed.
+ *
+ */
+
+/****************************************************************************
+ *
+ * GDB Debugger Init and Breakpoint Handler Routines
+ *
+ ****************************************************************************/
+
+ .global dbg__bkpt_init
+/* dbg__bkpt_init
+ * GDB set_debug_traps() routine
+ */
+dbg__bkpt_init:
+ stmfd sp!, {lr}
+ bl _dbg__clear_breakpoints
+ mov r0, #0
+ ldr r1, =debug_curr_breakpoint
+ str r0, [r1]
+ ldr r1, =debug_InMsgBuf
+ strb r0, [r1]
+ ldr r1, =debug_OutMsgBuf
+ strb r0, [r1]
+
+/* FIXME: Initialize other stuff here */
+ _dbg_setstate DBG_INIT
+ ldmfd sp!, {pc}
+
+
+/* _dbg__flush_icache
+ * Flush the Instruction cache
+ * Defined by GDB Stub, but not needed for ARMv4T architecture
+ */
+_dbg__flush_icache:
+ /* nop */
+ bx lr
+
+
+ .global dbg__bkpt_handler
+/* dbg__bkpt_handler
+ * GDB handle_exception() routine
+ */
+dbg__bkpt_handler:
+/* On entry, r0 contains breakpoint index value */
+/* FIXME: Currently we only deal with ARM mode, Thumb mode checks are missing! */
+ mov r4, #BKPT32_AUTO_BKPT
+ and r4, r0, #BKPT32_AUTO_BKPT /* keep AUTO flag value in r4 */
+ bic r0, r0, #BKPT32_AUTO_BKPT /* mask out AUTO flag */
+ _dbg_setcurrbkpt_index r0 /* keep current breakpoint index in memory */
+ ldr r1, =BKPT32_MANUAL_BKPT
+ teq r0, r1
+ beq _process_manual_breakpoint
+ ldr r1, =__breakpoints_num__
+ cmp r0, r1 /* Sanity check that index is in range */
+ bhs dbg__bkpt_offset_outofrange
+/* Valid index value found */
+ teq r4, #0 /* Check if AUTO flag set */
+ bne _process_auto_breakpoint
+/* else */
+ bl _dbg__restore_breakpoints
+ bl _dbg__restore_singlestep
+ bl _dbg__clear_singlestep
+ bl _dbg__flush_icache
+ _dbg_setstate DBG_NORMAL_BKPT_ARM
+ b dbg__bkpt_waitCMD
+
+_process_auto_breakpoint:
+/* Load Auto BKPT for Breakpoint index given in r0 */
+ _index2bkptindex_addr r0, r1 /* Calculate Breakpoint Entry Address */
+ ldm r1, {r1, r2} /* r1: Breakpoint Address, r2: Breakpoint Instruction */
+ teq r1, #0 /* Check that Breakpoint is active */
+ beq dbg__bkpt_inactive
+ bl _dbg__activate_one_breakpoint
+ bl _dbg__restore_singlestep
+ bl _dbg__clear_singlestep
+ b __dbg__resume_execution
+
+_process_manual_breakpoint:
+ _dbg_setstate DBG_MANUAL_BKPT_ARM
+/* b dbg__bkpt_waitCMD */
+
+dbg__bkpt_inactive:
+/* b dbg__bkpt_waitCMD */
+
+dbg__bkpt_offset_outofrange:
+/* b dbg__bkpt_waitCMD */
+
+ .global dbg__bkpt_waitCMD
+/* dbg__bkpt_waitCMD
+ * GDB Stub Remote Command Handler
+ */
+
+/****************************************************************************
+ *
+ * GDB Server Command Processing Routines
+ *
+ ****************************************************************************/
+dbg__bkpt_waitCMD:
+1: bl dbg__hasDebugMsg /* Check for messages */
+ beq 1b /* Busy wait */
+ bl dbg__getDebugMsg /* Read new message from Debugger, message buffer addr in R0, NULL if error */
+ teq r0, #0
+ moveq r0, #MSG_ERRCHKSUM /* Message invalid, checksum error? */
+ beq _dbg__cmdError /* Send response to GDB server */
+/* Message now has $<packet info>\0 */
+ mov r4, r0 /* Use R4 as Message Buffer pointer */
+ ldrb r0, [r4], #1 /* Look for '$' */
+ teq r0, #MSGBUF_STARTCHAR
+ beq _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
+ teq r0, r1
+ moveq r0, #MSG_UNKNOWNCMD /* Out of range, Command character not recognized */
+ beq _dbg__cmdError /* Send response to GDB server */
+
+_dbg__cmdValid:
+ stmfd sp!, {r0, r4}
+ _dbg_outputMsgValidResponse /* Setup R1 with address of output message buffer data pointer (after response prefix) */
+ ldmfd sp!, {r3} /* Command Handler Index */
+ ldmfd sp!, {r0} /* R1 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__bkpt_waitCMD
+
+_dbg__cmdError:
+ _dbg_outputMsgStatusErr
+ bl dbg__putDebugMsg /* Send error response to the GDB server */
+ b dbg__bkpt_waitCMD
+
+
+/* _dbg__cmdChar2Index
+ * Convert Command Character to Jump Table Index
+ * On entry:
+ * r0: command character
+ * On exit:
+ * r0: jump table index (-1 for command not found)
+ */
+_dbg__cmdChar2Index:
+ mov r1, r0 /* Copy command character to r1 */
+ mov r0, #0 /* Clear return value */
+ ldr r3, =debug_cmdIndexTable /* Convert command to index using r3 as Index Lookup Address Pointer */
+1: ldrb r2, [r3], #1 /* Get table entry */
+ teq r2, #0
+ moveq r0, #MSGBUF_CMDINDEX_OUTOFRANGE_VAL /* End of Index Table, Not found */
+ beq _exit_cmdIndexTable
+ teq r1, r2
+ addne r0, #1 /* Increment Index */
+ bne 1b /* No match, skip to next command char */
+_exit_cmdIndexTable:
+ bx lr
+
+
+/* _dbg__procGetOneReg
+ * Get One Register Value Command Handler
+ * On entry:
+ * r0: parameter buffer (contents after '$' and '<cmdchar>')
+ * r1: output message buffer
+ */
+_dbg__procGetOneReg:
+ bx lr
+
+/* _dbg__nop
+ * NOP Command Handler (placeholder)
+ * On entry:
+ * r0: parameter buffer (contents after '$' and '<cmdchar>')
+ * r1: output message buffer
+ */
+_dbg__nop:
+ bx lr /* Dummy, just return */
+
+
+/* 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
+ * On entry:
+ * r0: index of breakpoint to clear
+ */
+dbg__cmd_clear_breakpoint:
+ _index2bkptindex_addr r0, r0 /* Calculate Breakpoint Entry Address */
+ bl _dbg__clear_one_breakpoint
+ b dbg__bkpt_waitCMD
+
+
+/* dbg__cmd_run
+ * Continue execution of program
+ */
+dbg__cmd_run:
+ bl _dbg__activate_breakpoints
+ b __dbg__resume_execution
+
+/* dbg__cmd_step
+ * Single Step execution of program
+ */
+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
+ * 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:
+/* 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
+ teq r0, r1
+ beq __dbg_is_manual_breakpoint
+
+ bl _dbg_next_instruction_addr /* next instruction address returned in r1 */
+ bl _dbg__install_singlestep /* Setup Single Step, next instruction address returned in r1 */
+ _dbg_getcurrbkpt_index r0 /* load current breakpoint index in memory */
+ bl _dbg__activate_autobreakpoint /* pass next instruction address in r1 */
+ b __dbg__resume_execution
+
+__dbg_is_manual_breakpoint:
+ bl _dbg_next_instruction_addr /* Skip Manual Breakpoint Instruction(s) */
+ bl _dbg__activate_breakpoints
+ b __dbg__resume_execution
+
+/****************************************************************************
+// Selected Routines from the eCos arm_stub.c related to next instruction address
+// determination in ARM processors.
+
+//========================================================================
+//
+// arm_stub.c
+//
+// Helper functions for stub, generic to all ARM processors
+//
+//========================================================================
+// ####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later
+// version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with eCos; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// As a special exception, if other files instantiate templates or use
+// macros or inline functions from this file, or you compile this file
+// and link it with other works to produce a work based on this file,
+// this file does not by itself cause the resulting work to be covered by
+// the GNU General Public License. However the source code for this file
+// must still be made available in accordance with section (3) of the GNU
+// General Public License v2.
+//
+// This exception does not invalidate any other reasons why a work based
+// on this file might be covered by the GNU General Public License.
+// -------------------------------------------
+// ####ECOSGPLCOPYRIGHTEND####
+//========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): Red Hat, gthomas
+// Contributors: Red Hat, gthomas, jskov
+// Date: 1998-11-26
+// Purpose:
+// Description: Helper functions for stub, generic to all ARM processors
+// Usage:
+//
+//####DESCRIPTIONEND####
+//
+//========================================================================
+
+
+static int
+ins_will_execute(unsigned long ins)
+{
+ unsigned long psr = get_register(PS); // condition codes
+ int res = 0;
+ switch ((ins & 0xF0000000) >> 28) {
+ case 0x0: // EQ
+ res = (psr & PS_Z) != 0;
+ break;
+ case 0x1: // NE
+ res = (psr & PS_Z) == 0;
+ break;
+ case 0x2: // CS
+ res = (psr & PS_C) != 0;
+ break;
+ case 0x3: // CC
+ res = (psr & PS_C) == 0;
+ break;
+ case 0x4: // MI
+ res = (psr & PS_N) != 0;
+ break;
+ case 0x5: // PL
+ res = (psr & PS_N) == 0;
+ break;
+ case 0x6: // VS
+ res = (psr & PS_V) != 0;
+ break;
+ case 0x7: // VC
+ res = (psr & PS_V) == 0;
+ break;
+ case 0x8: // HI
+ res = ((psr & PS_C) != 0) && ((psr & PS_Z) == 0);
+ break;
+ case 0x9: // LS
+ res = ((psr & PS_C) == 0) || ((psr & PS_Z) != 0);
+ break;
+ case 0xA: // GE
+ res = ((psr & (PS_N|PS_V)) == (PS_N|PS_V)) ||
+ ((psr & (PS_N|PS_V)) == 0);
+ break;
+ case 0xB: // LT
+ res = ((psr & (PS_N|PS_V)) == PS_N) ||
+ ((psr & (PS_N|PS_V)) == PS_V);
+ break;
+ case 0xC: // GT
+ res = ((psr & (PS_N|PS_V)) == (PS_N|PS_V)) ||
+ ((psr & (PS_N|PS_V)) == 0);
+ res = ((psr & PS_Z) == 0) && res;
+ break;
+ case 0xD: // LE
+ res = ((psr & (PS_N|PS_V)) == PS_N) ||
+ ((psr & (PS_N|PS_V)) == PS_V);
+ res = ((psr & PS_Z) == PS_Z) || res;
+ break;
+ case 0xE: // AL
+ res = TRUE;
+ break;
+ case 0xF: // NV
+ if (((ins & 0x0E000000) >> 24) == 0xA)
+ res = TRUE;
+ else
+ res = FALSE;
+ break;
+ }
+ return res;
+}
+
+static unsigned long
+RmShifted(int shift)
+{
+ unsigned long Rm = get_register(shift & 0x00F);
+ int shift_count;
+ if ((shift & 0x010) == 0) {
+ shift_count = (shift & 0xF80) >> 7;
+ } else {
+ shift_count = get_register((shift & 0xF00) >> 8);
+ }
+ switch ((shift & 0x060) >> 5) {
+ case 0x0: // Logical left
+ Rm <<= shift_count;
+ break;
+ case 0x1: // Logical right
+ Rm >>= shift_count;
+ break;
+ case 0x2: // Arithmetic right
+ Rm = (unsigned long)((long)Rm >> shift_count);
+ break;
+ case 0x3: // Rotate right
+ if (shift_count == 0) {
+ // Special case, RORx
+ Rm >>= 1;
+ if (get_register(PS) & PS_C) Rm |= 0x80000000;
+ } else {
+ Rm = (Rm >> shift_count) | (Rm << (32-shift_count));
+ }
+ break;
+ }
+ return Rm;
+}
+
+// Decide the next instruction to be executed for a given instruction
+static unsigned long *
+target_ins(unsigned long *pc, unsigned long ins)
+{
+ unsigned long new_pc, offset, op2;
+ unsigned long Rn;
+ int i, reg_count, c;
+
+ switch ((ins & 0x0C000000) >> 26) {
+ case 0x0:
+ // BX or BLX
+ if ((ins & 0x0FFFFFD0) == 0x012FFF10) {
+ new_pc = (unsigned long)get_register(ins & 0x0000000F);
+ return ((unsigned long *)new_pc);
+ }
+ // Data processing
+ new_pc = (unsigned long)(pc+1);
+ if ((ins & 0x0000F000) == 0x0000F000) {
+ // Destination register is PC
+ if ((ins & 0x0FBF0000) != 0x010F0000) {
+ Rn = (unsigned long)get_register((ins & 0x000F0000) >> 16);
+ if ((ins & 0x000F0000) == 0x000F0000) Rn += 8; // PC prefetch!
+ if ((ins & 0x02000000) == 0) {
+ op2 = RmShifted(ins & 0x00000FFF);
+ } else {
+ op2 = ins & 0x000000FF;
+ i = (ins & 0x00000F00) >> 8; // Rotate count
+ op2 = (op2 >> (i*2)) | (op2 << (32-(i*2)));
+ }
+ switch ((ins & 0x01E00000) >> 21) {
+ case 0x0: // AND
+ new_pc = Rn & op2;
+ break;
+ case 0x1: // EOR
+ new_pc = Rn ^ op2;
+ break;
+ case 0x2: // SUB
+ new_pc = Rn - op2;
+ break;
+ case 0x3: // RSB
+ new_pc = op2 - Rn;
+ break;
+ case 0x4: // ADD
+ new_pc = Rn + op2;
+ break;
+ case 0x5: // ADC
+ c = (get_register(PS) & PS_C) != 0;
+ new_pc = Rn + op2 + c;
+ break;
+ case 0x6: // SBC
+ c = (get_register(PS) & PS_C) != 0;
+ new_pc = Rn - op2 + c - 1;
+ break;
+ case 0x7: // RSC
+ c = (get_register(PS) & PS_C) != 0;
+ new_pc = op2 - Rn +c - 1;
+ break;
+ case 0x8: // TST
+ case 0x9: // TEQ
+ case 0xA: // CMP
+ case 0xB: // CMN
+ break; // PC doesn't change
+ case 0xC: // ORR
+ new_pc = Rn | op2;
+ break;
+ case 0xD: // MOV
+ new_pc = op2;
+ break;
+ case 0xE: // BIC
+ new_pc = Rn & ~op2;
+ break;
+ case 0xF: // MVN
+ new_pc = ~op2;
+ break;
+ }
+ }
+ }
+ return ((unsigned long *)new_pc);
+ case 0x1:
+ if ((ins & 0x02000010) == 0x02000010) {
+ // Undefined!
+ return (pc+1);
+ } else {
+ if ((ins & 0x00100000) == 0) {
+ // STR
+ return (pc+1);
+ } else {
+ // LDR
+ if ((ins & 0x0000F000) != 0x0000F000) {
+ // Rd not PC
+ return (pc+1);
+ } else {
+ Rn = (unsigned long)get_register((ins & 0x000F0000) >> 16);
+ if ((ins & 0x000F0000) == 0x000F0000) Rn += 8; // PC prefetch!
+ if (ins & 0x01000000) {
+ // Add/subtract offset before
+ if ((ins & 0x02000000) == 0) {
+ // Immediate offset
+ if (ins & 0x00800000) {
+ // Add offset
+ Rn += (ins & 0x00000FFF);
+ } else {
+ // Subtract offset
+ Rn -= (ins & 0x00000FFF);
+ }
+ } else {
+ // Offset is in a register
+ if (ins & 0x00800000) {
+ // Add offset
+ Rn += RmShifted(ins & 0x00000FFF);
+ } else {
+ // Subtract offset
+ Rn -= RmShifted(ins & 0x00000FFF);
+ }
+ }
+ }
+ return ((unsigned long *)*(unsigned long *)Rn);
+ }
+ }
+ }
+ return (pc+1);
+ case 0x2: // Branch, LDM/STM
+ if ((ins & 0x02000000) == 0) {
+ // LDM/STM
+ if ((ins & 0x00100000) == 0) {
+ // STM
+ return (pc+1);
+ } else {
+ // LDM
+ if ((ins & 0x00008000) == 0) {
+ // PC not in list
+ return (pc+1);
+ } else {
+ Rn = (unsigned long)get_register((ins & 0x000F0000) >> 16);
+ if ((ins & 0x000F0000) == 0x000F0000) Rn += 8; // PC prefetch!
+ offset = ins & 0x0000FFFF;
+ reg_count = 0;
+ for (i = 0; i < 15; i++) {
+ if (offset & (1<<i)) reg_count++;
+ }
+ if (ins & 0x00800000) {
+ // Add offset
+ Rn += reg_count*4;
+ } else {
+ // Subtract offset
+ Rn -= 4;
+ }
+ return ((unsigned long *)*(unsigned long *)Rn);
+ }
+ }
+ } else {
+ // Branch
+ if (ins_will_execute(ins)) {
+ offset = (ins & 0x00FFFFFF) << 2;
+ if (ins & 0x00800000) offset |= 0xFC000000; // sign extend
+ new_pc = (unsigned long)(pc+2) + offset;
+ // If its BLX, make new_pc a thumb address.
+ if ((ins & 0xFE000000) == 0xFA000000) {
+ if ((ins & 0x01000000) == 0x01000000)
+ new_pc |= 2;
+ new_pc = MAKE_THUMB_ADDR(new_pc);
+ }
+ return ((unsigned long *)new_pc);
+ } else {
+ // Falls through
+ return (pc+1);
+ }
+ }
+ case 0x3: // Coprocessor & SWI
+ if (((ins & 0x03000000) == 0x03000000) && ins_will_execute(ins)) {
+ // SWI
+ return (unsigned long *)(CYGNUM_HAL_VECTOR_SOFTWARE_INTERRUPT * 4);
+ } else {
+ return (pc+1);
+ }
+ default:
+ // Never reached - but fixes compiler warning.
+ return 0;
+ }
+}
+
+// FIXME: target_ins also needs to check for CPSR/THUMB being set and
+// set the thumb bit accordingly.
+
+static unsigned long
+target_thumb_ins(unsigned long pc, unsigned short ins)
+{
+ unsigned long new_pc = MAKE_THUMB_ADDR(pc+2); // default is fall-through
+ // to next thumb instruction
+ unsigned long offset, arm_ins, sp;
+ int i;
+
+ switch ((ins & 0xf000) >> 12) {
+ case 0x4:
+ // Check for BX or BLX
+ if ((ins & 0xff07) == 0x4700)
+ new_pc = (unsigned long)get_register((ins & 0x00078) >> 3);
+ break;
+ case 0xb:
+ // push/pop
+ // Look for "pop {...,pc}"
+ if ((ins & 0xf00) == 0xd00) {
+ // find PC
+ sp = (unsigned long)get_register(SP);
+
+ for (offset = i = 0; i < 8; i++)
+ if (ins & (1 << i))
+ offset += 4;
+
+ new_pc = *(cyg_uint32 *)(sp + offset);
+
+ if (!v5T_semantics())
+ new_pc = MAKE_THUMB_ADDR(new_pc);
+ }
+ break;
+ case 0xd:
+ // Bcc | SWI
+ // Use ARM function to check condition
+ arm_ins = ((unsigned long)(ins & 0x0f00)) << 20;
+ if ((arm_ins & 0xF0000000) == 0xF0000000) {
+ // SWI
+ new_pc = CYGNUM_HAL_VECTOR_SOFTWARE_INTERRUPT * 4;
+ } else if (ins_will_execute(arm_ins)) {
+ offset = (ins & 0x00FF) << 1;
+ if (ins & 0x0080) offset |= 0xFFFFFE00; // sign extend
+ new_pc = MAKE_THUMB_ADDR((unsigned long)(pc+4) + offset);
+ }
+ break;
+ case 0xe:
+ // check for B
+ if ((ins & 0x0800) == 0) {
+ offset = (ins & 0x07FF) << 1;
+ if (ins & 0x0400) offset |= 0xFFFFF800; // sign extend
+ new_pc = MAKE_THUMB_ADDR((unsigned long)(pc+4) + offset);
+ }
+ break;
+ case 0xf:
+ // BL/BLX (4byte instruction!)
+ // First instruction (bit 11 == 0) holds top-part of offset
+ if ((ins & 0x0800) == 0) {
+ offset = (ins & 0x07FF) << 12;
+ if (ins & 0x0400) offset |= 0xFF800000; // sign extend
+ // Get second instruction
+ // Second instruction (bit 11 == 1) holds bottom-part of offset
+ ins = *(unsigned short*)(pc+2);
+ // Check for BL/BLX
+ if ((ins & 0xE800) == 0xE800) {
+ offset |= (ins & 0x07ff) << 1;
+ new_pc = (unsigned long)(pc+4) + offset;
+ // If its BLX, force a full word alignment
+ // Otherwise, its a thumb address.
+ if (!(ins & 0x1000))
+ new_pc &= ~3;
+ else
+ new_pc = MAKE_THUMB_ADDR(new_pc);
+ }
+ }
+ break;
+ }
+
+ return new_pc;
+}
+
+void __single_step (void)
+{
+ unsigned long pc = get_register(PC);
+ unsigned long cpsr = get_register(PS);
+
+ // Calculate address of next instruction to be executed
+ if (cpsr & CPSR_THUMB_ENABLE) {
+ // thumb
+ ss_saved_pc = target_thumb_ins(pc, *(unsigned short*)pc);
+ } else {
+ // ARM
+ unsigned long curins = *(unsigned long*)pc;
+ if (ins_will_execute(curins)) {
+ // Decode instruction to decide what the next PC will be
+ ss_saved_pc = (unsigned long) target_ins((unsigned long*)pc,
+ curins);
+ } else {
+ // The current instruction will not execute (the conditions
+ // don't hold)
+ ss_saved_pc = pc+4;
+ }
+ }
+
+ // Set breakpoint according to type
+ if (IS_THUMB_ADDR(ss_saved_pc)) {
+ // Thumb instruction
+ unsigned long t_pc = UNMAKE_THUMB_ADDR(ss_saved_pc);
+ ss_saved_thumb_instr = *(unsigned short*)t_pc;
+ *(unsigned short*)t_pc = HAL_BREAKINST_THUMB;
+ } else {
+ // ARM instruction
+ ss_saved_instr = *(unsigned long*)ss_saved_pc;
+ *(unsigned long*)ss_saved_pc = HAL_BREAKINST_ARM;
+ }
+}
+
+ ****************************************************************************/
+
+
+/* _dbg_next_instruction_addr
+ * Determine the address of the next instruction to execute.
+ * On exit:
+ * R1: Instruction Address (31 bits, b0 = THUMB flag)
+ *
+ * Here we make use of the Debugger Stack which contains the address of the aborted instruction that will be reexecuted
+ * when we resume the program.
+ *
+ * If it is a Manual Breakpoint inserted into the code, then we will need to update the aborted instruction
+ * address to skip the current aborted instruction and resume execution at the next instruction address,
+ * and the next instruction address to be returned to the calling routine is the following instruction
+ * address instead.
+ *
+ * We need to check the aborted instruction type, to see if it is a branch instruction, before we can determine
+ * the next instruction address (for inserting a Breakpoint).
+ */
+_dbg_next_instruction_addr:
+/* FIXME: Currently we only deal with ARM mode, Thumb mode checks are missing! */
+/* We assume that any BKPT instructions in the code will be Manual Breakpoints,
+ * i.e., the Debugger does not leave stray Single Step / Auto / Normal breakpoints in memory
+ */
+ _dbg_getabortedinstr_addr r2 /* Retrieve aborted instruction address */
+1: ldr r0, [r2] /* Read actual instruction from memory */
+ ldr r1, =(BKPT32_INSTR | BKPT32_MANUAL_BKPT) /* check for ARM Manual Breakpoint Instruction */
+ teq r0, r1
+ bne 2f /* Not Manual breakpoint */
+ add r2, r2, #4 /* Is Manual Breakpoint, Skip to next ARM instruction */
+ _dbg_setabortedinstr_addr r2 /* Update aborted instruction address */
+ b 1b /* To protect against a sequence of Manual Breakpoint Instructions */
+
+/* Here, r0 contains the instruction which will be reexecuted when program resumes. We need to dissect it to see if
+ * it is a branch instruction.
+ */
+2:
+@@@@@@@@@
+ bx lr
+
+/* __dbg__resume_execution
+ * cleanup, resume execution of program.
+ * Restore User Mode Regsiters from Debugger Stack, and resume execution from aborted instruction
+ */
+__dbg__resume_execution:
+@@@@@@
+ bl _dbg__flush_icache
+ b __dbg__resume_execution
+
+
+
+/****************************************************************************
+ *
+ * Breakpoint Manipulation Routines
+ *
+ ****************************************************************************/
+
+/* _dbg__clear_singlestep
+ * Clear the Single Step Breakpoint
+ */
+_dbg__clear_singlestep:
+ ldr r0, =__breakpoints_start__ /* Single Step Breakpoint is at the beginning of the Breakpoint State Struct */
+/* b _dbg__clear_one_breakpoint */
+
+/* _dbg__clear_one_breakpoint
+ * On entry, R0 contains the Breakpoint State slot address to be cleared
+ *
+ */
+_dbg__clear_one_breakpoint:
+ mov r1, #0
+ mov r2, #0
+ stmea r0!, {r1, r2} /* clear Breakpoint state */
+ bx lr
+
+/* _dbg__clear_breakpoints
+ * Routine iterates through the array of breakpoints (incl single step breakpoint) and clears the breakpoint
+ */
+_dbg__clear_breakpoints:
+ stmfd sp!, {lr}
+ ldr r0, =__breakpoints_start__ /* Single Step Breakpoint is at the beginning of the Breakpoint State Struct */
+ ldr r3, =__breakpoints_end__ /* start from top of the table */
+3: bl _dbg__clear_one_breakpoint
+ cmp r0, r3
+ blo 3b
+ ldmfd sp!, {pc}
+
+/* _dbg__install_singlestep
+ * Install the Single Step Breakpoint
+ * On entry:
+ * R1: Instruction Address (31 bits, b0 = THUMB flag)
+ */
+_dbg__install_singlestep:
+ mov r0, #0
+/* b _dbg__install_one_breakpoint */
+
+/* _dbg__install_one_breakpoint
+ * Install breakpoint entry into Breakpoint State Table
+ * On entry:
+ * R0: Breakpoint index (assumed valid)
+ * R1: Instruction Address (31 bits, b0 = THUMB flag)
+ *
+ * On exit:
+ * R2: Breakpoint Instruction
+ * R3: Breakpoint Entry address
+ */
+_dbg__install_one_breakpoint:
+/* Check for Thumb bit */
+ tst r1, #BKPT_STATE_THUMB_FLAG /* 1: Thumb instruction */
+/* Assume that the address entry is valid, otherwise we should sanitize it (mask out b1) */
+ ldreq r2, [r1] /* if 0: load ARM instruction from address location */
+ ldrneh r2, [r1] /* else load Thumb instruction */
+ _index2bkptindex_addr r0, r3 /* Calculate Breakpoint Entry Address */
+ stm r3, {r1, r2}
+ bx lr
+
+
+/* _dbg__restore_singlestep
+ * Restores the contents of the single step breakpoint to memory
+ */
+_dbg__restore_singlestep:
+ mov r0, #0 /* single step breakpoint index */
+ _index2bkptindex_addr r0, r1 /* Calculate Single Step Breakpoint Entry Address */
+ ldm r1, {r1, r2} /* r1: Breakpoint Address, r2: Breakpoint Instruction */
+ teq r1, #0
+ bxeq lr /* Exit if not active */
+/* b _dbg__restore_one_breakpoint */
+
+/* _dbg__restore_one_breakpoint
+ * Restores the contents to memory for one breakpoint
+ * On entry:
+ * R0: Breakpoint index (assumed valid) [not used -- can be used for validating BKPT]
+ * R1: Breakpoint Address (assumed valid)
+ * R2: Breakpoint Instruction (assumed valid)
+ */
+_dbg__restore_one_breakpoint:
+/* Check for Thumb bit */
+ tst r1, #BKPT_STATE_THUMB_FLAG /* 1: Thumb instruction */
+/* Assume that the address entry is valid, otherwise we should sanitize it (mask out b1) */
+ streq r2, [r1] /* if 0: restore ARM instruction to address location */
+ bicne r1, #BKPT_STATE_THUMB_FLAG /* else, clear Thumb Flag */
+ strneh r2, [r1] /* store Thumb instruction */
+ bx lr
+
+/* _dbg__restore_breakpoints
+ * Routine iterates through the array of breakpoints (incl single step breakpoint) and restores the contents to memory
+ * Only Active breakpoints (i.e., Non-zero Address) are processed.
+ */
+_dbg__restore_breakpoints:
+ stmfd sp!, {lr}
+ ldr r5, =_dbg__restore_one_breakpoint
+ b __dbg__iterate_breakpoint_array
+
+/* _dbg__activate_singlestep
+ * Activate the single step breakpoint to memory
+ */
+_dbg__activate_singlestep:
+ mov r0, #0 /* single step breakpoint index */
+ _index2bkptindex_addr r0, r1 /* Calculate Single Step Breakpoint Entry Address */
+ ldm r1, {r1, r2} /* r1: Breakpoint Address, r2: Breakpoint Instruction */
+ teq r1, #0
+ bxeq lr /* Exit if not active */
+/* b _dbg__activate_one_breakpoint */
+
+/* _dbg__activate_one_breakpoint
+ * Activate one breakpoint to memory
+ * On entry:
+ * R0: Breakpoint index (assumed valid)
+ * R1: Breakpoint Address (assumed valid)
+ * R2: Breakpoint Instruction (assumed valid)
+ */
+_dbg__activate_one_breakpoint:
+/* Check for Thumb bit */
+ tst r1, #BKPT_STATE_THUMB_FLAG /* 1: Thumb instruction */
+ bne _nx_is_thumb_bp
+_nx_is_arm_bp:
+/* Assume that the address entry is valid, otherwise we should sanitize it (mask out b1) */
+ ldr r3, [r1] /* if 0: load ARM instruction from address location */
+ teq r2, r3 /* check that the two instructions are identical */
+ bne _dbg__breakpoint_invalid_arm
+ ldr r2, =BKPT32_INSTR /* ARM BKPT instruction */
+ and r2, r2, r0 /* Merge Breakpoint index */
+ str r2, [r1] /* Store it into memory location */
+_dbg__breakpoint_invalid_arm:
+ bx lr
+_nx_is_thumb_bp:
+ bic r1, #BKPT_STATE_THUMB_FLAG /* else, clear Thumb Flag */
+ ldrh r3, [r1] /* load Thumb instruction from address location */
+ teq r2, r3 /* check that the two instructions are identical */
+ bne _dbg__breakpoint_invalid_thumb
+ ldr r2, =BKPT16_INSTR /* Thumb BKPT instruction */
+ and r2, r2, r0 /* Merge Breakpoint index */
+ strh r2, [r1] /* Store it into memory location */
+_dbg__breakpoint_invalid_thumb:
+ bx lr
+
+/* _dbg__activate_breakpoints
+ * Routine iterates through the array of breakpoints (incl single step breakpoint) and activates them
+ * Only Active breakpoints (i.e., Non-zero Address) are processed.
+ */
+_dbg__activate_breakpoints:
+ stmfd sp!, {lr}
+ ldr r5, =_dbg__activate_one_breakpoint
+ b __dbg__iterate_breakpoint_array
+
+
+/* __dbg__iterate_breakpoint_array
+ * Common routine iterates through the array of breakpoints (incl single step breakpoint)
+ * and executes routine given in R5, passing:
+ * R0: Breakpoint index
+ * R1: Breakpoint Address
+ * R2: Breakpoint Instruction
+ *
+ * On Entry:
+ * Assumes that lr has been push to stack (routine can't be called directly)
+ *
+ * Only Active breakpoints (i.e., Non-zero Address entries) are processed.
+ */
+__dbg__iterate_breakpoint_array:
+ ldr r4, =__breakpoints_end__ /* start from top of the table (Assume __breakpoints_end__ > __breakpoints_start__) */
+ ldr r3, =__breakpoints_start__ /* end address check */
+ ldr r0, =__breakpoints_num__ /* Number of Breakpoints (incl Single Step) (Assume Non-Zero) */
+4: sub r0, r0, #1 /* Decrement breakpoint index in r0 */
+ ldmea r4!, {r1, r2} /* r1: Breakpoint Address, r2: Breakpoint Instruction */
+ teq r1, #0 /* Is it active? */
+ movne lr, pc
+ bxne r5 /* active entry */
+ cmp r4, r3
+ bhi 4b /* if (pointer > start of Breakpoint Table address), get next slot */
+ ldmfd sp!, {pc}
+
+/* _dbg__activate_autobreakpoint
+ * Activate all other breakpoints except current breakpoint, activate auto breakpoint in next instr slot
+ * On entry:
+ * R0: Current Breakpoint index (assumed valid)
+ * R1: Next Instruction address (for AUTO Breakpoint) [Not used, assume Single Step Breakpoint already has correct info]
+ */
+_dbg__activate_autobreakpoint:
+ stmfd sp!, {lr}
+ mov r5, r0 /* Keep Current Breakpoint Index in r5 */
+ ldr r4, =__breakpoints_end__ /* start from top of the table */
+ ldr r0, =__breakpoints_num__ /* Number of Breakpoints (incl Single Step) (Assume Non-Zero) */
+4: subs r0, r0, #1 /* Decrement breakpoint index in r0 */
+ ldmea r4!, {r1, r2} /* r1: Breakpoint Address, r2: Breakpoint Instruction */
+ bls 5f /* Flag set by subs instruction previously. Reached Single Step, go activate AUTO Breakpoint */
+ teq r0, r5 /* Is it the Current Breakpoint? */
+ beq 4b /* Yes, so skip */
+ teq r1, #0 /* Is it active? */
+ blne _dbg__activate_one_breakpoint /* active entry */
+ b 4b /* Next iteration */
+5:
+/* Here, r1: Breakpoint Address, r2: Breakpoint Instruction */
+ tst r1, #BKPT_STATE_THUMB_FLAG /* Check for Thumb bit -- 1: Thumb instruction */
+ orreq r0, r5, #BKPT32_AUTO_BKPT /* Is ARM Instruction, merge AUTO flag with Current Breakpoint Index */
+ orrne r0, r5, #BKPT16_AUTO_BKPT /* Is Thumb Instruction, merge AUTO flag with Current Breakpoint Index */
+ bl _dbg__activate_one_breakpoint /* Activate AUTO Breakpoint */
+ ldmfd sp!, {pc}
+
diff --git a/AT91SAM7S256/Debugger/debug_stub.h b/AT91SAM7S256/Debugger/debug_stub.h
new file mode 100644
index 0000000..15f087f
--- /dev/null
+++ b/AT91SAM7S256/Debugger/debug_stub.h
@@ -0,0 +1,149 @@
+/** @file debug_stub.h
+ * @brief Shared C/ASM header file for debugger stub
+ *
+ */
+
+/* Copyright (C) 2007-2010 the NxOS developers
+ *
+ * Module Developed by: TC Wan <tcwan@cs.usm.my>
+ *
+ * See AUTHORS for a full list of the developers.
+ *
+ * Redistribution of this file is permitted under
+ * the terms of the GNU Public License (GPL) version 2.
+ */
+
+#ifndef __DEBUG_STUB_H__
+#define __DEBUG_STUB_H__
+
+#include "_c_arm_macros.h"
+
+#ifndef __ASSEMBLY__
+#include "types.h"
+#endif
+
+/** @addtogroup debugger */
+/*@{*/
+
+
+/* Declarations go here. */
+/** @name Debug Message Constants.
+ *
+ * Debug Message Values
+ */
+/*@{*/
+#define MSGBUF_SIZE 256 /* Debug Message Buffer Size */
+#define MSGBUF_STARTCHAR '$'
+#define MSGBUF_ACKCHAR '+'
+#define MSGBUF_NAKCHAR '-'
+#define MSGBUF_ERRCHAR 'E'
+#define MSGBUF_SIGCHAR 'S'
+#define MSG_ERRCHKSUM 1
+#define MSG_UNKNOWNCMD 2
+#define MSGBUF_CMDINDEX_OUTOFRANGE_VAL -1
+
+/*@}*/
+
+/** @name Bitmask Definitions.
+ *
+ * Various Bitmasks used for data manipulation.
+ */
+/*@{*/
+#define BKPT_STATE_THUMB_FLAG 0x01 /* Flag Thumb Breakpoint */
+#define ASCII_LOWER2UPPER_MASK 0x20 /* ASCII Conversion bitmask */
+#define NIBBLE0 0x0000000F /* Nibble 0 word(3:0) */
+#define NIBBLE1 0x000000F0 /* Nibble 1 word(7:4) */
+#define NIBBLE2 0x00000F00 /* Nibble 2 word(11:8) */
+#define NIBBLE3 0x0000F000 /* Nibble 3 word(15:12) */
+#define NIBBLE4 0x000F0000 /* Nibble 4 word(19:16) */
+#define NIBBLE5 0x00F00000 /* Nibble 5 word(23:20) */
+#define NIBBLE6 0x0F000000 /* Nibble 6 word(27:24) */
+#define NIBBLE7 0xF0000000 /* Nibble 7 word(31:28) */
+#define BYTE0 0x000000FF /* Byte 0 word(7:0) */
+#define BYTE1 0x0000FF00 /* Byte 1 word(15:8) */
+#define BYTE2 0x00FF0000 /* Byte 2 word(23:16) */
+#define BYTE3 0xFF000000 /* Byte 3 word(31:24) */
+#define HLFWRD0 0x0000FFFF /* Halfword 0 word(15:0) */
+#define HLFWRD1 0xFFFF0000 /* Halfword 0 word(31:16) */
+/*@}*/
+
+/** @name BKPT suppport constants
+ *
+ * ARM and Thumb Breakpoint Instructions.
+ */
+/*@{*/
+#define BKPT32_INSTR 0xE1200070 /* ARM BKPT instruction */
+#define BKPT32_ENUM_MASK 0x000FFF0F /* ARM BKPT Enum Mask */
+#define BKPT32_AUTO_BKPT 0x00080000 /* ARM BKPT Auto-Step Flag (for CONT support) */
+#define BKPT32_MANUAL_BKPT 0x0007FF0F /* Manually inserted ARM Breakpoint */
+
+#define BKPT16_INSTR 0xBE00 /* Thumb BKPT instruction (not supported currently) */
+#define BKPT16_ENUM_MASK 0x00FF /* Thumb BKPT Enum Mask */
+#define BKPT16_AUTO_BKPT 0x0080 /* Thumb BKPT Auto-Step Flag (for CONT support) */
+#define BKPT16_MANUAL_BKPT 0x007F /* Manually inserted Thumb Breakpoint */
+/*@}*/
+
+/** Debugger State Enums
+ *
+ * Debugger State.
+ * The enums must be consecutive, starting from 0
+ */
+ENUM_BEGIN
+ENUM_VALASSIGN(DBG_RESET, 0) /**< Initial State. */
+ENUM_VAL(DBG_INIT) /**< Debugger Initialized. */
+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. */
+ENUM_VAL(DBG_NORMAL_BKPT_THUMB) /**< Normal Thumb Breakpoint (Single Step, Normal). */
+ENUM_END(dbg_state_t)
+
+#ifndef __ASSEMBLY__
+
+/* Define C stuff */
+/** @defgroup debug_public */
+/*@{*/
+
+
+/** Initialize Debugger.
+ * Equivalent to GDB set_debug_traps() routine
+ */
+FUNCDEF void dbg__bkpt_init(void);
+
+/** Debugger Handler Routine (called by Exception Handler Trap).
+ * Equivalent to GDB handle_exception() routine
+ */
+FUNCDEF void dbg__bkpt_handler(void);
+
+/** dbg_breakpoint_arm.
+ * Equivalent to GDB breakpoint() routine for ARM code
+ */
+FUNCDEF inline void dbg_breakpoint_arm(void) { asm volatile (".word BKPT32_INSTR | BKPT32_MANUAL_BKPT") }
+
+/** dbg_breakpoint_thumb.
+ * Equivalent to GDB breakpoint() routine for Thumb code
+ */
+FUNCDEF inline void dbg_breakpoint_thumb(void) { asm volatile (".hword BKPT16_INSTR | BKPT16_MANUAL_BKPT") }
+
+/*@}*/
+
+#else
+/* Define Assembly stuff */
+
+/* dbg__bkpt_arm
+ * GDB breakpoint() for ARM mode
+ */
+ .macro dbg__bkpt_arm
+ .word (BKPT32_INSTR | BKPT32_MANUAL_BKPT)
+ .endm
+
+/* dbg__bkpt_arm
+ * GDB breakpoint() for Thumb mode
+ */
+ .macro dbg__bkpt_thumb
+ .hword (BKPT16_INSTR | BKPT16_MANUAL_BKPT)
+ .endm
+
+#endif
+ /*@}*/
+
+#endif /* __DEBUG_STUB_H__ */
diff --git a/AT91SAM7S256/Debugger/types.h b/AT91SAM7S256/Debugger/types.h
new file mode 100644
index 0000000..3a1d4cb
--- /dev/null
+++ b/AT91SAM7S256/Debugger/types.h
@@ -0,0 +1,46 @@
+/** @file types.h
+ * @brief Basic type definitions for the Arm7 platform.
+ */
+
+/* Copyright (c) 2007,2008 the NxOS developers
+ *
+ * See AUTHORS for a full list of the developers.
+ *
+ * Redistribution of this file is permitted under
+ * the terms of the GNU Public License (GPL) version 2.
+ */
+
+#ifndef __NXOS_BASE_TYPES_H__
+#define __NXOS_BASE_TYPES_H__
+
+/** @addtogroup typesAndUtils */
+/*@{*/
+
+typedef unsigned char U8; /**< Unsigned 8-bit integer. */
+typedef signed char S8; /**< Signed 8-bit integer. */
+typedef unsigned short U16; /**< Unsigned 16-bit integer. */
+typedef signed short S16; /**< Signed 16-bit integer. */
+typedef unsigned long U32; /**< Unsigned 32-bit integer. */
+typedef signed long S32; /**< Signed 32-bit integer. */
+
+#ifndef __SIZE_TYPE__
+#define __SIZE_TYPE__ U32 /**< Used to go conform with gcc, otherwise we are
+ risking an error because of conflicting types for size_t */
+#endif
+typedef __SIZE_TYPE__ size_t; /**< Abstract size type, needed by the memory allocator. */
+
+typedef U8 bool; /**< Boolean data type. */
+#define FALSE (0) /**< False boolean value. */
+#define TRUE (!FALSE) /**< True boolean value. */
+
+#ifndef NULL
+/** Definition of the NULL pointer. */
+#define NULL ((void*)0)
+#endif
+
+/** A function that takes no arguments and returns nothing. */
+typedef void (*nx_closure_t)(void);
+
+/*@}*/
+
+#endif