use COMMAND_HANDLER macro to define all commands
[fw/openocd] / src / target / arm7_9_common.c
index b6fd69701cf722effe4c09e4950a57fcea59b2fb..6a56417e26d1089e9c575331e6af775aed9b28db 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,2008 Øyvind Harboe                                 *
  *   oyvind.harboe@zylin.com                                               *
  *                                                                         *
  *   Copyright (C) 2008 by Spencer Oliver                                  *
 
 
 int arm7_9_debug_entry(target_t *target);
-int arm7_9_enable_sw_bkpts(struct target_s *target);
-
-/* command handler forward declarations */
-int handle_arm7_9_write_xpsr_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_arm7_9_write_xpsr_im8_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_arm7_9_read_core_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_arm7_9_write_core_reg_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_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);
 
 /**
  * Clear watchpoints for an ARM7/9 target.
@@ -58,8 +47,10 @@ int handle_arm7_9_etm_command(struct command_context_s *cmd_ctx, char *cmd, char
  */
 static int arm7_9_clear_watchpoints(arm7_9_common_t *arm7_9)
 {
+       LOG_DEBUG("-");
        embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], 0x0);
        embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE], 0x0);
+       arm7_9->sw_breakpoint_count = 0;
        arm7_9->sw_breakpoints_added = 0;
        arm7_9->wp0_used = 0;
        arm7_9->wp1_used = arm7_9->wp1_used_default;
@@ -93,6 +84,10 @@ static void arm7_9_assign_wp(arm7_9_common_t *arm7_9, breakpoint_t *breakpoint)
        {
                LOG_ERROR("BUG: no hardware comparator available");
        }
+       LOG_DEBUG("BPID: %d (0x%08" PRIx32 ") using hw wp: %d",
+                         breakpoint->unique_id,
+                         breakpoint->address,
+                         breakpoint->set );
 }
 
 /**
@@ -152,6 +147,8 @@ static int arm7_9_set_software_breakpoints(arm7_9_common_t *arm7_9)
                LOG_ERROR("BUG: both watchpoints used, but wp_available >= 1");
                return ERROR_FAIL;
        }
+       LOG_DEBUG("SW BP using hw wp: %d",
+                         arm7_9->sw_breakpoints_added );
 
        return jtag_execute_queue();
 }
@@ -164,8 +161,7 @@ static int arm7_9_set_software_breakpoints(arm7_9_common_t *arm7_9)
  */
 int arm7_9_setup(target_t *target)
 {
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       struct arm7_9_common_s *arm7_9 = target_to_arm7_9(target);
 
        return arm7_9_clear_watchpoints(arm7_9);
 }
@@ -184,18 +180,18 @@ int arm7_9_setup(target_t *target)
  */
 int arm7_9_get_arch_pointers(target_t *target, armv4_5_common_t **armv4_5_p, arm7_9_common_t **arm7_9_p)
 {
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       struct arm7_9_common_s *arm7_9 = target_to_arm7_9(target);
+       struct armv4_5_common_s *armv4_5 = &arm7_9->armv4_5_common;
 
+       /* FIXME stop using this routine; just target_to_arm7_9() and
+        * verify the resulting pointer using a replacement routine
+        * that emits a usage message.
+        */
        if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
-       {
-               return -1;
-       }
+               return ERROR_TARGET_INVALID;
 
        if (arm7_9->common_magic != ARM7_9_COMMON_MAGIC)
-       {
-               return -1;
-       }
+               return ERROR_TARGET_INVALID;
 
        *armv4_5_p = armv4_5;
        *arm7_9_p = arm7_9;
@@ -216,10 +212,14 @@ int arm7_9_get_arch_pointers(target_t *target, armv4_5_common_t **armv4_5_p, arm
  */
 int arm7_9_set_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;
+       struct arm7_9_common_s *arm7_9 = target_to_arm7_9(target);
        int retval = ERROR_OK;
 
+       LOG_DEBUG("BPID: %d, Address: 0x%08" PRIx32 ", Type: %d" ,
+                         breakpoint->unique_id,
+                         breakpoint->address,
+                         breakpoint->type);
+
        if (target->state != TARGET_HALTED)
        {
                LOG_WARNING("target not halted");
@@ -263,9 +263,6 @@ int arm7_9_set_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
        }
        else if (breakpoint->type == BKPT_SOFT)
        {
-               if ((retval = arm7_9_set_software_breakpoints(arm7_9)) != ERROR_OK)
-                       return retval;
-
                /* did we already set this breakpoint? */
                if (breakpoint->set)
                        return ERROR_OK;
@@ -318,6 +315,12 @@ int arm7_9_set_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
                                return ERROR_OK;
                        }
                }
+
+               if ((retval = arm7_9_set_software_breakpoints(arm7_9)) != ERROR_OK)
+                       return retval;
+
+               arm7_9->sw_breakpoint_count++;
+
                breakpoint->set = 1;
        }
 
