]> git.sur5r.net Git - openocd/blobdiff - src/target/arm7tdmi.c
- corrected stm32x_handle_options_write_command, incorrect options printed
[openocd] / src / target / arm7tdmi.c
index c207947790fbae256f28ac7edc0c7ebb15e04013..7c6b937f09e288a3767324dd494d8c0ec80b1715 100644 (file)
@@ -17,7 +17,9 @@
  *   Free Software Foundation, Inc.,                                       *
  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  ***************************************************************************/
+#ifdef HAVE_CONFIG_H
 #include "config.h"
+#endif
 
 #include "arm7tdmi.h"
 
@@ -49,7 +51,6 @@ int arm7tdmi_quit();
 /* target function declarations */
 enum target_state arm7tdmi_poll(struct target_s *target);
 int arm7tdmi_halt(target_t *target);
-int arm7tdmi_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);
                
 target_type_t arm7tdmi_target =
 {
@@ -65,6 +66,7 @@ target_type_t arm7tdmi_target =
        .assert_reset = arm7_9_assert_reset,
        .deassert_reset = arm7_9_deassert_reset,
        .soft_reset_halt = arm7_9_soft_reset_halt,
+       .prepare_reset_halt = arm7_9_prepare_reset_halt,
 
        .get_gdb_reg_list = armv4_5_get_gdb_reg_list,
        
@@ -122,9 +124,9 @@ int arm7tdmi_examine_debug_reason(target_t *target)
                fields[1].in_handler_priv = NULL;
                
                arm_jtag_scann(&arm7_9->jtag_info, 0x1);
-               arm_jtag_set_instr(&arm7_9->jtag_info, arm7_9->jtag_info.intest_instr);
+               arm_jtag_set_instr(&arm7_9->jtag_info, arm7_9->jtag_info.intest_instr, NULL);
 
-               jtag_add_dr_scan(2, fields, TAP_PD);
+               jtag_add_dr_scan(2, fields, TAP_PD, NULL);
                jtag_execute_queue();
                
                fields[0].in_value = NULL;
@@ -132,7 +134,7 @@ int arm7tdmi_examine_debug_reason(target_t *target)
                fields[1].in_value = NULL;
                fields[1].out_value = databus;
                
-               jtag_add_dr_scan(2, fields, TAP_PD);
+               jtag_add_dr_scan(2, fields, TAP_PD, NULL);
 
                if (breakpoint & 1)
                        target->debug_reason = DBG_REASON_WATCHPOINT; 
@@ -150,13 +152,12 @@ int arm7tdmi_clock_out(arm_jtag_t *jtag_info, u32 out, u32 *in, int breakpoint)
        u8 out_buf[4];
        u8 breakpoint_buf;
        
-       out = flip_u32(out, 32);
-       buf_set_u32(out_buf, 0, 32, out);
+       buf_set_u32(out_buf, 0, 32, flip_u32(out, 32));
        buf_set_u32(&breakpoint_buf, 0, 1, breakpoint);
 
        jtag_add_end_state(TAP_PD);
        arm_jtag_scann(jtag_info, 0x1);
-       arm_jtag_set_instr(jtag_info, jtag_info->intest_instr);
+       arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
        
        fields[0].device = jtag_info->chain_pos;
        fields[0].num_bits = 1;
@@ -172,52 +173,48 @@ int arm7tdmi_clock_out(arm_jtag_t *jtag_info, u32 out, u32 *in, int breakpoint)
        fields[1].num_bits = 32;
        fields[1].out_value = out_buf;
        fields[1].out_mask = NULL;
+       fields[1].in_value = NULL;
        if (in)
        {
-               fields[1].in_value = (u8*)in;
                fields[1].in_handler = arm_jtag_buf_to_u32_flip;
                fields[1].in_handler_priv = in;
-       } else
+       }
+       else
        {
-               fields[1].in_value = NULL;
                fields[1].in_handler = NULL;
                fields[1].in_handler_priv = NULL;
        }
-
        fields[1].in_check_value = NULL;
        fields[1].in_check_mask = NULL;
 
