From 53590217eee6106782b2bb85ed334adf7c5e68c1 Mon Sep 17 00:00:00 2001 From: ntfreak Date: Sat, 26 Jul 2008 10:32:11 +0000 Subject: [PATCH] - merged mips target into svn trunk git-svn-id: svn://svn.berlios.de/openocd/trunk@874 b42882b7-edfa-0310-969c-e2dbd0fdcd60 --- src/target/Makefile.am | 9 +- src/target/mips32.c | 338 +++++++++++++++ src/target/mips32.h | 112 +++++ src/target/mips32_pracc.c | 781 ++++++++++++++++++++++++++++++++++ src/target/mips32_pracc.h | 55 +++ src/target/mips_ejtag.c | 283 ++++++++++++ src/target/mips_ejtag.h | 107 +++++ src/target/mips_m4k.c | 642 ++++++++++++++++++++++++++++ src/target/mips_m4k.h | 52 +++ src/target/target.c | 2 + src/target/target/pic32mx.cfg | 22 + 11 files changed, 2399 insertions(+), 4 deletions(-) create mode 100644 src/target/mips32.c create mode 100644 src/target/mips32.h create mode 100644 src/target/mips32_pracc.c create mode 100644 src/target/mips32_pracc.h create mode 100644 src/target/mips_ejtag.c create mode 100644 src/target/mips_ejtag.h create mode 100644 src/target/mips_m4k.c create mode 100644 src/target/mips_m4k.h create mode 100644 src/target/target/pic32mx.cfg diff --git a/src/target/Makefile.am b/src/target/Makefile.am index 5b0ef6e527..adf1add4b9 100644 --- a/src/target/Makefile.am +++ b/src/target/Makefile.am @@ -12,11 +12,12 @@ noinst_LIBRARIES = libtarget.a libtarget_a_SOURCES = target.c register.c breakpoints.c armv4_5.c embeddedice.c etm.c arm7tdmi.c arm9tdmi.c \ arm_jtag.c arm7_9_common.c algorithm.c arm920t.c arm720t.c armv4_5_mmu.c armv4_5_cache.c arm_disassembler.c \ arm966e.c arm926ejs.c feroceon.c etb.c xscale.c arm_simulator.c image.c armv7m.c cortex_m3.c cortex_swjdp.c \ - etm_dummy.c $(OOCD_TRACE_FILES) target_request.c trace.c arm11.c arm11_dbgtap.c + etm_dummy.c $(OOCD_TRACE_FILES) target_request.c trace.c arm11.c arm11_dbgtap.c mips32.c mips_m4k.c \ + mips32_pracc.c mips_ejtag.c noinst_HEADERS = target.h trace.h register.h armv4_5.h embeddedice.h etm.h arm7tdmi.h arm9tdmi.h \ arm_jtag.h arm7_9_common.h arm920t.h arm720t.h armv4_5_mmu.h armv4_5_cache.h breakpoints.h algorithm.h \ arm_disassembler.h arm966e.h arm926ejs.h etb.h xscale.h arm_simulator.h image.h armv7m.h cortex_m3.h cortex_swjdp.h \ - etm_dummy.h oocd_trace.h target_request.h trace.h arm11.h + etm_dummy.h oocd_trace.h target_request.h trace.h arm11.h mips32.h mips_m4k.h mips_ejtag.h mips32_pracc.h nobase_dist_pkglib_DATA = xscale/debug_handler.bin event/at91eb40a_reset.script target/at91eb40a.cfg \ event/at91r40008_reset.script event/sam7s256_reset.script event/sam7x256_reset.script \ @@ -35,6 +36,6 @@ nobase_dist_pkglib_DATA = xscale/debug_handler.bin event/at91eb40a_reset.script interface/chameleon.cfg interface/at91rm9200.cfg interface/jlink.cfg interface/arm-usb-ocd.cfg \ interface/signalyzer.cfg event/eir-sam7se512_reset.script target/eir-sam7se512.cfg \ event/hammer_reset.script interface/flyswatter.cfg target/hammer.cfg target/mx31.cfg \ - event/str730_program.script event/str750_program.script interface/olimex-jtag-tiny-a.cfg - + event/str730_program.script event/str750_program.script interface/olimex-jtag-tiny-a.cfg \ + target/pic32mx.cfg diff --git a/src/target/mips32.c b/src/target/mips32.c new file mode 100644 index 0000000000..f338c1db0b --- /dev/null +++ b/src/target/mips32.c @@ -0,0 +1,338 @@ +/*************************************************************************** + * Copyright (C) 2008 by Spencer Oliver * + * spen@spen-soft.co.uk * + * * + * Copyright (C) 2008 by David T.L. Wong * + * * + * This program 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 of the License, or * + * (at your option) any later version. * + * * + * This program 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 this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "mips32.h" +#include "jtag.h" +#include "log.h" + +#include +#include + +char* mips32_core_reg_list[] = +{ + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", + "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", + "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", + "status", "lo", "hi", "badvaddr", "cause", "pc" +}; + +mips32_core_reg_t mips32_core_reg_list_arch_info[MIPS32NUMCOREREGS] = +{ + {0, NULL, NULL}, + {1, NULL, NULL}, + {2, NULL, NULL}, + {3, NULL, NULL}, + {4, NULL, NULL}, + {5, NULL, NULL}, + {6, NULL, NULL}, + {7, NULL, NULL}, + {8, NULL, NULL}, + {9, NULL, NULL}, + {10, NULL, NULL}, + {11, NULL, NULL}, + {12, NULL, NULL}, + {13, NULL, NULL}, + {14, NULL, NULL}, + {15, NULL, NULL}, + {16, NULL, NULL}, + {17, NULL, NULL}, + {18, NULL, NULL}, + {19, NULL, NULL}, + {20, NULL, NULL}, + {21, NULL, NULL}, + {22, NULL, NULL}, + {23, NULL, NULL}, + {24, NULL, NULL}, + {25, NULL, NULL}, + {26, NULL, NULL}, + {27, NULL, NULL}, + {28, NULL, NULL}, + {29, NULL, NULL}, + {30, NULL, NULL}, + {31, NULL, NULL}, + + {32, NULL, NULL}, + {33, NULL, NULL}, + {34, NULL, NULL}, + {35, NULL, NULL}, + {36, NULL, NULL}, + {37, NULL, NULL}, +}; + +u8 mips32_gdb_dummy_fsr_value[] = {0, 0, 0, 0}; + +reg_t mips32_gdb_dummy_fsr_reg = +{ + "GDB dummy floating-point status register", mips32_gdb_dummy_fsr_value, 0, 1, 32, NULL, 0, NULL, 0 +}; + +u8 mips32_gdb_dummy_fir_value[] = {0, 0, 0, 0}; + +reg_t mips32_gdb_dummy_fir_reg = +{ + "GDB dummy floating-point register", mips32_gdb_dummy_fir_value, 0, 1, 32, NULL, 0, NULL, 0 +}; + +int mips32_core_reg_arch_type = -1; + +int mips32_get_core_reg(reg_t *reg) +{ + int retval; + mips32_core_reg_t *mips32_reg = reg->arch_info; + target_t *target = mips32_reg->target; + mips32_common_t *mips32_target = target->arch_info; + + if (target->state != TARGET_HALTED) + { + return ERROR_TARGET_NOT_HALTED; + } + + retval = mips32_target->read_core_reg(target, mips32_reg->num); + + return retval; +} + +int mips32_set_core_reg(reg_t *reg, u8 *buf) +{ + mips32_core_reg_t *mips32_reg = reg->arch_info; + target_t *target = mips32_reg->target; + u32 value = buf_get_u32(buf, 0, 32); + + if (target->state != TARGET_HALTED) + { + return ERROR_TARGET_NOT_HALTED; + } + + buf_set_u32(reg->value, 0, 32, value); + reg->dirty = 1; + reg->valid = 1; + + return ERROR_OK; +} + +int mips32_read_core_reg(struct target_s *target, int num) +{ + u32 reg_value; + mips32_core_reg_t *mips_core_reg; + + /* get pointers to arch-specific information */ + mips32_common_t *mips32 = target->arch_info; + + if ((num < 0) || (num >= MIPS32NUMCOREREGS)) + return ERROR_INVALID_ARGUMENTS; + + mips_core_reg = mips32->core_cache->reg_list[num].arch_info; + reg_value = mips32->core_regs[num]; + buf_set_u32(mips32->core_cache->reg_list[num].value, 0, 32, reg_value); + mips32->core_cache->reg_list[num].valid = 1; + mips32->core_cache->reg_list[num].dirty = 0; + + return ERROR_OK; +} + +int mips32_write_core_reg(struct target_s *target, int num) +{ + u32 reg_value; + mips32_core_reg_t *mips_core_reg; + + /* get pointers to arch-specific information */ + mips32_common_t *mips32 = target->arch_info; + + if ((num < 0) || (num >= MIPS32NUMCOREREGS)) + return ERROR_INVALID_ARGUMENTS; + + reg_value = buf_get_u32(mips32->core_cache->reg_list[num].value, 0, 32); + mips_core_reg = mips32->core_cache->reg_list[num].arch_info; + mips32->core_regs[num] = reg_value; + LOG_DEBUG("write core reg %i value 0x%x", num , reg_value); + mips32->core_cache->reg_list[num].valid = 1; + mips32->core_cache->reg_list[num].dirty = 0; + + return ERROR_OK; +} + +int mips32_invalidate_core_regs(target_t *target) +{ + /* get pointers to arch-specific information */ + mips32_common_t *mips32 = target->arch_info; + int i; + + for (i = 0; i < mips32->core_cache->num_regs; i++) + { + mips32->core_cache->reg_list[i].valid = 0; + mips32->core_cache->reg_list[i].dirty = 0; + } + + return ERROR_OK; +} + +int mips32_get_gdb_reg_list(target_t *target, reg_t **reg_list[], int *reg_list_size) +{ + /* get pointers to arch-specific information */ + mips32_common_t *mips32 = target->arch_info; + int i; + + /* include fsr/fir reg */ + *reg_list_size = MIPS32NUMCOREREGS + 2; + *reg_list = malloc(sizeof(reg_t*) * (*reg_list_size)); + + for (i = 0; i < MIPS32NUMCOREREGS; i++) + { + (*reg_list)[i] = &mips32->core_cache->reg_list[i]; + } + + /* add dummy floating points regs */ + (*reg_list)[38] = &mips32_gdb_dummy_fsr_reg; + (*reg_list)[39] = &mips32_gdb_dummy_fir_reg; + + return ERROR_OK; +} + +int mips32_save_context(target_t *target) +{ + int i; + + /* get pointers to arch-specific information */ + mips32_common_t *mips32 = target->arch_info; + mips_ejtag_t *ejtag_info = &mips32->ejtag_info; + + /* read core registers */ + mips32_pracc_read_regs(ejtag_info, mips32->core_regs); + + for (i = 0; i < MIPS32NUMCOREREGS; i++) + { + if (!mips32->core_cache->reg_list[i].valid) + { + mips32->read_core_reg(target, i); + } + } + + return ERROR_OK; +} + +int mips32_restore_context(target_t *target) +{ + int i; + + /* get pointers to arch-specific information */ + mips32_common_t *mips32 = target->arch_info; + mips_ejtag_t *ejtag_info = &mips32->ejtag_info; + + for (i = 0; i < MIPS32NUMCOREREGS; i++) + { + if (mips32->core_cache->reg_list[i].dirty) + { + mips32->write_core_reg(target, i); + } + } + + /* write core regs */ + mips32_pracc_write_regs(ejtag_info, mips32->core_regs); + + return ERROR_OK; +} + +int mips32_arch_state(struct target_s *target) +{ + mips32_common_t *mips32 = target->arch_info; + + if (mips32->common_magic != MIPS32_COMMON_MAGIC) + { + LOG_ERROR("BUG: called for a non-MIPS32 target"); + exit(-1); + } + + LOG_USER("target halted due to %s, pc: 0x%8.8x", + target_debug_reason_strings[target->debug_reason], + buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32)); + + return ERROR_OK; +} + +reg_cache_t *mips32_build_reg_cache(target_t *target) +{ + /* get pointers to arch-specific information */ + mips32_common_t *mips32 = target->arch_info; + + int num_regs = MIPS32NUMCOREREGS; + reg_cache_t **cache_p = register_get_last_cache_p(&target->reg_cache); + reg_cache_t *cache = malloc(sizeof(reg_cache_t)); + reg_t *reg_list = malloc(sizeof(reg_t) * num_regs); + mips32_core_reg_t *arch_info = malloc(sizeof(mips32_core_reg_t) * num_regs); + int i; + + if (mips32_core_reg_arch_type == -1) + mips32_core_reg_arch_type = register_reg_arch_type(mips32_get_core_reg, mips32_set_core_reg); + + /* Build the process context cache */ + cache->name = "mips32 registers"; + cache->next = NULL; + cache->reg_list = reg_list; + cache->num_regs = num_regs; + (*cache_p) = cache; + mips32->core_cache = cache; + + for (i = 0; i < num_regs; i++) + { + arch_info[i] = mips32_core_reg_list_arch_info[i]; + arch_info[i].target = target; + arch_info[i].mips32_common = mips32; + reg_list[i].name = mips32_core_reg_list[i]; + reg_list[i].size = 32; + reg_list[i].value = calloc(1, 4); + reg_list[i].dirty = 0; + reg_list[i].valid = 0; + reg_list[i].bitfield_desc = NULL; + reg_list[i].num_bitfields = 0; + reg_list[i].arch_type = mips32_core_reg_arch_type; + reg_list[i].arch_info = &arch_info[i]; + } + + return cache; +} + +int mips32_init_arch_info(target_t *target, mips32_common_t *mips32, int chain_pos, char *variant) +{ + target->arch_info = mips32; + mips32->common_magic = MIPS32_COMMON_MAGIC; + + mips32->ejtag_info.chain_pos = chain_pos; + mips32->read_core_reg = mips32_read_core_reg; + mips32->write_core_reg = mips32_write_core_reg; + + return ERROR_OK; +} + +int mips32_register_commands(struct command_context_s *cmd_ctx) +{ + return ERROR_OK; +} + +int mips32_run_algorithm(struct target_s *target, int num_mem_params, mem_param_t *mem_params, int num_reg_params, reg_param_t *reg_params, u32 entry_point, u32 exit_point, int timeout_ms, void *arch_info) +{ + /*TODO*/ + return ERROR_OK; +} diff --git a/src/target/mips32.h b/src/target/mips32.h new file mode 100644 index 0000000000..aeed1a605e --- /dev/null +++ b/src/target/mips32.h @@ -0,0 +1,112 @@ +/*************************************************************************** + * Copyright (C) 2008 by Spencer Oliver * + * spen@spen-soft.co.uk * + * * + * Copyright (C) 2008 by David T.L. Wong * + * * + * This program 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 of the License, or * + * (at your option) any later version. * + * * + * This program 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 this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef MIPS32_H +#define MIPS32_H + +#include "target.h" +#include "register.h" +#include "mips_ejtag.h" +#include "mips32_pracc.h" + +#define MIPS32_COMMON_MAGIC 0xB320B320 + +/* offsets into mips32 core register cache */ +enum +{ + MIPS32_PC = 37, + MIPS32NUMCOREREGS +}; + +typedef struct mips32_common_s +{ + int common_magic; + void *arch_info; + reg_cache_t *core_cache; + mips_ejtag_t ejtag_info; + u32 core_regs[MIPS32NUMCOREREGS]; + + /* register cache to processor synchronization */ + int (*read_core_reg)(struct target_s *target, int num); + int (*write_core_reg)(struct target_s *target, int num); +} mips32_common_t; + +typedef struct mips32_core_reg_s +{ + u32 num; + target_t *target; + mips32_common_t *mips32_common; +} mips32_core_reg_t; + +#define MIPS32_OP_BEQ 0x04 +#define MIPS32_OP_ADDI 0x08 +#define MIPS32_OP_AND 0x24 +#define MIPS32_OP_COP0 0x10 +#define MIPS32_OP_LUI 0x0F +#define MIPS32_OP_LW 0x23 +#define MIPS32_OP_LBU 0x24 +#define MIPS32_OP_LHU 0x25 +#define MIPS32_OP_MFHI 0x10 +#define MIPS32_OP_MFLO 0x12 +#define MIPS32_OP_SB 0x28 +#define MIPS32_OP_SH 0x29 +#define MIPS32_OP_SW 0x2B +#define MIPS32_OP_ORI 0x0D + +#define MIPS32_COP0_MF 0x00 +#define MIPS32_COP0_MT 0x04 + +#define MIPS32_R_INST(opcode, rs, rt, rd, shamt, funct) (((opcode)<<26) |((rs)<<21)|((rt)<<16)|((rd)<<11)| ((shamt)<<5) | (funct)) +#define MIPS32_I_INST(opcode, rs, rt, immd) (((opcode)<<26) |((rs)<<21)|((rt)<<16)|(immd)) +#define MIPS32_J_INST(opcode, addr) (((opcode)<<26) |(addr)) + +#define MIPS32_NOP 0 +#define MIPS32_ADDI(tar, src, val) MIPS32_I_INST(MIPS32_OP_ADDI, src, tar, val) +#define MIPS32_AND(reg, off, val) MIPS32_R_INST(0, off, val, reg, 0, MIPS32_OP_AND) +#define MIPS32_B(off) MIPS32_BEQ(0, 0, off) +#define MIPS32_BEQ(src,tar,off) MIPS32_I_INST(MIPS32_OP_BEQ, src, tar, off) +#define MIPS32_MFC0(gpr, cpr, sel) MIPS32_R_INST(MIPS32_OP_COP0, MIPS32_COP0_MF, gpr, cpr, 0, sel) +#define MIPS32_MTC0(gpr,cpr, sel) MIPS32_R_INST(MIPS32_OP_COP0, MIPS32_COP0_MT, gpr, cpr, 0, sel) +#define MIPS32_LBU(reg, off, base) MIPS32_I_INST(MIPS32_OP_LBU, base, reg, off) +#define MIPS32_LHU(reg, off, base) MIPS32_I_INST(MIPS32_OP_LHU, base, reg, off) +#define MIPS32_LUI(reg, val) MIPS32_I_INST(MIPS32_OP_LUI, 0, reg, val) +#define MIPS32_LW(reg, off, base) MIPS32_I_INST(MIPS32_OP_LW, base, reg, off) +#define MIPS32_LO(reg) MIPS32_R_INST(0, 0, 0, reg, 0, MIPS32_OP_MFHI) +#define MIPS32_HI(reg) MIPS32_R_INST(0, 0, 0, reg, 0, MIPS32_OP_MFLO) +#define MIPS32_ORI(src, tar, val) MIPS32_I_INST(MIPS32_OP_ORI, src, tar, val) +#define MIPS32_SB(reg, off, base) MIPS32_I_INST(MIPS32_OP_SB, base, reg, off) +#define MIPS32_SH(reg, off, base) MIPS32_I_INST(MIPS32_OP_SH, base, reg, off) +#define MIPS32_SW(reg, off, base) MIPS32_I_INST(MIPS32_OP_SW, base, reg, off) +#define MIPS32_DRET 0x4200001F + +extern int mips32_arch_state(struct target_s *target); +extern int mips32_init_arch_info(target_t *target, mips32_common_t *mips32, int chain_pos, char *variant); +extern int mips32_restore_context(target_t *target); +extern int mips32_save_context(target_t *target); +extern reg_cache_t *mips32_build_reg_cache(target_t *target); +extern int mips32_run_algorithm(struct target_s *target, int num_mem_params, mem_param_t *mem_params, int num_reg_params, reg_param_t *reg_params, u32 entry_point, u32 exit_point, int timeout_ms, void *arch_info); + +extern int mips32_register_commands(struct command_context_s *cmd_ctx); +extern int mips32_invalidate_core_regs(target_t *target); +extern int mips32_get_gdb_reg_list(target_t *target, reg_t **reg_list[], int *reg_list_size); + +#endif /*MIPS32_H*/ diff --git a/src/target/mips32_pracc.c b/src/target/mips32_pracc.c new file mode 100644 index 0000000000..400227e93c --- /dev/null +++ b/src/target/mips32_pracc.c @@ -0,0 +1,781 @@ +/*************************************************************************** + * Copyright (C) 2008 by Spencer Oliver * + * spen@spen-soft.co.uk * + * * + * Copyright (C) 2008 by David T.L. Wong * + * * + * This program 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 of the License, or * + * (at your option) any later version. * + * * + * This program 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 this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "log.h" +#include "mips32.h" +#include "mips32_pracc.h" + +typedef struct { + u32 *local_iparam; + int num_iparam; + u32 *local_oparam; + int num_oparam; + u32 *code; + int code_len; + u32 stack[32]; + int stack_offset; + mips_ejtag_t *ejtag_info; +} mips32_pracc_context; + +static int wait_for_pracc_rw(mips_ejtag_t *ejtag_info, u32 *ctrl) +{ + u32 ejtag_ctrl; + + while (1) + { + mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL, NULL); + ejtag_ctrl = EJTAG_CTRL_ROCC | EJTAG_CTRL_PRACC | EJTAG_CTRL_PROBEN | EJTAG_CTRL_SETDEV; + mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl); + if (ejtag_ctrl & EJTAG_CTRL_PRACC) + break; + LOG_DEBUG("DEBUGMODULE: No memory access in progress!\n"); + return ERROR_JTAG_DEVICE_ERROR; + } + + *ctrl = ejtag_ctrl; + return ERROR_OK; +} + +static int mips32_pracc_exec_read(mips32_pracc_context *ctx, u32 address) +{ + int offset; + u32 ctrl, data; + + if ((address >= MIPS32_PRACC_PARAM_IN) + && (address <= MIPS32_PRACC_PARAM_IN + ctx->num_iparam * 4)) + { + offset = (address - MIPS32_PRACC_PARAM_IN) / 4; + data = ctx->local_iparam[offset]; + } + else if ((address >= MIPS32_PRACC_PARAM_OUT) + && (address <= MIPS32_PRACC_PARAM_OUT + ctx->num_oparam * 4)) + { + offset = (address - MIPS32_PRACC_PARAM_OUT) / 4; + data = ctx->local_oparam[offset]; + } + else if ((address >= MIPS32_PRACC_TEXT) + && (address <= MIPS32_PRACC_TEXT + ctx->code_len*4)) + { + offset = (address - MIPS32_PRACC_TEXT) / 4; + data = ctx->code[offset]; + } + else if (address == MIPS32_PRACC_STACK) + { + /* save to our debug stack */ + data = ctx->stack[--ctx->stack_offset]; + } + else + { + /* TODO: send JMP 0xFF200000 instruction. Hopefully processor jump back + * to start of debug vector */ + + data = 0; + LOG_ERROR("Error reading unexpected address"); + return ERROR_JTAG_DEVICE_ERROR; + } + + /* Send the data out */ + mips_ejtag_set_instr(ctx->ejtag_info, EJTAG_INST_DATA, NULL); + mips_ejtag_drscan_32(ctx->ejtag_info, &data); + + /* Clear the access pending bit (let the processor eat!) */ + ctrl = EJTAG_CTRL_ROCC | EJTAG_CTRL_PROBEN | EJTAG_CTRL_SETDEV; + mips_ejtag_set_instr(ctx->ejtag_info, EJTAG_INST_CONTROL, NULL); + mips_ejtag_drscan_32(ctx->ejtag_info, &ctrl); + + return ERROR_OK; +} + +static int mips32_pracc_exec_write(mips32_pracc_context *ctx, u32 address) +{ + u32 ctrl,data; + int offset; + + mips_ejtag_set_instr(ctx->ejtag_info, EJTAG_INST_DATA, NULL); + mips_ejtag_drscan_32(ctx->ejtag_info, &data); + + /* Clear access pending bit */ + ctrl = EJTAG_CTRL_ROCC | EJTAG_CTRL_PROBEN | EJTAG_CTRL_SETDEV; + mips_ejtag_set_instr(ctx->ejtag_info, EJTAG_INST_CONTROL, NULL); + mips_ejtag_drscan_32(ctx->ejtag_info, &ctrl); + + if ((address >= MIPS32_PRACC_PARAM_IN) + && (address <= MIPS32_PRACC_PARAM_IN + ctx->num_iparam * 4)) + { + offset = (address - MIPS32_PRACC_PARAM_IN) / 4; + ctx->local_iparam[offset] = data; + } + else if ((address >= MIPS32_PRACC_PARAM_OUT ) + && (address <= MIPS32_PRACC_PARAM_OUT + ctx->num_oparam * 4)) + { + offset = (address - MIPS32_PRACC_PARAM_OUT) / 4; + ctx->local_oparam[offset] = data; + } + else if (address == MIPS32_PRACC_STACK) + { + /* save data onto our stack */ + ctx->stack[ctx->stack_offset++] = data; + } + else + { + LOG_ERROR("Error writing unexpected address"); + return ERROR_JTAG_DEVICE_ERROR; + } + + return ERROR_OK; +} + +int mips32_pracc_exec( mips_ejtag_t *ejtag_info, int code_len, u32 *code, int num_param_in, u32 *param_in, int num_param_out, u32 *param_out, int cycle) +{ + u32 ctrl; + u32 address, data; + mips32_pracc_context ctx; + int retval; + int pass = 0; + + ctx.local_iparam = param_in; + ctx.local_oparam = param_out; + ctx.num_iparam = num_param_in; + ctx.num_oparam = num_param_out; + ctx.code = code; + ctx.code_len = code_len; + ctx.ejtag_info = ejtag_info; + ctx.stack_offset = 0; + + while (1) + { + if ((retval = wait_for_pracc_rw(ejtag_info, &ctrl)) != ERROR_OK) + return retval; + + address = data = 0; + mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS, NULL); + mips_ejtag_drscan_32(ejtag_info, &address); + + /* Check for read or write */ + if (ctrl & EJTAG_CTRL_PRNW) + { + if ((retval = mips32_pracc_exec_write(&ctx, address)) != ERROR_OK) + return retval; + } + else + { + /* Check to see if its reading at the debug vector. The first pass through + * the module is always read at the vector, so the first one we allow. When + * the second read from the vector occurs we are done and just exit. */ + if ((address == MIPS32_PRACC_TEXT) && (pass++)) + { + break; + } + + if ((retval = mips32_pracc_exec_read(&ctx, address)) != ERROR_OK) + return retval; + } + + if (cycle == 0) + break; + } + + /* stack sanity check */ + if (ctx.stack_offset != 0) + { + LOG_DEBUG("Pracc Stack not zero"); + } + + return ERROR_OK; +} + +int mips32_pracc_read_mem(mips_ejtag_t *ejtag_info, u32 addr, int size, int count, void *buf) +{ + switch (size) + { + case 1: + return mips32_pracc_read_mem8(ejtag_info, addr, count, (u8*)buf); + case 2: + return mips32_pracc_read_mem16(ejtag_info, addr, count, (u16*)buf); + case 4: + return mips32_pracc_read_mem32(ejtag_info, addr, count, (u32*)buf); + } + + return ERROR_OK; +} + +int mips32_pracc_read_mem32(mips_ejtag_t *ejtag_info, u32 addr, int count, u32 *buf) +{ + u32 code[] = { + /* start: */ + MIPS32_MTC0(15,31,0), /* move $15 to COP0 DeSave */ + MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */ + MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)), + MIPS32_SW(8,0,15), /* sw $8,($15) */ + MIPS32_SW(9,0,15), /* sw $9,($15) */ + MIPS32_SW(10,0,15), /* sw $10,($15) */ + MIPS32_SW(11,0,15), /* sw $10,($15) */ + + MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)), /* $8 = MIPS32_PRACC_PARAM_IN */ + MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)), + MIPS32_LW(9,0,8), /* $9=mem[$8]; read addr */ + MIPS32_LW(10,4,8), /* $10=mem[$8+4]; read count */ + MIPS32_LUI(11,UPPER16(MIPS32_PRACC_PARAM_OUT)), /* $11=MIPS32_PRACC_PARAM_OUT */ + MIPS32_ORI(11,11,LOWER16(MIPS32_PRACC_PARAM_OUT)), + MIPS32_NOP, + /* loop: */ + MIPS32_BEQ(0,10,9), /* beq 0, $10, end */ + MIPS32_NOP, + + MIPS32_LW(12,0,9), /* lw $12,0($9), Load $12 with the word @mem[$9] */ + MIPS32_SW(12,0,11), /* sw $12,0($11) */ + + MIPS32_ADDI(10,10,NEG16(1)), /* $10-- */ + MIPS32_ADDI(9,9,4), /* $1+=4 */ + MIPS32_ADDI(11,11,4), /* $11+=4 */ + + MIPS32_NOP, + MIPS32_B(NEG16(9)), /* b loop */ + MIPS32_NOP, + /* end: */ + MIPS32_LW(11,0,15), /* sw $11,($15) */ + MIPS32_LW(10,0,15), /* sw $10,($15) */ + MIPS32_LW(9,0,15), /* sw $9,($15) */ + MIPS32_LW(8,0,15), /* sw $8,($15) */ + MIPS32_MFC0(15,31,0), /* move COP0 DeSave to $15 */ + MIPS32_NOP, + MIPS32_B(NEG16(31)), /* b start */ + MIPS32_NOP, + }; + + int retval; + int blocksize; + int bytesread; + u32 param_in[2]; + + bytesread = 0; + + while (count > 0) + { + blocksize = count; + if (count > 0x400) + blocksize = 0x400; + + param_in[0] = addr; + param_in[1] = blocksize; + + if ((retval = mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \ + sizeof(param_in)/sizeof(param_in[0]), param_in, blocksize, &buf[bytesread], 1)) != ERROR_OK) + return retval; + + count -= blocksize; + addr += blocksize; + bytesread += blocksize; + } + + return retval; +} + +int mips32_pracc_read_mem16(mips_ejtag_t *ejtag_info, u32 addr, int count, u16 *buf) +{ + u32 code[] = { + /* start: */ + MIPS32_MTC0(15,31,0), /* move $15 to COP0 DeSave */ + MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */ + MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)), + MIPS32_SW(8,0,15), /* sw $8,($15) */ + MIPS32_SW(9,0,15), /* sw $9,($15) */ + MIPS32_SW(10,0,15), /* sw $10,($15) */ + MIPS32_SW(11,0,15), /* sw $10,($15) */ + + MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)), /* $8 = MIPS32_PRACC_PARAM_IN */ + MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)), + MIPS32_LW(9,0,8), /* $9=mem[$8]; read addr */ + MIPS32_LW(10,4,8), /* $10=mem[$8+4]; read count */ + MIPS32_LUI(11,UPPER16(MIPS32_PRACC_PARAM_OUT)), /* $11=MIPS32_PRACC_PARAM_OUT */ + MIPS32_ORI(11,11,LOWER16(MIPS32_PRACC_PARAM_OUT)), + MIPS32_NOP, + /* loop: */ + MIPS32_BEQ(0,10,9), /* beq 0, $10, end */ + MIPS32_NOP, + + MIPS32_LHU(12,0,9), /* lw $12,0($9), Load $12 with the halfword @mem[$9] */ + MIPS32_SW(12,0,11), /* sw $12,0($11) */ + + MIPS32_ADDI(10,10,NEG16(1)), /* $10-- */ + MIPS32_ADDI(9,9,2), /* $9+=2 */ + MIPS32_ADDI(11,11,4), /* $11+=4 */ + MIPS32_NOP, + MIPS32_B(NEG16(9)), /* b loop */ + MIPS32_NOP, + + MIPS32_LW(11,0,15), /* sw $11,($15) */ + MIPS32_LW(10,0,15), /* sw $10,($15) */ + MIPS32_LW(9,0,15), /* sw $9,($15) */ + MIPS32_LW(8,0,15), /* sw $8,($15) */ + MIPS32_MFC0(15,31,0), /* move COP0 DeSave to $15 */ + MIPS32_NOP, + MIPS32_B(NEG16(31)), /* b start */ + MIPS32_NOP, + }; + +// /* TODO remove array */ + u32 param_out[count]; + int i; + +// int retval; + int blocksize; + int bytesread; + u32 param_in[2]; + + bytesread = 0; + + //while (count > 0) + { + blocksize = count; + if (count > 0x400) + blocksize = 0x400; + + param_in[0] = addr; + param_in[1] = blocksize; + + mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \ + sizeof(param_in)/sizeof(param_in[0]), param_in, count, param_out, 1); + +// count -= blocksize; +// addr += blocksize; +// bytesread += blocksize; + } + + for (i = 0; i < count; i++) + { + buf[i] = param_out[i]; + } + + return ERROR_OK; +} + +int mips32_pracc_read_mem8(mips_ejtag_t *ejtag_info, u32 addr, int count, u8 *buf) +{ + u32 code[] = { + /* start: */ + MIPS32_MTC0(15,31,0), /* move $15 to COP0 DeSave */ + MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */ + MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)), + MIPS32_SW(8,0,15), /* sw $8,($15) */ + MIPS32_SW(9,0,15), /* sw $9,($15) */ + MIPS32_SW(10,0,15), /* sw $10,($15) */ + MIPS32_SW(11,0,15), /* sw $10,($15) */ + + MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)), /* $8 = MIPS32_PRACC_PARAM_IN */ + MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)), + MIPS32_LW(9,0,8), /* $9=mem[$8]; read addr */ + MIPS32_LW(10,4,8), /* $10=mem[$8+4]; read count */ + MIPS32_LUI(11,UPPER16(MIPS32_PRACC_PARAM_OUT)), /* $11=MIPS32_PRACC_PARAM_OUT */ + MIPS32_ORI(11,11,LOWER16(MIPS32_PRACC_PARAM_OUT)), + MIPS32_NOP, + /* loop: */ + MIPS32_BEQ(0,10,9), /* beq 0, $10, end */ + MIPS32_NOP, + + MIPS32_LBU(12,0,9), /* lw $12,0($9), Load t4 with the byte @mem[t1] */ + MIPS32_SW(12,0,11), /* sw $12,0($11) */ + + MIPS32_ADDI(10,10,NEG16(1)), /* $10-- */ + MIPS32_ADDI(9,9,1), /* $9+=1 */ + MIPS32_ADDI(11,11,4), /* $11+=4 */ + MIPS32_NOP, + MIPS32_B(NEG16(9)), /* b loop */ + MIPS32_NOP, + /* end: */ + MIPS32_LW(11,0,15), /* sw $11,($15) */ + MIPS32_LW(10,0,15), /* sw $10,($15) */ + MIPS32_LW(9,0,15), /* sw $9,($15) */ + MIPS32_LW(8,0,15), /* sw $8,($15) */ + MIPS32_MFC0(15,31,0), /* move COP0 DeSave to $15 */ + MIPS32_NOP, + MIPS32_B(NEG16(31)), /* b start */ + MIPS32_NOP, + }; + +// /* TODO remove array */ + u32 param_out[count]; + int i; + +// int retval; + int blocksize; + int bytesread; + u32 param_in[2]; + + bytesread = 0; + +// while (count > 0) + { + blocksize = count; + if (count > 0x400) + blocksize = 0x400; + + param_in[0] = addr; + param_in[1] = blocksize; + + mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \ + sizeof(param_in)/sizeof(param_in[0]), param_in, count, param_out, 1); + +// count -= blocksize; +// addr += blocksize; +// bytesread += blocksize; + } + + for (i = 0; i < count; i++) + { + buf[i] = param_out[i]; + } + + return ERROR_OK; +} + +int mips32_pracc_write_mem(mips_ejtag_t *ejtag_info, u32 addr, int size, int count, void *buf) +{ + switch (size) + { + case 1: + return mips32_pracc_write_mem8(ejtag_info, addr, count, (u8*)buf); + case 2: + return mips32_pracc_write_mem16(ejtag_info, addr, count,(u16*)buf); + case 4: + return mips32_pracc_write_mem32(ejtag_info, addr, count, (u32*)buf); + } + + return ERROR_OK; +} + +int mips32_pracc_write_mem32(mips_ejtag_t *ejtag_info, u32 addr, int count, u32 *buf) +{ + u32 code[] = { + /* start: */ + MIPS32_MTC0(15,31,0), /* move $15 to COP0 DeSave */ + MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */ + MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)), + MIPS32_SW(8,0,15), /* sw $8,($15) */ + MIPS32_SW(9,0,15), /* sw $9,($15) */ + MIPS32_SW(10,0,15), /* sw $10,($15) */ + MIPS32_SW(11,0,15), /* sw $10,($15) */ + + MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)), /* $8 = MIPS32_PRACC_PARAM_IN */ + MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)), + MIPS32_LW(9,0,8), /* Load write addr to $9 */ + MIPS32_LW(10,4,8), /* Load write count to $10 */ + MIPS32_ADDI(8,8,8), /* $8+=8 */ + MIPS32_NOP, + /* loop: */ + MIPS32_BEQ(0,10,9), /* beq $0, $10, end */ + MIPS32_NOP, + + MIPS32_LW(11,0,8), /* lw $11,0($8), Load $11 with the word @mem[$8] */ + MIPS32_SW(11,0,9), /* sw $11,0($9) */ + + MIPS32_ADDI(10,10,NEG16(1)), /* $10-- */ + MIPS32_ADDI(9,9,4), /* $9+=4 */ + MIPS32_ADDI(8,8,4), /* $8+=4 */ + MIPS32_NOP, + MIPS32_B(NEG16(9)), /* b loop */ + MIPS32_NOP, + /* end: */ + MIPS32_LW(11,0,15), /* sw $11,($15) */ + MIPS32_LW(10,0,15), /* sw $10,($15) */ + MIPS32_LW(9,0,15), /* sw $9,($15) */ + MIPS32_LW(8,0,15), /* sw $8,($15) */ + MIPS32_MFC0(15,31,0), /* move COP0 DeSave to $15 */ + MIPS32_NOP, + MIPS32_B(NEG16(30)), /* b start */ + MIPS32_NOP, + }; + + /* TODO remove array */ + u32 param_in[count+2]; + param_in[0] = addr; + param_in[1] = count; + + memcpy(¶m_in[2], buf, count * sizeof(u32)); + + mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \ + sizeof(param_in)/sizeof(param_in[0]),param_in, 0, NULL, 1); + + return ERROR_OK; +} + +int mips32_pracc_write_mem16(mips_ejtag_t *ejtag_info, u32 addr, int count, u16 *buf) +{ + u32 code[] = { + /* start: */ + MIPS32_MTC0(15,31,0), /* move $15 to COP0 DeSave */ + MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */ + MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)), + MIPS32_SW(8,0,15), /* sw $8,($15) */ + MIPS32_SW(9,0,15), /* sw $9,($15) */ + MIPS32_SW(10,0,15), /* sw $10,($15) */ + MIPS32_SW(11,0,15), /* sw $10,($15) */ + + MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)), /* $8 = MIPS32_PRACC_PARAM_IN */ + MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)), + MIPS32_LW(9,0,8), /* Load write addr to $9 */ + MIPS32_LW(10,4,8), /* Load write count to $10 */ + MIPS32_ADDI(8,8,8), /* $8+=8 */ + MIPS32_NOP, + /* loop: */ + MIPS32_BEQ(0,10,9), /* beq $0, $10, end */ + MIPS32_NOP, + + MIPS32_LW(11,0,8), /* lw $11,0($8), Load $11 with the word @mem[$8] */ + MIPS32_SH(11,0,9), /* sh $11,0($9) */ + + MIPS32_ADDI(10,10,NEG16(1)), /* $10-- */ + MIPS32_ADDI(9,9,2), /* $9+=2 */ + MIPS32_ADDI(8,8,4), /* $8+=4 */ + + MIPS32_NOP, + MIPS32_B(NEG16(9)), /* b loop */ + MIPS32_NOP, + /* end: */ + MIPS32_LW(11,0,15), /* sw $11,($15) */ + MIPS32_LW(10,0,15), /* sw $10,($15) */ + MIPS32_LW(9,0,15), /* sw $9,($15) */ + MIPS32_LW(8,0,15), /* sw $8,($15) */ + MIPS32_MFC0(15,31,0), /* move COP0 DeSave to $15 */ + MIPS32_NOP, + MIPS32_B(NEG16(30)), /* b start */ + MIPS32_NOP, + }; + + /* TODO remove array */ + u32 param_in[count+2]; + int i; + param_in[0] = addr; + param_in[1] = count; + + for (i = 0; i < count; i++) + { + param_in[i+2] = buf[i]; + } + + mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \ + sizeof(param_in)/sizeof(param_in[0]), param_in, 0, NULL, 1); + + return ERROR_OK; +} + +int mips32_pracc_write_mem8(mips_ejtag_t *ejtag_info, u32 addr, int count, u8 *buf) +{ + u32 code[] = { + /* start: */ + MIPS32_MTC0(15,31,0), /* move $15 to COP0 DeSave */ + MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */ + MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)), + MIPS32_SW(8,0,15), /* sw $8,($15) */ + MIPS32_SW(9,0,15), /* sw $9,($15) */ + MIPS32_SW(10,0,15), /* sw $10,($15) */ + MIPS32_SW(11,0,15), /* sw $10,($15) */ + + MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)), /* $8 = MIPS32_PRACC_PARAM_IN */ + MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)), + MIPS32_LW(9,0,8), /* Load write addr to $9 */ + MIPS32_LW(10,4,8), /* Load write count to $10 */ + MIPS32_ADDI(8,8,8), /* $8+=8 */ + MIPS32_NOP, + /* loop: */ + MIPS32_BEQ(0,10,9), /* beq $0, $10, end */ + MIPS32_NOP, + + MIPS32_LW(11,0,8), /* lw $11,0($8), Load $11 with the word @mem[$8] */ + MIPS32_SB(11,0,9), /* sb $11,0($9) */ + + MIPS32_ADDI(10,10,NEG16(1)), /* $10-- */ + MIPS32_ADDI(9,9,1), /* $9+=1 */ + MIPS32_ADDI(8,8,4), /* $8+=4 */ + + MIPS32_NOP, + MIPS32_B(NEG16(9)), /* b loop */ + MIPS32_NOP, + /* end: */ + MIPS32_LW(11,0,15), /* sw $11,($15) */ + MIPS32_LW(10,0,15), /* sw $10,($15) */ + MIPS32_LW(9,0,15), /* sw $9,($15) */ + MIPS32_LW(8,0,15), /* sw $8,($15) */ + MIPS32_MFC0(15,31,0), /* move COP0 DeSave to $15 */ + MIPS32_NOP, + MIPS32_B(NEG16(30)), /* b start */ + MIPS32_NOP, + }; + + /* TODO remove array */ + u32 param_in[count+2]; + int retval; + int i; + param_in[0] = addr; + param_in[1] = count; + + for (i = 0; i < count; i++) + { + param_in[i+2] = buf[i]; + } + + retval = mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \ + sizeof(param_in)/sizeof(param_in[0]), param_in, 0, NULL, 1); + + return retval; +} + +int mips32_pracc_write_regs(mips_ejtag_t *ejtag_info, u32 *regs) +{ + /* TODO restore all core registers */ + + u32 code[] = { + /* start: */ + MIPS32_MTC0(2,31,0), /* move $2 to COP0 DeSave */ + MIPS32_LUI(2,UPPER16(MIPS32_PRACC_PARAM_IN)), /* $2 = MIPS32_PRACC_PARAM_IN */ + MIPS32_ORI(2,2,LOWER16(MIPS32_PRACC_PARAM_IN)), + /*MIPS32_LW(0,0*4,2),*/ /* lw $0,0*4($2) */ + MIPS32_LW(1,1*4,2), /* lw $1,1*4($2) */ + MIPS32_MFC0(2,31,0), /* move COP0 DeSave to $2 */ + + MIPS32_MTC0(1,31,0), /* move $1 to COP0 DeSave */ + MIPS32_LUI(1,UPPER16(MIPS32_PRACC_PARAM_IN)), /* $1 = MIPS32_PRACC_PARAM_IN */ + MIPS32_ORI(1,1,LOWER16(MIPS32_PRACC_PARAM_IN)), + MIPS32_LW(2,2*4,1), /* lw $2,2*4($1) */ + MIPS32_LW(3,3*4,1), /* lw $3,3*4($1) */ + MIPS32_LW(4,4*4,1), /* lw $4,4*4($1) */ + MIPS32_LW(5,5*4,1), /* lw $5,5*4($1) */ + MIPS32_LW(6,6*4,1), /* lw $6,6*4($1) */ + MIPS32_LW(7,7*4,1), /* lw $7,7*4($1) */ + MIPS32_LW(8,8*4,1), /* lw $8,8*4($1) */ + MIPS32_LW(9,9*4,1), /* lw $9,9*4($1) */ + MIPS32_LW(10,10*4,1), /* lw $10,10*4($1) */ + MIPS32_LW(11,11*4,1), /* lw $11,11*4($1) */ + MIPS32_LW(12,12*4,1), /* lw $12,12*4($1) */ + MIPS32_LW(13,13*4,1), /* lw $13,13*4($1) */ + MIPS32_LW(14,14*4,1), /* lw $14,14*4($1) */ + MIPS32_LW(15,15*4,1), /* lw $15,15*4($1) */ + MIPS32_LW(16,16*4,1), /* lw $16,16*4($1) */ + MIPS32_LW(17,17*4,1), /* lw $17,17*4($1) */ + MIPS32_LW(18,18*4,1), /* lw $18,18*4($1) */ + MIPS32_LW(19,19*4,1), /* lw $19,19*4($1) */ + MIPS32_LW(20,20*4,1), /* lw $20,20*4($1) */ + MIPS32_LW(21,21*4,1), /* lw $21,21*4($1) */ + MIPS32_LW(22,22*4,1), /* lw $22,22*4($1) */ + MIPS32_LW(23,23*4,1), /* lw $23,23*4($1) */ + MIPS32_LW(24,24*4,1), /* lw $24,24*4($1) */ + MIPS32_LW(25,25*4,1), /* lw $25,25*4($1) */ + MIPS32_LW(26,26*4,1), /* lw $26,26*4($1) */ + MIPS32_LW(27,27*4,1), /* lw $27,27*4($1) */ + MIPS32_LW(28,28*4,1), /* lw $28,28*4($1) */ + MIPS32_LW(29,29*4,1), /* lw $29,29*4($1) */ + MIPS32_LW(30,30*4,1), /* lw $30,30*4($1) */ + MIPS32_LW(31,31*4,1), /* lw $31,31*4($1) */ + + MIPS32_MFC0(1,31,0), /* move COP0 DeSave to $1 */ + MIPS32_NOP, + MIPS32_B(NEG16(41)), /* b start */ + MIPS32_NOP, + }; + + int retval; + + retval = mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \ + 32, regs, 0, NULL, 1); + + return retval; +} + +int mips32_pracc_read_regs(mips_ejtag_t *ejtag_info, u32 *regs) +{ + u32 code[] = { + /* start: */ + MIPS32_MTC0(2,31,0), /* move $2 to COP0 DeSave */ + MIPS32_LUI(2,UPPER16(MIPS32_PRACC_PARAM_OUT)), /* $2 = MIPS32_PRACC_PARAM_OUT */ + MIPS32_ORI(2,2,LOWER16(MIPS32_PRACC_PARAM_OUT)), + MIPS32_SW(0,0*4,2), /* sw $0,0*4($2) */ + MIPS32_SW(1,1*4,2), /* sw $1,1*4($2) */ + MIPS32_SW(15,15*4,2), /* sw $15,15*4($2) */ + MIPS32_MFC0(2,31,0), /* move COP0 DeSave to $2 */ + MIPS32_MTC0(15,31,0), /* move $15 to COP0 DeSave */ + MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */ + MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)), + MIPS32_SW(1,0,15), /* sw $1,($15) */ + MIPS32_SW(2,0,15), /* sw $2,($15) */ + MIPS32_LUI(1,UPPER16(MIPS32_PRACC_PARAM_OUT)), /* $1 = MIPS32_PRACC_PARAM_OUT */ + MIPS32_ORI(1,1,LOWER16(MIPS32_PRACC_PARAM_OUT)), + MIPS32_SW(2,2*4,1), /* sw $2,2*4($1) */ + MIPS32_SW(3,3*4,1), /* sw $3,3*4($1) */ + MIPS32_SW(4,4*4,1), /* sw $4,4*4($1) */ + MIPS32_SW(5,5*4,1), /* sw $5,5*4($1) */ + MIPS32_SW(6,6*4,1), /* sw $6,6*4($1) */ + MIPS32_SW(7,7*4,1), /* sw $7,7*4($1) */ + MIPS32_SW(8,8*4,1), /* sw $8,8*4($1) */ + MIPS32_SW(9,9*4,1), /* sw $9,9*4($1) */ + MIPS32_SW(10,10*4,1), /* sw $10,10*4($1) */ + MIPS32_SW(11,11*4,1), /* sw $11,11*4($1) */ + MIPS32_SW(12,12*4,1), /* sw $12,12*4($1) */ + MIPS32_SW(13,13*4,1), /* sw $13,13*4($1) */ + MIPS32_SW(14,14*4,1), /* sw $14,14*4($1) */ + MIPS32_SW(16,16*4,1), /* sw $16,16*4($1) */ + MIPS32_SW(17,17*4,1), /* sw $17,17*4($1) */ + MIPS32_SW(18,18*4,1), /* sw $18,18*4($1) */ + MIPS32_SW(19,19*4,1), /* sw $19,19*4($1) */ + MIPS32_SW(20,20*4,1), /* sw $20,20*4($1) */ + MIPS32_SW(21,21*4,1), /* sw $21,21*4($1) */ + MIPS32_SW(22,22*4,1), /* sw $22,22*4($1) */ + MIPS32_SW(23,23*4,1), /* sw $23,23*4($1) */ + MIPS32_SW(24,24*4,1), /* sw $24,24*4($1) */ + MIPS32_SW(25,25*4,1), /* sw $25,25*4($1) */ + MIPS32_SW(26,26*4,1), /* sw $26,26*4($1) */ + MIPS32_SW(27,27*4,1), /* sw $27,27*4($1) */ + MIPS32_SW(28,28*4,1), /* sw $28,28*4($1) */ + MIPS32_SW(29,29*4,1), /* sw $29,29*4($1) */ + MIPS32_SW(30,30*4,1), /* sw $30,30*4($1) */ + MIPS32_SW(31,31*4,1), /* sw $31,31*4($1) */ + + MIPS32_MFC0(2,12,0), /* move status to $2 */ + MIPS32_SW(2,32*4,1), /* sw $2,32*4($1) */ + MIPS32_LO(2), /* move lo to $2 */ + MIPS32_SW(2,33*4,1), /* sw $2,33*4($1) */ + MIPS32_HI(2), /* move hi to $2 */ + MIPS32_SW(2,34*4,1), /* sw $2,34*4($1) */ + MIPS32_MFC0(2,8,0), /* move badvaddr to $2 */ + MIPS32_SW(2,35*4,1), /* sw $2,35*4($1) */ + MIPS32_MFC0(2,13,0), /* move cause to $2 */ + MIPS32_SW(2,36*4,1), /* sw $2,36*4($1) */ + MIPS32_MFC0(2,24,0), /* move pc to $2 */ + MIPS32_SW(2,37*4,1), /* sw $2,37*4($1) */ + + MIPS32_LW(2,0,15), /* sw $2,($15) */ + MIPS32_LW(1,0,15), /* sw $1,($15) */ + MIPS32_MFC0(15,31,0), /* move COP0 DeSave to $15 */ + MIPS32_NOP, + MIPS32_B(NEG16(60)), /* b start */ + MIPS32_NOP, + }; + + int retval; + + retval = mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \ + 0, NULL, 38, regs, 1); + + return retval; +} diff --git a/src/target/mips32_pracc.h b/src/target/mips32_pracc.h new file mode 100644 index 0000000000..5cda497d33 --- /dev/null +++ b/src/target/mips32_pracc.h @@ -0,0 +1,55 @@ +/*************************************************************************** + * Copyright (C) 2008 by Spencer Oliver * + * spen@spen-soft.co.uk * + * * + * Copyright (C) 2008 by David T.L. Wong * + * * + * This program 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 of the License, or * + * (at your option) any later version. * + * * + * This program 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 this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef MIPS32_PRACC_H +#define MIPS32_PRACC_H + +#include "mips_ejtag.h" + +#define MIPS32_PRACC_TEXT 0xFF200200 +#define MIPS32_PRACC_STACK 0xFF2FFFFC +#define MIPS32_PRACC_PARAM_IN 0xFF201000 +#define MIPS32_PRACC_PARAM_IN_SIZE 0x1000 +#define MIPS32_PRACC_PARAM_OUT (MIPS32_PRACC_PARAM_IN + MIPS32_PRACC_PARAM_IN_SIZE) +#define MIPS32_PRACC_PARAM_OUT_SIZE 0x1000 + +#define UPPER16(u32) (u32 >> 16) +#define LOWER16(u32) (u32 & 0xFFFF) +#define NEG16(v) (((~(v)) + 1) & 0xFFFF) +//#define NEG18(v) ( ((~(v)) + 1) & 0x3FFFF ) + +extern int mips32_pracc_read_mem(mips_ejtag_t *ejtag_info, u32 addr, int size, int count, void *buf); +extern int mips32_pracc_write_mem(mips_ejtag_t *ejtag_info, u32 addr, int size, int count, void *buf); + +extern int mips32_pracc_read_mem8(mips_ejtag_t *ejtag_info, u32 addr, int count, u8 *buf); +extern int mips32_pracc_read_mem16(mips_ejtag_t *ejtag_info, u32 addr, int count, u16 *buf); +extern int mips32_pracc_read_mem32(mips_ejtag_t *ejtag_info, u32 addr, int count, u32 *buf); + +extern int mips32_pracc_write_mem8(mips_ejtag_t *ejtag_info, u32 addr, int count, u8 *buf); +extern int mips32_pracc_write_mem16(mips_ejtag_t *ejtag_info, u32 addr, int count, u16 *buf); +extern int mips32_pracc_write_mem32(mips_ejtag_t *ejtag_info, u32 addr, int count, u32 *buf); + +extern int mips32_pracc_read_regs(mips_ejtag_t *ejtag_info, u32 *regs); +extern int mips32_pracc_write_regs(mips_ejtag_t *ejtag_info, u32 *regs); + +extern int mips32_pracc_exec( mips_ejtag_t *ejtag_info, int code_len, u32 *code, int num_param_in, u32 *param_in, int num_param_out, u32 *param_out, int cycle); + +#endif diff --git a/src/target/mips_ejtag.c b/src/target/mips_ejtag.c new file mode 100644 index 0000000000..d22036859c --- /dev/null +++ b/src/target/mips_ejtag.c @@ -0,0 +1,283 @@ +/*************************************************************************** + * Copyright (C) 2008 by Spencer Oliver * + * spen@spen-soft.co.uk * + * * + * Copyright (C) 2008 by David T.L. Wong * + * * + * This program 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 of the License, or * + * (at your option) any later version. * + * * + * This program 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 this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "mips32.h" +#include "mips_ejtag.h" + +#include "binarybuffer.h" +#include "log.h" +#include "jtag.h" + +#include + +int mips_ejtag_set_instr(mips_ejtag_t *ejtag_info, int new_instr, in_handler_t handler) +{ + jtag_device_t *device = jtag_get_device(ejtag_info->chain_pos); + + if (buf_get_u32(device->cur_instr, 0, device->ir_length) != new_instr) + { + scan_field_t field; + u8 t[4]; + + field.device = ejtag_info->chain_pos; + field.num_bits = device->ir_length; + field.out_value = t; + buf_set_u32(field.out_value, 0, field.num_bits, new_instr); + field.out_mask = NULL; + field.in_value = NULL; + field.in_check_value = NULL; + field.in_check_mask = NULL; + field.in_handler = handler; + field.in_handler_priv = NULL; + jtag_add_ir_scan(1, &field, -1); + } + + return ERROR_OK; +} + +int mips_ejtag_get_idcode(mips_ejtag_t *ejtag_info, u32 *idcode, in_handler_t handler) +{ + scan_field_t field; + + jtag_add_end_state(TAP_RTI); + + mips_ejtag_set_instr(ejtag_info, EJTAG_INST_IDCODE, NULL); + + field.device = ejtag_info->chain_pos; + field.num_bits = 32; + field.out_value = NULL; + field.out_mask = NULL; + field.in_value = (void*)idcode; + field.in_check_value = NULL; + field.in_check_mask = NULL; + field.in_handler = NULL; + field.in_handler_priv = NULL; + jtag_add_dr_scan(1, &field, -1); + + if (jtag_execute_queue() != ERROR_OK) + { + LOG_ERROR("register read failed"); + } + + return ERROR_OK; +} + +int mips_ejtag_get_impcode(mips_ejtag_t *ejtag_info, u32 *impcode, in_handler_t handler) +{ + scan_field_t field; + + jtag_add_end_state(TAP_RTI); + + mips_ejtag_set_instr(ejtag_info, EJTAG_INST_IMPCODE, NULL); + + field.device = ejtag_info->chain_pos; + field.num_bits = 32; + field.out_value = NULL; + field.out_mask = NULL; + field.in_value = (void*)impcode; + field.in_check_value = NULL; + field.in_check_mask = NULL; + field.in_handler = NULL; + field.in_handler_priv = NULL; + jtag_add_dr_scan(1, &field, -1); + + if (jtag_execute_queue() != ERROR_OK) + { + LOG_ERROR("register read failed"); + } + + return ERROR_OK; +} + +int mips_ejtag_drscan_32(mips_ejtag_t *ejtag_info, u32 *data) +{ + jtag_device_t *device; + device = jtag_get_device(ejtag_info->chain_pos); + scan_field_t field; + u8 t[4]; + int retval; + + field.device = ejtag_info->chain_pos; + field.num_bits = 32; + field.out_value = t; + buf_set_u32(field.out_value, 0, field.num_bits, *data); + field.out_mask = NULL; + field.in_value = (u8*)data; + field.in_check_value = NULL; + field.in_check_mask = NULL; + field.in_handler = NULL; + field.in_handler_priv = NULL; + jtag_add_dr_scan(1, &field, -1); + + if ((retval = jtag_execute_queue()) != ERROR_OK) + { + LOG_ERROR("register read failed"); + return retval; + } + + return ERROR_OK; +} + +int mips_ejtag_step_enable(mips_ejtag_t *ejtag_info) +{ + u32 code[] = { + MIPS32_MTC0(1,31,0), /* move $1 to COP0 DeSave */ + MIPS32_MFC0(1,23,0), /* move COP0 Debug to $1 */ + MIPS32_ORI(1,1,0x0100), /* set SSt bit in debug reg */ + MIPS32_MTC0(1,23,0), /* move $1 to COP0 Debug */ + MIPS32_MFC0(1,31,0), /* move COP0 DeSave to $1 */ + MIPS32_NOP, + MIPS32_B(NEG16(7)), + MIPS32_NOP, + }; + + mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \ + 0, NULL, 0, NULL, 1); + + return ERROR_OK; +} +int mips_ejtag_step_disable(mips_ejtag_t *ejtag_info) +{ + u32 code[] = { + MIPS32_MTC0(15,31,0), /* move $15 to COP0 DeSave */ + MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */ + MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)), + MIPS32_SW(1,0,15), /* sw $2,($15) */ + MIPS32_SW(2,0,15), /* sw $3,($15) */ + MIPS32_MFC0(1,23,0), /* move COP0 Debug to $1 */ + MIPS32_LUI(2,0xFFFF), /* $2 = 0xfffffeff */ + MIPS32_ORI(2,2,0xFEFF), + MIPS32_AND(1,1,2), + MIPS32_MTC0(1,23,0), /* move $1 to COP0 Debug */ + MIPS32_LW(2,0,15), + MIPS32_LW(1,0,15), + MIPS32_MFC0(15,31,0), /* move COP0 DeSave to $15 */ + MIPS32_NOP, + MIPS32_B(NEG16(15)), + MIPS32_NOP, + }; + + mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \ + 0, NULL, 0, NULL, 1); + + return ERROR_OK; +} + +int mips_ejtag_config_step(mips_ejtag_t *ejtag_info, int enable_step) +{ + if (enable_step) + return mips_ejtag_step_enable(ejtag_info); + return mips_ejtag_step_disable(ejtag_info); +} + +int mips_ejtag_enter_debug(mips_ejtag_t *ejtag_info) +{ + jtag_add_end_state(TAP_RTI); + mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL, NULL); + + /* set debug break bit */ + ejtag_info->ejtag_ctrl = EJTAG_CTRL_ROCC | EJTAG_CTRL_PRACC | EJTAG_CTRL_PROBEN | EJTAG_CTRL_SETDEV | EJTAG_CTRL_JTAGBRK; + mips_ejtag_drscan_32(ejtag_info, &ejtag_info->ejtag_ctrl); + + /* break bit will be cleared by hardware */ + ejtag_info->ejtag_ctrl = EJTAG_CTRL_ROCC | EJTAG_CTRL_PRACC | EJTAG_CTRL_PROBEN | EJTAG_CTRL_SETDEV; + mips_ejtag_drscan_32(ejtag_info, &ejtag_info->ejtag_ctrl); + + return ERROR_OK; +} + +int mips_ejtag_exit_debug(mips_ejtag_t *ejtag_info, int enable_interrupts) +{ + u32 inst; + inst = MIPS32_DRET; + + /* TODO : enable/disable interrrupts */ + + /* execute our dret instruction */ + mips32_pracc_exec(ejtag_info, 1, &inst, 0, NULL, 0, NULL, 0); + + return ERROR_OK; +} + +int mips_ejtag_read_debug(mips_ejtag_t *ejtag_info, u32* debug_reg) +{ + u32 code[] = { + MIPS32_MTC0(15,31,0), /* move $15 to COP0 DeSave */ + MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */ + MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)), + MIPS32_SW(1,0,15), /* sw $1,($15) */ + MIPS32_SW(2,0,15), /* sw $2,($15) */ + MIPS32_LUI(1,UPPER16(MIPS32_PRACC_PARAM_OUT)), /* $1 = MIPS32_PRACC_PARAM_OUT */ + MIPS32_ORI(1,1,LOWER16(MIPS32_PRACC_PARAM_OUT)), + MIPS32_MFC0(2,23,0), /* move COP0 Debug to $1 */ + MIPS32_SW(2,0,1), + MIPS32_LW(2,0,15), + MIPS32_LW(1,0,15), + MIPS32_MFC0(15,31,0), /* move COP0 DeSave to $15 */ + MIPS32_NOP, + MIPS32_B(NEG16(14)), + MIPS32_NOP, + }; + + mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \ + 0, NULL, 1, debug_reg, 1); + + return ERROR_OK; +} + +int mips_ejtag_init(mips_ejtag_t *ejtag_info) +{ + u32 ejtag_version; + + mips_ejtag_get_impcode(ejtag_info, &ejtag_info->impcode, NULL); + LOG_DEBUG("impcode: 0x%8.8x", ejtag_info->impcode); + + /* get ejtag version */ + ejtag_version = ((ejtag_info->impcode >> 29) & 0x07); + + switch (ejtag_version) + { + case 0: + LOG_DEBUG("EJTAG: Version 1 or 2.0 Detected"); + break; + case 1: + LOG_DEBUG("EJTAG: Version 2.5 Detected"); + break; + case 2: + LOG_DEBUG("EJTAG: Version 2.6 Detected"); + break; + case 3: + LOG_DEBUG("EJTAG: Version 3.1 Detected"); + break; + default: + LOG_DEBUG("EJTAG: Unknown Version Detected"); + break; + } + + /* set initial state for ejtag control reg */ + ejtag_info->ejtag_ctrl = EJTAG_CTRL_ROCC | EJTAG_CTRL_PRACC | EJTAG_CTRL_PROBEN | EJTAG_CTRL_SETDEV; + + return ERROR_OK; +} diff --git a/src/target/mips_ejtag.h b/src/target/mips_ejtag.h new file mode 100644 index 0000000000..b25bd02652 --- /dev/null +++ b/src/target/mips_ejtag.h @@ -0,0 +1,107 @@ +/*************************************************************************** + * Copyright (C) 2008 by Spencer Oliver * + * spen@spen-soft.co.uk * + * * + * Copyright (C) 2008 by David T.L. Wong * + * * + * This program 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 of the License, or * + * (at your option) any later version. * + * * + * This program 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 this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef MIPS_EJTAG +#define MIPS_EJTAG + +#include "types.h" +#include "jtag.h" + +#define EJTAG_INST_IDCODE 0x01 +#define EJTAG_INST_IMPCODE 0x03 +#define EJTAG_INST_ADDRESS 0x08 +#define EJTAG_INST_DATA 0x09 +#define EJTAG_INST_CONTROL 0x0A +#define EJTAG_INST_ALL 0x0B +#define EJTAG_INST_EJTAGBOOT 0x0C +#define EJTAG_INST_NORMALBOOT 0x0D +#define EJTAG_INST_FASTDATA 0x0E +#define EJTAG_INST_TCBCONTROLA 0x10 +#define EJTAG_INST_TCBCONTROLB 0x11 +#define EJTAG_INST_TCBDATA 0x12 +#define EJTAG_INST_BYPASS 0x1F + +#define EJTAG_CTRL_TOF (1 << 1) +#define EJTAG_CTRL_TIF (1 << 2) +#define EJTAG_CTRL_BRKST (1 << 3) +#define EJTAG_CTRL_DLOCK (1 << 5) +#define EJTAG_CTRL_DRWN (1 << 9) +#define EJTAG_CTRL_DERR (1 << 10) +#define EJTAG_CTRL_DSTRT (1 << 11) +#define EJTAG_CTRL_JTAGBRK (1 << 12) +#define EJTAG_CTRL_SETDEV (1 << 14) +#define EJTAG_CTRL_PROBEN (1 << 15) +#define EJTAG_CTRL_PRRST (1 << 16) +#define EJTAG_CTRL_DMAACC (1 << 17) +#define EJTAG_CTRL_PRACC (1 << 18) +#define EJTAG_CTRL_PRNW (1 << 19) +#define EJTAG_CTRL_PERRST (1 << 20) +#define EJTAG_CTRL_SYNC (1 << 23) +#define EJTAG_CTRL_DNM (1 << 28) +#define EJTAG_CTRL_ROCC (1 << 31) + +/* Debug Register (CP0 Register 23, Select 0) */ + +#define EJTAG_DEBUG_DSS (1 << 0) +#define EJTAG_DEBUG_DBP (1 << 1) +#define EJTAG_DEBUG_DDBL (1 << 2) +#define EJTAG_DEBUG_DDBS (1 << 3) +#define EJTAG_DEBUG_DIB (1 << 4) +#define EJTAG_DEBUG_DINT (1 << 5) +#define EJTAG_DEBUG_OFFLINE (1 << 7) +#define EJTAG_DEBUG_SST (1 << 8) +#define EJTAG_DEBUG_NOSST (1 << 9) +#define EJTAG_DEBUG_DDBLIMPR (1 << 18) +#define EJTAG_DEBUG_DDBSIMPR (1 << 19) +#define EJTAG_DEBUG_IEXI (1 << 20) +#define EJTAG_DEBUG_DBUSEP (1 << 21) +#define EJTAG_DEBUG_CACHEEP (1 << 22) +#define EJTAG_DEBUG_MCHECKP (1 << 23) +#define EJTAG_DEBUG_IBUSEP (1 << 24) +#define EJTAG_DEBUG_COUNTDM (1 << 25) +#define EJTAG_DEBUG_HALT (1 << 26) +#define EJTAG_DEBUG_DOZE (1 << 27) +#define EJTAG_DEBUG_LSNM (1 << 28) +#define EJTAG_DEBUG_NODCR (1 << 29) +#define EJTAG_DEBUG_DM (1 << 30) +#define EJTAG_DEBUG_DBD (1 << 31) + +typedef struct mips_ejtag_s +{ + int chain_pos; + u32 impcode; +// int use_dma; + u32 ejtag_ctrl; +} mips_ejtag_t; + +extern int mips_ejtag_set_instr(mips_ejtag_t *ejtag_info, int new_instr, in_handler_t handler); +extern int mips_ejtag_enter_debug(mips_ejtag_t *ejtag_info); +extern int mips_ejtag_exit_debug(mips_ejtag_t *ejtag_info, int enable_interrupts); +extern int mips_ejtag_get_impcode(mips_ejtag_t *ejtag_info, u32 *impcode, in_handler_t handler); +extern int mips_ejtag_get_idcode(mips_ejtag_t *ejtag_info, u32 *idcode, in_handler_t handler); +extern int mips_ejtag_drscan_32(mips_ejtag_t *ejtag_info, u32 *data); + +extern int mips_ejtag_init(mips_ejtag_t *ejtag_info); +extern int mips_ejtag_config_step(mips_ejtag_t *ejtag_info, int enable_step); +extern int mips_ejtag_read_debug(mips_ejtag_t *ejtag_info, u32* debug_reg); + +#endif /* MIPS_EJTAG */ diff --git a/src/target/mips_m4k.c b/src/target/mips_m4k.c new file mode 100644 index 0000000000..8695a6269b --- /dev/null +++ b/src/target/mips_m4k.c @@ -0,0 +1,642 @@ +/*************************************************************************** + * Copyright (C) 2008 by Spencer Oliver * + * spen@spen-soft.co.uk * + * * + * Copyright (C) 2008 by David T.L. Wong * + * * + * This program 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 of the License, or * + * (at your option) any later version. * + * * + * This program 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 this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "mips32.h" +#include "mips_m4k.h" +#include "jtag.h" +#include "log.h" + +#include +#include + +/* cli handling */ + +/* forward declarations */ +int mips_m4k_poll(target_t *target); +int mips_m4k_halt(struct target_s *target); +int mips_m4k_soft_reset_halt(struct target_s *target); +int mips_m4k_resume(struct target_s *target, int current, u32 address, int handle_breakpoints, int debug_execution); +int mips_m4k_step(struct target_s *target, int current, u32 address, int handle_breakpoints); +int mips_m4k_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer); +int mips_m4k_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer); +int mips_m4k_register_commands(struct command_context_s *cmd_ctx); +int mips_m4k_init_target(struct command_context_s *cmd_ctx, struct target_s *target); +int mips_m4k_quit(); +int mips_m4k_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target); + +int mips_m4k_examine(struct command_context_s *cmd_ctx, struct target_s *target); +int mips_m4k_assert_reset(target_t *target); +int mips_m4k_deassert_reset(target_t *target); + +target_type_t mips_m4k_target = +{ + .name = "mips_m4k", + + .poll = mips_m4k_poll, + .arch_state = mips32_arch_state, + + .target_request_data = NULL, + + .halt = mips_m4k_halt, + .resume = mips_m4k_resume, + .step = mips_m4k_step, + + .assert_reset = mips_m4k_assert_reset, + .deassert_reset = mips_m4k_deassert_reset, + .soft_reset_halt = mips_m4k_soft_reset_halt, + + .get_gdb_reg_list = mips32_get_gdb_reg_list, + + .read_memory = mips_m4k_read_memory, + .write_memory = mips_m4k_write_memory, + .bulk_write_memory = mips_m4k_bulk_write_memory, + .checksum_memory = NULL, + .blank_check_memory = NULL, + + .run_algorithm = mips32_run_algorithm, + + .add_breakpoint = mips_m4k_add_breakpoint, + .remove_breakpoint = mips_m4k_remove_breakpoint, + .add_watchpoint = mips_m4k_add_watchpoint, + .remove_watchpoint = mips_m4k_remove_watchpoint, + + .register_commands = mips_m4k_register_commands, + .target_command = mips_m4k_target_command, + .init_target = mips_m4k_init_target, + .examine = mips_m4k_examine, + .quit = mips_m4k_quit +}; + +int mips_m4k_debug_entry(target_t *target) +{ + u32 debug_reg; + mips32_common_t *mips32 = target->arch_info; + mips_ejtag_t *ejtag_info = &mips32->ejtag_info; + + /* read debug register */ + mips_ejtag_read_debug(ejtag_info, &debug_reg); + + if ((target->debug_reason != DBG_REASON_DBGRQ) + && (target->debug_reason != DBG_REASON_SINGLESTEP)) + { +// if (cortex_m3->nvic_dfsr & DFSR_BKPT) +// { +// target->debug_reason = DBG_REASON_BREAKPOINT; +// if (cortex_m3->nvic_dfsr & DFSR_DWTTRAP) +// target->debug_reason = DBG_REASON_WPTANDBKPT; +// } +// else if (cortex_m3->nvic_dfsr & DFSR_DWTTRAP) +// target->debug_reason = DBG_REASON_WATCHPOINT; + } + + if (debug_reg & EJTAG_DEBUG_DSS) + { + /* stopped due to single step - clear step bit */ + mips_ejtag_config_step(ejtag_info, 0); + } + + mips32_save_context(target); + + LOG_DEBUG("entered debug state at PC 0x%x, target->state: %s", \ + *(u32*)(mips32->core_cache->reg_list[MIPS32_PC].value), target_state_strings[target->state]); + + return ERROR_OK; +} + +int mips_m4k_poll(target_t *target) +{ + int retval; + mips32_common_t *mips32 = target->arch_info; + mips_ejtag_t *ejtag_info = &mips32->ejtag_info; + + /* read ejtag control reg */ + jtag_add_end_state(TAP_RTI); + mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL, NULL); + mips_ejtag_drscan_32(ejtag_info, &ejtag_info->ejtag_ctrl); + + if (ejtag_info->ejtag_ctrl & EJTAG_CTRL_BRKST) + { + if ((target->state == TARGET_RUNNING) || (target->state == TARGET_RESET)) + { + jtag_add_end_state(TAP_RTI); + mips_ejtag_set_instr(ejtag_info, EJTAG_INST_NORMALBOOT, NULL); + + target->state = TARGET_HALTED; + + if ((retval = mips_m4k_debug_entry(target)) != ERROR_OK) + return retval; + + target_call_event_callbacks(target, TARGET_EVENT_HALTED); + } + else if (target->state == TARGET_DEBUG_RUNNING) + { + target->state = TARGET_HALTED; + + if ((retval = mips_m4k_debug_entry(target)) != ERROR_OK) + return retval; + + target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED); + } + } + else + { + target->state = TARGET_RUNNING; + } + + if (ejtag_info->ejtag_ctrl & EJTAG_CTRL_ROCC) + { + /* we have detected a reset, clear flag + * otherwise ejtag will not work */ + jtag_add_end_state(TAP_RTI); + ejtag_info->ejtag_ctrl &= ~EJTAG_CTRL_ROCC; + + mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL, NULL); + mips_ejtag_drscan_32(ejtag_info, &ejtag_info->ejtag_ctrl); + LOG_DEBUG("Reset Detected"); + } + +// LOG_DEBUG("ctrl=0x%08X", ejtag_info->ejtag_ctrl); + + return ERROR_OK; +} + +int mips_m4k_halt(struct target_s *target) +{ + mips32_common_t *mips32 = target->arch_info; + mips_ejtag_t *ejtag_info = &mips32->ejtag_info; + + LOG_DEBUG("target->state: %s", target_state_strings[target->state]); + + if (target->state == TARGET_HALTED) + { + LOG_DEBUG("target was already halted"); + return ERROR_OK; + } + + if (target->state == TARGET_UNKNOWN) + { + LOG_WARNING("target was in unknown state when halt was requested"); + } + + if (target->state == TARGET_RESET) + { + if ((jtag_reset_config & RESET_SRST_PULLS_TRST) && jtag_srst) + { + LOG_ERROR("can't request a halt while in reset if nSRST pulls nTRST"); + return ERROR_TARGET_FAILURE; + } + else + { + /* we came here in a reset_halt or reset_init sequence + * debug entry was already prepared in mips32_prepare_reset_halt() + */ + target->debug_reason = DBG_REASON_DBGRQ; + + return ERROR_OK; + } + } + + /* break processor */ + mips_ejtag_enter_debug(ejtag_info); + + target->debug_reason = DBG_REASON_DBGRQ; + + return ERROR_OK; +} + +int mips_m4k_assert_reset(target_t *target) +{ + mips32_common_t *mips32 = target->arch_info; + mips_ejtag_t *ejtag_info = &mips32->ejtag_info; + + LOG_DEBUG("target->state: %s", target_state_strings[target->state]); + + if (!(jtag_reset_config & RESET_HAS_SRST)) + { + LOG_ERROR("Can't assert SRST"); + return ERROR_FAIL; + } + + if (target->reset_halt) + { + /* use hardware to catch reset */ + jtag_add_end_state(TAP_RTI); + mips_ejtag_set_instr(ejtag_info, EJTAG_INST_EJTAGBOOT, NULL); + } + else + { + jtag_add_end_state(TAP_RTI); + mips_ejtag_set_instr(ejtag_info, EJTAG_INST_NORMALBOOT, NULL); + } + + /* here we should issue a srst only, but we may have to assert trst as well */ + if (jtag_reset_config & RESET_SRST_PULLS_TRST) + { + jtag_add_reset(1, 1); + } + else + { + jtag_add_reset(0, 1); + } + + target->state = TARGET_RESET; + jtag_add_sleep(50000); + + mips32_invalidate_core_regs(target); + + return ERROR_OK; +} + +int mips_m4k_deassert_reset(target_t *target) +{ + LOG_DEBUG("target->state: %s", target_state_strings[target->state]); + + /* deassert reset lines */ + jtag_add_reset(0, 0); + + return ERROR_OK; +} + +int mips_m4k_soft_reset_halt(struct target_s *target) +{ + /* TODO */ + return ERROR_OK; +} + +int mips_m4k_resume(struct target_s *target, int current, u32 address, int handle_breakpoints, int debug_execution) +{ + mips32_common_t *mips32 = target->arch_info; + mips_ejtag_t *ejtag_info = &mips32->ejtag_info; + breakpoint_t *breakpoint = NULL; + u32 resume_pc; + + if (target->state != TARGET_HALTED) + { + LOG_WARNING("target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + if (!debug_execution) + { + target_free_all_working_areas(target); + mips_m4k_enable_breakpoints(target); + mips_m4k_enable_watchpoints(target); + } + + /* current = 1: continue on current pc, otherwise continue at
*/ + if (!current) + { + buf_set_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32, address); + mips32->core_cache->reg_list[MIPS32_PC].dirty = 1; + mips32->core_cache->reg_list[MIPS32_PC].valid = 1; + } + + resume_pc = buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32); + + mips32_restore_context(target); + + /* the front-end may request us not to handle breakpoints */ + if (handle_breakpoints) + { + /* Single step past breakpoint at current address */ + if ((breakpoint = breakpoint_find(target, resume_pc))) + { + LOG_DEBUG("unset breakpoint at 0x%8.8x", breakpoint->address); + mips_m4k_unset_breakpoint(target, breakpoint); + //mips_m4k_single_step_core(target); + mips_m4k_set_breakpoint(target, breakpoint); + } + } + + /* exit debug mode - enable interrupts if required */ + mips_ejtag_exit_debug(ejtag_info, !debug_execution); + + /* registers are now invalid */ + mips32_invalidate_core_regs(target); + + if (!debug_execution) + { + target->state = TARGET_RUNNING; + target_call_event_callbacks(target, TARGET_EVENT_RESUMED); + LOG_DEBUG("target resumed at 0x%x", resume_pc); + } + else + { + target->state = TARGET_DEBUG_RUNNING; + target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED); + LOG_DEBUG("target debug resumed at 0x%x", resume_pc); + } + + return ERROR_OK; +} + +int mips_m4k_step(struct target_s *target, int current, u32 address, int handle_breakpoints) +{ + /* get pointers to arch-specific information */ + mips32_common_t *mips32 = target->arch_info; + mips_ejtag_t *ejtag_info = &mips32->ejtag_info; + breakpoint_t *breakpoint = NULL; + + if (target->state != TARGET_HALTED) + { + LOG_WARNING("target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + /* current = 1: continue on current pc, otherwise continue at
*/ + if (!current) + buf_set_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32, address); + + /* the front-end may request us not to handle breakpoints */ + if (handle_breakpoints) + if ((breakpoint = breakpoint_find(target, buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32)))) + mips_m4k_unset_breakpoint(target, breakpoint); + + /* restore context */ + mips32_restore_context(target); + + /* configure single step mode */ + mips_ejtag_config_step(ejtag_info, 1); + + target->debug_reason = DBG_REASON_SINGLESTEP; + + target_call_event_callbacks(target, TARGET_EVENT_RESUMED); + + /* exit debug mode */ + mips_ejtag_exit_debug(ejtag_info, 1); + + /* registers are now invalid */ + mips32_invalidate_core_regs(target); + + if (breakpoint) + mips_m4k_set_breakpoint(target, breakpoint); + + LOG_DEBUG("target stepped "); + + mips_m4k_debug_entry(target); + target_call_event_callbacks(target, TARGET_EVENT_HALTED); + + return ERROR_OK; +} + +void mips_m4k_enable_breakpoints(struct target_s *target) +{ + breakpoint_t *breakpoint = target->breakpoints; + + /* set any pending breakpoints */ + while (breakpoint) + { + if (breakpoint->set == 0) + mips_m4k_set_breakpoint(target, breakpoint); + breakpoint = breakpoint->next; + } +} + +int mips_m4k_set_breakpoint(struct target_s *target, breakpoint_t *breakpoint) +{ + /* TODO */ + return ERROR_OK; +} + +int mips_m4k_unset_breakpoint(struct target_s *target, breakpoint_t *breakpoint) +{ + /* TODO */ + return ERROR_OK; +} + +int mips_m4k_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint) +{ + /* TODO */ + return ERROR_OK; +} + +int mips_m4k_remove_breakpoint(struct target_s *target, breakpoint_t *breakpoint) +{ + /* TODO */ + return ERROR_OK; +} + +int mips_m4k_set_watchpoint(struct target_s *target, watchpoint_t *watchpoint) +{ + /* TODO */ + return ERROR_OK; +} + +int mips_m4k_unset_watchpoint(struct target_s *target, watchpoint_t *watchpoint) +{ + /* TODO */ + return ERROR_OK; +} + +int mips_m4k_add_watchpoint(struct target_s *target, watchpoint_t *watchpoint) +{ + /* TODO */ + return ERROR_OK; +} + +int mips_m4k_remove_watchpoint(struct target_s *target, watchpoint_t *watchpoint) +{ + /* TODO */ + return ERROR_OK; +} + +void mips_m4k_enable_watchpoints(struct target_s *target) +{ + watchpoint_t *watchpoint = target->watchpoints; + + /* set any pending watchpoints */ + while (watchpoint) + { + if (watchpoint->set == 0) + mips_m4k_set_watchpoint(target, watchpoint); + watchpoint = watchpoint->next; + } +} + +int mips_m4k_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer) +{ + mips32_common_t *mips32 = target->arch_info; + mips_ejtag_t *ejtag_info = &mips32->ejtag_info; + + LOG_DEBUG("address: 0x%8.8x, size: 0x%8.8x, count: 0x%8.8x", address, size, count); + + if (target->state != TARGET_HALTED) + { + LOG_WARNING("target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + /* sanitize arguments */ + if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer)) + return ERROR_INVALID_ARGUMENTS; + + if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u))) + return ERROR_TARGET_UNALIGNED_ACCESS; + + switch (size) + { + case 4: + case 2: + case 1: + return mips32_pracc_read_mem(ejtag_info, address, size, count, (void *)buffer); + default: + LOG_ERROR("BUG: we shouldn't get here"); + exit(-1); + break; + } + + return ERROR_OK; +} + +int mips_m4k_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer) +{ + mips32_common_t *mips32 = target->arch_info; + mips_ejtag_t *ejtag_info = &mips32->ejtag_info; + + LOG_DEBUG("address: 0x%8.8x, size: 0x%8.8x, count: 0x%8.8x", address, size, count); + + if (target->state != TARGET_HALTED) + { + LOG_WARNING("target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + /* sanitize arguments */ + if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer)) + return ERROR_INVALID_ARGUMENTS; + + if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u))) + return ERROR_TARGET_UNALIGNED_ACCESS; + + switch (size) + { + case 4: + case 2: + case 1: + mips32_pracc_write_mem(ejtag_info, address, size, count, (void *)buffer); + break; + default: + LOG_ERROR("BUG: we shouldn't get here"); + exit(-1); + break; + } + + return ERROR_OK; +} + +int mips_m4k_register_commands(struct command_context_s *cmd_ctx) +{ + int retval; + + retval = mips32_register_commands(cmd_ctx); + return retval; +} + +int mips_m4k_init_target(struct command_context_s *cmd_ctx, struct target_s *target) +{ + mips32_build_reg_cache(target); + + return ERROR_OK; +} + +int mips_m4k_quit() +{ + return ERROR_OK; +} + +int mips_m4k_init_arch_info(target_t *target, mips_m4k_common_t *mips_m4k, int chain_pos, char *variant) +{ + mips32_common_t *mips32 = &mips_m4k->mips32_common; + + if (variant) + { + mips_m4k->variant = strdup(variant); + } + else + { + mips_m4k->variant = strdup(""); + } + + mips_m4k->common_magic = MIPSM4K_COMMON_MAGIC; + + /* initialize mips4k specific info */ + mips32_init_arch_info(target, mips32, chain_pos, variant); + mips32->arch_info = mips_m4k; + + return ERROR_OK; +} + +int mips_m4k_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target) +{ + int chain_pos; + char *variant = NULL; + mips_m4k_common_t *mips_m4k = malloc(sizeof(mips_m4k_common_t)); + + if (argc < 4) + { + LOG_ERROR("'target mips4k' requires at least one additional argument"); + exit(-1); + } + + chain_pos = strtoul(args[3], NULL, 0); + + if (argc >= 5) + variant = args[4]; + + mips_m4k_init_arch_info(target, mips_m4k, chain_pos, variant); + + return ERROR_OK; +} + +int mips_m4k_examine(struct command_context_s *cmd_ctx, struct target_s *target) +{ + int retval; + mips32_common_t *mips32 = target->arch_info; + mips_ejtag_t *ejtag_info = &mips32->ejtag_info; + u32 idcode = 0; + + target->type->examined = 1; + + mips_ejtag_get_idcode(ejtag_info, &idcode, NULL); + + if (((idcode >> 1) & 0x7FF) == 0x29) + { + /* we are using a pic32mx so select ejtag port + * as it is not selected by default */ + mips_ejtag_set_instr(ejtag_info, 0x05, NULL); + LOG_DEBUG("PIC32MX Detected - using EJTAG Interface"); + } + + /* init rest of ejtag interface */ + if ((retval = mips_ejtag_init(ejtag_info)) != ERROR_OK) + return retval; + + return ERROR_OK; +} + +int mips_m4k_bulk_write_memory(target_t *target, u32 address, u32 count, u8 *buffer) +{ + return mips_m4k_write_memory(target, address, 4, count, buffer); +} diff --git a/src/target/mips_m4k.h b/src/target/mips_m4k.h new file mode 100644 index 0000000000..4f5d3bff59 --- /dev/null +++ b/src/target/mips_m4k.h @@ -0,0 +1,52 @@ +/*************************************************************************** + * Copyright (C) 2008 by Spencer Oliver * + * spen@spen-soft.co.uk * + * * + * Copyright (C) 2008 by David T.L. Wong * + * * + * This program 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 of the License, or * + * (at your option) any later version. * + * * + * This program 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 this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef MIPS_M4K_H +#define MIPS_M4K_H + +#include "register.h" +#include "target.h" + +#define MIPSM4K_COMMON_MAGIC 0xB321B321 + +typedef struct mips_m4k_common_s +{ + int common_magic; + mips32_common_t mips32_common; + + char *variant; +} mips_m4k_common_t; + +extern int mips_m4k_bulk_write_memory(target_t *target, u32 address, u32 count, u8 *buffer); + +extern void mips_m4k_enable_breakpoints(struct target_s *target); +extern int mips_m4k_set_breakpoint(struct target_s *target, breakpoint_t *breakpoint); +extern int mips_m4k_unset_breakpoint(struct target_s *target, breakpoint_t *breakpoint); +extern int mips_m4k_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint); +extern int mips_m4k_remove_breakpoint(struct target_s *target, breakpoint_t *breakpoint); +extern int mips_m4k_set_watchpoint(struct target_s *target, watchpoint_t *watchpoint); +extern int mips_m4k_unset_watchpoint(struct target_s *target, watchpoint_t *watchpoint); +extern int mips_m4k_add_watchpoint(struct target_s *target, watchpoint_t *watchpoint); +extern int mips_m4k_remove_watchpoint(struct target_s *target, watchpoint_t *watchpoint); +extern void mips_m4k_enable_watchpoints(struct target_s *target); + +#endif /*MIPS_M4K_H*/ diff --git a/src/target/target.c b/src/target/target.c index 3d0c4afdad..58a940bd7d 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -92,6 +92,7 @@ extern target_type_t feroceon_target; extern target_type_t xscale_target; extern target_type_t cortexm3_target; extern target_type_t arm11_target; +extern target_type_t mips_m4k_target; target_type_t *target_types[] = { @@ -105,6 +106,7 @@ target_type_t *target_types[] = &xscale_target, &cortexm3_target, &arm11_target, + &mips_m4k_target, NULL, }; diff --git a/src/target/target/pic32mx.cfg b/src/target/target/pic32mx.cfg new file mode 100644 index 0000000000..25ef0294cb --- /dev/null +++ b/src/target/target/pic32mx.cfg @@ -0,0 +1,22 @@ +jtag_nsrst_delay 100 +jtag_ntrst_delay 100 + +#use combined on interfaces or targets that can't set TRST/SRST separately +reset_config srst_only + +#jtag scan chain +#format L IRC IRCM IDCODE (Length, IR Capture, IR Capture Mask, IDCODE) +jtag_device 5 0x1 0x1 0x1e + +#target +#target arm7tdmi +target mips_m4k little 0 +run_and_halt_time 0 30 + +working_area 0 0xa0000000 16384 nobackup + +#flash bank str7x 0 0 +#flash bank stm32x 0 0 0 0 0 + +# For more information about the configuration files, take a look at: +# http://openfacts.berlios.de/index-en.phtml?title=Open+On-Chip+Debugger -- 2.30.2