- convert all files to unix line-ending
[fw/openocd] / src / target / arm7_9_common.c
index e0ccd7a5ea237fb54b460b364c8176242509d80a..af0205d6855b8371d6560dadbf1d63a77e53c337 100644 (file)
  *   Free Software Foundation, Inc.,                                       *
  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  ***************************************************************************/
+#ifdef HAVE_CONFIG_H
 #include "config.h"
+#endif
+
+#include "replacements.h"
 
 #include "embeddedice.h"
 #include "target.h"
+#include "target_request.h"
 #include "armv4_5.h"
 #include "arm_jtag.h"
 #include "jtag.h"
@@ -48,8 +53,9 @@ int handle_arm7_9_write_core_reg_command(struct command_context_s *cmd_ctx, char
 int handle_arm7_9_sw_bkpts_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
 int handle_arm7_9_force_hw_bkpts_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
 int handle_arm7_9_dbgrq_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_arm7_9_fast_writes_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_arm7_9_fast_memory_access_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
 int handle_arm7_9_dcc_downloads_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_arm7_9_etm_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
 
 int arm7_9_reinit_embeddedice(target_t *target)
 {
@@ -180,13 +186,33 @@ int arm7_9_set_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
        {
                if (breakpoint->length == 4)
                {
+                       u32 verify = 0xffffffff;
+                       /* keep the original instruction in target endianness */
                        target->type->read_memory(target, breakpoint->address, 4, 1, breakpoint->orig_instr);
-                       target->type->write_memory(target, breakpoint->address, 4, 1, (u8*)(&arm7_9->arm_bkpt));
+                       /* write the breakpoint instruction in target endianness (arm7_9->arm_bkpt is host endian) */
+                       target_write_u32(target, breakpoint->address, arm7_9->arm_bkpt);
+                       
+                       target->type->read_memory(target, breakpoint->address, 4, 1, (u8 *)&verify);
+                       if (verify != arm7_9->arm_bkpt)
+                       {
+                               ERROR("Unable to set 32 bit software breakpoint at address %08x", breakpoint->address);
+                               return ERROR_OK;
+                       }
                }
                else
                {
+                       u16 verify = 0xffff;
+                       /* keep the original instruction in target endianness */
                        target->type->read_memory(target, breakpoint->address, 2, 1, breakpoint->orig_instr);
-                       target->type->read_memory(target, breakpoint->address, 2, 1, (u8*)(&arm7_9->arm_bkpt));
+                       /* write the breakpoint instruction in target endianness (arm7_9->thumb_bkpt is host endian) */
+                       target_write_u16(target, breakpoint->address, arm7_9->thumb_bkpt);
+                       
+                       target->type->read_memory(target, breakpoint->address, 2, 1, (u8 *)&verify);
+                       if (verify != arm7_9->thumb_bkpt)
+                       {
+                               ERROR("Unable to set thumb software breakpoint at address %08x", breakpoint->address);
+                               return ERROR_OK;
+                       }
                }
                breakpoint->set = 1;
        }
@@ -230,13 +256,22 @@ int arm7_9_unset_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
        }
        else
        {
+               /* restore original instruction (kept in target endianness) */
                if (breakpoint->length == 4)
                {
-                       target->type->write_memory(target, breakpoint->address, 4, 1, breakpoint->orig_instr);
+                       u32 current_instr;
+                       /* check that user program as not modified breakpoint instruction */
+                       target->type->read_memory(target, breakpoint->address, 4, 1, (u8*)&current_instr);
+                       if (current_instr==arm7_9->arm_bkpt)
+                               target->type->write_memory(target, breakpoint->address, 4, 1, breakpoint->orig_instr);
                }
                else
                {
-                       target->type->write_memory(target, breakpoint->address, 2, 1, breakpoint->orig_instr);
+                       u16 current_instr;
+                       /* check that user program as not modified breakpoint instruction */
+                       target->type->read_memory(target, breakpoint->address, 2, 1, (u8*)&current_instr);
+                       if (current_instr==arm7_9->thumb_bkpt)
+                               target->type->write_memory(target, breakpoint->address, 2, 1, breakpoint->orig_instr);
                }
                breakpoint->set = 0;
        }
@@ -244,7 +279,7 @@ int arm7_9_unset_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
        return ERROR_OK;
 }
 
-int arm7_9_add_breakpoint(struct target_s *target, u32 address, u32 length, enum breakpoint_type type)
+int arm7_9_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
 {
        armv4_5_common_t *armv4_5 = target->arch_info;
        arm7_9_common_t *arm7_9 = armv4_5->arch_info;
@@ -257,30 +292,31 @@ int arm7_9_add_breakpoint(struct target_s *target, u32 address, u32 length, enum
        
        if (arm7_9->force_hw_bkpts)
        {
-               type = BKPT_HARD;
+               DEBUG("forcing use of hardware breakpoint at address 0x%8.8x", breakpoint->address);
+               breakpoint->type = BKPT_HARD;
        }
        
-       if ((type == BKPT_SOFT) && (arm7_9->sw_bkpts_enabled == 0))
+       if ((breakpoint->type == BKPT_SOFT) && (arm7_9->sw_bkpts_enabled == 0))
        {
                INFO("sw breakpoint requested, but software breakpoints not enabled");
                return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
        }
        
-       if ((type == BKPT_HARD) && (arm7_9->wp_available < 1))
+       if ((breakpoint->type == BKPT_HARD) && (arm7_9->wp_available < 1))
        {
                INFO("no watchpoint unit available for hardware breakpoint");
                return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
        }
        
-       if (type == BKPT_HARD)
-               arm7_9->wp_available--;
-       
-       if ((length != 2) && (length != 4))
+       if ((breakpoint->length != 2) && (breakpoint->length != 4))
        {
                INFO("only breakpoints of two (Thumb) or four (ARM) bytes length supported");
                return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
        }
        
+       if (breakpoint->type == BKPT_HARD)
+               arm7_9->wp_available--;
+       
        return ERROR_OK;
 }
 
@@ -300,7 +336,8 @@ int arm7_9_remove_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
                arm7_9_unset_breakpoint(target, breakpoint);
        }
        
-       arm7_9->wp_available++;
+       if (breakpoint->type == BKPT_HARD)
+               arm7_9->wp_available++;
        
        return ERROR_OK;
 }
@@ -396,7 +433,7 @@ int arm7_9_unset_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
        return ERROR_OK;
 }
 
