X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Ftarget%2Farm7_9_common.c;h=ed913024dbfb1f1d90a13cd3b213f8d262febb97;hp=03071dfd7ba394823d74b516d4f5be25e248a6e1;hb=0c2f8b6eb8f4b379aa0c78caba73ec1ebaae8414;hpb=0529c14bfeb113ee37f4d961f9309102d57a1e39 diff --git a/src/target/arm7_9_common.c b/src/target/arm7_9_common.c index 03071dfd7b..ed913024db 100644 --- a/src/target/arm7_9_common.c +++ b/src/target/arm7_9_common.c @@ -2,7 +2,7 @@ * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * - * Copyright (C) 2007,2008 Øyvind Harboe * + * Copyright (C) 2007-2010 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2008 by Spencer Oliver * @@ -11,6 +11,8 @@ * Copyright (C) 2008 by Hongtao Zheng * * hontor@126.com * * * + * Copyright (C) 2009 by David Brownell * + * * * 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 * @@ -39,6 +41,7 @@ #include "arm_semihosting.h" #include "algorithm.h" #include "register.h" +#include "armv4_5.h" /** @@ -181,7 +184,7 @@ static int arm7_9_set_software_breakpoints(struct arm7_9_common *arm7_9) * @param target Pointer to an ARM7/9 target to setup * @return Result of clearing the watchpoints on the target */ -int arm7_9_setup(struct target *target) +static int arm7_9_setup(struct target *target) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); @@ -199,7 +202,7 @@ int arm7_9_setup(struct target *target) * queue. For software breakpoints, this will be the status of the * required memory reads and writes */ -int arm7_9_set_breakpoint(struct target *target, struct breakpoint *breakpoint) +static int arm7_9_set_breakpoint(struct target *target, struct breakpoint *breakpoint) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); int retval = ERROR_OK; @@ -328,7 +331,7 @@ int arm7_9_set_breakpoint(struct target *target, struct breakpoint *breakpoint) * queue. For software breakpoints, this will be the status of the * required memory reads and writes */ -int arm7_9_unset_breakpoint(struct target *target, struct breakpoint *breakpoint) +static int arm7_9_unset_breakpoint(struct target *target, struct breakpoint *breakpoint) { int retval = ERROR_OK; struct arm7_9_common *arm7_9 = target_to_arm7_9(target); @@ -374,6 +377,7 @@ int arm7_9_unset_breakpoint(struct target *target, struct breakpoint *breakpoint { return retval; } + current_instr = target_buffer_get_u32(target, (uint8_t *)¤t_instr); if (current_instr == arm7_9->arm_bkpt) if ((retval = target_write_memory(target, breakpoint->address, 4, 1, breakpoint->orig_instr)) != ERROR_OK) { @@ -388,6 +392,7 @@ int arm7_9_unset_breakpoint(struct target *target, struct breakpoint *breakpoint { return retval; } + current_instr = target_buffer_get_u16(target, (uint8_t *)¤t_instr); if (current_instr == arm7_9->thumb_bkpt) if ((retval = target_write_memory(target, breakpoint->address, 2, 1, breakpoint->orig_instr)) != ERROR_OK) { @@ -503,7 +508,7 @@ int arm7_9_remove_breakpoint(struct target *target, struct breakpoint *breakpoin * @return Error status if watchpoint set fails or the result of executing the * JTAG queue */ -int arm7_9_set_watchpoint(struct target *target, struct watchpoint *watchpoint) +static int arm7_9_set_watchpoint(struct target *target, struct watchpoint *watchpoint) { int retval = ERROR_OK; struct arm7_9_common *arm7_9 = target_to_arm7_9(target); @@ -574,7 +579,7 @@ int arm7_9_set_watchpoint(struct target *target, struct watchpoint *watchpoint) * @return Error status while trying to unset the watchpoint or the result of * executing the JTAG queue */ -int arm7_9_unset_watchpoint(struct target *target, struct watchpoint *watchpoint) +static int arm7_9_unset_watchpoint(struct target *target, struct watchpoint *watchpoint) { int retval = ERROR_OK; struct arm7_9_common *arm7_9 = target_to_arm7_9(target); @@ -684,12 +689,15 @@ int arm7_9_execute_sys_speed(struct target *target) struct reg *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT]; /* set RESTART instruction */ - jtag_set_end_state(TAP_IDLE); if (arm7_9->need_bypass_before_restart) { arm7_9->need_bypass_before_restart = 0; - arm_jtag_set_instr(jtag_info, 0xf, NULL); + retval = arm_jtag_set_instr(jtag_info, 0xf, NULL, TAP_IDLE); + if (retval != ERROR_OK) + return retval; } - arm_jtag_set_instr(jtag_info, 0x4, NULL); + retval = arm_jtag_set_instr(jtag_info, 0x4, NULL, TAP_IDLE); + if (retval != ERROR_OK) + return retval; long long then = timeval_ms(); int timeout; @@ -727,7 +735,7 @@ int arm7_9_execute_sys_speed(struct target *target) * @param target Pointer to the target to issue commands to * @return Always ERROR_OK */ -int arm7_9_execute_fast_sys_speed(struct target *target) +static int arm7_9_execute_fast_sys_speed(struct target *target) { static int set = 0; static uint8_t check_value[4], check_mask[4]; @@ -735,14 +743,18 @@ int arm7_9_execute_fast_sys_speed(struct target *target) struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; struct reg *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT]; + int retval; /* set RESTART instruction */ - jtag_set_end_state(TAP_IDLE); if (arm7_9->need_bypass_before_restart) { arm7_9->need_bypass_before_restart = 0; - arm_jtag_set_instr(jtag_info, 0xf, NULL); + retval = arm_jtag_set_instr(jtag_info, 0xf, NULL, TAP_IDLE); + if (retval != ERROR_OK) + return retval; } - arm_jtag_set_instr(jtag_info, 0x4, NULL); + retval = arm_jtag_set_instr(jtag_info, 0x4, NULL, TAP_IDLE); + if (retval != ERROR_OK) + return retval; if (!set) { @@ -803,7 +815,7 @@ int arm7_9_target_request_data(struct target *target, uint32_t size, uint8_t *bu * @return ERROR_OK unless there are issues with the JTAG queue or when reading * from the Embedded ICE unit */ -int arm7_9_handle_target_request(void *priv) +static int arm7_9_handle_target_request(void *priv) { int retval = ERROR_OK; struct target *target = priv; @@ -888,34 +900,11 @@ int arm7_9_poll(struct target *target) } if ((target->state == TARGET_RUNNING) || (target->state == TARGET_RESET)) { - int check_pc = 0; - if (target->state == TARGET_RESET) - { - if (target->reset_halt) - { - enum reset_types jtag_reset_config = jtag_get_reset_config(); - if ((jtag_reset_config & RESET_SRST_PULLS_TRST) == 0) - { - check_pc = 1; - } - } - } - target->state = TARGET_HALTED; if ((retval = arm7_9_debug_entry(target)) != ERROR_OK) return retval; - if (check_pc) - { - struct reg *reg = register_get_by_name(target->reg_cache, "pc", 1); - uint32_t t=*((uint32_t *)reg->value); - if (t != 0) - { - LOG_ERROR("PC was not 0. Does this target need srst_pulls_trst?"); - } - } - if (arm_semihosting(target, &retval) != 0) return retval; @@ -963,14 +952,16 @@ int arm7_9_poll(struct target *target) int arm7_9_assert_reset(struct target *target) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); + enum reset_types jtag_reset_config = jtag_get_reset_config(); + bool use_event = false; LOG_DEBUG("target->state: %s", target_state_name(target)); - enum reset_types jtag_reset_config = jtag_get_reset_config(); - if (!(jtag_reset_config & RESET_HAS_SRST)) - { - LOG_ERROR("Can't assert SRST"); + if (target_has_event_action(target, TARGET_EVENT_RESET_ASSERT)) + use_event = true; + else if (!(jtag_reset_config & RESET_HAS_SRST)) { + LOG_ERROR("%s: how to reset?", target_name(target)); return ERROR_FAIL; } @@ -985,7 +976,8 @@ int arm7_9_assert_reset(struct target *target) */ bool srst_asserted = false; - if (((jtag_reset_config & RESET_SRST_PULLS_TRST) == 0) + if (!use_event + && !(jtag_reset_config & RESET_SRST_PULLS_TRST) && (jtag_reset_config & RESET_SRST_NO_GATING)) { jtag_add_reset(0, 1); @@ -995,48 +987,70 @@ int arm7_9_assert_reset(struct target *target) if (target->reset_halt) { /* - * Some targets do not support communication while SRST is asserted. We need to - * set up the reset vector catch here. + * For targets that don't support communication while SRST is + * asserted, we need to set up the reset vector catch first. * - * If TRST is asserted, then these settings will be reset anyway, so setting them - * here is harmless. + * When we use TRST+SRST and that's equivalent to a power-up + * reset, these settings may well be reset anyway; so setting + * them here won't matter. */ 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); + /* program vector catch register to catch reset */ + embeddedice_write_reg(&arm7_9->eice_cache + ->reg_list[EICE_VEC_CATCH], 0x1); - /* extra runtest added as issues were found with certain ARM9 cores (maybe more) - AT91SAM9260 and STR9 */ - jtag_add_runtest(1, jtag_get_end_state()); + /* extra runtest added as issues were found with + * certain ARM9 cores (maybe more) - AT91SAM9260 + * and STR9 + */ + jtag_add_runtest(1, TAP_IDLE); } else { - /* program watchpoint unit to match on reset vector address */ - embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_VALUE], 0x0); - 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], 0xffffffff); - embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], EICE_W_CTRL_ENABLE); - embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK], ~EICE_W_CTRL_nOPC & 0xff); + /* program watchpoint unit to match on reset vector + * address + */ + embeddedice_write_reg(&arm7_9->eice_cache + ->reg_list[EICE_W0_ADDR_VALUE], 0x0); + 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], + 0xffffffff); + embeddedice_write_reg(&arm7_9->eice_cache + ->reg_list[EICE_W0_CONTROL_VALUE], + EICE_W_CTRL_ENABLE); + embeddedice_write_reg(&arm7_9->eice_cache + ->reg_list[EICE_W0_CONTROL_MASK], + ~EICE_W_CTRL_nOPC & 0xff); } } - /* here we should issue an 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 if (!srst_asserted) - { - jtag_add_reset(0, 1); + if (use_event) { + target_handle_event(target, TARGET_EVENT_RESET_ASSERT); + } else { + /* If we use SRST ... we'd like to issue just SRST, but the + * board or chip may be set up so we have to assert TRST as + * well. On some chips that combination is equivalent to a + * power-up reset, and generally clobbers EICE state. + */ + if (jtag_reset_config & RESET_SRST_PULLS_TRST) + jtag_add_reset(1, 1); + else if (!srst_asserted) + jtag_add_reset(0, 1); + jtag_add_sleep(50000); } target->state = TARGET_RESET; - jtag_add_sleep(50000); - register_cache_invalidate(arm7_9->armv4_5_common.core_cache); - if ((target->reset_halt) && ((jtag_reset_config & RESET_SRST_PULLS_TRST) == 0)) + /* REVISIT why isn't standard debug entry logic sufficient?? */ + if (target->reset_halt + && (!(jtag_reset_config & RESET_SRST_PULLS_TRST) + || use_event)) { - /* debug entry was already prepared in arm7_9_assert_reset() */ + /* debug entry was prepared above */ target->debug_reason = DBG_REASON_DBGRQ; } @@ -1061,24 +1075,29 @@ int arm7_9_deassert_reset(struct target *target) /* deassert reset lines */ jtag_add_reset(0, 0); + /* In case polling is disabled, we need to examine the + * target and poll here for this target to work correctly. + * + * Otherwise, e.g. halt will fail afterwards with bogus + * error messages as halt will believe that reset is + * still in effect. + */ + if ((retval = target_examine_one(target)) != ERROR_OK) + return retval; + + if ((retval = target_poll(target)) != ERROR_OK) + { + return retval; + } + enum reset_types jtag_reset_config = jtag_get_reset_config(); if (target->reset_halt && (jtag_reset_config & RESET_SRST_PULLS_TRST) != 0) { LOG_WARNING("srst pulls trst - can not reset into halted mode. Issuing halt after reset."); - /* set up embedded ice registers again */ - if ((retval = target_examine_one(target)) != ERROR_OK) - return retval; - - if ((retval = target_poll(target)) != ERROR_OK) - { - return retval; - } - if ((retval = target_halt(target)) != ERROR_OK) { return retval; } - } return retval; } @@ -1092,7 +1111,7 @@ int arm7_9_deassert_reset(struct target *target) * @param target Pointer to the ARM7/9 target to have halt cleared * @return Always ERROR_OK */ -int arm7_9_clear_halt(struct target *target) +static int arm7_9_clear_halt(struct target *target) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct reg *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]; @@ -1230,9 +1249,9 @@ int arm7_9_soft_reset_halt(struct target *target) armv4_5->cpsr->dirty = 1; /* start fetching from 0x0 */ - buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, 0x0); - armv4_5->core_cache->reg_list[15].dirty = 1; - armv4_5->core_cache->reg_list[15].valid = 1; + buf_set_u32(armv4_5->pc->value, 0, 32, 0x0); + armv4_5->pc->dirty = 1; + armv4_5->pc->valid = 1; /* reset registers */ for (i = 0; i <= 14; i++) @@ -1466,7 +1485,11 @@ static int arm7_9_debug_entry(struct target *target) return retval; if (arm7_9->post_debug_entry) - arm7_9->post_debug_entry(target); + { + retval = arm7_9->post_debug_entry(target); + if (retval != ERROR_OK) + return retval; + } return ERROR_OK; } @@ -1480,7 +1503,7 @@ static int arm7_9_debug_entry(struct target *target) * @return Error if the target is not halted, has an invalid core mode, or if * the JTAG queue fails to execute */ -int arm7_9_full_context(struct target *target) +static int arm7_9_full_context(struct target *target) { int i; int retval; @@ -1496,7 +1519,10 @@ int arm7_9_full_context(struct target *target) } if (!is_arm_mode(armv4_5->core_mode)) + { + LOG_ERROR("not a valid arm core mode - communication failure?"); return ERROR_FAIL; + } /* iterate through processor modes (User, FIQ, IRQ, SVC, ABT, UND) * SYS shares registers with User, so we don't touch SYS @@ -1576,12 +1602,11 @@ int arm7_9_full_context(struct target *target) * @return Error status if the target is not halted or the core mode in the * armv4_5 struct is invalid. */ -int arm7_9_restore_context(struct target *target) +static int arm7_9_restore_context(struct target *target) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm *armv4_5 = &arm7_9->armv4_5_common; struct reg *reg; - struct arm_reg *reg_arch_info; enum arm_mode current_mode = armv4_5->core_mode; int i, j; int dirty; @@ -1599,7 +1624,10 @@ int arm7_9_restore_context(struct target *target) arm7_9->pre_restore_context(target); if (!is_arm_mode(armv4_5->core_mode)) + { + LOG_ERROR("not a valid arm core mode - communication failure?"); return ERROR_FAIL; + } /* iterate through processor modes (User, FIQ, IRQ, SVC, ABT, UND) * SYS shares registers with User, so we don't touch SYS @@ -1615,13 +1643,14 @@ int arm7_9_restore_context(struct target *target) for (j = 0; j <= 16; j++) { reg = &ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), j); - reg_arch_info = reg->arch_info; if (reg->dirty == 1) { if (reg->valid == 1) { dirty = 1; LOG_DEBUG("examining dirty reg: %s", reg->name); + struct arm_reg *reg_arch_info; + reg_arch_info = reg->arch_info; if ((reg_arch_info->mode != ARM_MODE_ANY) && (reg_arch_info->mode != current_mode) && !((reg_arch_info->mode == ARM_MODE_USR) && (armv4_5->core_mode == ARM_MODE_SYS)) @@ -1660,8 +1689,6 @@ int arm7_9_restore_context(struct target *target) for (j = 0; j <= 14; j++) { reg = &ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), j); - reg_arch_info = reg->arch_info; - if (reg->dirty == 1) { @@ -1683,6 +1710,7 @@ int arm7_9_restore_context(struct target *target) } reg = &ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), 16); + struct arm_reg *reg_arch_info; reg_arch_info = reg->arch_info; if ((reg->dirty) && (reg_arch_info->mode != ARM_MODE_ANY)) { @@ -1716,12 +1744,10 @@ int arm7_9_restore_context(struct target *target) } /* restore PC */ - LOG_DEBUG("writing PC with value 0x%8.8" PRIx32 "", buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32)); - arm7_9->write_pc(target, buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32)); - armv4_5->core_cache->reg_list[15].dirty = 0; - - if (arm7_9->post_restore_context) - arm7_9->post_restore_context(target); + LOG_DEBUG("writing PC with value 0x%8.8" PRIx32, + buf_get_u32(armv4_5->pc->value, 0, 32)); + arm7_9->write_pc(target, buf_get_u32(armv4_5->pc->value, 0, 32)); + armv4_5->pc->dirty = 0; return ERROR_OK; } @@ -1734,20 +1760,25 @@ int arm7_9_restore_context(struct target *target) * @param target Pointer to the ARM7/9 target to be restarted * @return Result of executing the JTAG queue */ -int arm7_9_restart_core(struct target *target) +static int arm7_9_restart_core(struct target *target) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; + int retval; /* set RESTART instruction */ - jtag_set_end_state(TAP_IDLE); if (arm7_9->need_bypass_before_restart) { arm7_9->need_bypass_before_restart = 0; - arm_jtag_set_instr(jtag_info, 0xf, NULL); + + retval = arm_jtag_set_instr(jtag_info, 0xf, NULL, TAP_IDLE); + if (retval != ERROR_OK) + return retval; } - arm_jtag_set_instr(jtag_info, 0x4, NULL); + retval = arm_jtag_set_instr(jtag_info, 0x4, NULL, TAP_IDLE); + if (retval != ERROR_OK) + return retval; - jtag_add_runtest(1, jtag_set_end_state(TAP_IDLE)); + jtag_add_runtest(1, TAP_IDLE); return jtag_execute_queue(); } @@ -1757,7 +1788,7 @@ int arm7_9_restart_core(struct target *target) * * @param target Pointer to the ARM7/9 target to enable watchpoints on */ -void arm7_9_enable_watchpoints(struct target *target) +static void arm7_9_enable_watchpoints(struct target *target) { struct watchpoint *watchpoint = target->watchpoints; @@ -1775,7 +1806,7 @@ void arm7_9_enable_watchpoints(struct target *target) * * @param target Pointer to the ARM7/9 target to enable breakpoints on */ -void arm7_9_enable_breakpoints(struct target *target) +static void arm7_9_enable_breakpoints(struct target *target) { struct breakpoint *breakpoint = target->breakpoints; @@ -1791,7 +1822,6 @@ int arm7_9_resume(struct target *target, int current, uint32_t address, int hand { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm *armv4_5 = &arm7_9->armv4_5_common; - struct breakpoint *breakpoint = target->breakpoints; struct reg *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]; int err, retval = ERROR_OK; @@ -1810,15 +1840,18 @@ int arm7_9_resume(struct target *target, int current, uint32_t address, int hand /* current = 1: continue on current pc, otherwise continue at
*/ if (!current) - buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, address); + buf_set_u32(armv4_5->pc->value, 0, 32, address); uint32_t current_pc; - current_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32); + current_pc = buf_get_u32(armv4_5->pc->value, 0, 32); /* the front-end may request us not to handle breakpoints */ if (handle_breakpoints) { - if ((breakpoint = breakpoint_find(target, buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32)))) + struct breakpoint *breakpoint; + breakpoint = breakpoint_find(target, + buf_get_u32(armv4_5->pc->value, 0, 32)); + if (breakpoint != NULL) { LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 " (id: %d)", breakpoint->address, breakpoint->unique_id ); if ((retval = arm7_9_unset_breakpoint(target, breakpoint)) != ERROR_OK) @@ -1875,8 +1908,11 @@ int arm7_9_resume(struct target *target, int current, uint32_t address, int hand return err; } - arm7_9_debug_entry(target); - LOG_DEBUG("new PC after step: 0x%8.8" PRIx32 "", buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32)); + retval = arm7_9_debug_entry(target); + if (retval != ERROR_OK) + return retval; + LOG_DEBUG("new PC after step: 0x%8.8" PRIx32, + buf_get_u32(armv4_5->pc->value, 0, 32)); LOG_DEBUG("set breakpoint at 0x%8.8" PRIx32 "", breakpoint->address); if ((retval = arm7_9_set_breakpoint(target, breakpoint)) != ERROR_OK) @@ -1952,7 +1988,7 @@ void arm7_9_enable_eice_step(struct target *target, uint32_t next_pc) struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm *armv4_5 = &arm7_9->armv4_5_common; uint32_t current_pc; - current_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32); + current_pc = buf_get_u32(armv4_5->pc->value, 0, 32); if (next_pc != current_pc) { @@ -2014,18 +2050,18 @@ int arm7_9_step(struct target *target, int current, uint32_t address, int handle /* current = 1: continue on current pc, otherwise continue at
*/ if (!current) - buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, address); + buf_set_u32(armv4_5->pc->value, 0, 32, address); - uint32_t current_pc; - current_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32); + uint32_t current_pc = buf_get_u32(armv4_5->pc->value, 0, 32); /* the front-end may request us not to handle breakpoints */ if (handle_breakpoints) - if ((breakpoint = breakpoint_find(target, buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32)))) - if ((retval = arm7_9_unset_breakpoint(target, breakpoint)) != ERROR_OK) - { - return retval; - } + breakpoint = breakpoint_find(target, current_pc); + if (breakpoint != NULL) { + retval = arm7_9_unset_breakpoint(target, breakpoint); + if (retval != ERROR_OK) + return retval; + } target->debug_reason = DBG_REASON_SINGLESTEP; @@ -2075,7 +2111,9 @@ int arm7_9_step(struct target *target, int current, uint32_t address, int handle { target->state = TARGET_UNKNOWN; } else { - arm7_9_debug_entry(target); + retval = arm7_9_debug_entry(target); + if (retval != ERROR_OK) + return retval; if ((retval = target_call_event_callbacks(target, TARGET_EVENT_HALTED)) != ERROR_OK) { return retval; @@ -2096,7 +2134,6 @@ static int arm7_9_read_core_reg(struct target *target, struct reg *r, int num, enum arm_mode mode) { uint32_t* reg_p[16]; - uint32_t value; int retval; struct arm_reg *areg = r->arch_info; struct arm7_9_common *arm7_9 = target_to_arm7_9(target); @@ -2105,7 +2142,7 @@ static int arm7_9_read_core_reg(struct target *target, struct reg *r, if (!is_arm_mode(armv4_5->core_mode)) return ERROR_FAIL; if ((num < 0) || (num > 16)) - return ERROR_INVALID_ARGUMENTS; + return ERROR_COMMAND_SYNTAX_ERROR; if ((mode != ARM_MODE_ANY) && (mode != armv4_5->core_mode) @@ -2120,6 +2157,7 @@ static int arm7_9_read_core_reg(struct target *target, struct reg *r, arm7_9->write_xpsr_im8(target, tmp_cpsr & 0xff, 0, 0); } + uint32_t value = 0; if ((num >= 0) && (num <= 15)) { /* read a normal core register */ @@ -2167,7 +2205,7 @@ static int arm7_9_write_core_reg(struct target *target, struct reg *r, if (!is_arm_mode(armv4_5->core_mode)) return ERROR_FAIL; if ((num < 0) || (num > 16)) - return ERROR_INVALID_ARGUMENTS; + return ERROR_COMMAND_SYNTAX_ERROR; if ((mode != ARM_MODE_ANY) && (mode != armv4_5->core_mode) @@ -2239,7 +2277,7 @@ int arm7_9_read_memory(struct target *target, uint32_t address, uint32_t size, u /* sanitize arguments */ if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer)) - return ERROR_INVALID_ARGUMENTS; + return ERROR_COMMAND_SYNTAX_ERROR; if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u))) return ERROR_TARGET_UNALIGNED_ACCESS; @@ -2361,10 +2399,6 @@ int arm7_9_read_memory(struct target *target, uint32_t address, uint32_t size, u } } break; - default: - LOG_ERROR("BUG: we shouldn't get here"); - exit(-1); - break; } if (!is_arm_mode(armv4_5->core_mode)) @@ -2397,7 +2431,7 @@ int arm7_9_read_memory(struct target *target, uint32_t address, uint32_t size, u return ERROR_OK; } -int arm7_9_write_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) +int arm7_9_write_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm *armv4_5 = &arm7_9->armv4_5_common; @@ -2423,7 +2457,7 @@ int arm7_9_write_memory(struct target *target, uint32_t address, uint32_t size, /* sanitize arguments */ if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer)) - return ERROR_INVALID_ARGUMENTS; + return ERROR_COMMAND_SYNTAX_ERROR; if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u))) return ERROR_TARGET_UNALIGNED_ACCESS; @@ -2463,7 +2497,20 @@ int arm7_9_write_memory(struct target *target, uint32_t address, uint32_t size, if (arm7_9->fast_memory_access) retval = arm7_9_execute_fast_sys_speed(target); else + { retval = arm7_9_execute_sys_speed(target); + + /* + * if memory writes are made when the clock is running slow + * (i.e. 32 kHz) which is necessary in some scripts to reconfigure + * processor operations after a "reset halt" or "reset init", + * need to immediately stroke the keep alive or will end up with + * gdb "keep alive not sent error message" problem. + */ + + keep_alive(); + } + if (retval != ERROR_OK) { return retval; @@ -2499,7 +2546,20 @@ int arm7_9_write_memory(struct target *target, uint32_t address, uint32_t size, if (arm7_9->fast_memory_access) retval = arm7_9_execute_fast_sys_speed(target); else + { retval = arm7_9_execute_sys_speed(target); + + /* + * if memory writes are made when the clock is running slow + * (i.e. 32 kHz) which is necessary in some scripts to reconfigure + * processor operations after a "reset halt" or "reset init", + * need to immediately stroke the keep alive or will end up with + * gdb "keep alive not sent error message" problem. + */ + + keep_alive(); + } + if (retval != ERROR_OK) { return retval; @@ -2534,7 +2594,20 @@ int arm7_9_write_memory(struct target *target, uint32_t address, uint32_t size, if (arm7_9->fast_memory_access) retval = arm7_9_execute_fast_sys_speed(target); else - retval = arm7_9_execute_sys_speed(target); + { + retval = arm7_9_execute_sys_speed(target); + + /* + * if memory writes are made when the clock is running slow + * (i.e. 32 kHz) which is necessary in some scripts to reconfigure + * processor operations after a "reset halt" or "reset init", + * need to immediately stroke the keep alive or will end up with + * gdb "keep alive not sent error message" problem. + */ + + keep_alive(); + } + if (retval != ERROR_OK) { return retval; @@ -2545,10 +2618,6 @@ int arm7_9_write_memory(struct target *target, uint32_t address, uint32_t size, num_accesses += thisrun_accesses; } break; - default: - LOG_ERROR("BUG: we shouldn't get here"); - exit(-1); - break; } /* Re-Set DBGACK */ @@ -2586,7 +2655,7 @@ int arm7_9_write_memory(struct target *target, uint32_t address, uint32_t size, } static int dcc_count; -static uint8_t *dcc_buffer; +static const uint8_t *dcc_buffer; static int arm7_9_dcc_completion(struct target *target, uint32_t exit_point, int timeout_ms, void *arch_info) { @@ -2598,7 +2667,7 @@ static int arm7_9_dcc_completion(struct target *target, uint32_t exit_point, int int little = target->endianness == TARGET_LITTLE_ENDIAN; int count = dcc_count; - uint8_t *buffer = dcc_buffer; + const uint8_t *buffer = dcc_buffer; if (count > 2) { /* Handle first & last using standard embeddedice_write_reg and the middle ones w/the @@ -2651,15 +2720,7 @@ static const uint32_t dcc_code[] = 0xeafffff9 /* b w */ }; -extern int armv4_5_run_algorithm_inner(struct target *target, - int num_mem_params, struct mem_param *mem_params, - int num_reg_params, struct reg_param *reg_params, - uint32_t entry_point, uint32_t exit_point, - int timeout_ms, void *arch_info, - int (*run_it)(struct target *target, uint32_t exit_point, - int timeout_ms, void *arch_info)); - -int arm7_9_bulk_write_memory(struct target *target, uint32_t address, uint32_t count, uint8_t *buffer) +int arm7_9_bulk_write_memory(struct target *target, uint32_t address, uint32_t count, const uint8_t *buffer) { int retval; struct arm7_9_common *arm7_9 = target_to_arm7_9(target); @@ -2761,6 +2822,29 @@ int arm7_9_examine(struct target *target) return retval; } + +int arm7_9_check_reset(struct target *target) +{ + struct arm7_9_common *arm7_9 = target_to_arm7_9(target); + + if (get_target_reset_nag() && !arm7_9->dcc_downloads) + { + LOG_WARNING("NOTE! DCC downloads have not been enabled, defaulting to slow memory writes. Type 'help dcc'."); + } + + if (get_target_reset_nag() && (target->working_area_size == 0)) + { + LOG_WARNING("NOTE! Severe performance degradation without working memory enabled."); + } + + if (get_target_reset_nag() && !arm7_9->fast_memory_access) + { + LOG_WARNING("NOTE! Severe performance degradation without fast memory access enabled. Type 'help fast'."); + } + + return ERROR_OK; +} + COMMAND_HANDLER(handle_arm7_9_dbgrq_command) { struct target *target = get_current_target(CMD_CTX); @@ -2818,48 +2902,32 @@ COMMAND_HANDLER(handle_arm7_9_dcc_downloads_command) return ERROR_OK; } -COMMAND_HANDLER(handle_arm7_9_semihosting_command) +static int arm7_9_setup_semihosting(struct target *target, int enable) { - struct target *target = get_current_target(CMD_CTX); struct arm7_9_common *arm7_9 = target_to_arm7_9(target); if (!is_arm7_9(arm7_9)) { - command_print(CMD_CTX, "current target isn't an ARM7/ARM9 target"); + LOG_USER("current target isn't an ARM7/ARM9 target"); return ERROR_TARGET_INVALID; } - if (CMD_ARGC > 0) - { - int semihosting; - - COMMAND_PARSE_ENABLE(CMD_ARGV[0], semihosting); - - if (arm7_9->has_vector_catch) { - struct reg *vector_catch = &arm7_9->eice_cache - ->reg_list[EICE_VEC_CATCH]; - - if (!vector_catch->valid) - embeddedice_read_reg(vector_catch); - buf_set_u32(vector_catch->value, 2, 1, semihosting); - embeddedice_store_reg(vector_catch); - } else { - /* TODO: allow optional high vectors and/or BKPT_HARD */ - if (semihosting) - breakpoint_add(target, 8, 4, BKPT_SOFT); - else - breakpoint_remove(target, 8); - } - - /* FIXME never let that "catch" be dropped! */ - arm7_9->armv4_5_common.is_semihosting = semihosting; + if (arm7_9->has_vector_catch) { + struct reg *vector_catch = &arm7_9->eice_cache + ->reg_list[EICE_VEC_CATCH]; + if (!vector_catch->valid) + embeddedice_read_reg(vector_catch); + buf_set_u32(vector_catch->value, 2, 1, enable); + embeddedice_store_reg(vector_catch); + } else { + /* TODO: allow optional high vectors and/or BKPT_HARD */ + if (enable) + breakpoint_add(target, 8, 4, BKPT_SOFT); + else + breakpoint_remove(target, 8); } - command_print(CMD_CTX, "semihosting is %s", - arm7_9->armv4_5_common.is_semihosting - ? "enabled" : "disabled"); - return ERROR_OK; } @@ -2884,6 +2952,7 @@ int arm7_9_init_arch_info(struct target *target, struct arm7_9_common *arm7_9) armv4_5->read_core_reg = arm7_9_read_core_reg; armv4_5->write_core_reg = arm7_9_write_core_reg; armv4_5->full_context = arm7_9_full_context; + armv4_5->setup_semihosting = arm7_9_setup_semihosting; retval = arm_init_arch_info(target, armv4_5); if (retval != ERROR_OK) @@ -2896,34 +2965,27 @@ int arm7_9_init_arch_info(struct target *target, struct arm7_9_common *arm7_9) static const struct command_registration arm7_9_any_command_handlers[] = { { "dbgrq", - .handler = &handle_arm7_9_dbgrq_command, + .handler = handle_arm7_9_dbgrq_command, .mode = COMMAND_ANY, - .usage = "", + .usage = "['enable'|'disable']", .help = "use EmbeddedICE dbgrq instead of breakpoint " "for target halt requests", }, { "fast_memory_access", - .handler = &handle_arm7_9_fast_memory_access_command, + .handler = handle_arm7_9_fast_memory_access_command, .mode = COMMAND_ANY, - .usage = "", + .usage = "['enable'|'disable']", .help = "use fast memory accesses instead of slower " "but potentially safer accesses", }, { "dcc_downloads", - .handler = &handle_arm7_9_dcc_downloads_command, + .handler = handle_arm7_9_dcc_downloads_command, .mode = COMMAND_ANY, - .usage = "", + .usage = "['enable'|'disable']", .help = "use DCC downloads for larger memory writes", }, - { - "semihosting", - .handler = &handle_arm7_9_semihosting_command, - .mode = COMMAND_EXEC, - .usage = "", - .help = "activate support for semihosting operations", - }, COMMAND_REGISTRATION_DONE }; const struct command_registration arm7_9_command_handlers[] = { @@ -2937,6 +2999,7 @@ const struct command_registration arm7_9_command_handlers[] = { .name = "arm7_9", .mode = COMMAND_ANY, .help = "arm7/9 specific commands", + .usage = "", .chain = arm7_9_any_command_handlers, }, COMMAND_REGISTRATION_DONE