-       jtag_add_dr_scan(2, fields, -1);
+       jtag_add_dr_scan(2, fields, -1, NULL);
 
        jtag_add_runtest(0, -1);
        
 #ifdef _DEBUG_INSTRUCTION_EXECUTION_
 {
-               char* in_string;
                jtag_execute_queue();
                
                if (in)
                {
-                       in_string = buf_to_char((u8*)in, 32);
-                       DEBUG("out: 0x%8.8x, in: %s", flip_u32(out, 32), in_string);
-                       free(in_string);
+                       DEBUG("out: 0x%8.8x, in: 0x%8.8x", out, *in);
                }
                else
-                       DEBUG("out: 0x%8.8x", flip_u32(out, 32));
+                       DEBUG("out: 0x%8.8x", out);
 }
 #endif
 
        return ERROR_OK;
 }
 
-/* put an instruction in the ARM7TDMI pipeline, and optionally read data */
+/* clock the target, reading the databus */
 int arm7tdmi_clock_data_in(arm_jtag_t *jtag_info, u32 *in)
 {
        scan_field_t fields[2];
 
        jtag_add_end_state(TAP_PD);
        arm_jtag_scann(jtag_info, 0x1);
-       arm_jtag_set_instr(jtag_info, jtag_info->intest_instr);
+       arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
        
        fields[0].device = jtag_info->chain_pos;
        fields[0].num_bits = 1;
@@ -233,26 +230,92 @@ int arm7tdmi_clock_data_in(arm_jtag_t *jtag_info, u32 *in)
        fields[1].num_bits = 32;
        fields[1].out_value = NULL;
        fields[1].out_mask = NULL;
-       fields[1].in_value = (u8*)in;
+       fields[1].in_value = NULL;
        fields[1].in_handler = arm_jtag_buf_to_u32_flip;
        fields[1].in_handler_priv = in;
        fields[1].in_check_value = NULL;
        fields[1].in_check_mask = NULL;
 
-       jtag_add_dr_scan(2, fields, -1);
+       jtag_add_dr_scan(2, fields, -1, NULL);
+
+       jtag_add_runtest(0, -1);
+       
+#ifdef _DEBUG_INSTRUCTION_EXECUTION_
+{
+               jtag_execute_queue();
+                       
+               if (in)
+               {
+                       DEBUG("in: 0x%8.8x", *in);
+               }
+               else
+               {
+                       ERROR("BUG: called with in == NULL");
+               }
+}
+#endif
+
+       return ERROR_OK;
+}
+
+/* clock the target, and read the databus
+ * the *in pointer points to a buffer where elements of 'size' bytes
+ * are stored in big (be==1) or little (be==0) endianness
+ */ 
+int arm7tdmi_clock_data_in_endianness(arm_jtag_t *jtag_info, void *in, int size, int be)
+{
+       scan_field_t fields[2];
+
+       jtag_add_end_state(TAP_PD);
+       arm_jtag_scann(jtag_info, 0x1);
+       arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
+       
+       fields[0].device = jtag_info->chain_pos;
+       fields[0].num_bits = 1;
+       fields[0].out_value = NULL;
+       fields[0].out_mask = NULL;
+       fields[0].in_value = NULL;
+       fields[0].in_check_value = NULL;
+       fields[0].in_check_mask = NULL;
+       fields[0].in_handler = NULL;
+       fields[0].in_handler_priv = NULL;
+               
+       fields[1].device = jtag_info->chain_pos;
+       fields[1].num_bits = 32;
+       fields[1].out_value = NULL;
+       fields[1].out_mask = NULL;
+       fields[1].in_value = NULL;
+       switch (size)
+       {
+               case 4:
+                       fields[1].in_handler = (be) ? arm_jtag_buf_to_be32_flip : arm_jtag_buf_to_le32_flip;
+                       break;
+               case 2:
+                       fields[1].in_handler = (be) ? arm_jtag_buf_to_be16_flip : arm_jtag_buf_to_le16_flip;
+                       break;
+               case 1:
+                       fields[1].in_handler = arm_jtag_buf_to_8_flip;
+                       break;
+       }
+       fields[1].in_handler_priv = in;
+       fields[1].in_check_value = NULL;
+       fields[1].in_check_mask = NULL;
+
+       jtag_add_dr_scan(2, fields, -1, NULL);
 
        jtag_add_runtest(0, -1);
        
 #ifdef _DEBUG_INSTRUCTION_EXECUTION_
 {
-               char* in_string;
                jtag_execute_queue();
                        
                if (in)
                {
-                       in_string = buf_to_char((u8*)in, 32);
-                       DEBUG("in: %s", in_string);
-                       free(in_string);
+                       DEBUG("in: 0x%8.8x", *in);
+               }
+               else
+               {
+                       ERROR("BUG: called with in == NULL");
                }
 }
 #endif
@@ -285,8 +348,14 @@ void arm7tdmi_change_to_arm(target_t *target, u32 *r0, u32 *pc)
        /* nothing fetched, STR r0, [r0] in Execute (2) */
        arm7tdmi_clock_data_in(jtag_info, pc);
 
-       /* fetch MOV */
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_MOV_IM(0, 0x0), NULL, 0);
+       /* use pc-relative LDR to clear r0[1:0] (for switch to ARM mode) */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_LDR_PCREL(0), NULL, 0);
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
+       /* nothing fetched, data for LDR r0, [PC, #0] */
+       arm7tdmi_clock_out(jtag_info, 0x0, NULL, 0);
+       /* nothing fetched, data from previous cycle is written to register */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
        
        /* fetch BX */
        arm7tdmi_clock_out(jtag_info, ARMV4_5_T_BX(0), NULL, 0);
