jtag: stop using sharp corner of JTAG API
[fw/openocd] / src / target / arm7_9_common.c
index e5969806148bc6dbe367d23b3338421ec4110125..5fbcd4dee23c3684916bff82e2b2b9b149482203 100644 (file)
@@ -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     *
@@ -182,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);
 
@@ -200,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;
@@ -329,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);
@@ -375,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 *)&current_instr);
                        if (current_instr == arm7_9->arm_bkpt)
                                if ((retval = target_write_memory(target, breakpoint->address, 4, 1, breakpoint->orig_instr)) != ERROR_OK)
                                {
@@ -389,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 *)&current_instr);
                        if (current_instr == arm7_9->thumb_bkpt)
                                if ((retval = target_write_memory(target, breakpoint->address, 2, 1, breakpoint->orig_instr)) != ERROR_OK)
                                {
@@ -504,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);
@@ -575,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);
@@ -685,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;
@@ -728,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];
@@ -736,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)
        {
@@ -804,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;
@@ -941,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;
        }
 
@@ -963,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);
@@ -973,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;
        }
 
@@ -1039,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;
 }
@@ -1070,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];
@@ -1208,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++)
@@ -1444,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;
 }
@@ -1458,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;
@@ -1474,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
@@ -1554,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;
@@ -1577,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
@@ -1593,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))
@@ -1638,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)
                                {
@@ -1661,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))
                        {
@@ -1694,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;
 }
@@ -1712,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();
 }
 
@@ -1735,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;
 
@@ -1753,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;
 
@@ -1769,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;
 
@@ -1788,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 <address> */
        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)
@@ -1853,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)
@@ -1930,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)
        {
@@ -1992,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 <address> */
        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;
 
@@ -2053,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;
@@ -2074,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);
@@ -2098,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 */
@@ -2371,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;
@@ -2437,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;
@@ -2473,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;
@@ -2508,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;
@@ -2556,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)
 {
@@ -2568,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
@@ -2621,7 +2720,7 @@ static const uint32_t dcc_code[] =
        0xeafffff9      /*    b   w                   */
 };
 
-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);
@@ -2723,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);
@@ -2780,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;
 }
 
@@ -2846,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)
@@ -2858,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 = "<enable|disable>",
+               .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 = "<enable|disable>",
+               .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 = "<enable | disable>",
+               .usage = "['enable'|'disable']",
                .help = "use DCC downloads for larger memory writes",
        },
-       {
-               "semihosting",
-               .handler = &handle_arm7_9_semihosting_command,
-               .mode = COMMAND_EXEC,
-               .usage = "<enable | disable>",
-               .help = "activate support for semihosting operations",
-       },
        COMMAND_REGISTRATION_DONE
 };
 const struct command_registration arm7_9_command_handlers[] = {