-int arm7_9_add_watchpoint(struct target_s *target, u32 address, u32 length, enum watchpoint_rw rw)
+int arm7_9_add_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
 {
        armv4_5_common_t *armv4_5 = target->arch_info;
        arm7_9_common_t *arm7_9 = armv4_5->arch_info;
@@ -412,7 +449,7 @@ int arm7_9_add_watchpoint(struct target_s *target, u32 address, u32 length, enum
                return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
        }
        
-       if ((length != 1) && (length != 2) && (length != 4))
+       if ((watchpoint->length != 1) && (watchpoint->length != 2) && (watchpoint->length != 4))
        {
                return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
        }
@@ -452,11 +489,12 @@ int arm7_9_enable_sw_bkpts(struct target_s *target)
        if (arm7_9->sw_bkpts_enabled)
                return ERROR_OK;
        
-       if (arm7_9->wp_available-- < 1)
+       if (arm7_9->wp_available < 1)
        {
                WARNING("can't enable sw breakpoints with no watchpoint unit available");
                return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
        }
+       arm7_9->wp_available--;
        
        if (!arm7_9->wp0_used)
        {
@@ -528,10 +566,10 @@ int arm7_9_execute_sys_speed(struct target_s *target)
        arm7_9_common_t *arm7_9 = armv4_5->arch_info;
        arm_jtag_t *jtag_info = &arm7_9->jtag_info;
        reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
-                       
+                               
        /* set RESTART instruction */
        jtag_add_end_state(TAP_RTI);
-       arm_jtag_set_instr(jtag_info, 0x4);
+       arm_jtag_set_instr(jtag_info, 0x4, NULL);
        
        for (timeout=0; timeout<50; timeout++)
        {
@@ -555,20 +593,30 @@ int arm7_9_execute_sys_speed(struct target_s *target)
 
 int arm7_9_execute_fast_sys_speed(struct target_s *target)
 {
-       u8 check_value[4], check_mask[4];
+       static int set=0;
+       static u8 check_value[4], check_mask[4];
        
        armv4_5_common_t *armv4_5 = target->arch_info;
        arm7_9_common_t *arm7_9 = armv4_5->arch_info;
        arm_jtag_t *jtag_info = &arm7_9->jtag_info;
        reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
-                       
+                               
        /* set RESTART instruction */
        jtag_add_end_state(TAP_RTI);
-       arm_jtag_set_instr(jtag_info, 0x4);
+       arm_jtag_set_instr(jtag_info, 0x4, NULL);
        
-       /* check for DBGACK and SYSCOMP set (others don't care) */
-       buf_set_u32(check_value, 0, 32, 0x9);
-       buf_set_u32(check_mask, 0, 32, 0x9);
+       if (!set)
+       {
+               /* check for DBGACK and SYSCOMP set (others don't care) */
+               
+               /* NB! These are constants that must be available until after next jtag_execute() and
+                  we evaluate the values upon first execution in lieu of setting up these constants
+                  during early setup.
+               */
+               buf_set_u32(check_value, 0, 32, 0x9);
+               buf_set_u32(check_mask, 0, 32, 0x9);
+               set=1;
+       }
        
        /* read debug status register */
        embeddedice_read_reg_w_check(dbg_stat, check_value, check_value);
@@ -576,13 +624,64 @@ int arm7_9_execute_fast_sys_speed(struct target_s *target)
        return ERROR_OK;
 }
 
-enum target_state arm7_9_poll(target_t *target)
+int arm7_9_target_request_data(target_t *target, u32 size, u8 *buffer)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+       u32 *data;
+       int i;
+       
+       data = malloc(size * (sizeof(u32)));
+       
+       embeddedice_receive(jtag_info, data, size);
+       
+       for (i = 0; i < size; i++)
+       {
+               h_u32_to_le(buffer + (i * 4), data[i]);
+       }
+       
+       free(data);
+       
+       return ERROR_OK;
+}
+
+int arm7_9_handle_target_request(void *priv)
+{
+       target_t *target = priv;
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm_jtag_t *jtag_info = &arm7_9->jtag_info; 
+       reg_t *dcc_control = &arm7_9->eice_cache->reg_list[EICE_COMMS_CTRL];
+       
+       if (!target->dbg_msg_enabled)
+               return ERROR_OK;
+               
+       if (target->state == TARGET_RUNNING)
+       {
+               /* read DCC control register */
+               embeddedice_read_reg(dcc_control);
+               jtag_execute_queue();
+               
+               /* check W bit */
+               if (buf_get_u32(dcc_control->value, 1, 1) == 1)
+               {
+                       u32 request;
+                       
+                       embeddedice_receive(jtag_info, &request, 1);
+                       target_request(target, request);
+               }
+       }
+       
+       return ERROR_OK;
+}
+
+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;
        reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
-       reg_t *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];
 
        if (arm7_9->reinit_embeddedice)
        {
@@ -593,24 +692,15 @@ enum target_state arm7_9_poll(target_t *target)
        embeddedice_read_reg(dbg_stat);
        if ((retval = jtag_execute_queue()) != ERROR_OK)
        {
-               switch (retval)
-               {
-                       case ERROR_JTAG_QUEUE_FAILED:
-                               ERROR("JTAG queue failed while reading EmbeddedICE status register");
-                               exit(-1);
-                               break;
-                       default:
-                               break;
-               }
+               return retval;
        }
        
        if (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1))
        {
                DEBUG("DBGACK set, dbg_state->value: 0x%x", buf_get_u32(dbg_stat->value, 0, 32));
-               if ((target->state == TARGET_UNKNOWN))
+               if (target->state == TARGET_UNKNOWN)
                {
-                       WARNING("DBGACK set while target was in unknown state. Reset or initialize target before resuming");
-                       target->state = TARGET_RUNNING;
+                       WARNING("DBGACK set while target was in unknown state. Reset or initialize target.");
                }
                if ((target->state == TARGET_RUNNING) || (target->state == TARGET_RESET))
                {
@@ -628,6 +718,10 @@ enum target_state arm7_9_poll(target_t *target)
                        
                        target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
                }
+               if (target->state != TARGET_HALTED)
+               {
+                       WARNING("DBGACK set, but the target did not end up in the halted stated %d", target->state);
+               }
        }
        else
        {
@@ -635,7 +729,7 @@ enum target_state arm7_9_poll(target_t *target)
                        target->state = TARGET_RUNNING;
        }
        
-       return target->state;
+       return ERROR_OK;
 }
 
 int arm7_9_assert_reset(target_t *target)
@@ -646,6 +740,9 @@ int arm7_9_assert_reset(target_t *target)
        
        if (target->state == TARGET_HALTED || target->state == TARGET_UNKNOWN)
        {
+               /* if the target wasn't running, there might be working areas allocated */
+               target_free_all_working_areas(target);
+               
                /* assert SRST and TRST */
                /* system would get ouf sync if we didn't reset test-logic, too */
                if ((retval = jtag_add_reset(1, 1)) != ERROR_OK)
@@ -709,9 +806,52 @@ int arm7_9_deassert_reset(target_t *target)
        
        /* deassert reset lines */
        jtag_add_reset(0, 0);
-               
+       
        return ERROR_OK;
+}
 
