* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
+#ifdef HAVE_CONFIG_H
#include "config.h"
+#endif
+
+#include "replacements.h"
#include "embeddedice.h"
#include "target.h"
+#include "target_request.h"
#include "armv4_5.h"
#include "arm_jtag.h"
#include "jtag.h"
int handle_arm7_9_sw_bkpts_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
int handle_arm7_9_force_hw_bkpts_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
int handle_arm7_9_dbgrq_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_arm7_9_fast_writes_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_arm7_9_fast_memory_access_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
int handle_arm7_9_dcc_downloads_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_arm7_9_etm_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
int arm7_9_reinit_embeddedice(target_t *target)
{
{
if (breakpoint->length == 4)
{
+ /* keep the original instruction in target endianness */
target->type->read_memory(target, breakpoint->address, 4, 1, breakpoint->orig_instr);
- target->type->write_memory(target, breakpoint->address, 4, 1, (u8*)(&arm7_9->arm_bkpt));
+ /* write the breakpoint instruction in target endianness (arm7_9->arm_bkpt is host endian) */
+ target_write_u32(target, breakpoint->address, arm7_9->arm_bkpt);
}
else
{
+ /* keep the original instruction in target endianness */
target->type->read_memory(target, breakpoint->address, 2, 1, breakpoint->orig_instr);
- target->type->read_memory(target, breakpoint->address, 2, 1, (u8*)(&arm7_9->arm_bkpt));
+ /* write the breakpoint instruction in target endianness (arm7_9->thumb_bkpt is host endian) */
+ target_write_u16(target, breakpoint->address, arm7_9->thumb_bkpt);
}
breakpoint->set = 1;
}
}
else
{
+ /* restore original instruction (kept in target endianness) */
if (breakpoint->length == 4)
{
- target->type->write_memory(target, breakpoint->address, 4, 1, breakpoint->orig_instr);
+ u32 current_instr;
+ /* check that user program as not modified breakpoint instruction */
+ target->type->read_memory(target, breakpoint->address, 4, 1, (u8*)¤t_instr);
+ if (current_instr==arm7_9->arm_bkpt)
+ target->type->write_memory(target, breakpoint->address, 4, 1, breakpoint->orig_instr);
}
else
{
- target->type->write_memory(target, breakpoint->address, 2, 1, breakpoint->orig_instr);
+ u16 current_instr;
+ /* check that user program as not modified breakpoint instruction */
+ target->type->read_memory(target, breakpoint->address, 2, 1, (u8*)¤t_instr);
+ if (current_instr==arm7_9->thumb_bkpt)
+ target->type->write_memory(target, breakpoint->address, 2, 1, breakpoint->orig_instr);
}
breakpoint->set = 0;
}
return ERROR_OK;
}
-int arm7_9_add_breakpoint(struct target_s *target, u32 address, u32 length, enum breakpoint_type type)
+int arm7_9_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
{
armv4_5_common_t *armv4_5 = target->arch_info;
arm7_9_common_t *arm7_9 = armv4_5->arch_info;
if (arm7_9->force_hw_bkpts)
{
- type = BKPT_HARD;
+ DEBUG("forcing use of hardware breakpoint at address 0x%8.8x", breakpoint->address);
+ breakpoint->type = BKPT_HARD;
}
- if ((type == BKPT_SOFT) && (arm7_9->sw_bkpts_enabled == 0))
+ if ((breakpoint->type == BKPT_SOFT) && (arm7_9->sw_bkpts_enabled == 0))
{
INFO("sw breakpoint requested, but software breakpoints not enabled");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
- if ((type == BKPT_HARD) && (arm7_9->wp_available < 1))
+ if ((breakpoint->type == BKPT_HARD) && (arm7_9->wp_available < 1))
{
INFO("no watchpoint unit available for hardware breakpoint");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
- if (type == BKPT_HARD)
- arm7_9->wp_available--;
-
- if ((length != 2) && (length != 4))
+ if ((breakpoint->length != 2) && (breakpoint->length != 4))
{
INFO("only breakpoints of two (Thumb) or four (ARM) bytes length supported");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
+ if (breakpoint->type == BKPT_HARD)
+ arm7_9->wp_available--;
+
return ERROR_OK;
}
arm7_9_unset_breakpoint(target, breakpoint);
}
- arm7_9->wp_available++;
+ if (breakpoint->type == BKPT_HARD)
+ arm7_9->wp_available++;
return ERROR_OK;
}
return ERROR_OK;
}
-int arm7_9_add_watchpoint(struct target_s *target, u32 address, u32 length, enum watchpoint_rw rw)
+int arm7_9_add_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
{
armv4_5_common_t *armv4_5 = target->arch_info;
arm7_9_common_t *arm7_9 = armv4_5->arch_info;
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
- if ((length != 1) && (length != 2) && (length != 4))
+ if ((watchpoint->length != 1) && (watchpoint->length != 2) && (watchpoint->length != 4))
{
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
if (arm7_9->sw_bkpts_enabled)
return ERROR_OK;
- if (arm7_9->wp_available-- < 1)
+ if (arm7_9->wp_available < 1)
{
WARNING("can't enable sw breakpoints with no watchpoint unit available");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
+ arm7_9->wp_available--;
if (!arm7_9->wp0_used)
{
arm7_9_common_t *arm7_9 = armv4_5->arch_info;
arm_jtag_t *jtag_info = &arm7_9->jtag_info;
reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
-
+
/* set RESTART instruction */
jtag_add_end_state(TAP_RTI);
- arm_jtag_set_instr(jtag_info, 0x4);
+ arm_jtag_set_instr(jtag_info, 0x4, NULL);
for (timeout=0; timeout<50; timeout++)
{
int arm7_9_execute_fast_sys_speed(struct target_s *target)
{
- u8 check_value[4], check_mask[4];
+ static int set=0;
+ static u8 check_value[4], check_mask[4];
armv4_5_common_t *armv4_5 = target->arch_info;
arm7_9_common_t *arm7_9 = armv4_5->arch_info;
arm_jtag_t *jtag_info = &arm7_9->jtag_info;
reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
-
+
/* set RESTART instruction */
jtag_add_end_state(TAP_RTI);
- arm_jtag_set_instr(jtag_info, 0x4);
+ arm_jtag_set_instr(jtag_info, 0x4, NULL);
- /* check for DBGACK and SYSCOMP set (others don't care) */
- buf_set_u32(check_value, 0, 32, 0x9);
- buf_set_u32(check_mask, 0, 32, 0x9);
+ if (!set)
+ {
+ /* check for DBGACK and SYSCOMP set (others don't care) */
+
+ /* NB! These are constants that must be available until after next jtag_execute() and
+ we evaluate the values upon first execution in lieu of setting up these constants
+ during early setup.
+ */
+ buf_set_u32(check_value, 0, 32, 0x9);
+ buf_set_u32(check_mask, 0, 32, 0x9);
+ set=1;
+ }
/* read debug status register */
embeddedice_read_reg_w_check(dbg_stat, check_value, check_value);
return ERROR_OK;
}
+int arm7_9_target_request_data(target_t *target, u32 size, u8 *buffer)
+{
+ armv4_5_common_t *armv4_5 = target->arch_info;
+ arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+ arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+ u32 *data;
+ int i;
+
+ data = malloc(size * (sizeof(u32)));
+
+ embeddedice_receive(jtag_info, data, size);
+
+ for (i = 0; i < size; i++)
+ {
+ h_u32_to_le(buffer + (i * 4), data[i]);
+ }
+
+ free(data);
+
+ return ERROR_OK;
+}
+
+int arm7_9_handle_target_request(void *priv)
+{
+ target_t *target = priv;
+ armv4_5_common_t *armv4_5 = target->arch_info;
+ arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+ arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+ reg_t *dcc_control = &arm7_9->eice_cache->reg_list[EICE_COMMS_CTRL];
+
+ if (!target->dbg_msg_enabled)
+ return ERROR_OK;
+
+ if (target->state == TARGET_RUNNING)
+ {
+ /* read DCC control register */
+ embeddedice_read_reg(dcc_control);
+ jtag_execute_queue();
+
+ /* check W bit */
+ if (buf_get_u32(dcc_control->value, 1, 1) == 1)
+ {
+ u32 request;
+
+ embeddedice_receive(jtag_info, &request, 1);
+ target_request(target, request);
+ }
+ }
+
+ return ERROR_OK;
+}
+
enum target_state arm7_9_poll(target_t *target)
{
int retval;
armv4_5_common_t *armv4_5 = target->arch_info;
arm7_9_common_t *arm7_9 = armv4_5->arch_info;
reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
- reg_t *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];
if (arm7_9->reinit_embeddedice)
{
if (target->state == TARGET_HALTED || target->state == TARGET_UNKNOWN)
{
+ /* if the target wasn't running, there might be working areas allocated */
+ target_free_all_working_areas(target);
+
/* assert SRST and TRST */
/* system would get ouf sync if we didn't reset test-logic, too */
if ((retval = jtag_add_reset(1, 1)) != ERROR_OK)
/* deassert reset lines */
jtag_add_reset(0, 0);
-
+
return ERROR_OK;
+}
+int arm7_9_clear_halt(target_t *target)
+{
+ armv4_5_common_t *armv4_5 = target->arch_info;
+ arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+ reg_t *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];
+
+ /* we used DBGRQ only if we didn't come out of reset */
+ if (!arm7_9->debug_entry_from_reset && arm7_9->use_dbgrq)
+ {
+ /* program EmbeddedICE Debug Control Register to deassert DBGRQ
+ */
+ buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_DBGRQ, 1, 0);
+ embeddedice_store_reg(dbg_ctrl);
+ }
+ else
+ {
+ if (arm7_9->debug_entry_from_reset && arm7_9->has_vector_catch)
+ {
+ /* if we came out of reset, and vector catch is supported, we used
+ * vector catch to enter debug state
+ * restore the register in that case
+ */
+ embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_VEC_CATCH]);
+ }
+ else
+ {
+ /* restore registers if watchpoint unit 0 was in use
+ */
+ if (arm7_9->wp0_used)
+ {
+ embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK]);
+ embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK]);
+ embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK]);
+ }
+ /* control value always has to be restored, as it was either disabled,
+ * or enabled with possibly different bits
+ */
+ embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE]);
+ }
+ }
+
+ return ERROR_OK;
}
int arm7_9_soft_reset_halt(struct target_s *target)
armv4_5_common_t *armv4_5 = target->arch_info;
arm7_9_common_t *arm7_9 = armv4_5->arch_info;
reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
+ reg_t *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];
int i;
if (target->state == TARGET_RUNNING)
target->type->halt(target);
}
- while (buf_get_u32(dbg_stat->value, EICE_DBG_CONTROL_DBGACK, 1) == 0)
+ while (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1) == 0)
{
embeddedice_read_reg(dbg_stat);
jtag_execute_queue();
}
target->state = TARGET_HALTED;
+ /* program EmbeddedICE Debug Control Register to assert DBGACK and INTDIS
+ * ensure that DBGRQ is cleared
+ */
+ buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_DBGACK, 1, 1);
+ buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_DBGRQ, 1, 0);
+ buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_INTDIS, 1, 1);
+ embeddedice_store_reg(dbg_ctrl);
+
+ arm7_9_clear_halt(target);
+
+ /* if the target is in Thumb state, change to ARM state */
+ if (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_ITBIT, 1))
+ {
+ u32 r0_thumb, pc_thumb;
+ DEBUG("target entered debug from Thumb state, changing to ARM");
+ /* Entered debug from Thumb mode */
+ armv4_5->core_state = ARMV4_5_STATE_THUMB;
+ arm7_9->change_to_arm(target, &r0_thumb, &pc_thumb);
+ }
+
/* all register content is now invalid */
armv4_5_invalidate_core_regs(target);
return ERROR_OK;
}
+int arm7_9_prepare_reset_halt(target_t *target)
+{
+ armv4_5_common_t *armv4_5 = target->arch_info;
+ arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+
+ /* poll the target, and resume if it was currently halted */
+ arm7_9_poll(target);
+ if (target->state == TARGET_HALTED)
+ {
+ arm7_9_resume(target, 1, 0x0, 0, 1);
+ }
+
+ if (arm7_9->has_vector_catch)
+ {
+ /* program vector catch register to catch reset vector */
+ embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_VEC_CATCH], 0x1);
+ }
+ else
+ {
+ /* program watchpoint unit to match on reset vector address */
+ embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK], 0x3);
+ embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK], 0x0);
+ embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], 0x100);
+ embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK], 0xf7);
+ }
+
+ return ERROR_OK;
+}
+
int arm7_9_halt(target_t *target)
{
armv4_5_common_t *armv4_5 = target->arch_info;
{
WARNING("target was already halted");
return ERROR_TARGET_ALREADY_HALTED;
- }
+ }
if (target->state == TARGET_UNKNOWN)
{
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)
+ {
+ 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 arm7_9_prepare_reset_halt()
+ */
+ target->debug_reason = DBG_REASON_DBGRQ;
+
+ return ERROR_OK;
+ }
+ }
if (arm7_9->use_dbgrq)
{
return ERROR_OK;
}
-int arm7_9_clear_halt(target_t *target)
-{
- armv4_5_common_t *armv4_5 = target->arch_info;
- arm7_9_common_t *arm7_9 = armv4_5->arch_info;
- reg_t *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];
-
- if (arm7_9->use_dbgrq)
- {
- /* program EmbeddedICE Debug Control Register to deassert DBGRQ
- */
- buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_DBGRQ, 1, 0);
- embeddedice_store_reg(dbg_ctrl);
- }
- else
- {
- /* restore registers if watchpoint unit 0 was in use
- */
- if (arm7_9->wp0_used)
- {
- embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK]);
- embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK]);
- embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK]);
- }
- /* control value always has to be restored, as it was either disabled,
- * or enabled with possibly different bits
- */
- embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE]);
- }
-
- return ERROR_OK;
-}
-
int arm7_9_debug_entry(target_t *target)
{
int i;
reg_t *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];
#ifdef _DEBUG_ARM7_9_
- DEBUG("");
+ DEBUG("-");
#endif
if (arm7_9->pre_debug_entry)
if ((retval = jtag_execute_queue()) != ERROR_OK)
return retval;
+
+ /* if the core has been executing in Thumb state, set the T bit */
+ if (armv4_5->core_state == ARMV4_5_STATE_THUMB)
+ cpsr |= 0x20;
+
buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32, cpsr);
armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 0;
armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
armv4_5->core_mode = cpsr & 0x1f;
- DEBUG("target entered debug state in %s mode", armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)]);
if (armv4_5_mode_to_number(armv4_5->core_mode) == -1)
{
ERROR("cpsr contains invalid mode value - communication failure");
return ERROR_TARGET_FAILURE;
}
+
+ DEBUG("target entered debug state in %s mode", armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)]);
if (armv4_5->core_state == ARMV4_5_STATE_THUMB)
{
for (i=0; i<=15; i++)
{
+ DEBUG("r%i: 0x%8.8x", i, context[i]);
buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i).value, 0, 32, context[i]);
ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i).dirty = 0;
ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i).valid = 1;
armv4_5_common_t *armv4_5 = target->arch_info;
arm7_9_common_t *arm7_9 = armv4_5->arch_info;
- DEBUG("");
+ DEBUG("-");
if (target->state != TARGET_HALTED)
{
{
u32 tmp_cpsr;
- /* change processor mode */
+ /* change processor mode (and mask T bit) */
tmp_cpsr = buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8) & 0xE0;
tmp_cpsr |= armv4_5_number_to_mode(i);
+ tmp_cpsr &= ~0x20;
arm7_9->write_xpsr_im8(target, tmp_cpsr & 0xff, 0, 0);
for (j = 0; j < 15; j++)
}
}
- /* restore processor mode */
- arm7_9->write_xpsr_im8(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8), 0, 0);
+ /* restore processor mode (mask T bit) */
+ arm7_9->write_xpsr_im8(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8) & ~0x20, 0, 0);
if ((retval = jtag_execute_queue()) != ERROR_OK)
{
int dirty;
int mode_change;
- DEBUG("");
+ DEBUG("-");
if (target->state != TARGET_HALTED)
{
{
u32 tmp_cpsr;
- /* change processor mode */
+ /* change processor mode (mask T bit) */
tmp_cpsr = buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8) & 0xE0;
tmp_cpsr |= armv4_5_number_to_mode(i);
+ tmp_cpsr &= ~0x20;
arm7_9->write_xpsr_im8(target, tmp_cpsr & 0xff, 0, 0);
current_mode = armv4_5_number_to_mode(i);
}
if ((armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty == 0) && (armv4_5->core_mode != current_mode))
{
- /* restore processor mode */
+ /* restore processor mode (mask T bit) */
u32 tmp_cpsr;
tmp_cpsr = buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8) & 0xE0;
tmp_cpsr |= armv4_5_number_to_mode(i);
+ tmp_cpsr &= ~0x20;
DEBUG("writing lower 8 bit of cpsr with value 0x%2.2x", tmp_cpsr);
arm7_9->write_xpsr_im8(target, tmp_cpsr & 0xff, 0, 0);
}
else if (armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty == 1)
{
- /* CPSR has been changed, full restore necessary */
+ /* CPSR has been changed, full restore necessary (mask T bit) */
DEBUG("writing cpsr with value 0x%8.8x", buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32));
- arm7_9->write_xpsr(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32), 0);
+ arm7_9->write_xpsr(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32) & ~0x20, 0);
armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 0;
armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
}
/* set RESTART instruction */
jtag_add_end_state(TAP_RTI);
- arm_jtag_set_instr(jtag_info, 0x4);
+ arm_jtag_set_instr(jtag_info, 0x4, NULL);
jtag_add_runtest(1, TAP_RTI);
if ((jtag_execute_queue()) != ERROR_OK)
breakpoint_t *breakpoint = target->breakpoints;
reg_t *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];
- DEBUG("");
+ DEBUG("-");
if (target->state != TARGET_HALTED)
{
{
armv4_5_common_t *armv4_5 = target->arch_info;
arm7_9_common_t *arm7_9 = armv4_5->arch_info;
- breakpoint_t *breakpoint = target->breakpoints;
+ breakpoint_t *breakpoint = NULL;
if (target->state != TARGET_HALTED)
{
int arm7_9_read_core_reg(struct target_s *target, int num, enum armv4_5_mode mode)
{
u32* reg_p[16];
+ u32 value;
int retval;
armv4_5_common_t *armv4_5 = target->arch_info;
arm7_9_common_t *arm7_9 = armv4_5->arch_info;
{
u32 tmp_cpsr;
- /* change processor mode */
+ /* change processor mode (mask T bit) */
tmp_cpsr = buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8) & 0xE0;
tmp_cpsr |= mode;
+ tmp_cpsr &= ~0x20;
arm7_9->write_xpsr_im8(target, tmp_cpsr & 0xff, 0, 0);
}
if ((num >= 0) && (num <= 15))
{
/* read a normal core register */
- reg_p[num] = (u32*)ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, mode, num).value;
+ reg_p[num] = &value;
arm7_9->read_core_regs(target, 1 << num, reg_p);
}
armv4_5_core_reg_t *arch_info = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, mode, num).arch_info;
int spsr = (arch_info->mode == ARMV4_5_MODE_ANY) ? 0 : 1;
- arm7_9->read_xpsr(target, (u32*)ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, mode, num).value, spsr);
+ arm7_9->read_xpsr(target, &value, spsr);
}
+ if ((retval = jtag_execute_queue()) != ERROR_OK)
+ {
+ ERROR("JTAG failure");
+ exit(-1);
+ }
+
ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, mode, num).valid = 1;
ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, mode, num).dirty = 0;
+ buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, mode, num).value, 0, 32, value);
if ((mode != ARMV4_5_MODE_ANY)
&& (mode != armv4_5->core_mode)
&& (reg_mode != ARMV4_5_MODE_ANY)) {
- /* restore processor mode */
- arm7_9->write_xpsr_im8(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8), 0, 0);
- }
-
- if ((retval = jtag_execute_queue()) != ERROR_OK)
- {
- ERROR("JTAG failure");
- exit(-1);
+ /* restore processor mode (mask T bit) */
+ arm7_9->write_xpsr_im8(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8) & ~0x20, 0, 0);
}
return ERROR_OK;
&& (reg_mode != ARMV4_5_MODE_ANY)) {
u32 tmp_cpsr;
- /* change processor mode */
+ /* change processor mode (mask T bit) */
tmp_cpsr = buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8) & 0xE0;
tmp_cpsr |= mode;
+ tmp_cpsr &= ~0x20;
arm7_9->write_xpsr_im8(target, tmp_cpsr & 0xff, 0, 0);
}
armv4_5_core_reg_t *arch_info = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, mode, num).arch_info;
int spsr = (arch_info->mode == ARMV4_5_MODE_ANY) ? 0 : 1;
+ /* if we're writing the CPSR, mask the T bit */
+ if (!spsr)
+ value &= ~0x20;
+
arm7_9->write_xpsr(target, value, spsr);
}
if ((mode != ARMV4_5_MODE_ANY)
&& (mode != armv4_5->core_mode)
&& (reg_mode != ARMV4_5_MODE_ANY)) {
- /* restore processor mode */
- arm7_9->write_xpsr_im8(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8), 0, 0);
+ /* restore processor mode (mask T bit) */
+ arm7_9->write_xpsr_im8(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8) & ~0x20, 0, 0);
}
if ((retval = jtag_execute_queue()) != ERROR_OK)
arm7_9_common_t *arm7_9 = armv4_5->arch_info;
u32 reg[16];
- u32 *reg_p[16];
int num_accesses = 0;
int thisrun_accesses;
int i;
u32 cpsr;
int retval;
int last_reg = 0;
-
+
DEBUG("address: 0x%8.8x, size: 0x%8.8x, count: 0x%8.8x", address, size, count);
if (target->state != TARGET_HALTED)
if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
return ERROR_TARGET_UNALIGNED_ACCESS;
- for (i = 0; i < 16; i++)
- {
- reg_p[i] = ®[i];
- }
-
/* load the base register with the address of the first word */
reg[0] = address;
arm7_9->write_core_regs(target, 0x1, reg);
thisrun_accesses = ((count - num_accesses) >= 14) ? 14 : (count - num_accesses);
reg_list = (0xffff >> (15 - thisrun_accesses)) & 0xfffe;
+ if (last_reg <= thisrun_accesses)
+ last_reg = thisrun_accesses;
+
arm7_9->load_word_regs(target, reg_list);
- arm7_9_execute_sys_speed(target);
- arm7_9->read_core_regs(target, reg_list, reg_p);
- jtag_execute_queue();
+ /* fast memory reads are only safe when the target is running
+ * from a sufficiently high clock (32 kHz is usually too slow)
+ */
+ if (arm7_9->fast_memory_access)
+ arm7_9_execute_fast_sys_speed(target);
+ else
+ arm7_9_execute_sys_speed(target);
+
+ arm7_9->read_core_regs_target_buffer(target, reg_list, buffer, 4);
- for (i = 1; i <= thisrun_accesses; i++)
- {
- if (i > last_reg)
- last_reg = i;
- target_buffer_set_u32(target, buffer, reg[i]);
- buffer += 4;
- }
+ /* advance buffer, count number of accesses */
+ buffer += thisrun_accesses * 4;
num_accesses += thisrun_accesses;
}
break;
if (i > last_reg)
last_reg = i;
arm7_9->load_hword_reg(target, i);
- arm7_9_execute_sys_speed(target);
+ /* fast memory reads are only safe when the target is running
+ * from a sufficiently high clock (32 kHz is usually too slow)
+ */
+ if (arm7_9->fast_memory_access)
+ arm7_9_execute_fast_sys_speed(target);
+ else
+ arm7_9_execute_sys_speed(target);
}
- arm7_9->read_core_regs(target, reg_list, reg_p);
- jtag_execute_queue();
+ arm7_9->read_core_regs_target_buffer(target, reg_list, buffer, 2);
- for (i = 1; i <= thisrun_accesses; i++)
- {
- target_buffer_set_u16(target, buffer, reg[i]);
- buffer += 2;
- }
+ /* advance buffer, count number of accesses */
+ buffer += thisrun_accesses * 2;
num_accesses += thisrun_accesses;
}
break;
if (i > last_reg)
last_reg = i;
arm7_9->load_byte_reg(target, i);
- arm7_9_execute_sys_speed(target);
+ /* fast memory reads are only safe when the target is running
+ * from a sufficiently high clock (32 kHz is usually too slow)
+ */
+ if (arm7_9->fast_memory_access)
+ arm7_9_execute_fast_sys_speed(target);
+ else
+ arm7_9_execute_sys_speed(target);
}
- arm7_9->read_core_regs(target, reg_list, reg_p);
- jtag_execute_queue();
+ arm7_9->read_core_regs_target_buffer(target, reg_list, buffer, 1);
- for (i = 1; i <= thisrun_accesses; i++)
- {
- *(buffer++) = reg[i] & 0xff;
- }
+ /* advance buffer, count number of accesses */
+ buffer += thisrun_accesses * 1;
num_accesses += thisrun_accesses;
}
break;
if (((cpsr & 0x1f) == ARMV4_5_MODE_ABT) && (armv4_5->core_mode != ARMV4_5_MODE_ABT))
{
- ERROR("memory read caused data abort");
+ WARNING("memory read caused data abort (address: 0x%8.8x, size: 0x%x, count: 0x%x)", address, size, count);
- arm7_9->write_xpsr_im8(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8), 0, 0);
+ arm7_9->write_xpsr_im8(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8) & ~0x20, 0, 0);
return ERROR_TARGET_DATA_ABORT;
}
{
armv4_5_common_t *armv4_5 = target->arch_info;
arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+ reg_t *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];
u32 reg[16];
int num_accesses = 0;
reg[0] = address;
arm7_9->write_core_regs(target, 0x1, reg);
+ /* Clear DBGACK, to make sure memory fetches work as expected */
+ buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_DBGACK, 1, 0);
+ embeddedice_store_reg(dbg_ctrl);
+
switch (size)
{
case 4:
/* fast memory writes are only safe when the target is running
* from a sufficiently high clock (32 kHz is usually too slow)
*/
- if (arm7_9->fast_memory_writes)
+ if (arm7_9->fast_memory_access)
arm7_9_execute_fast_sys_speed(target);
else
arm7_9_execute_sys_speed(target);
/* fast memory writes are only safe when the target is running
* from a sufficiently high clock (32 kHz is usually too slow)
*/
- if (arm7_9->fast_memory_writes)
+ if (arm7_9->fast_memory_access)
arm7_9_execute_fast_sys_speed(target);
else
arm7_9_execute_sys_speed(target);
/* fast memory writes are only safe when the target is running
* from a sufficiently high clock (32 kHz is usually too slow)
*/
- if (arm7_9->fast_memory_writes)
+ if (arm7_9->fast_memory_access)
arm7_9_execute_fast_sys_speed(target);
else
arm7_9_execute_sys_speed(target);
break;
}
- if ((retval = jtag_execute_queue()) != ERROR_OK)
- {
- ERROR("JTAG error while writing target memory");
- exit(-1);
- }
+ /* Re-Set DBGACK */
+ buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_DBGACK, 1, 1);
+ embeddedice_store_reg(dbg_ctrl);
for (i=0; i<=last_reg; i++)
ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i).dirty = 1;
if (((cpsr & 0x1f) == ARMV4_5_MODE_ABT) && (armv4_5->core_mode != ARMV4_5_MODE_ABT))
{
- ERROR("memory write caused data abort");
+ WARNING("memory write caused data abort (address: 0x%8.8x, size: 0x%x, count: 0x%x)", address, size, count);
- arm7_9->write_xpsr_im8(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8), 0, 0);
+ arm7_9->write_xpsr_im8(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8) & ~0x20, 0, 0);
return ERROR_TARGET_DATA_ABORT;
}
/* regrab previously allocated working_area, or allocate a new one */
if (!arm7_9->dcc_working_area)
{
+ u8 dcc_code_buf[6 * 4];
+
/* make sure we have a working area */
if (target_alloc_working_area(target, 24, &arm7_9->dcc_working_area) != ERROR_OK)
{
return target->type->write_memory(target, address, 4, count, buffer);
}
+ /* copy target instructions to target endianness */
+ for (i = 0; i < 6; i++)
+ {
+ target_buffer_set_u32(target, dcc_code_buf + i*4, dcc_code[i]);
+ }
+
/* write DCC code to working area */
- target->type->write_memory(target, arm7_9->dcc_working_area->address, 4, 6, (u8*)dcc_code);
+ target->type->write_memory(target, arm7_9->dcc_working_area->address, 4, 6, dcc_code_buf);
}
buf_set_u32(armv4_5->core_cache->reg_list[0].value, 0, 32, address);
return ERROR_OK;
}
+int arm7_9_checksum_memory(struct target_s *target, u32 address, u32 count, u32* checksum)
+{
+ working_area_t *crc_algorithm;
+ armv4_5_algorithm_t armv4_5_info;
+ reg_param_t reg_params[2];
+ int retval;
+
+ u32 arm7_9_crc_code[] = {
+ 0xE1A02000, /* mov r2, r0 */
+ 0xE3E00000, /* mov r0, #0xffffffff */
+ 0xE1A03001, /* mov r3, r1 */
+ 0xE3A04000, /* mov r4, #0 */
+ 0xEA00000B, /* b ncomp */
+ /* nbyte: */
+ 0xE7D21004, /* ldrb r1, [r2, r4] */
+ 0xE59F7030, /* ldr r7, CRC32XOR */
+ 0xE0200C01, /* eor r0, r0, r1, asl 24 */
+ 0xE3A05000, /* mov r5, #0 */
+ /* loop: */
+ 0xE3500000, /* cmp r0, #0 */
+ 0xE1A06080, /* mov r6, r0, asl #1 */
+ 0xE2855001, /* add r5, r5, #1 */
+ 0xE1A00006, /* mov r0, r6 */
+ 0xB0260007, /* eorlt r0, r6, r7 */
+ 0xE3550008, /* cmp r5, #8 */
+ 0x1AFFFFF8, /* bne loop */
+ 0xE2844001, /* add r4, r4, #1 */
+ /* ncomp: */
+ 0xE1540003, /* cmp r4, r3 */
+ 0x1AFFFFF1, /* bne nbyte */
+ /* end: */
+ 0xEAFFFFFE, /* b end */
+ 0x04C11DB7 /* CRC32XOR: .word 0x04C11DB7 */
+ };
+
+ int i;
+
+ if (target_alloc_working_area(target, sizeof(arm7_9_crc_code), &crc_algorithm) != ERROR_OK)
+ {
+ return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+ }
+
+ /* convert flash writing code into a buffer in target endianness */
+ for (i = 0; i < (sizeof(arm7_9_crc_code)/sizeof(u32)); i++)
+ target_write_u32(target, crc_algorithm->address + i*sizeof(u32), arm7_9_crc_code[i]);
+
+ armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;
+ armv4_5_info.core_mode = ARMV4_5_MODE_SVC;
+ armv4_5_info.core_state = ARMV4_5_STATE_ARM;
+
+ init_reg_param(®_params[0], "r0", 32, PARAM_IN_OUT);
+ init_reg_param(®_params[1], "r1", 32, PARAM_OUT);
+
+ buf_set_u32(reg_params[0].value, 0, 32, address);
+ buf_set_u32(reg_params[1].value, 0, 32, count);
+
+ if ((retval = target->type->run_algorithm(target, 0, NULL, 2, reg_params,
+ crc_algorithm->address, crc_algorithm->address + (sizeof(arm7_9_crc_code) - 8), 20000, &armv4_5_info)) != ERROR_OK)
+ {
+ ERROR("error executing arm7_9 crc algorithm");
+ destroy_reg_param(®_params[0]);
+ destroy_reg_param(®_params[1]);
+ target_free_working_area(target, crc_algorithm);
+ return retval;
+ }
+
+ *checksum = buf_get_u32(reg_params[0].value, 0, 32);
+
+ destroy_reg_param(®_params[0]);
+ destroy_reg_param(®_params[1]);
+
+ target_free_working_area(target, crc_algorithm);
+
+ return ERROR_OK;
+}
+
int arm7_9_register_commands(struct command_context_s *cmd_ctx)
{
command_t *arm7_9_cmd;
- arm7_9_cmd = register_command(cmd_ctx, NULL, "arm7_9", NULL, COMMAND_ANY, NULL);
-
+ arm7_9_cmd = register_command(cmd_ctx, NULL, "arm7_9", NULL, COMMAND_ANY, "arm7/9 specific commands");
+
register_command(cmd_ctx, arm7_9_cmd, "write_xpsr", handle_arm7_9_write_xpsr_command, COMMAND_EXEC, "write program status register <value> <not cpsr|spsr>");
register_command(cmd_ctx, arm7_9_cmd, "write_xpsr_im8", handle_arm7_9_write_xpsr_im8_command, COMMAND_EXEC, "write program status register <8bit immediate> <rotate> <not cpsr|spsr>");
register_command(cmd_ctx, arm7_9_cmd, "force_hw_bkpts", handle_arm7_9_force_hw_bkpts_command, COMMAND_EXEC, "use hardware breakpoints for all breakpoints (disables sw breakpoint support) <enable|disable>");
register_command(cmd_ctx, arm7_9_cmd, "dbgrq", handle_arm7_9_dbgrq_command,
COMMAND_ANY, "use EmbeddedICE dbgrq instead of breakpoint for target halt requests <enable|disable>");
- register_command(cmd_ctx, arm7_9_cmd, "fast_writes", handle_arm7_9_fast_writes_command,
- COMMAND_ANY, "use fast memory writes instead of slower but potentially unsafe slow writes <enable|disable>");
+ register_command(cmd_ctx, arm7_9_cmd, "fast_writes", handle_arm7_9_fast_memory_access_command,
+ COMMAND_ANY, "(deprecated, see: arm7_9 fast_memory_access)");
+ register_command(cmd_ctx, arm7_9_cmd, "fast_memory_access", handle_arm7_9_fast_memory_access_command,
+ COMMAND_ANY, "use fast memory accesses instead of slower but potentially unsafe slow accesses <enable|disable>");
register_command(cmd_ctx, arm7_9_cmd, "dcc_downloads", handle_arm7_9_dcc_downloads_command,
COMMAND_ANY, "use DCC downloads for larger memory writes <enable|disable>");
armv4_5_register_commands(cmd_ctx);
+ etm_register_commands(cmd_ctx);
+
return ERROR_OK;
}
value = strtoul(args[0], NULL, 0);
spsr = strtol(args[1], NULL, 0);
+ /* if we're writing the CPSR, mask the T bit */
+ if (!spsr)
+ value &= ~0x20;
+
arm7_9->write_xpsr(target, value, spsr);
if ((retval = jtag_execute_queue()) != ERROR_OK)
{
value = strtoul(args[0], NULL, 0);
rotate = strtol(args[1], NULL, 0);
spsr = strtol(args[2], NULL, 0);
-
+
arm7_9->write_xpsr_im8(target, value, rotate, spsr);
if ((retval = jtag_execute_queue()) != ERROR_OK)
{
return ERROR_OK;
}
-int handle_arm7_9_fast_writes_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+int handle_arm7_9_fast_memory_access_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
{
target_t *target = get_current_target(cmd_ctx);
armv4_5_common_t *armv4_5;
{
if (strcmp("enable", args[0]) == 0)
{
- arm7_9->fast_memory_writes = 1;
+ arm7_9->fast_memory_access = 1;
}
else if (strcmp("disable", args[0]) == 0)
{
- arm7_9->fast_memory_writes = 0;
+ arm7_9->fast_memory_access = 0;
}
else
{
- command_print(cmd_ctx, "usage: arm7_9 fast_writes <enable|disable>");
+ command_print(cmd_ctx, "usage: arm7_9 fast_memory_access <enable|disable>");
}
}
- command_print(cmd_ctx, "fast memory writes are %s", (arm7_9->fast_memory_writes) ? "enabled" : "disabled");
+ command_print(cmd_ctx, "fast memory access is %s", (arm7_9->fast_memory_access) ? "enabled" : "disabled");
return ERROR_OK;
}
arm7_9->wp1_used = 0;
arm7_9->force_hw_bkpts = 0;
arm7_9->use_dbgrq = 0;
- arm7_9->has_etm = 0;
+
+ arm7_9->etm_ctx = NULL;
+ arm7_9->has_single_step = 0;
+ arm7_9->has_monitor_mode = 0;
+ arm7_9->has_vector_catch = 0;
arm7_9->reinit_embeddedice = 0;
+ arm7_9->debug_entry_from_reset = 0;
+
arm7_9->dcc_working_area = NULL;
- arm7_9->fast_memory_writes = 0;
+ arm7_9->fast_memory_access = 0;
arm7_9->dcc_downloads = 0;
jtag_register_event_callback(arm7_9_jtag_callback, target);
armv4_5_init_arch_info(target, armv4_5);
+ target_register_timer_callback(arm7_9_handle_target_request, 1, 1, target);
+
return ERROR_OK;
}