@@ -332,6 +401,50 @@ void arm7tdmi_read_core_regs(target_t *target, u32 mask, u32* core_regs[16])
 
 }
 
+void arm7tdmi_read_core_regs_target_buffer(target_t *target, u32 mask, void* buffer, int size)
+{
+       int i;
+       /* get pointers to arch-specific information */
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+       int be = (target->endianness == TARGET_BIG_ENDIAN) ? 1 : 0;
+       u32 *buf_u32 = buffer;
+       u16 *buf_u16 = buffer;
+       u8 *buf_u8 = buffer;
+               
+       /* STMIA r0-15, [r0] at debug speed
+        * register values will start to appear on 4th DCLK
+        */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), NULL, 0);
+
+       /* fetch NOP, STM in DECODE stage */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+       /* fetch NOP, STM in EXECUTE stage (1st cycle) */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+
+       for (i = 0; i <= 15; i++)
+       {
+               /* nothing fetched, STM still in EXECUTE (1+i cycle), read databus */
+               if (mask & (1 << i))
+               {
+                       switch (size)
+                       {
+                               case 4:
+                                       arm7tdmi_clock_data_in_endianness(jtag_info, buf_u32++, 4, be);
+                                       break;
+                               case 2:
+                                       arm7tdmi_clock_data_in_endianness(jtag_info, buf_u16++, 2, be);
+                                       break;
+                               case 1:
+                                       arm7tdmi_clock_data_in_endianness(jtag_info, buf_u8++, 1, be);
+                                       break;
+                       }
+               }
+       }
+       
+}
+
 void arm7tdmi_read_xpsr(target_t *target, u32 *xpsr, int spsr)
 {
        /* get pointers to arch-specific information */
@@ -557,7 +670,7 @@ void arm7tdmi_branch_resume(target_t *target)
 
 void arm7tdmi_branch_resume_thumb(target_t *target)
 {
-       DEBUG("");
+       DEBUG("-");
        
        /* get pointers to arch-specific information */
        armv4_5_common_t *armv4_5 = target->arch_info;
@@ -596,11 +709,9 @@ void arm7tdmi_branch_resume_thumb(target_t *target)
        /* target is now in Thumb state */
        embeddedice_read_reg(dbg_stat);
 
-       /* clean r0 bits to avoid alignment problems */
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_MOV_IM(0, 0x0), NULL, 0);
-       /* load r0 value, MOV_IM in Decode*/
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_LDR(0, 0), NULL, 0);
-       /* fetch NOP, LDR in Decode, MOV_IM in Execute */
+       /* load r0 value */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_LDR_PCREL(0), NULL, 0);
+       /* fetch NOP, LDR in Decode */
        arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
        /* fetch NOP, LDR in Execute */
        arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
@@ -615,7 +726,7 @@ void arm7tdmi_branch_resume_thumb(target_t *target)
        embeddedice_read_reg(dbg_stat);
        
        arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 1);
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_B(0x7f7), NULL, 0);
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_B(0x7f8), NULL, 0);
 
 }
                
@@ -626,28 +737,18 @@ void arm7tdmi_build_reg_cache(target_t *target)
        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;
-       arm7tdmi_common_t *arch_info = arm7_9->arch_info;
-
 
        (*cache_p) = armv4_5_build_reg_cache(target, armv4_5);
        armv4_5->core_cache = (*cache_p);
        