+int arm7_9_clear_halt(target_t *target)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       reg_t *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];
+       
+       /* we used DBGRQ only if we didn't come out of reset */
+       if (!arm7_9->debug_entry_from_reset && arm7_9->use_dbgrq)
+       {
+               /* program EmbeddedICE Debug Control Register to deassert DBGRQ
+                */
+               buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_DBGRQ, 1, 0);     
+               embeddedice_store_reg(dbg_ctrl);
+       }
+       else
+       {
+               if (arm7_9->debug_entry_from_reset && arm7_9->has_vector_catch)
+               {
+                       /* if we came out of reset, and vector catch is supported, we used
+                        * vector catch to enter debug state
+                        * restore the register in that case
+                        */
+                       embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_VEC_CATCH]);
+               }
+               else
+               {
+                       /* restore registers if watchpoint unit 0 was in use
+                        */
+                       if (arm7_9->wp0_used)
+                       {
+                               embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK]);
+                               embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK]);
+                               embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK]);
+                       }
+                       /* control value always has to be restored, as it was either disabled, 
+                        * or enabled with possibly different bits
+                        */
+                       embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE]);
+               }
+       }
+       
+       return ERROR_OK;
 }
 
 int arm7_9_soft_reset_halt(struct target_s *target)
@@ -719,6 +859,7 @@ int arm7_9_soft_reset_halt(struct target_s *target)
        armv4_5_common_t *armv4_5 = target->arch_info;
        arm7_9_common_t *arm7_9 = armv4_5->arch_info;
        reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
+       reg_t *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];
        int i;
        
        if (target->state == TARGET_RUNNING)
@@ -726,13 +867,33 @@ int arm7_9_soft_reset_halt(struct target_s *target)
                target->type->halt(target);
        }
        
-       while (buf_get_u32(dbg_stat->value, EICE_DBG_CONTROL_DBGACK, 1) == 0)
+       while (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1) == 0)
        {
                embeddedice_read_reg(dbg_stat);
                jtag_execute_queue();
        }
        target->state = TARGET_HALTED;
        
+       /* program EmbeddedICE Debug Control Register to assert DBGACK and INTDIS
+        * ensure that DBGRQ is cleared
+        */
+       buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_DBGACK, 1, 1);
+       buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_DBGRQ, 1, 0);
+       buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_INTDIS, 1, 1);
+       embeddedice_store_reg(dbg_ctrl);
+       
+       arm7_9_clear_halt(target);
+       
+       /* if the target is in Thumb state, change to ARM state */
+       if (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_ITBIT, 1))
+       {
+               u32 r0_thumb, pc_thumb;
+               DEBUG("target entered debug from Thumb state, changing to ARM");
+               /* Entered debug from Thumb mode */
+               armv4_5->core_state = ARMV4_5_STATE_THUMB;
+               arm7_9->change_to_arm(target, &r0_thumb, &pc_thumb);
+       }
+       
        /* all register content is now invalid */
        armv4_5_invalidate_core_regs(target);
        
@@ -762,6 +923,35 @@ int arm7_9_soft_reset_halt(struct target_s *target)
        return ERROR_OK;
 }
 
+int arm7_9_prepare_reset_halt(target_t *target)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       
+       /* poll the target, and resume if it was currently halted */
+       arm7_9_poll(target);
+       if (target->state == TARGET_HALTED)
+       {
+               arm7_9_resume(target, 1, 0x0, 0, 1);
+       }
+       
+       if (arm7_9->has_vector_catch)
+       {
+               /* program vector catch register to catch reset vector */
+               embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_VEC_CATCH], 0x1);
+       }
+       else
+       {
+               /* program watchpoint unit to match on reset vector address */
+               embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK], 0x3);
+               embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK], 0x0);
+               embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], 0x100);
+               embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK], 0xf7);
+       }
+       
+       return ERROR_OK;
+}
+
 int arm7_9_halt(target_t *target)
 {
        armv4_5_common_t *armv4_5 = target->arch_info;
@@ -774,12 +964,30 @@ int arm7_9_halt(target_t *target)
        {
                WARNING("target was already halted");
                return ERROR_TARGET_ALREADY_HALTED;
-       } 
+       }
        
        if (target->state == TARGET_UNKNOWN)
        {
                WARNING("target was in unknown state when halt was requested");
        }
+       
+       if (target->state == TARGET_RESET) 
+       {
+               if ((jtag_reset_config & RESET_SRST_PULLS_TRST) && jtag_srst)
+               {
+                       ERROR("can't request a halt while in reset if nSRST pulls nTRST");
+                       return ERROR_TARGET_FAILURE;
+               }
+               else
+               {
+                       /* we came here in a reset_halt or reset_init sequence
+                        * debug entry was already prepared in arm7_9_prepare_reset_halt()
+                        */
+                       target->debug_reason = DBG_REASON_DBGRQ;
+                       
+                       return ERROR_OK; 
+               }
+       }
 
        if (arm7_9->use_dbgrq)
        {
@@ -803,38 +1011,6 @@ int arm7_9_halt(target_t *target)
        return ERROR_OK;
 }
 
-int arm7_9_clear_halt(target_t *target)
-{
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-       reg_t *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];
-       
-       if (arm7_9->use_dbgrq)
-       {
-               /* program EmbeddedICE Debug Control Register to deassert DBGRQ
-                */
-               buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_DBGRQ, 1, 0);     
-               embeddedice_store_reg(dbg_ctrl);
-       }
-       else
-       {
-               /* restore registers if watchpoint unit 0 was in use
-                */
-               if (arm7_9->wp0_used)
-               {
-                       embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK]);
-                       embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK]);
-                       embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK]);
-               }
-               /* control value always has to be restored, as it was either disabled, 
-                * or enabled with possibly different bits
-                */
-               embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE]);
-       }
-       
-       return ERROR_OK;
-}
-
 int arm7_9_debug_entry(target_t *target)
 {
        int i;
@@ -850,7 +1026,7 @@ int arm7_9_debug_entry(target_t *target)
        reg_t *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];
 
 #ifdef _DEBUG_ARM7_9_
-       DEBUG("");
+       DEBUG("-");
 #endif
 
        if (arm7_9->pre_debug_entry)
@@ -914,12 +1090,16 @@ int arm7_9_debug_entry(target_t *target)
        
        if ((retval = jtag_execute_queue()) != ERROR_OK)
                return retval;
+       
+       /* if the core has been executing in Thumb state, set the T bit */
+       if (armv4_5->core_state == ARMV4_5_STATE_THUMB)
+               cpsr |= 0x20;   
+       
        buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32, cpsr);
        armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 0;
        armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
        
        armv4_5->core_mode = cpsr & 0x1f;
