- fixed arm926 cp15 command bug (thanks to Vincent Palatin for this patch)
[openocd.git] / src / target / arm7_9_common.c
index 904d0ca0faea7be2d31c0965370d050825cf0dcc..7a409b0fae10d4570da37992da556f5831c91099 100644 (file)
@@ -52,8 +52,10 @@ 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 handle_arm7_9_etb_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
 
 int arm7_9_reinit_embeddedice(target_t *target)
 {
@@ -184,13 +186,17 @@ int arm7_9_set_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
        {
                if (breakpoint->length == 4)
                {
+                       /* keep the original instruction in target endianness */
                        target->type->read_memory(target, breakpoint->address, 4, 1, breakpoint->orig_instr);
-                       target->type->write_memory(target, breakpoint->address, 4, 1, (u8*)(&arm7_9->arm_bkpt));
+                       /* write the original instruction in target endianness (arm7_9->arm_bkpt is host endian) */
+                       target_write_u32(target, breakpoint->address, arm7_9->arm_bkpt);
                }
                else
                {
+                       /* keep the original instruction in target endianness */
                        target->type->read_memory(target, breakpoint->address, 2, 1, breakpoint->orig_instr);
-                       target->type->write_memory(target, breakpoint->address, 2, 1, (u8*)(&arm7_9->thumb_bkpt));
+                       /* write the original instruction in target endianness (arm7_9->arm_bkpt is host endian) */
+                       target_write_u32(target, breakpoint->address, arm7_9->thumb_bkpt);
                }
                breakpoint->set = 1;
        }
@@ -234,6 +240,7 @@ 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);
@@ -248,7 +255,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;
@@ -261,30 +268,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;
 }
 
@@ -401,7 +409,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;
@@ -417,7 +425,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;
        }
@@ -534,7 +542,7 @@ 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);
@@ -567,7 +575,7 @@ int arm7_9_execute_fast_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);
@@ -588,7 +596,6 @@ enum target_state arm7_9_poll(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_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)
        {
@@ -652,6 +659,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)
@@ -720,11 +730,44 @@ 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;
+       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_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)
@@ -739,6 +782,26 @@ int arm7_9_soft_reset_halt(struct target_s *target)
        }
        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);
        
@@ -815,38 +878,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;
@@ -862,7 +893,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)
@@ -926,12 +957,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)
        {
@@ -939,6 +974,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)
        {
@@ -967,6 +1004,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;
@@ -1005,7 +1043,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)
        {
@@ -1035,9 +1073,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++)
@@ -1065,8 +1104,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)
        {
@@ -1087,7 +1126,7 @@ int arm7_9_restore_context(target_t *target)
        int dirty;
        int mode_change;
        
-       DEBUG("");
+       DEBUG("-");
        
        if (target->state != TARGET_HALTED)
        {
@@ -1145,9 +1184,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);
                        }
@@ -1186,19 +1226,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;
        }
@@ -1286,7 +1327,7 @@ int arm7_9_resume(struct target_s *target, int current, u32 address, int handle_
        breakpoint_t *breakpoint = target->breakpoints;
        reg_t *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];
        
-       DEBUG("");
+       DEBUG("-");
        
        if (target->state != TARGET_HALTED)
        {
@@ -1434,7 +1475,7 @@ 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;
 
        if (target->state != TARGET_HALTED)
        {
@@ -1495,6 +1536,7 @@ int arm7_9_step(struct target_s *target, int current, u32 address, int handle_br
 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;
@@ -1509,16 +1551,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);
        }
@@ -1530,23 +1573,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;
@@ -1569,9 +1613,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);
        }
        
@@ -1590,6 +1635,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);
        }
        
@@ -1599,8 +1648,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)
@@ -1619,14 +1668,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)
@@ -1642,11 +1690,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);
@@ -1660,19 +1703,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;
@@ -1688,17 +1735,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;
@@ -1714,16 +1763,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;
@@ -1745,9 +1797,9 @@ int arm7_9_read_memory(struct target_s *target, u32 address, u32 size, u32 count
 
        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;
        }
@@ -1759,6 +1811,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;
@@ -1787,6 +1840,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:
@@ -1811,7 +1868,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);
@@ -1843,7 +1900,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);
@@ -1874,7 +1931,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);
@@ -1889,11 +1946,9 @@ 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;
@@ -1907,9 +1962,9 @@ int arm7_9_write_memory(struct target_s *target, u32 address, u32 size, u32 coun
 
        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;
        }
@@ -1939,6 +1994,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)
                {
@@ -1946,8 +2003,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);
@@ -1988,6 +2051,9 @@ 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, "etm", handle_arm7_9_etm_command, COMMAND_CONFIG, NULL);
+       register_command(cmd_ctx, arm7_9_cmd, "etb", handle_arm7_9_etb_command, COMMAND_CONFIG, NULL);
        
        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>");
@@ -1998,8 +2064,10 @@ 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>");
 
@@ -2038,6 +2106,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)
        {
@@ -2079,7 +2151,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)
        {
@@ -2243,7 +2315,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;
@@ -2259,19 +2331,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,6 +2381,81 @@ int handle_arm7_9_dcc_downloads_command(struct command_context_s *cmd_ctx, char
        return ERROR_OK;
 }
 
+int handle_arm7_9_etm_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       target_t *target;
+       armv4_5_common_t *armv4_5;
+       arm7_9_common_t *arm7_9;
+       
+       if (argc != 1)
+       {
+               ERROR("incomplete 'arm7_9 etm <target>' command");
+               exit(-1);
+       }
+       
+       target = get_target_by_num(strtoul(args[0], NULL, 0));
+       
+       if (!target)
+       {
+               ERROR("target number '%s' not defined", args[0]);
+               exit(-1);
+       }
+       
+       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
+       {
+               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
+               return ERROR_OK;
+       }
+       
+       arm7_9->has_etm = 1;
+       
+       return ERROR_OK;
+}
+
+int handle_arm7_9_etb_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       target_t *target;
+       jtag_device_t *jtag_device;
+       armv4_5_common_t *armv4_5;
+       arm7_9_common_t *arm7_9;
+       
+       if (argc != 2)
+       {
+               ERROR("incomplete 'arm7_9 etb <target> <chain_pos>' command");
+               exit(-1);
+       }
+       
+       target = get_target_by_num(strtoul(args[0], NULL, 0));
+       
+       if (!target)
+       {
+               ERROR("target number '%s' not defined", args[0]);
+               exit(-1);
+       }
+       
+       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
+       {
+               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
+               return ERROR_OK;
+       }
+       
+       jtag_device = jtag_get_device(strtoul(args[1], NULL, 0));
+       
+       if (!jtag_device)
+       {
+               ERROR("jtag device number '%s' not defined", args[1]);
+               exit(-1);
+       }
+
+       arm7_9->etb = malloc(sizeof(etb_t));
+       
+       arm7_9->etb->chain_pos = strtoul(args[1], NULL, 0);
+       arm7_9->etb->cur_scan_chain = -1;
+       arm7_9->etb->reg_cache = NULL;
+
+       return ERROR_OK;
+}
+
 int arm7_9_init_arch_info(target_t *target, arm7_9_common_t *arm7_9)
 {
        armv4_5_common_t *armv4_5 = &arm7_9->armv4_5_common;
@@ -2321,13 +2468,18 @@ 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->etb = 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->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);

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)