@@ -339,9 +342,11 @@ int arm7_9_set_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
 int arm7_9_unset_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
 {
        int retval = ERROR_OK;
+       struct arm7_9_common_s *arm7_9 = target_to_arm7_9(target);
 
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       LOG_DEBUG("BPID: %d, Address: 0x%08" PRIx32,
+                         breakpoint->unique_id,
+                         breakpoint->address );
 
        if (!breakpoint->set)
        {
@@ -351,6 +356,9 @@ int arm7_9_unset_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
 
        if (breakpoint->type == BKPT_HARD)
        {
+               LOG_DEBUG("BPID: %d Releasing hw wp: %d",
+                                 breakpoint->unique_id,
+                                 breakpoint->set );
                if (breakpoint->set == 1)
                {
                        embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], 0x0);
@@ -397,6 +405,20 @@ int arm7_9_unset_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
                                        return retval;
                                }
                }
+
+               if (--arm7_9->sw_breakpoint_count==0)
+               {
+                       /* We have removed the last sw breakpoint, clear the hw breakpoint we used to implement it */
+                       if (arm7_9->sw_breakpoints_added == 1)
+                       {
+                               embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], 0);
+                       }
+                       else if (arm7_9->sw_breakpoints_added == 2)
+                       {
+                               embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE], 0);
+                       }
+               }
+
                breakpoint->set = 0;
        }
 
@@ -414,8 +436,7 @@ int arm7_9_unset_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
  */
 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;
+       struct arm7_9_common_s *arm7_9 = target_to_arm7_9(target);
 
        if (target->state != TARGET_HALTED)
        {
@@ -466,8 +487,7 @@ int arm7_9_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
 int arm7_9_remove_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
 {
        int retval = ERROR_OK;
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       struct arm7_9_common_s *arm7_9 = target_to_arm7_9(target);
 
        if ((retval = arm7_9_unset_breakpoint(target, breakpoint)) != ERROR_OK)
        {
@@ -503,8 +523,7 @@ int arm7_9_remove_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
 int arm7_9_set_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
 {
        int retval = ERROR_OK;
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       struct arm7_9_common_s *arm7_9 = target_to_arm7_9(target);
        int rw_mask = 1;
        uint32_t mask;
 
@@ -526,7 +545,7 @@ int arm7_9_set_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
                embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_VALUE], watchpoint->address);
                embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK], mask);
                embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK], watchpoint->mask);
-               if (watchpoint->mask != 0xffffffffu )
+               if (watchpoint->mask != 0xffffffffu)
                        embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_VALUE], watchpoint->value);
                embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK], 0xff & ~EICE_W_CTRL_nOPC & ~rw_mask);
                embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], EICE_W_CTRL_ENABLE | EICE_W_CTRL_nOPC | (watchpoint->rw & 1));
@@ -543,7 +562,7 @@ int arm7_9_set_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
                embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_ADDR_VALUE], watchpoint->address);
                embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_ADDR_MASK], mask);
                embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_DATA_MASK], watchpoint->mask);
-               if (watchpoint->mask != 0xffffffffu )
+               if (watchpoint->mask != 0xffffffffu)
                        embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_DATA_VALUE], watchpoint->value);
                embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_MASK], 0xff & ~EICE_W_CTRL_nOPC & ~rw_mask);
                embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE], EICE_W_CTRL_ENABLE | EICE_W_CTRL_nOPC | (watchpoint->rw & 1));