-       DEBUG("target entered debug state in %s mode", armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)]);
        
        if (armv4_5_mode_to_number(armv4_5->core_mode) == -1)
        {
@@ -927,6 +1107,8 @@ int arm7_9_debug_entry(target_t *target)
                ERROR("cpsr contains invalid mode value - communication failure");
                return ERROR_TARGET_FAILURE;
        }
+
+       DEBUG("target entered debug state in %s mode", armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)]);
        
        if (armv4_5->core_state == ARMV4_5_STATE_THUMB)
        {
@@ -955,6 +1137,7 @@ int arm7_9_debug_entry(target_t *target)
        
        for (i=0; i<=15; i++)
        {
+               DEBUG("r%i: 0x%8.8x", i, context[i]);
                buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i).value, 0, 32, context[i]);
                ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i).dirty = 0;
                ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i).valid = 1;
@@ -974,8 +1157,8 @@ int arm7_9_debug_entry(target_t *target)
        }
 
        /* r0 and r15 (pc) have to be restored later */
-       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 0).dirty = 1;
-       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 15).dirty = 1;
+       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 0).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 0).valid;
+       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 15).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 15).valid;
 
        if ((retval = jtag->execute_queue()) != ERROR_OK)
                return retval;
@@ -993,7 +1176,7 @@ int arm7_9_full_context(target_t *target)
        armv4_5_common_t *armv4_5 = target->arch_info;
        arm7_9_common_t *arm7_9 = armv4_5->arch_info;
 
-       DEBUG("");
+       DEBUG("-");
        
        if (target->state != TARGET_HALTED)
        {
@@ -1023,9 +1206,10 @@ int arm7_9_full_context(target_t *target)
                {
                        u32 tmp_cpsr;
                        
-                       /* change processor mode */
+                       /* change processor mode (and mask T bit) */
                        tmp_cpsr = buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8) & 0xE0;
                        tmp_cpsr |= armv4_5_number_to_mode(i);
+                       tmp_cpsr &= ~0x20;
                        arm7_9->write_xpsr_im8(target, tmp_cpsr & 0xff, 0, 0);
 
                        for (j = 0; j < 15; j++)
@@ -1053,8 +1237,8 @@ int arm7_9_full_context(target_t *target)
                }
        }
 
-       /* restore processor mode */
-       arm7_9->write_xpsr_im8(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8), 0, 0);
+       /* restore processor mode (mask T bit) */
+       arm7_9->write_xpsr_im8(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8) & ~0x20, 0, 0);
        
        if ((retval = jtag_execute_queue()) != ERROR_OK)
        {
@@ -1075,7 +1259,7 @@ int arm7_9_restore_context(target_t *target)
        int dirty;
        int mode_change;
        
-       DEBUG("");
+       DEBUG("-");
        
        if (target->state != TARGET_HALTED)
        {
@@ -1118,7 +1302,6 @@ int arm7_9_restore_context(target_t *target)
                                else
                                {
                                        ERROR("BUG: dirty register '%s', but no valid data", reg->name);
-                                       exit(-1);
                                }
                        }
                }
@@ -1133,9 +1316,10 @@ int arm7_9_restore_context(target_t *target)
                        {
                                u32 tmp_cpsr;
                        
-                               /* change processor mode */
+                               /* change processor mode (mask T bit) */
                                tmp_cpsr = buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8) & 0xE0;
                                tmp_cpsr |= armv4_5_number_to_mode(i);
+                               tmp_cpsr &= ~0x20;
                                arm7_9->write_xpsr_im8(target, tmp_cpsr & 0xff, 0, 0);
                                current_mode = armv4_5_number_to_mode(i);
                        }
@@ -1174,19 +1358,20 @@ int arm7_9_restore_context(target_t *target)
        
        if ((armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty == 0) && (armv4_5->core_mode != current_mode))
        {
-               /* restore processor mode */
+               /* restore processor mode (mask T bit) */
                u32 tmp_cpsr;
                        
                tmp_cpsr = buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8) & 0xE0;
                tmp_cpsr |= armv4_5_number_to_mode(i);
+               tmp_cpsr &= ~0x20;
                DEBUG("writing lower 8 bit of cpsr with value 0x%2.2x", tmp_cpsr);
                arm7_9->write_xpsr_im8(target, tmp_cpsr & 0xff, 0, 0);
        }
        else if (armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty == 1)
        {
-               /* CPSR has been changed, full restore necessary */
+               /* CPSR has been changed, full restore necessary (mask T bit) */
                DEBUG("writing cpsr with value 0x%8.8x", buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32));
-               arm7_9->write_xpsr(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32), 0);
+               arm7_9->write_xpsr(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32) & ~0x20, 0);
                armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 0;
                armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
        }
@@ -1210,7 +1395,7 @@ int arm7_9_restart_core(struct target_s *target)
        
        /* set RESTART instruction */
        jtag_add_end_state(TAP_RTI);
-       arm_jtag_set_instr(jtag_info, 0x4);
+       arm_jtag_set_instr(jtag_info, 0x4, NULL);
        
        jtag_add_runtest(1, TAP_RTI);
        if ((jtag_execute_queue()) != ERROR_OK)
@@ -1273,8 +1458,9 @@ int arm7_9_resume(struct target_s *target, int current, u32 address, int handle_
        arm7_9_common_t *arm7_9 = armv4_5->arch_info;
        breakpoint_t *breakpoint = target->breakpoints;
        reg_t *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];
+       int err;
        
-       DEBUG("");
+       DEBUG("-");
        
        if (target->state != TARGET_HALTED)
        {
@@ -1320,14 +1506,21 @@ int arm7_9_resume(struct target_s *target, int current, u32 address, int handle_
                                
                        buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_DBGACK, 1, 0);
                        embeddedice_write_reg(dbg_ctrl, buf_get_u32(dbg_ctrl->value, 0, dbg_ctrl->size));
-                       arm7_9_execute_sys_speed(target);
+                       err = arm7_9_execute_sys_speed(target);
                        
                        DEBUG("disable single-step");
                        arm7_9->disable_single_step(target);
-                       
+
+                       if (err != ERROR_OK)
+                       {
+                               arm7_9_set_breakpoint(target, breakpoint);
+                               target->state = TARGET_UNKNOWN;
+                               return err;
+                       }
+
                        arm7_9_debug_entry(target);
                        DEBUG("new PC after step: 0x%8.8x", buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));
-               
+
                        DEBUG("set breakpoint at 0x%8.8x", breakpoint->address);
                        arm7_9_set_breakpoint(target, breakpoint);
                }