-       (*cache_p)->next = embeddedice_build_reg_cache(target, jtag_info, 0);
+       (*cache_p)->next = embeddedice_build_reg_cache(target, arm7_9);
        arm7_9->eice_cache = (*cache_p)->next;
        
-       if (arm7_9->has_etm)
+       if (arm7_9->etm_ctx)
        {
-               (*cache_p)->next->next = etm_build_reg_cache(target, jtag_info, 0);
-               arm7_9->etm_cache = (*cache_p)->next->next;
+               (*cache_p)->next->next = etm_build_reg_cache(target, jtag_info, arm7_9->etm_ctx);
+               arm7_9->etm_ctx->reg_cache = (*cache_p)->next->next;
        }
-               
-       if (arch_info->has_monitor_mode)
-               (*cache_p)->next->reg_list[0].size = 6;
-       else
-               (*cache_p)->next->reg_list[0].size = 3;
-       
-       (*cache_p)->next->reg_list[1].size = 5;
-
 }
 
 int arm7tdmi_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
@@ -669,7 +770,6 @@ int arm7tdmi_init_arch_info(target_t *target, arm7tdmi_common_t *arm7tdmi, int c
 {
        armv4_5_common_t *armv4_5;
        arm7_9_common_t *arm7_9;
-       int has_etm = 0;
        
        arm7_9 = &arm7tdmi->arm7_9_common;
        armv4_5 = &arm7_9->armv4_5_common;
@@ -682,6 +782,7 @@ int arm7tdmi_init_arch_info(target_t *target, arm7tdmi_common_t *arm7tdmi, int c
        arm7_9->examine_debug_reason = arm7tdmi_examine_debug_reason;
        arm7_9->change_to_arm = arm7tdmi_change_to_arm;
        arm7_9->read_core_regs = arm7tdmi_read_core_regs;
+       arm7_9->read_core_regs_target_buffer = arm7tdmi_read_core_regs_target_buffer;
        arm7_9->read_xpsr = arm7tdmi_read_xpsr;
        
        arm7_9->write_xpsr = arm7tdmi_write_xpsr;
@@ -710,37 +811,27 @@ int arm7tdmi_init_arch_info(target_t *target, arm7tdmi_common_t *arm7tdmi, int c
        arm7_9->post_restore_context = NULL;
        
        /* initialize arch-specific breakpoint handling */
-       buf_set_u32((u8*)(&arm7_9->arm_bkpt), 0, 32, 0xdeeedeee);
-       buf_set_u32((u8*)(&arm7_9->thumb_bkpt), 0, 16, 0xdeee);
+       arm7_9->arm_bkpt = 0xdeeedeee;
+       arm7_9->thumb_bkpt = 0xdeee;
        
        arm7_9->sw_bkpts_use_wp = 1;
        arm7_9->sw_bkpts_enabled = 0;
        arm7_9->dbgreq_adjust_pc = 2;
        arm7_9->arch_info = arm7tdmi;
-       
-       arm7tdmi->has_monitor_mode = 0;
+
        arm7tdmi->arch_info = NULL;
        arm7tdmi->common_magic = ARM7TDMI_COMMON_MAGIC;
        
        if (variant)
        {
-               if (strcmp(variant, "arm7tdmi-s_r4") == 0)
-                       arm7tdmi->has_monitor_mode = 1;
-               else if (strcmp(variant, "arm7tdmi_r4") == 0)
-                       arm7tdmi->has_monitor_mode = 1;
-               else if (strcmp(variant, "lpc2000") == 0)
-               {
-                       arm7tdmi->has_monitor_mode = 1;
-                       has_etm = 1;
-               }
                arm7tdmi->variant = strdup(variant);
        }
        else
+       {
                arm7tdmi->variant = strdup("");
+       }
        
        arm7_9_init_arch_info(target, arm7_9);
-       
-       arm7_9->has_etm = has_etm;
 
        return ERROR_OK;
 }
@@ -758,7 +849,7 @@ int arm7tdmi_target_command(struct command_context_s *cmd_ctx, char *cmd, char *
                exit(-1);
        }
        
-       chain_pos = strtoul(args[2], NULL, 0);
+       chain_pos = strtoul(args[3], NULL, 0);
        
        if (argc >= 5)
                variant = args[4];