@@ -575,8 +594,7 @@ int arm7_9_set_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
 int arm7_9_unset_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
 {
        int retval = ERROR_OK;
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       struct arm7_9_common_s *arm7_9 = target_to_arm7_9(target);
 
        if (target->state != TARGET_HALTED)
        {
@@ -623,8 +641,7 @@ int arm7_9_unset_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
  */
 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;
+       struct arm7_9_common_s *arm7_9 = target_to_arm7_9(target);
 
        if (target->state != TARGET_HALTED)
        {
@@ -658,8 +675,7 @@ int arm7_9_add_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
 int arm7_9_remove_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
 {
        int retval = ERROR_OK;
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       struct arm7_9_common_s *arm7_9 = target_to_arm7_9(target);
 
        if (watchpoint->set)
        {
@@ -686,9 +702,7 @@ int arm7_9_remove_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
 int arm7_9_execute_sys_speed(struct target_s *target)
 {
        int retval;
-
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       struct arm7_9_common_s *arm7_9 = target_to_arm7_9(target);
        arm_jtag_t *jtag_info = &arm7_9->jtag_info;
        reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
 
@@ -741,8 +755,7 @@ int arm7_9_execute_fast_sys_speed(struct target_s *target)
        static int set = 0;
        static uint8_t 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;
+       struct arm7_9_common_s *arm7_9 = target_to_arm7_9(target);
        arm_jtag_t *jtag_info = &arm7_9->jtag_info;
        reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
 
@@ -783,8 +796,7 @@ int arm7_9_execute_fast_sys_speed(struct target_s *target)
  */
 int arm7_9_target_request_data(target_t *target, uint32_t size, uint8_t *buffer)
 {
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       struct arm7_9_common_s *arm7_9 = target_to_arm7_9(target);
        arm_jtag_t *jtag_info = &arm7_9->jtag_info;
        uint32_t *data;
        int retval = ERROR_OK;
@@ -820,8 +832,7 @@ int arm7_9_handle_target_request(void *priv)
        target_t *target = priv;
        if (!target_was_examined(target))
                return ERROR_OK;
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       struct arm7_9_common_s *arm7_9 = target_to_arm7_9(target);
        arm_jtag_t *jtag_info = &arm7_9->jtag_info;
        reg_t *dcc_control = &arm7_9->eice_cache->reg_list[EICE_COMMS_CTRL];
 
@@ -879,8 +890,7 @@ int arm7_9_handle_target_request(void *priv)
 int 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;
+       struct arm7_9_common_s *arm7_9 = target_to_arm7_9(target);
        reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
 
        /* read debug status register */
@@ -895,8 +905,9 @@ int arm7_9_poll(target_t *target)
 /*             LOG_DEBUG("DBGACK set, dbg_state->value: 0x%x", buf_get_u32(dbg_stat->value, 0, 32));*/
                if (target->state == TARGET_UNKNOWN)
                {
+                       /* Starting OpenOCD with target in debug-halt */
                        target->state = TARGET_RUNNING;
-                       LOG_WARNING("DBGACK set while target was in unknown state. Reset or initialize target.");
+                       LOG_DEBUG("DBGACK already set during server startup.");
                }
                if ((target->state == TARGET_RUNNING) || (target->state == TARGET_RESET))
                {
@@ -971,10 +982,10 @@ int arm7_9_poll(target_t *target)
  */
 int arm7_9_assert_reset(target_t *target)
 {
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       struct arm7_9_common_s *arm7_9 = target_to_arm7_9(target);
+
        LOG_DEBUG("target->state: %s",
-                 Jim_Nvp_value2name_simple(nvp_target_state,target->state)->name);
+                 target_state_name(target));
 
        enum reset_types jtag_reset_config = jtag_get_reset_config();
        if (!(jtag_reset_config & RESET_HAS_SRST))
@@ -983,6 +994,24 @@ int arm7_9_assert_reset(target_t *target)
                return ERROR_FAIL;
        }
 
+       /* At this point trst has been asserted/deasserted once. We would
+        * like to program EmbeddedICE while SRST is asserted, instead of
+        * depending on SRST to leave that module alone.  However, many CPUs
+        * gate the JTAG clock while SRST is asserted; or JTAG may need
+        * clock stability guarantees (adaptive clocking might help).
+        *
+        * So we assume JTAG access during SRST is off the menu unless it's
+        * been specifically enabled.
+        */
+       bool srst_asserted = false;
+
+       if (((jtag_reset_config & RESET_SRST_PULLS_TRST) == 0)
+                       && (jtag_reset_config & RESET_SRST_NO_GATING))
+       {
+               jtag_add_reset(0, 1);
+               srst_asserted = true;
+       }
+
        if (target->reset_halt)
        {
                /*
@@ -996,6 +1025,9 @@ int arm7_9_assert_reset(target_t *target)
                {
                        /* program vector catch register to catch reset vector */
                        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());
                }
                else
                {
@@ -1012,7 +1044,7 @@ int arm7_9_assert_reset(target_t *target)
        if (jtag_reset_config & RESET_SRST_PULLS_TRST)
        {
                jtag_add_reset(1, 1);
-       } else
+       } else if (!srst_asserted)
        {
                jtag_add_reset(0, 1);
        }
@@ -1044,7 +1076,7 @@ int arm7_9_deassert_reset(target_t *target)
 {
        int retval = ERROR_OK;
        LOG_DEBUG("target->state: %s",
-               Jim_Nvp_value2name_simple(nvp_target_state,target->state)->name);
+               target_state_name(target));
 
        /* deassert reset lines */
        jtag_add_reset(0, 0);
@@ -1082,8 +1114,7 @@ int arm7_9_deassert_reset(target_t *target)
  */
 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;
+       struct arm7_9_common_s *arm7_9 = target_to_arm7_9(target);
        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 */
@@ -1140,13 +1171,20 @@ int arm7_9_clear_halt(target_t *target)
  */
 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;
+       struct arm7_9_common_s *arm7_9 = target_to_arm7_9(target);
+       struct armv4_5_common_s *armv4_5 = &arm7_9->armv4_5_common;
        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;
        int retval;
 
+       /* FIX!!! replace some of this code with tcl commands
+        *
+        * halt # the halt command is synchronous
+        * armv4_5 core_state arm
+        *
+        */
+
        if ((retval = target_halt(target)) != ERROR_OK)
                return retval;
 
@@ -1252,12 +1290,11 @@ int arm7_9_halt(target_t *target)
                return ERROR_OK;
        }
 
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       struct arm7_9_common_s *arm7_9 = target_to_arm7_9(target);
        reg_t *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];
 
        LOG_DEBUG("target->state: %s",
-                 Jim_Nvp_value2name_simple(nvp_target_state,target->state)->name);
+                 target_state_name(target));
 
        if (target->state == TARGET_HALTED)
        {
@@ -1315,9 +1352,8 @@ int arm7_9_debug_entry(target_t *target)
        uint32_t r0_thumb, pc_thumb;
        uint32_t cpsr;
        int retval;
-       /* get pointers to arch-specific information */
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       struct arm7_9_common_s *arm7_9 = target_to_arm7_9(target);
+       struct armv4_5_common_s *armv4_5 = &arm7_9->armv4_5_common;
        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];
 
@@ -1325,9 +1361,6 @@ int arm7_9_debug_entry(target_t *target)
        LOG_DEBUG("-");
 #endif
 
-       if (arm7_9->pre_debug_entry)
-               arm7_9->pre_debug_entry(target);
-
        /* program EmbeddedICE Debug Control Register to assert DBGACK and INTDIS
         * ensure that DBGRQ is cleared
         */
@@ -1412,18 +1445,10 @@ int arm7_9_debug_entry(target_t *target)
                context[15] -= 3 * 4;
        }
 
-       if ((target->debug_reason == DBG_REASON_BREAKPOINT)
-                       || (target->debug_reason == DBG_REASON_SINGLESTEP)
-                       || (target->debug_reason == DBG_REASON_WATCHPOINT)
-                       || (target->debug_reason == DBG_REASON_WPTANDBKPT)
-                       || ((target->debug_reason == DBG_REASON_DBGRQ) && (arm7_9->use_dbgrq == 0)))
+       if ((target->debug_reason != DBG_REASON_DBGRQ) || (!arm7_9->use_dbgrq))
                context[15] -= 3 * ((armv4_5->core_state == ARMV4_5_STATE_ARM) ? 4 : 2);
-       else if (target->debug_reason == DBG_REASON_DBGRQ)
-               context[15] -= arm7_9->dbgreq_adjust_pc * ((armv4_5->core_state == ARMV4_5_STATE_ARM) ? 4 : 2);
        else
-       {
-               LOG_ERROR("unknown debug reason: %i", target->debug_reason);
-       }
+               context[15] -= arm7_9->dbgreq_adjust_pc * ((armv4_5->core_state == ARMV4_5_STATE_ARM) ? 4 : 2);
 
        if (armv4_5_mode_to_number(armv4_5->core_mode)==-1)
                return ERROR_FAIL;
@@ -1481,8 +1506,8 @@ int arm7_9_full_context(target_t *target)
 {
        int i;
        int retval;
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       struct arm7_9_common_s *arm7_9 = target_to_arm7_9(target);
+       struct armv4_5_common_s *armv4_5 = &arm7_9->armv4_5_common;
 
        LOG_DEBUG("-");
 
@@ -1572,8 +1597,8 @@ int arm7_9_full_context(target_t *target)
  */
 int arm7_9_restore_context(target_t *target)
 {
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       struct arm7_9_common_s *arm7_9 = target_to_arm7_9(target);
+       struct armv4_5_common_s *armv4_5 = &arm7_9->armv4_5_common;
        reg_t *reg;
        armv4_5_core_reg_t *reg_arch_info;
        enum armv4_5_mode current_mode = armv4_5->core_mode;
@@ -1722,8 +1747,7 @@ int arm7_9_restore_context(target_t *target)
  */
 int arm7_9_restart_core(struct target_s *target)
 {
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       struct arm7_9_common_s *arm7_9 = target_to_arm7_9(target);
        arm_jtag_t *jtag_info = &arm7_9->jtag_info;
 
        /* set RESTART instruction */
@@ -1776,8 +1800,8 @@ void arm7_9_enable_breakpoints(struct target_s *target)
 
 int arm7_9_resume(struct target_s *target, int current, uint32_t address, int handle_breakpoints, int debug_execution)
 {
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       struct arm7_9_common_s *arm7_9 = target_to_arm7_9(target);
+       struct armv4_5_common_s *armv4_5 = &arm7_9->armv4_5_common;
        breakpoint_t *breakpoint = target->breakpoints;
        reg_t *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];
        int err, retval = ERROR_OK;
@@ -1807,7 +1831,7 @@ int arm7_9_resume(struct target_s *target, int current, uint32_t address, int ha
        {
                if ((breakpoint = breakpoint_find(target, buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32))))
                {
-                       LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 "", breakpoint->address);
+                       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)
                        {
                                return retval;
@@ -1819,7 +1843,7 @@ int arm7_9_resume(struct target_s *target, int current, uint32_t address, int ha
                        {
                                uint32_t current_opcode;
                                target_read_u32(target, current_pc, &current_opcode);
-                               LOG_ERROR("BUG: couldn't calculate PC of next instruction, current opcode was 0x%8.8" PRIx32 "", current_opcode);
+                               LOG_ERROR("Couldn't calculate PC of next instruction, current opcode was 0x%8.8" PRIx32 "", current_opcode);
                                return retval;
                        }
 
@@ -1936,9 +1960,8 @@ int arm7_9_resume(struct target_s *target, int current, uint32_t address, int ha
 
 void arm7_9_enable_eice_step(target_t *target, uint32_t next_pc)
 {
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-
+       struct arm7_9_common_s *arm7_9 = target_to_arm7_9(target);
+       struct armv4_5_common_s *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);
 
@@ -1974,8 +1997,7 @@ void arm7_9_enable_eice_step(target_t *target, uint32_t next_pc)
 
 void arm7_9_disable_eice_step(target_t *target)
 {
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       struct arm7_9_common_s *arm7_9 = target_to_arm7_9(target);
 
        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]);
@@ -1990,8 +2012,8 @@ void arm7_9_disable_eice_step(target_t *target)
 
 int arm7_9_step(struct target_s *target, int current, uint32_t address, int handle_breakpoints)
 {
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       struct arm7_9_common_s *arm7_9 = target_to_arm7_9(target);
+       struct armv4_5_common_s *armv4_5 = &arm7_9->armv4_5_common;
        breakpoint_t *breakpoint = NULL;
        int err, retval;
 
@@ -2024,7 +2046,7 @@ int arm7_9_step(struct target_s *target, int current, uint32_t address, int hand
        {
                uint32_t current_opcode;
                target_read_u32(target, current_pc, &current_opcode);
-               LOG_ERROR("BUG: couldn't calculate PC of next instruction, current opcode was 0x%8.8" PRIx32 "", current_opcode);
+               LOG_ERROR("Couldn't calculate PC of next instruction, current opcode was 0x%8.8" PRIx32 "", current_opcode);
                return retval;
        }
 
@@ -2086,8 +2108,8 @@ int arm7_9_read_core_reg(struct target_s *target, int num, enum armv4_5_mode mod
        uint32_t* reg_p[16];
        uint32_t value;
        int retval;
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       struct arm7_9_common_s *arm7_9 = target_to_arm7_9(target);
+       struct armv4_5_common_s *armv4_5 = &arm7_9->armv4_5_common;
 
        if (armv4_5_mode_to_number(armv4_5->core_mode)==-1)
                return ERROR_FAIL;
@@ -2150,8 +2172,8 @@ int arm7_9_read_core_reg(struct target_s *target, int num, enum armv4_5_mode mod
 int arm7_9_write_core_reg(struct target_s *target, int num, enum armv4_5_mode mode, uint32_t value)
 {
        uint32_t reg[16];
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       struct arm7_9_common_s *arm7_9 = target_to_arm7_9(target);
+       struct armv4_5_common_s *armv4_5 = &arm7_9->armv4_5_common;
 
        if (armv4_5_mode_to_number(armv4_5->core_mode)==-1)
                return ERROR_FAIL;
@@ -2210,9 +2232,8 @@ int arm7_9_write_core_reg(struct target_s *target, int num, enum armv4_5_mode mo
 
 int arm7_9_read_memory(struct target_s *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
 {
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-
+       struct arm7_9_common_s *arm7_9 = target_to_arm7_9(target);
+       struct armv4_5_common_s *armv4_5 = &arm7_9->armv4_5_common;
        uint32_t reg[16];
        uint32_t num_accesses = 0;
        int thisrun_accesses;
@@ -2386,8 +2407,8 @@ int arm7_9_read_memory(struct target_s *target, uint32_t address, uint32_t size,
 
 int arm7_9_write_memory(struct target_s *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
 {
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       struct arm7_9_common_s *arm7_9 = target_to_arm7_9(target);
+       struct armv4_5_common_s *armv4_5 = &arm7_9->armv4_5_common;
        reg_t *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];
 
        uint32_t reg[16];
@@ -2573,8 +2594,7 @@ static uint8_t *dcc_buffer;
 static int arm7_9_dcc_completion(struct target_s *target, uint32_t exit_point, int timeout_ms, void *arch_info)
 {
        int retval = ERROR_OK;
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       struct arm7_9_common_s *arm7_9 = target_to_arm7_9(target);
 
        if ((retval = target_wait_state(target, TARGET_DEBUG_RUNNING, 500)) != ERROR_OK)
                return retval;
@@ -2617,8 +2637,21 @@ static int arm7_9_dcc_completion(struct target_s *target, uint32_t exit_point, i
 
 static const uint32_t dcc_code[] =
 {
-       /* MRC      TST         BNE         MRC         STR         B */
-       0xee101e10, 0xe3110001, 0x0afffffc, 0xee111e10, 0xe4801004, 0xeafffff9
+       /* r0 == input, points to memory buffer
+        * r1 == scratch
+        */
+
+       /* spin until DCC control (c0) reports data arrived */
+       0xee101e10,     /* w: mrc p14, #0, r1, c0, c0 */
+       0xe3110001,     /*    tst r1, #1              */
+       0x0afffffc,     /*    bne w                   */
+
+       /* read word from DCC (c1), write to memory */
+       0xee111e10,     /*    mrc p14, #0, r1, c1, c0 */
+       0xe4801004,     /*    str r1, [r0], #4        */
+
+       /* repeat */
+       0xeafffff9      /*    b   w                   */
 };
 
 int armv4_5_run_algorithm_inner(struct target_s *target, int num_mem_params, mem_param_t *mem_params, int num_reg_params, reg_param_t *reg_params, uint32_t entry_point, uint32_t exit_point, int timeout_ms, void *arch_info, int (*run_it)(struct target_s *target, uint32_t exit_point, int timeout_ms, void *arch_info));
@@ -2626,8 +2659,7 @@ int armv4_5_run_algorithm_inner(struct target_s *target, int num_mem_params, mem
 int arm7_9_bulk_write_memory(target_t *target, uint32_t address, uint32_t count, uint8_t *buffer)
 {
        int retval;
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       struct arm7_9_common_s *arm7_9 = target_to_arm7_9(target);
        int i;
 
        if (!arm7_9->dcc_downloads)
@@ -2696,7 +2728,7 @@ int arm7_9_checksum_memory(struct target_s *target, uint32_t address, uint32_t c
        reg_param_t reg_params[2];
        int retval;
 
-       uint32_t arm7_9_crc_code[] = {
+       static const uint32_t arm7_9_crc_code[] = {
                0xE1A02000,                             /* mov          r2, r0 */
                0xE3E00000,                             /* mov          r0, #0xffffffff */
                0xE1A03001,                             /* mov          r3, r1 */
@@ -2750,8 +2782,11 @@ int arm7_9_checksum_memory(struct target_s *target, uint32_t address, uint32_t c
        buf_set_u32(reg_params[0].value, 0, 32, address);
        buf_set_u32(reg_params[1].value, 0, 32, count);
 
+       /* 20 second timeout/megabyte */
+       int timeout = 20000 * (1 + (count / (1024*1024)));
+
        if ((retval = target_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)
+               crc_algorithm->address, crc_algorithm->address + (sizeof(arm7_9_crc_code) - 8), timeout, &armv4_5_info)) != ERROR_OK)
        {
                LOG_ERROR("error executing arm7_9 crc algorithm");
                destroy_reg_param(&reg_params[0]);
@@ -2778,15 +2813,15 @@ int arm7_9_blank_check_memory(struct target_s *target, uint32_t address, uint32_
        int retval;
        uint32_t i;
 
-       uint32_t erase_check_code[] =
+       static const uint32_t erase_check_code[] =
        {
-                                               /* loop: */
-               0xe4d03001,             /* ldrb r3, [r0], #1    */
-               0xe0022003,             /* and r2, r2, r3               */
-               0xe2511001,     /* subs r1, r1, #1              */
-               0x1afffffb,             /* bne loop                             */
-                                               /* end: */
-               0xeafffffe              /* b end                                */
+               /* loop: */
+               0xe4d03001,             /* ldrb r3, [r0], #1 */
+               0xe0022003,             /* and r2, r2, r3    */
+               0xe2511001,             /* subs r1, r1, #1   */
+               0x1afffffb,             /* bne loop          */
+               /* end: */
+               0xeafffffe              /* b end             */
        };
 
        /* make sure we have a working area */
@@ -2836,32 +2871,7 @@ int arm7_9_blank_check_memory(struct target_s *target, uint32_t address, uint32_
        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, "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, "write_core_reg", handle_arm7_9_write_core_reg_command, COMMAND_EXEC, "write core register <num> <mode> <value>");
-
-       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_memory_access", handle_arm7_9_fast_memory_access_command,
-                COMMAND_ANY, "use fast memory accesses instead of slower but potentially safer 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;
-}
-
-int handle_arm7_9_write_xpsr_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+COMMAND_HANDLER(handle_arm7_9_write_xpsr_command)
 {
        uint32_t value;
        int spsr;
@@ -2888,8 +2898,8 @@ int handle_arm7_9_write_xpsr_command(struct command_context_s *cmd_ctx, char *cm
                return ERROR_OK;
        }
 
-       value = strtoul(args[0], NULL, 0);
-       spsr = strtol(args[1], NULL, 0);
+       COMMAND_PARSE_NUMBER(u32, args[0], value);
+       COMMAND_PARSE_NUMBER(int, args[1], spsr);
 
        /* if we're writing the CPSR, mask the T bit */
        if (!spsr)
@@ -2905,7 +2915,7 @@ int handle_arm7_9_write_xpsr_command(struct command_context_s *cmd_ctx, char *cm
        return ERROR_OK;
 }
 
-int handle_arm7_9_write_xpsr_im8_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+COMMAND_HANDLER(handle_arm7_9_write_xpsr_im8_command)
 {
        uint32_t value;
        int rotate;
@@ -2933,9 +2943,9 @@ int handle_arm7_9_write_xpsr_im8_command(struct command_context_s *cmd_ctx, char
                return ERROR_OK;
        }
 
-       value = strtoul(args[0], NULL, 0);
-       rotate = strtol(args[1], NULL, 0);
-       spsr = strtol(args[2], NULL, 0);
+       COMMAND_PARSE_NUMBER(u32, args[0], value);
+       COMMAND_PARSE_NUMBER(int, args[1], rotate);
+       COMMAND_PARSE_NUMBER(int, args[2], spsr);
 
        arm7_9->write_xpsr_im8(target, value, rotate, spsr);
        if ((retval = jtag_execute_queue()) != ERROR_OK)
@@ -2947,7 +2957,7 @@ int handle_arm7_9_write_xpsr_im8_command(struct command_context_s *cmd_ctx, char
        return ERROR_OK;
 }
 
-int handle_arm7_9_write_core_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+COMMAND_HANDLER(handle_arm7_9_write_core_reg_command)
 {
        uint32_t value;
        uint32_t mode;
@@ -2974,14 +2984,14 @@ int handle_arm7_9_write_core_reg_command(struct command_context_s *cmd_ctx, char
                return ERROR_OK;
        }
 
-       num = strtol(args[0], NULL, 0);
-       mode = strtoul(args[1], NULL, 0);
-       value = strtoul(args[2], NULL, 0);
+       COMMAND_PARSE_NUMBER(int, args[0], num);
+       COMMAND_PARSE_NUMBER(u32, args[1], mode);
+       COMMAND_PARSE_NUMBER(u32, args[2], value);
 
        return arm7_9_write_core_reg(target, num, mode, value);
 }
 
-int handle_arm7_9_dbgrq_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+COMMAND_HANDLER(handle_arm7_9_dbgrq_command)
 {
        target_t *target = get_current_target(cmd_ctx);
        armv4_5_common_t *armv4_5;
@@ -3014,7 +3024,7 @@ int handle_arm7_9_dbgrq_command(struct command_context_s *cmd_ctx, char *cmd, ch
        return ERROR_OK;
 }
 
-int handle_arm7_9_fast_memory_access_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+COMMAND_HANDLER(handle_arm7_9_fast_memory_access_command)
 {
        target_t *target = get_current_target(cmd_ctx);
        armv4_5_common_t *armv4_5;
@@ -3047,7 +3057,7 @@ int handle_arm7_9_fast_memory_access_command(struct command_context_s *cmd_ctx,
        return ERROR_OK;
 }
 
-int handle_arm7_9_dcc_downloads_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+COMMAND_HANDLER(handle_arm7_9_dcc_downloads_command)
 {
        target_t *target = get_current_target(cmd_ctx);
        armv4_5_common_t *armv4_5;
@@ -3088,47 +3098,61 @@ int arm7_9_init_arch_info(target_t *target, arm7_9_common_t *arm7_9)
        arm7_9->common_magic = ARM7_9_COMMON_MAGIC;
 
        if ((retval = arm_jtag_setup_connection(&arm7_9->jtag_info)) != ERROR_OK)
-       {
                return retval;
-       }
 
-       arm7_9->wp_available = 0; /* this is set up in arm7_9_clear_watchpoints() */
-       arm7_9->wp_available_max = 2;
-       arm7_9->sw_breakpoints_added = 0;
-       arm7_9->breakpoint_count = 0;
-       arm7_9->wp0_used = 0;
-       arm7_9->wp1_used = 0;
-       arm7_9->wp1_used_default = 0;
-       arm7_9->use_dbgrq = 0;
-
-       arm7_9->etm_ctx = NULL;
-       arm7_9->has_single_step = 0;
-       arm7_9->has_monitor_mode = 0;
-       arm7_9->has_vector_catch = 0;
+       /* caller must have allocated via calloc(), so everything's zeroed */
 
-       arm7_9->debug_entry_from_reset = 0;
-
-       arm7_9->dcc_working_area = NULL;
+       arm7_9->wp_available_max = 2;
 
        arm7_9->fast_memory_access = fast_and_dangerous;
        arm7_9->dcc_downloads = fast_and_dangerous;
 
-       arm7_9->need_bypass_before_restart = 0;
-
        armv4_5->arch_info = 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;
 
        if ((retval = armv4_5_init_arch_info(target, armv4_5)) != ERROR_OK)
-       {
                return retval;
-       }
 
-       if ((retval = target_register_timer_callback(arm7_9_handle_target_request, 1, 1, target)) != ERROR_OK)
-       {
-               return retval;
-       }
+       return target_register_timer_callback(arm7_9_handle_target_request,
+                       1, 1, target);
+}
+
+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, "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, "write_core_reg",
+                       handle_arm7_9_write_core_reg_command, COMMAND_EXEC,
+                       "write core register <num> <mode> <value>");
+
+       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_memory_access",
+                       handle_arm7_9_fast_memory_access_command, COMMAND_ANY,
+                       "use fast memory accesses instead of slower "
+                       "but potentially safer 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;
 }