@@ -1422,7 +1615,8 @@ int arm7_9_step(struct target_s *target, int current, u32 address, int handle_br
 {
        armv4_5_common_t *armv4_5 = target->arch_info;
        arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-       breakpoint_t *breakpoint = target->breakpoints;
+       breakpoint_t *breakpoint = NULL;
+       int err;
 
        if (target->state != TARGET_HALTED)
        {
@@ -1461,28 +1655,32 @@ int arm7_9_step(struct target_s *target, int current, u32 address, int handle_br
        
        target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
 
-       arm7_9_execute_sys_speed(target);
+       err = arm7_9_execute_sys_speed(target);
        arm7_9->disable_single_step(target);
        
        /* registers are now invalid */
        armv4_5_invalidate_core_regs(target);
        
-       arm7_9_debug_entry(target);
+       if (err != ERROR_OK)
+       {
+               target->state = TARGET_UNKNOWN;
+       } else {
+               arm7_9_debug_entry(target);
+               target_call_event_callbacks(target, TARGET_EVENT_HALTED);
+               DEBUG("target stepped");
+       }
        
-       target_call_event_callbacks(target, TARGET_EVENT_HALTED);
-
        if (breakpoint)
                arm7_9_set_breakpoint(target, breakpoint);
        
-       DEBUG("target stepped");
-
-       return ERROR_OK;
+       return err;
 
 }
 
 int arm7_9_read_core_reg(struct target_s *target, int num, enum armv4_5_mode mode)
 {
        u32* reg_p[16];
+       u32 value;
        int retval;
        armv4_5_common_t *armv4_5 = target->arch_info;
        arm7_9_common_t *arm7_9 = armv4_5->arch_info;
@@ -1497,16 +1695,17 @@ int arm7_9_read_core_reg(struct target_s *target, int num, enum armv4_5_mode mod
        {
                u32 tmp_cpsr;
                        
-               /* change processor mode */
+               /* change processor mode (mask T bit) */
                tmp_cpsr = buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8) & 0xE0;
                tmp_cpsr |= mode;
+               tmp_cpsr &= ~0x20;
                arm7_9->write_xpsr_im8(target, tmp_cpsr & 0xff, 0, 0);
        }
        
        if ((num >= 0) && (num <= 15))
        {
                /* read a normal core register */
-               reg_p[num] = (u32*)ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, mode, num).value;
+               reg_p[num] = &value;
                
                arm7_9->read_core_regs(target, 1 << num, reg_p);
        }
@@ -1518,23 +1717,24 @@ int arm7_9_read_core_reg(struct target_s *target, int num, enum armv4_5_mode mod
                armv4_5_core_reg_t *arch_info = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, mode, num).arch_info;
                int spsr = (arch_info->mode == ARMV4_5_MODE_ANY) ? 0 : 1;
                
-               arm7_9->read_xpsr(target, (u32*)ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, mode, num).value, spsr);
+               arm7_9->read_xpsr(target, &value, spsr);
        }
        
+       if ((retval = jtag_execute_queue()) != ERROR_OK)
+       {
+               ERROR("JTAG failure");
+               exit(-1);
+       }
+               
        ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, mode, num).valid = 1;
        ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, mode, num).dirty = 0;
+       buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, mode, num).value, 0, 32, value);
                
        if ((mode != ARMV4_5_MODE_ANY)
                        && (mode != armv4_5->core_mode)
                        && (reg_mode != ARMV4_5_MODE_ANY))      {
-               /* restore processor mode */
-               arm7_9->write_xpsr_im8(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8), 0, 0);
-       }
-       
-       if ((retval = jtag_execute_queue()) != ERROR_OK)
-       {
-               ERROR("JTAG failure");
-               exit(-1);
+               /* restore processor mode (mask T bit) */
+               arm7_9->write_xpsr_im8(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8) & ~0x20, 0, 0);
        }
        
        return ERROR_OK;
@@ -1557,9 +1757,10 @@ int arm7_9_write_core_reg(struct target_s *target, int num, enum armv4_5_mode mo
                        && (reg_mode != ARMV4_5_MODE_ANY))      {
                u32 tmp_cpsr;
                        
-               /* change processor mode */
+               /* change processor mode (mask T bit) */
                tmp_cpsr = buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8) & 0xE0;
                tmp_cpsr |= mode;
+               tmp_cpsr &= ~0x20;
                arm7_9->write_xpsr_im8(target, tmp_cpsr & 0xff, 0, 0);
        }
        
@@ -1578,6 +1779,10 @@ int arm7_9_write_core_reg(struct target_s *target, int num, enum armv4_5_mode mo
                armv4_5_core_reg_t *arch_info = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, mode, num).arch_info;
                int spsr = (arch_info->mode == ARMV4_5_MODE_ANY) ? 0 : 1;
                
+               /* if we're writing the CPSR, mask the T bit */
+               if (!spsr)
+                       value &= ~0x20;
+               
                arm7_9->write_xpsr(target, value, spsr);
        }
        
@@ -1587,8 +1792,8 @@ int arm7_9_write_core_reg(struct target_s *target, int num, enum armv4_5_mode mo
        if ((mode != ARMV4_5_MODE_ANY)
                        && (mode != armv4_5->core_mode)
                        && (reg_mode != ARMV4_5_MODE_ANY))      {
-               /* restore processor mode */
-               arm7_9->write_xpsr_im8(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8), 0, 0);
+               /* restore processor mode (mask T bit) */
+               arm7_9->write_xpsr_im8(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8) & ~0x20, 0, 0);
        }
        
        if ((retval = jtag_execute_queue()) != ERROR_OK)
