This is an automated email from Gerrit. Bernhard Kiesbauer ([email protected]) just uploaded a new patch set to Gerrit, which you can find at http://openocd.zylin.com/1468
-- gerrit commit 9a2d04497fd5f79863b3a9aa328e9466c292bb7c Author: Bernhard Kiesbauer <[email protected]> Date: Mon Jul 1 21:27:05 2013 +0200 topic: Adding breakpoint/watchpoint commands to dsp563xx. Added missing breakpoint/watchpoint implementation to dsp563xx target. Implementation is not yet complete, which means it does not leverage all available features of the once debug interface. This does NOT use the openocd breakpoint/watchpoint command because of the "special" memory address spaces (X/Y/P/L) of the 56k DSP series. Change-Id: I6840a3ff1e6fdebb38ab7758f164886aff773af6 Signed-off-by: Bernhard Kiesbauer <[email protected]> diff --git a/src/target/dsp563xx.c b/src/target/dsp563xx.c index 4dfb66e..dd487d5 100644 --- a/src/target/dsp563xx.c +++ b/src/target/dsp563xx.c @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -25,6 +25,7 @@ #include <jim.h> #include "target.h" +#include "breakpoints.h" #include "target_type.h" #include "algorithm.h" #include "register.h" @@ -94,6 +95,29 @@ #define ASM_REG_W_AAR2 0xFFFFF7 #define ASM_REG_W_AAR3 0xFFFFF6 +/* + * OBCR Register bit definitions + */ +#define OBCR_b0_and_b1 ((0x0) << 10) +#define OBCR_b0_or_b1 ((0x1) << 10) +#define OBCR_b1_after_b0 ((0x2) << 10) +#define OBCR_b0_after_b1 ((0x3) << 10) + +#define OBCR_BP_DISABLED (0x0) +#define OBCR_BP_MEM_P (0x1) +#define OBCR_BP_MEM_X (0x2) +#define OBCR_BP_MEM_Y (0x3) +#define OBCR_BP_ON_READ ((0x2) << 0) +#define OBCR_BP_ON_WRITE ((0x1) << 0) +#define OBCR_BP_CC_NOT_EQUAL ((0x0) << 2) +#define OBCR_BP_CC_EQUAL ((0x1) << 2) +#define OBCR_BP_CC_LESS_THAN ((0x2) << 2) +#define OBCR_BP_CC_GREATER_THAN ((0x3) << 2) + +#define OBCR_BP_0(x) ((x)<<2) +#define OBCR_BP_1(x) ((x)<<6) + + enum once_reg_idx { ONCE_REG_IDX_OSCR = 0, ONCE_REG_IDX_OMBC = 1, @@ -290,6 +314,13 @@ enum memory_type { MEM_L = 3, }; +enum watchpoint_condition { + EQUAL, + NOT_EQUAL, + GREATER, + LESS_THAN +}; + #define INSTR_JUMP 0x0AF080 /* Effective Addressing Mode Encoding */ #define EAME_R0 0x10 @@ -880,6 +911,10 @@ static int dsp563xx_init_target(struct command_context *cmd_ctx, struct target * LOG_DEBUG("%s", __func__); dsp563xx_build_reg_cache(target); + struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target); + + dsp563xx->hardware_breakpoints_cleared = 0; + dsp563xx->hardware_breakpoint[0].used = BPU_NONE; return ERROR_OK; } @@ -903,6 +938,9 @@ static int dsp563xx_examine(struct target *target) chip += 300; LOG_INFO("DSP56%03d device found", chip); + + //Clear all breakpoints + dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OBCR, 0); } return ERROR_OK; @@ -1024,8 +1062,9 @@ static int dsp563xx_poll(struct target *target) } err = dsp563xx_once_reg_read(target->tap, 1, DSP563XX_ONCE_OSCR, &once_status); - if (err != ERROR_OK) + if (err != ERROR_OK) { return err; + } if ((once_status & DSP563XX_ONCE_OSCR_DEBUG_M) == DSP563XX_ONCE_OSCR_DEBUG_M) { if (target->state != TARGET_HALTED) { @@ -1045,6 +1084,13 @@ static int dsp563xx_poll(struct target *target) } } + if(!dsp563xx->hardware_breakpoints_cleared) { + err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OBCR, 0); + err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OMLR0, 0); + err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OMLR1, 0); + dsp563xx->hardware_breakpoints_cleared=1; + } + return ERROR_OK; } @@ -1814,24 +1860,25 @@ static int dsp563xx_write_buffer_default(struct target *target, buffer); } -static int dsp563xx_add_breakpoint(struct target *target, struct breakpoint *breakpoint) -{ - return ERROR_OK; -} - -static int dsp563xx_remove_breakpoint(struct target *target, struct breakpoint *breakpoint) -{ - return ERROR_OK; -} +/* + * Exit with error here, because we support watchpoints over a custom command. + * This is because the DSP has separate X,Y,P memspace which is not compatible to the + * traditional watchpoint logic. + */ static int dsp563xx_add_watchpoint(struct target *target, struct watchpoint *watchpoint) { - return ERROR_OK; + int err = ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + return err; } +/* + * @see dsp563xx_add_watchpoint + */ static int dsp563xx_remove_watchpoint(struct target *target, struct watchpoint *watchpoint) { - return ERROR_OK; + int err = ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + return err; } static void handle_md_output(struct command_context *cmd_ctx, @@ -1895,6 +1942,236 @@ static void handle_md_output(struct command_context *cmd_ctx, } } +static int dsp563xx_add_custom_watchpoint(struct target* target, uint32_t address, uint32_t memType, + enum watchpoint_rw rw, enum watchpoint_condition cond) +{ + int err = ERROR_OK; + struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target); + + bool wasRunning = false; + //Only set breakpoint when halted + if(target->state != TARGET_HALTED) { + dsp563xx_halt(target); + wasRunning = true; + } + + if(dsp563xx->hardware_breakpoint[0].used) { + LOG_ERROR("Cannot add watchpoint. Hardware resource already used."); + err = ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + } + + uint32_t obcr_value = 0; + if(err == ERROR_OK) { + obcr_value |= OBCR_b0_or_b1; + switch(memType) { + case MEM_X: + obcr_value |= OBCR_BP_MEM_X; + break; + case MEM_Y: + obcr_value |= OBCR_BP_MEM_Y; + break; + case MEM_P: + obcr_value |= OBCR_BP_MEM_P; + break; + default: + LOG_ERROR("Unknown memType parameter (%d)", memType); + err = ERROR_TARGET_INVALID; + } + } + + if(err == ERROR_OK) { + switch(rw) { + case WPT_READ: + obcr_value |= OBCR_BP_0(OBCR_BP_ON_READ); + break; + case WPT_WRITE: + obcr_value |= OBCR_BP_0(OBCR_BP_ON_WRITE); + break; + case WPT_ACCESS: + obcr_value |= OBCR_BP_0(OBCR_BP_ON_READ|OBCR_BP_ON_WRITE); + break; + default: + LOG_ERROR("Unsupported write mode (%d)", rw); + err = ERROR_TARGET_INVALID; + } + } + + if(err == ERROR_OK) { + switch(cond) { + case EQUAL: + obcr_value |= OBCR_BP_0(OBCR_BP_CC_EQUAL); + break; + case NOT_EQUAL: + obcr_value |= OBCR_BP_0(OBCR_BP_CC_NOT_EQUAL); + break; + case LESS_THAN: + obcr_value |= OBCR_BP_0(OBCR_BP_CC_LESS_THAN); + break; + case GREATER: + obcr_value |= OBCR_BP_0(OBCR_BP_CC_GREATER_THAN); + break; + default: + LOG_ERROR("Unsupported condition code (%d)", cond); + err = ERROR_TARGET_INVALID; + } + } + + if(err == ERROR_OK) { + err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OMLR0, address); + } + + if(err == ERROR_OK) { + err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OMLR1, 0x0); + } + + if(err == ERROR_OK) { + err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OBCR, obcr_value); + } + + if(err == ERROR_OK) { + //You should write the memory breakpoint counter to 0 + err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OMBC, 0); + } + + if(err == ERROR_OK) { + //You should write the memory breakpoint counter to 0 + err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OTC, 0); + } + + if(err == ERROR_OK) { + dsp563xx->hardware_breakpoint[0].used = BPU_WATCHPOINT; + } + + if(err == ERROR_OK && wasRunning) { + //Resume from current PC + err = dsp563xx_resume(target, 1, 0x0, 0, 0); + } + + return err; +} + +static int dsp563xx_remove_custom_watchpoint(struct target* target) +{ + int err = ERROR_OK; + struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target); + + if(dsp563xx->hardware_breakpoint[0].used != BPU_WATCHPOINT) { + LOG_ERROR("Cannot remove watchpoint, as no watchpoint is currently configured!"); + err = ERROR_TARGET_INVALID; + } + + if(err == ERROR_OK) { + /* + * Clear watchpoint by clearing OBCR. + */ + err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OBCR, 0); + } + + if(err == ERROR_OK) { + dsp563xx->hardware_breakpoint[0].used = BPU_NONE; + } + + return err; +} + +COMMAND_HANDLER(dsp563xx_add_watchpoint_command) +{ + int err = ERROR_OK; + struct target *target = get_current_target(CMD_CTX); + + uint32_t mem_type=0; + //Match wp[ ] + switch (CMD_NAME[2]) { + case 'x': + mem_type = MEM_X; + break; + case 'y': + mem_type = MEM_Y; + break; + case 'p': + mem_type = MEM_P; + break; + default: + return ERROR_COMMAND_SYNTAX_ERROR; + } + + if(CMD_ARGC < 2) { + return ERROR_COMMAND_SYNTAX_ERROR; + } + + uint32_t address = 0; + if (CMD_ARGC > 2) + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], address); + + enum watchpoint_condition cond; + switch(CMD_ARGV[0][0]) { + case '>': + cond = GREATER; + break; + case '<': + cond = LESS_THAN; + break; + case '=': + cond = EQUAL; + break; + case '!': + cond = NOT_EQUAL; + break; + default: + return ERROR_COMMAND_SYNTAX_ERROR; + } + + enum watchpoint_rw rw; + switch(CMD_ARGV[1][0]) { + case 'r': + rw = WPT_READ; + break; + case 'w': + rw = WPT_WRITE; + break; + case 'a': + rw = WPT_ACCESS; + break; + default: + return ERROR_COMMAND_SYNTAX_ERROR; + } + + err = dsp563xx_add_custom_watchpoint(target, address, mem_type, rw, cond); + + return err; +} + +/**Adding a breakpoint using the once breakpoint logic. + * Note that this mechanism is a true hw breakpoint and is share between the watchpoint logic. + * This means, you can only have one breakpoint/watchpoint at any time. + */ +static int dsp563xx_add_breakpoint(struct target *target, struct breakpoint *breakpoint) +{ + int err = ERROR_OK; + err = dsp563xx_add_custom_watchpoint(target, breakpoint->address, MEM_P, WPT_READ, EQUAL); + + return err; +} + +static int dsp563xx_remove_breakpoint(struct target *target, struct breakpoint *breakpoint) +{ + int err = ERROR_OK; + err = dsp563xx_remove_custom_watchpoint(target); + + return err; +} + + +COMMAND_HANDLER(dsp563xx_remove_watchpoint_command) +{ + int err = ERROR_OK; + struct target *target = get_current_target(CMD_CTX); + + err = dsp563xx_remove_custom_watchpoint(target); + + return err; +} + COMMAND_HANDLER(dsp563xx_mem_command) { struct target *target = get_current_target(CMD_CTX); @@ -1985,42 +2262,73 @@ static const struct command_registration dsp563xx_command_handlers[] = { .handler = dsp563xx_mem_command, .mode = COMMAND_EXEC, .help = "write x memory words", - .usage = "mwwx address value [count]", + .usage = "address value [count]", }, { .name = "mwwy", .handler = dsp563xx_mem_command, .mode = COMMAND_EXEC, .help = "write y memory words", - .usage = "mwwy address value [count]", + .usage = "address value [count]", }, { .name = "mwwp", .handler = dsp563xx_mem_command, .mode = COMMAND_EXEC, .help = "write p memory words", - .usage = "mwwp address value [count]", + .usage = "address value [count]", }, { .name = "mdwx", .handler = dsp563xx_mem_command, .mode = COMMAND_EXEC, .help = "display x memory words", - .usage = "mdwx address [count]", + .usage = "address [count]", }, { .name = "mdwy", .handler = dsp563xx_mem_command, .mode = COMMAND_EXEC, .help = "display y memory words", - .usage = "mdwy address [count]", + .usage = "address [count]", }, { .name = "mdwp", .handler = dsp563xx_mem_command, .mode = COMMAND_EXEC, .help = "display p memory words", - .usage = "mdwp address [count]", + .usage = "address [count]", + }, + /* + * Watchpoint commands + */ + { + .name = "wpp", + .handler = dsp563xx_add_watchpoint_command, + .mode = COMMAND_EXEC, + .help = "Create p memspace watchpoint", + .usage = "(>|<|=|!) (r|w|a) address", + }, + { + .name = "wpx", + .handler = dsp563xx_add_watchpoint_command, + .mode = COMMAND_EXEC, + .help = "Create x memspace watchpoint", + .usage = "(>|<|=|!) (r|w|a) address", + }, + { + .name = "wpy", + .handler = dsp563xx_add_watchpoint_command, + .mode = COMMAND_EXEC, + .help = "Create y memspace watchpoint", + .usage = "(>|<|=|!) (r|w|a) address", + }, + { + .name = "rwpc", + .handler = dsp563xx_remove_watchpoint_command, + .mode = COMMAND_EXEC, + .help = "remove watchpoint custom", + .usage = " ", }, COMMAND_REGISTRATION_DONE }; diff --git a/src/target/dsp563xx.h b/src/target/dsp563xx.h index b2ee9d1..92a09f2 100644 --- a/src/target/dsp563xx.h +++ b/src/target/dsp563xx.h @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef DSP563XX_H @@ -31,6 +31,16 @@ struct mcu_jtag { struct jtag_tap *tap; }; +enum breakpoint_usage { + BPU_NONE = 0, + BPU_BREAKPOINT, + BPU_WATCHPOINT +}; + +struct hardware_breakpoint { + enum breakpoint_usage used; +}; + struct dsp563xx_common { struct mcu_jtag jtag_info; struct reg_cache *core_cache; @@ -40,6 +50,11 @@ struct dsp563xx_common { /* register cache to processor synchronization */ int (*read_core_reg) (struct target *target, int num); int (*write_core_reg) (struct target *target, int num); + + struct hardware_breakpoint hardware_breakpoint[1]; + + /*Were the hardware breakpoints cleared on startup?*/ + int hardware_breakpoints_cleared; }; struct dsp563xx_core_reg { diff --git a/src/target/dsp563xx_once.c b/src/target/dsp563xx_once.c index 193c715..62b93fc 100644 --- a/src/target/dsp563xx_once.c +++ b/src/target/dsp563xx_once.c @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -61,6 +61,7 @@ static inline int dsp563xx_write_dr_u8(struct jtag_tap *tap, uint8_t * dr_in, ui return dsp563xx_write_dr(tap, dr_in, &dr_out, dr_len, rti); } + /** */ static inline int dsp563xx_write_dr_u32(struct jtag_tap *tap, uint32_t * dr_in, uint32_t dr_out, int dr_len, int rti) { @@ -179,6 +180,8 @@ int dsp563xx_once_request_debug(struct jtag_tap *tap, int reset_state) return ERROR_OK; } + + /** once read registers */ int dsp563xx_once_read_register(struct jtag_tap *tap, int flush, struct once_reg *regs, int len) { @@ -196,6 +199,8 @@ int dsp563xx_once_read_register(struct jtag_tap *tap, int flush, struct once_reg return err; } + + /** once read register with register len */ int dsp563xx_once_reg_read_ex(struct jtag_tap *tap, int flush, uint8_t reg, uint8_t len, uint32_t * data) { @@ -209,6 +214,7 @@ int dsp563xx_once_reg_read_ex(struct jtag_tap *tap, int flush, uint8_t reg, uint return err; if (flush) err = jtag_execute_queue(); + return err; } @@ -225,6 +231,7 @@ int dsp563xx_once_reg_read(struct jtag_tap *tap, int flush, uint8_t reg, uint32_ return err; if (flush) err = jtag_execute_queue(); + return err; } diff --git a/src/target/dsp563xx_once.h b/src/target/dsp563xx_once.h index dcf3bc0..80274ef 100644 --- a/src/target/dsp563xx_once.h +++ b/src/target/dsp563xx_once.h @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef DSP563XX_ONCE_H @@ -23,6 +23,10 @@ #include <jtag/jtag.h> +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #define DSP563XX_ONCE_OCR_EX (1<<5) #define DSP563XX_ONCE_OCR_GO (1<<6) #define DSP563XX_ONCE_OCR_RW (1<<7) diff --git a/src/target/dsp5680xx.c b/src/target/dsp5680xx.c index ee40947..f82fa63 100644 --- a/src/target/dsp5680xx.c +++ b/src/target/dsp5680xx.c @@ -18,7 +18,7 @@ * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/target/dsp5680xx.h b/src/target/dsp5680xx.h index 1b71009..b2260db 100644 --- a/src/target/dsp5680xx.h +++ b/src/target/dsp5680xx.h @@ -18,7 +18,7 @@ * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef DSP5680XX_H -- ------------------------------------------------------------------------------ This SF.net email is sponsored by Windows: Build for Windows Store. http://p.sf.net/sfu/windows-dev2dev _______________________________________________ OpenOCD-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/openocd-devel