@@ -1607,14 +1812,13 @@ int arm7_9_read_memory(struct target_s *target, u32 address, u32 size, u32 count
        arm7_9_common_t *arm7_9 = armv4_5->arch_info;
        
        u32 reg[16];
-       u32 *reg_p[16];
        int num_accesses = 0;
        int thisrun_accesses;
        int i;
        u32 cpsr;
        int retval;
        int last_reg = 0;
-
+       
        DEBUG("address: 0x%8.8x, size: 0x%8.8x, count: 0x%8.8x", address, size, count);
 
        if (target->state != TARGET_HALTED)
@@ -1630,11 +1834,6 @@ int arm7_9_read_memory(struct target_s *target, u32 address, u32 size, u32 count
        if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
                return ERROR_TARGET_UNALIGNED_ACCESS;
        
-       for (i = 0; i < 16; i++)
-       {
-               reg_p[i] = &reg[i];
-       }
-       
        /* load the base register with the address of the first word */
        reg[0] = address;
        arm7_9->write_core_regs(target, 0x1, reg);
@@ -1648,19 +1847,23 @@ int arm7_9_read_memory(struct target_s *target, u32 address, u32 size, u32 count
                                thisrun_accesses = ((count - num_accesses) >= 14) ? 14 : (count - num_accesses);
                                reg_list = (0xffff >> (15 - thisrun_accesses)) & 0xfffe;
                                
+                               if (last_reg <= thisrun_accesses)
+                                       last_reg = thisrun_accesses;
+                               
                                arm7_9->load_word_regs(target, reg_list);
-                               arm7_9_execute_sys_speed(target);
                                
-                               arm7_9->read_core_regs(target, reg_list, reg_p);
-                               jtag_execute_queue();
+                               /* fast memory reads are only safe when the target is running
+                                * from a sufficiently high clock (32 kHz is usually too slow)
+                                */
+                               if (arm7_9->fast_memory_access)
+                                       arm7_9_execute_fast_sys_speed(target);
+                               else
+                                       arm7_9_execute_sys_speed(target);
+                                                                       
+                               arm7_9->read_core_regs_target_buffer(target, reg_list, buffer, 4);
                                
-                               for (i = 1; i <= thisrun_accesses; i++)
-                               {
-                                       if (i > last_reg)
-                                               last_reg = i;
-                                       target_buffer_set_u32(target, buffer, reg[i]);
-                                       buffer += 4;
-                               }
+                               /* advance buffer, count number of accesses */
+                               buffer += thisrun_accesses * 4;
                                num_accesses += thisrun_accesses;
                        }       
                        break;
@@ -1676,17 +1879,19 @@ int arm7_9_read_memory(struct target_s *target, u32 address, u32 size, u32 count
                                        if (i > last_reg)
                                                last_reg = i;
                                        arm7_9->load_hword_reg(target, i);
-                                       arm7_9_execute_sys_speed(target);
+                                       /* fast memory reads are only safe when the target is running
+                                        * from a sufficiently high clock (32 kHz is usually too slow)
+                                        */
+                                       if (arm7_9->fast_memory_access)
+                                               arm7_9_execute_fast_sys_speed(target);
+                                       else
+                                               arm7_9_execute_sys_speed(target);
                                }
                                
-                               arm7_9->read_core_regs(target, reg_list, reg_p);
-                               jtag_execute_queue();
+                               arm7_9->read_core_regs_target_buffer(target, reg_list, buffer, 2);
                                
-                               for (i = 1; i <= thisrun_accesses; i++)
-                               {
-                                       target_buffer_set_u16(target, buffer, reg[i]);
-                                       buffer += 2;
-                               }
+                               /* advance buffer, count number of accesses */
+                               buffer += thisrun_accesses * 2;
                                num_accesses += thisrun_accesses;
                        }       
                        break;
@@ -1702,16 +1907,19 @@ int arm7_9_read_memory(struct target_s *target, u32 address, u32 size, u32 count
                                        if (i > last_reg)
                                                last_reg = i;
                                        arm7_9->load_byte_reg(target, i);
-                                       arm7_9_execute_sys_speed(target);
+                                       /* fast memory reads are only safe when the target is running
+                                        * from a sufficiently high clock (32 kHz is usually too slow)
+                                        */
+                                       if (arm7_9->fast_memory_access)
+                                               arm7_9_execute_fast_sys_speed(target);
+                                       else
+                                               arm7_9_execute_sys_speed(target);
                                }
                                
-                               arm7_9->read_core_regs(target, reg_list, reg_p);
-                               jtag_execute_queue();
+                               arm7_9->read_core_regs_target_buffer(target, reg_list, buffer, 1);
                                
-                               for (i = 1; i <= thisrun_accesses; i++)
-                               {
-                                       *(buffer++) = reg[i] & 0xff;
-                               }
+                               /* advance buffer, count number of accesses */
+                               buffer += thisrun_accesses * 1;
                                num_accesses += thisrun_accesses;
                        }       
                        break;
@@ -1722,20 +1930,20 @@ int arm7_9_read_memory(struct target_s *target, u32 address, u32 size, u32 count
        }
        
        for (i=0; i<=last_reg; i++)
-               ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i).dirty = 1;
+               ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i).valid;
 
        arm7_9->read_xpsr(target, &cpsr, 0);
        if ((retval = jtag_execute_queue()) != ERROR_OK)
        {
                ERROR("JTAG error while reading cpsr");
-               exit(-1);
+               return ERROR_TARGET_DATA_ABORT;
        }
 
        if (((cpsr & 0x1f) == ARMV4_5_MODE_ABT) && (armv4_5->core_mode != ARMV4_5_MODE_ABT))
        {
-               ERROR("memory read caused data abort");
+               WARNING("memory read caused data abort (address: 0x%8.8x, size: 0x%x, count: 0x%x)", address, size, count);
 
-               arm7_9->write_xpsr_im8(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8), 0, 0);
+               arm7_9->write_xpsr_im8(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8) & ~0x20, 0, 0);
 
                return ERROR_TARGET_DATA_ABORT;
        }
@@ -1747,6 +1955,7 @@ int arm7_9_write_memory(struct target_s *target, u32 address, u32 size, u32 coun
 {
        armv4_5_common_t *armv4_5 = target->arch_info;
        arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       reg_t *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];
        
        u32 reg[16];
        int num_accesses = 0;
@@ -1756,7 +1965,9 @@ int arm7_9_write_memory(struct target_s *target, u32 address, u32 size, u32 coun
        int retval;
        int last_reg = 0;
 
+#ifdef _DEBUG_ARM7_9_
        DEBUG("address: 0x%8.8x, size: 0x%8.8x, count: 0x%8.8x", address, size, count);
+#endif
 
        if (target->state != TARGET_HALTED)
        {
@@ -1775,6 +1986,10 @@ int arm7_9_write_memory(struct target_s *target, u32 address, u32 size, u32 coun
        reg[0] = address;
        arm7_9->write_core_regs(target, 0x1, reg);
        
+       /* Clear DBGACK, to make sure memory fetches work as expected */
+       buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_DBGACK, 1, 0);
+       embeddedice_store_reg(dbg_ctrl);
+       
        switch (size)
        {
                case 4:
@@ -1799,7 +2014,7 @@ int arm7_9_write_memory(struct target_s *target, u32 address, u32 size, u32 coun
                                /* fast memory writes are only safe when the target is running
                                 * from a sufficiently high clock (32 kHz is usually too slow)
                                 */
-                               if (arm7_9->fast_memory_writes)
+                               if (arm7_9->fast_memory_access)
                                        arm7_9_execute_fast_sys_speed(target);
                                else
                                        arm7_9_execute_sys_speed(target);
@@ -1831,7 +2046,7 @@ int arm7_9_write_memory(struct target_s *target, u32 address, u32 size, u32 coun
                                        /* fast memory writes are only safe when the target is running
                                         * from a sufficiently high clock (32 kHz is usually too slow)
                                         */
-                                       if (arm7_9->fast_memory_writes)
+                                       if (arm7_9->fast_memory_access)
                                                arm7_9_execute_fast_sys_speed(target);
                                        else
                                                arm7_9_execute_sys_speed(target);
@@ -1862,7 +2077,7 @@ int arm7_9_write_memory(struct target_s *target, u32 address, u32 size, u32 coun
                                        /* fast memory writes are only safe when the target is running
                                         * from a sufficiently high clock (32 kHz is usually too slow)
                                         */
-                                       if (arm7_9->fast_memory_writes)
+                                       if (arm7_9->fast_memory_access)
                                                arm7_9_execute_fast_sys_speed(target);
                                        else
                                                arm7_9_execute_sys_speed(target);
@@ -1877,27 +2092,25 @@ int arm7_9_write_memory(struct target_s *target, u32 address, u32 size, u32 coun
                        break;
        }
        
-       if ((retval = jtag_execute_queue()) != ERROR_OK)
-       {
-               ERROR("JTAG error while writing target memory");
-               exit(-1);
-       }
+       /* Re-Set DBGACK */
+       buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_DBGACK, 1, 1);
+       embeddedice_store_reg(dbg_ctrl);
        
        for (i=0; i<=last_reg; i++)
-               ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i).dirty = 1;
+               ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i).valid;
 
        arm7_9->read_xpsr(target, &cpsr, 0);
        if ((retval = jtag_execute_queue()) != ERROR_OK)
        {
                ERROR("JTAG error while reading cpsr");
-               exit(-1);
+               return ERROR_TARGET_DATA_ABORT;
        }
 
        if (((cpsr & 0x1f) == ARMV4_5_MODE_ABT) && (armv4_5->core_mode != ARMV4_5_MODE_ABT))
        {
-               ERROR("memory write caused data abort");
+               WARNING("memory write caused data abort (address: 0x%8.8x, size: 0x%x, count: 0x%x)", address, size, count);
 
-               arm7_9->write_xpsr_im8(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8), 0, 0);
+               arm7_9->write_xpsr_im8(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8) & ~0x20, 0, 0);
 
                return ERROR_TARGET_DATA_ABORT;
        }
@@ -1927,6 +2140,8 @@ int arm7_9_bulk_write_memory(target_t *target, u32 address, u32 count, u8 *buffe
        /* regrab previously allocated working_area, or allocate a new one */
        if (!arm7_9->dcc_working_area)
        {
+               u8 dcc_code_buf[6 * 4];
+               
                /* make sure we have a working area */
                if (target_alloc_working_area(target, 24, &arm7_9->dcc_working_area) != ERROR_OK)
                {
@@ -1934,8 +2149,14 @@ int arm7_9_bulk_write_memory(target_t *target, u32 address, u32 count, u8 *buffe
                        return target->type->write_memory(target, address, 4, count, buffer);
                }
                
+               /* copy target instructions to target endianness */
+               for (i = 0; i < 6; i++)
+               {
+                       target_buffer_set_u32(target, dcc_code_buf + i*4, dcc_code[i]);
+               }
+               
                /* write DCC code to working area */
-               target->type->write_memory(target, arm7_9->dcc_working_area->address, 4, 6, (u8*)dcc_code);
+               target->type->write_memory(target, arm7_9->dcc_working_area->address, 4, 6, dcc_code_buf);
        }
        
        buf_set_u32(armv4_5->core_cache->reg_list[0].value, 0, 32, address);
@@ -1971,12 +2192,88 @@ int arm7_9_bulk_write_memory(target_t *target, u32 address, u32 count, u8 *buffe
        return ERROR_OK;
 }
 
+int arm7_9_checksum_memory(struct target_s *target, u32 address, u32 count, u32* checksum)
+{
+       working_area_t *crc_algorithm;
+       armv4_5_algorithm_t armv4_5_info;
+       reg_param_t reg_params[2];
+       int retval;
+       
+       u32 arm7_9_crc_code[] = {
+               0xE1A02000,                             /* mov          r2, r0 */
+               0xE3E00000,                             /* mov          r0, #0xffffffff */
+               0xE1A03001,                             /* mov          r3, r1 */
+               0xE3A04000,                             /* mov          r4, #0 */
+               0xEA00000B,                             /* b            ncomp */
+                                                               /* nbyte: */
+               0xE7D21004,                             /* ldrb r1, [r2, r4] */
+               0xE59F7030,                             /* ldr          r7, CRC32XOR */
+               0xE0200C01,                             /* eor          r0, r0, r1, asl 24 */
+               0xE3A05000,                             /* mov          r5, #0 */
+                                                               /* loop: */
+               0xE3500000,                             /* cmp          r0, #0 */
+               0xE1A06080,                             /* mov          r6, r0, asl #1 */
+               0xE2855001,                             /* add          r5, r5, #1 */
+               0xE1A00006,                             /* mov          r0, r6 */
+               0xB0260007,                             /* eorlt        r0, r6, r7 */
+               0xE3550008,                             /* cmp          r5, #8 */
+               0x1AFFFFF8,                             /* bne          loop */
+               0xE2844001,                             /* add          r4, r4, #1 */
+                                                               /* ncomp: */
+               0xE1540003,                             /* cmp          r4, r3 */
+               0x1AFFFFF1,                             /* bne          nbyte */
+                                                               /* end: */
+               0xEAFFFFFE,                             /* b            end */
+               0x04C11DB7                              /* CRC32XOR:    .word 0x04C11DB7 */
+       };
+       
+       int i;
+       
+       if (target_alloc_working_area(target, sizeof(arm7_9_crc_code), &crc_algorithm) != ERROR_OK)
+       {
+               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+       }
+       
+       /* convert flash writing code into a buffer in target endianness */
+       for (i = 0; i < (sizeof(arm7_9_crc_code)/sizeof(u32)); i++)
+               target_write_u32(target, crc_algorithm->address + i*sizeof(u32), arm7_9_crc_code[i]);
+       
+       armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;
+       armv4_5_info.core_mode = ARMV4_5_MODE_SVC;
+       armv4_5_info.core_state = ARMV4_5_STATE_ARM;
+       
+       init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT);
+       init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
+       
+       buf_set_u32(reg_params[0].value, 0, 32, address);
+       buf_set_u32(reg_params[1].value, 0, 32, count);
+               
+       if ((retval = target->type->run_algorithm(target, 0, NULL, 2, reg_params,
+               crc_algorithm->address, crc_algorithm->address + (sizeof(arm7_9_crc_code) - 8), 20000, &armv4_5_info)) != ERROR_OK)
+       {
+               ERROR("error executing arm7_9 crc algorithm");
+               destroy_reg_param(&reg_params[0]);
+               destroy_reg_param(&reg_params[1]);
+               target_free_working_area(target, crc_algorithm);
+               return retval;
+       }
+       
+       *checksum = buf_get_u32(reg_params[0].value, 0, 32);
+       
+       destroy_reg_param(&reg_params[0]);
+       destroy_reg_param(&reg_params[1]);
+       
+       target_free_working_area(target, crc_algorithm);
+       
+       return ERROR_OK;
+}
+
 int arm7_9_register_commands(struct command_context_s *cmd_ctx)
 {
        command_t *arm7_9_cmd;
        
-       arm7_9_cmd = register_command(cmd_ctx, NULL, "arm7_9", NULL, COMMAND_ANY, NULL);
-       
+       arm7_9_cmd = register_command(cmd_ctx, NULL, "arm7_9", NULL, COMMAND_ANY, "arm7/9 specific commands");
+
        register_command(cmd_ctx, arm7_9_cmd, "write_xpsr", handle_arm7_9_write_xpsr_command, COMMAND_EXEC, "write program status register <value> <not cpsr|spsr>");
        register_command(cmd_ctx, arm7_9_cmd, "write_xpsr_im8", handle_arm7_9_write_xpsr_im8_command, COMMAND_EXEC, "write program status register <8bit immediate> <rotate> <not cpsr|spsr>");
        
@@ -1986,13 +2283,17 @@ int arm7_9_register_commands(struct command_context_s *cmd_ctx)
        register_command(cmd_ctx, arm7_9_cmd, "force_hw_bkpts", handle_arm7_9_force_hw_bkpts_command, COMMAND_EXEC, "use hardware breakpoints for all breakpoints (disables sw breakpoint support) <enable|disable>");
        register_command(cmd_ctx, arm7_9_cmd, "dbgrq", handle_arm7_9_dbgrq_command,
                COMMAND_ANY, "use EmbeddedICE dbgrq instead of breakpoint for target halt requests <enable|disable>");
-       register_command(cmd_ctx, arm7_9_cmd, "fast_writes", handle_arm7_9_fast_writes_command,
-                COMMAND_ANY, "use fast memory writes instead of slower but potentially unsafe slow writes <enable|disable>");
+       register_command(cmd_ctx, arm7_9_cmd, "fast_writes", handle_arm7_9_fast_memory_access_command,
+                COMMAND_ANY, "(deprecated, see: arm7_9 fast_memory_access)");
+       register_command(cmd_ctx, arm7_9_cmd, "fast_memory_access", handle_arm7_9_fast_memory_access_command,
+                COMMAND_ANY, "use fast memory accesses instead of slower but potentially unsafe slow accesses <enable|disable>");
        register_command(cmd_ctx, arm7_9_cmd, "dcc_downloads", handle_arm7_9_dcc_downloads_command,
                COMMAND_ANY, "use DCC downloads for larger memory writes <enable|disable>");
 
        armv4_5_register_commands(cmd_ctx);
        
+       etm_register_commands(cmd_ctx);
+       
        return ERROR_OK;
 }
 
@@ -2026,6 +2327,10 @@ int handle_arm7_9_write_xpsr_command(struct command_context_s *cmd_ctx, char *cm
        value = strtoul(args[0], NULL, 0);
        spsr = strtol(args[1], NULL, 0);
        
+       /* if we're writing the CPSR, mask the T bit */
+       if (!spsr)
+               value &= ~0x20;
+       
        arm7_9->write_xpsr(target, value, spsr);
        if ((retval = jtag_execute_queue()) != ERROR_OK)
        {
@@ -2067,7 +2372,7 @@ int handle_arm7_9_write_xpsr_im8_command(struct command_context_s *cmd_ctx, char
        value = strtoul(args[0], NULL, 0);
        rotate = strtol(args[1], NULL, 0);
        spsr = strtol(args[2], NULL, 0);
-       
+               
        arm7_9->write_xpsr_im8(target, value, rotate, spsr);
        if ((retval = jtag_execute_queue()) != ERROR_OK)
        {
@@ -2231,7 +2536,7 @@ int handle_arm7_9_dbgrq_command(struct command_context_s *cmd_ctx, char *cmd, ch
        return ERROR_OK;
 }
 
-int handle_arm7_9_fast_writes_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+int handle_arm7_9_fast_memory_access_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
        target_t *target = get_current_target(cmd_ctx);
        armv4_5_common_t *armv4_5;
@@ -2247,19 +2552,19 @@ int handle_arm7_9_fast_writes_command(struct command_context_s *cmd_ctx, char *c
        {
                if (strcmp("enable", args[0]) == 0)
                {
-                       arm7_9->fast_memory_writes = 1;
+                       arm7_9->fast_memory_access = 1;
                }
                else if (strcmp("disable", args[0]) == 0)
                {
-                       arm7_9->fast_memory_writes = 0;
+                       arm7_9->fast_memory_access = 0;
                }
                else
                {
-                       command_print(cmd_ctx, "usage: arm7_9 fast_writes <enable|disable>");
+                       command_print(cmd_ctx, "usage: arm7_9 fast_memory_access <enable|disable>");
                }
        }
                
-       command_print(cmd_ctx, "fast memory writes are %s", (arm7_9->fast_memory_writes) ? "enabled" : "disabled");
+       command_print(cmd_ctx, "fast memory access is %s", (arm7_9->fast_memory_access) ? "enabled" : "disabled");
 
        return ERROR_OK;
 }
@@ -2309,13 +2614,19 @@ int arm7_9_init_arch_info(target_t *target, arm7_9_common_t *arm7_9)
        arm7_9->wp1_used = 0;
        arm7_9->force_hw_bkpts = 0;
        arm7_9->use_dbgrq = 0;
-       arm7_9->has_etm = 0;
+       
+       arm7_9->etm_ctx = NULL;
+       arm7_9->has_single_step = 0;
+       arm7_9->has_monitor_mode = 0;
+       arm7_9->has_vector_catch = 0;
        
        arm7_9->reinit_embeddedice = 0;
        
+       arm7_9->debug_entry_from_reset = 0;
+       
        arm7_9->dcc_working_area = NULL;
        
-       arm7_9->fast_memory_writes = 0;
+       arm7_9->fast_memory_access = 0;
        arm7_9->dcc_downloads = 0;
 
        jtag_register_event_callback(arm7_9_jtag_callback, target);
@@ -2327,5 +2638,7 @@ int arm7_9_init_arch_info(target_t *target, arm7_9_common_t *arm7_9)
        
        armv4_5_init_arch_info(target, armv4_5);
        
+       target_register_timer_callback(arm7_9_handle_target_request, 1, 1, target);
+       
        return ERROR_OK;
 }