- slight mips32 cleanup/reformat
[fw/openocd] / src / target / xscale.c
index 6bcd0251f3c48b4a51377e69ecaf0c2f350c2c44..0290c9ecb1b872bac3b06674adfc6060d5ce634a 100644 (file)
@@ -2,7 +2,7 @@
  *   Copyright (C) 2006, 2007 by Dominic Rath                              *
  *   Dominic.Rath@gmx.de                                                   *
  *                                                                         *
- *   Copyright (C) 2007,2008 Øyvind Harboe                                      *
+ *   Copyright (C) 2007,2008 Øyvind Harboe                                 *
  *   oyvind.harboe@zylin.com                                               *
  *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
@@ -53,7 +53,7 @@
 int xscale_register_commands(struct command_context_s *cmd_ctx);
 
 /* forward declarations */
-int xscale_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target);
+int xscale_target_create(struct target_s *target, Jim_Interp *interp);
 int xscale_init_target(struct command_context_s *cmd_ctx, struct target_s *target);
 int xscale_quit(void);
 
@@ -124,7 +124,7 @@ target_type_t xscale_target =
        .remove_watchpoint = xscale_remove_watchpoint,
 
        .register_commands = xscale_register_commands,
-       .target_command = xscale_target_command,
+       .target_create = xscale_target_create,
        .init_target = xscale_init_target,
        .quit = xscale_quit,
        
@@ -487,41 +487,43 @@ int xscale_read_tx(target_t *target, int consume)
 
        for (;;)
        {
-               int i;
-               for (i=0; i<100; i++)
+               /* if we want to consume the register content (i.e. clear TX_READY),
+                * we have to go straight from Capture-DR to Shift-DR
+                * otherwise, we go from Capture-DR to Exit1-DR to Pause-DR
+               */
+               if (consume)
+                       jtag_add_pathmove(3, path);
+               else
                {
-                       /* if we want to consume the register content (i.e. clear TX_READY),
-                        * we have to go straight from Capture-DR to Shift-DR
-                        * otherwise, we go from Capture-DR to Exit1-DR to Pause-DR
-                       */
-                       if (consume)
-                               jtag_add_pathmove(3, path);
-                       else
-                       {
-                               jtag_add_pathmove(sizeof(noconsume_path)/sizeof(*noconsume_path), noconsume_path);
-                       }
-       
-                       jtag_add_dr_scan(3, fields, TAP_RTI);
-       
-                       if ((retval = jtag_execute_queue()) != ERROR_OK)
-                       {
-                               LOG_ERROR("JTAG error while reading TX");
-                               return ERROR_TARGET_TIMEOUT;
-                       }
-       
-                       gettimeofday(&now, NULL);
-                       if ((now.tv_sec > timeout.tv_sec) || ((now.tv_sec == timeout.tv_sec)&& (now.tv_usec > timeout.tv_usec)))
-                       {
-                               LOG_ERROR("time out reading TX register");
-                               return ERROR_TARGET_TIMEOUT;
-                       }
-                       if (!((!(field0_in & 1)) && consume))
-                       {
-                               goto done;
-                       }
+                       jtag_add_pathmove(sizeof(noconsume_path)/sizeof(*noconsume_path), noconsume_path);
+               }
+
+               jtag_add_dr_scan(3, fields, TAP_RTI);
+
+               if ((retval = jtag_execute_queue()) != ERROR_OK)
+               {
+                       LOG_ERROR("JTAG error while reading TX");
+                       return ERROR_TARGET_TIMEOUT;
+               }
+
+               gettimeofday(&now, NULL);
+               if ((now.tv_sec > timeout.tv_sec) || ((now.tv_sec == timeout.tv_sec)&& (now.tv_usec > timeout.tv_usec)))
+               {
+                       LOG_ERROR("time out reading TX register");
+                       return ERROR_TARGET_TIMEOUT;
+               }
+               if (!((!(field0_in & 1)) && consume))
+               {
+                       goto done;
+               }
+               if (debug_level>=3)
+               {
+                       LOG_DEBUG("waiting 100ms");
+                       alive_sleep(100); /* avoid flooding the logs */
+               } else
+               {
+                       keep_alive();
                }
-               LOG_DEBUG("waiting 10ms");
-               usleep(10*1000); /* avoid flooding the logs */
        } 
        done:
 
@@ -585,28 +587,30 @@ int xscale_write_rx(target_t *target)
        LOG_DEBUG("polling RX");
        for (;;)
        {
-               int i;
-               for (i=0; i<100; i++)
+               jtag_add_dr_scan(3, fields, TAP_RTI);
+
+               if ((retval = jtag_execute_queue()) != ERROR_OK)
                {
-                       jtag_add_dr_scan(3, fields, TAP_RTI);
-       
-                       if ((retval = jtag_execute_queue()) != ERROR_OK)
-                       {
-                               LOG_ERROR("JTAG error while writing RX");
-                               return retval;
-                       }
-       
-                       gettimeofday(&now, NULL);
-                       if ((now.tv_sec > timeout.tv_sec) || ((now.tv_sec == timeout.tv_sec)&& (now.tv_usec > timeout.tv_usec)))
-                       {
-                               LOG_ERROR("time out writing RX register");
-                               return ERROR_TARGET_TIMEOUT;
-                       }
-                       if (!(field0_in & 1))
-                               goto done;
+                       LOG_ERROR("JTAG error while writing RX");
+                       return retval;
+               }
+
+               gettimeofday(&now, NULL);
+               if ((now.tv_sec > timeout.tv_sec) || ((now.tv_sec == timeout.tv_sec)&& (now.tv_usec > timeout.tv_usec)))
+               {
+                       LOG_ERROR("time out writing RX register");
+                       return ERROR_TARGET_TIMEOUT;
+               }
+               if (!(field0_in & 1))
+                       goto done;
+               if (debug_level>=3)
+               {
+                       LOG_DEBUG("waiting 100ms");
+                       alive_sleep(100); /* avoid flooding the logs */
+               } else
+               {
+                       keep_alive();
                }
-               LOG_DEBUG("waiting 10ms");
-               usleep(10*1000); /* wait 10ms to avoid flooding the logs */
        }
        done:
        
@@ -979,7 +983,7 @@ int xscale_arch_state(struct target_s *target)
                        "MMU: %s, D-Cache: %s, I-Cache: %s"
                        "%s",
                         armv4_5_state_strings[armv4_5->core_state],
-                        target_debug_reason_strings[target->debug_reason],
+                        Jim_Nvp_value2name_simple( nvp_target_debug_reason, target->debug_reason )->name ,
                         armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)],
                         buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32),
                         buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32),
@@ -1221,7 +1225,8 @@ int xscale_halt(target_t *target)
        armv4_5_common_t *armv4_5 = target->arch_info;
        xscale_common_t *xscale = armv4_5->arch_info;
 
-       LOG_DEBUG("target->state: %s", target_state_strings[target->state]);
+       LOG_DEBUG("target->state: %s", 
+                 Jim_Nvp_value2name_simple( nvp_target_state, target->state )->name);
 
        if (target->state == TARGET_HALTED)
        {
@@ -1255,6 +1260,7 @@ int xscale_enable_single_step(struct target_s *target, u32 next_pc)
        armv4_5_common_t *armv4_5 = target->arch_info;
        xscale_common_t *xscale= armv4_5->arch_info;
        reg_t *ibcr0 = &xscale->reg_cache->reg_list[XSCALE_IBCR0];
+       int retval;
 
        if (xscale->ibcr0_used)
        {
@@ -1271,7 +1277,8 @@ int xscale_enable_single_step(struct target_s *target, u32 next_pc)
                }
        }
 
-       xscale_set_reg_u32(ibcr0, next_pc | 0x1);
+       if ((retval=xscale_set_reg_u32(ibcr0, next_pc | 0x1))!=ERROR_OK)
+               return retval;
 
        return ERROR_OK;
 }
@@ -1281,8 +1288,10 @@ int xscale_disable_single_step(struct target_s *target)
        armv4_5_common_t *armv4_5 = target->arch_info;
        xscale_common_t *xscale= armv4_5->arch_info;
        reg_t *ibcr0 = &xscale->reg_cache->reg_list[XSCALE_IBCR0];
+       int retval;
 
-       xscale_set_reg_u32(ibcr0, 0x0);
+       if ((retval=xscale_set_reg_u32(ibcr0, 0x0))!=ERROR_OK)
+               return retval;
 
        return ERROR_OK;
 }
@@ -1443,46 +1452,15 @@ int xscale_resume(struct target_s *target, int current, u32 address, int handle_
        return ERROR_OK;
 }
 
-int xscale_step(struct target_s *target, int current, u32 address, int handle_breakpoints)
+static int xscale_step_inner(struct target_s *target, int current, u32 address, int handle_breakpoints)
 {
        armv4_5_common_t *armv4_5 = target->arch_info;
        xscale_common_t *xscale = armv4_5->arch_info;
-       breakpoint_t *breakpoint = target->breakpoints;
 
        u32 current_pc, next_pc;
-       int i;
        int retval;
+       int i;
 
-       if (target->state != TARGET_HALTED)
-       {
-               LOG_WARNING("target not halted");
-               return ERROR_TARGET_NOT_HALTED;
-       }
-
-       /* current = 1: continue on current pc, otherwise continue at <address> */
-       if (!current)
-               buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, address);
-
-       current_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
-
-       /* if we're at the reset vector, we have to simulate the step */
-       if (current_pc == 0x0)
-       {
-               arm_simulate_step(target, NULL);
-               current_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
-
-               target->debug_reason = DBG_REASON_SINGLESTEP;
-               target_call_event_callbacks(target, TARGET_EVENT_HALTED);
-
-               return ERROR_OK;
-       }
-
-       /* the front-end may request us not to handle breakpoints */
-       if (handle_breakpoints)
-               if ((breakpoint = breakpoint_find(target, buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32))))
-               {
-                       xscale_unset_breakpoint(target, breakpoint);
-               }
 
        target->debug_reason = DBG_REASON_SINGLESTEP;
 
@@ -1492,52 +1470,110 @@ int xscale_step(struct target_s *target, int current, u32 address, int handle_br
                u32 current_opcode;
                target_read_u32(target, current_pc, &current_opcode);
                LOG_ERROR("BUG: couldn't calculate PC of next instruction, current opcode was 0x%8.8x", current_opcode);
+               return retval;
        }
 
        LOG_DEBUG("enable single-step");
-       xscale_enable_single_step(target, next_pc);
+       if ((retval=xscale_enable_single_step(target, next_pc))!=ERROR_OK)
+               return retval;
 
        /* restore banked registers */
-       xscale_restore_context(target);
+       if ((retval=xscale_restore_context(target))!=ERROR_OK)
+               return retval;
 
        /* send resume request (command 0x30 or 0x31)
         * clean the trace buffer if it is to be enabled (0x62) */
        if (xscale->trace.buffer_enabled)
        {
-               xscale_send_u32(target, 0x62);
-               xscale_send_u32(target, 0x31);
+               if ((retval=xscale_send_u32(target, 0x62))!=ERROR_OK)
+                       return retval;
+               if ((retval=xscale_send_u32(target, 0x31))!=ERROR_OK)
+                       return retval;
        }
        else
-               xscale_send_u32(target, 0x30);
+               if ((retval=xscale_send_u32(target, 0x30))!=ERROR_OK)
+                       return retval;
 
        /* send CPSR */
-       xscale_send_u32(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32));
+       if ((retval=xscale_send_u32(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32)))!=ERROR_OK)
+               return retval;
        LOG_DEBUG("writing cpsr with value 0x%8.8x", buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32));
 
        for (i = 7; i >= 0; i--)
        {
                /* send register */
-               xscale_send_u32(target, buf_get_u32(armv4_5->core_cache->reg_list[i].value, 0, 32));
+               if ((retval=xscale_send_u32(target, buf_get_u32(armv4_5->core_cache->reg_list[i].value, 0, 32)))!=ERROR_OK)
+                       return retval;
                LOG_DEBUG("writing r%i with value 0x%8.8x", i, buf_get_u32(armv4_5->core_cache->reg_list[i].value, 0, 32));
        }
 
        /* send PC */
-       xscale_send_u32(target, buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));
+       if ((retval=xscale_send_u32(target, buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32)))!=ERROR_OK)
+               return retval;
        LOG_DEBUG("writing PC with value 0x%8.8x", buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));
 
        target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
 
        /* registers are now invalid */
-       armv4_5_invalidate_core_regs(target);
+       if ((retval=armv4_5_invalidate_core_regs(target))!=ERROR_OK)
+               return retval;
 
        /* wait for and process debug entry */
-       xscale_debug_entry(target);
+       if ((retval=xscale_debug_entry(target))!=ERROR_OK)
+               return retval;
 
        LOG_DEBUG("disable single-step");
-       xscale_disable_single_step(target);
+       if ((retval=xscale_disable_single_step(target))!=ERROR_OK)
+               return retval;
 
        target_call_event_callbacks(target, TARGET_EVENT_HALTED);
 
+       return ERROR_OK;
+}
+
+int xscale_step(struct target_s *target, int current, u32 address, int handle_breakpoints)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       breakpoint_t *breakpoint = target->breakpoints;
+
+       u32 current_pc;
+       int retval;
+
+       if (target->state != TARGET_HALTED)
+       {
+               LOG_WARNING("target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       /* current = 1: continue on current pc, otherwise continue at <address> */
+       if (!current)
+               buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, address);
+
+       current_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
+
+       /* if we're at the reset vector, we have to simulate the step */
+       if (current_pc == 0x0)
+       {
+               if ((retval=arm_simulate_step(target, NULL))!=ERROR_OK)
+                       return retval;
+               current_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
+
+               target->debug_reason = DBG_REASON_SINGLESTEP;
+               target_call_event_callbacks(target, TARGET_EVENT_HALTED);
+
+               return ERROR_OK;
+       }
+
+       /* the front-end may request us not to handle breakpoints */
+       if (handle_breakpoints)
+               if ((breakpoint = breakpoint_find(target, buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32))))
+               {
+                       if ((retval=xscale_unset_breakpoint(target, breakpoint))!=ERROR_OK)
+                               return retval;
+               }
+
+       retval = xscale_step_inner(target, current, address, handle_breakpoints);
+
        if (breakpoint)
        {
                xscale_set_breakpoint(target, breakpoint);
@@ -1554,7 +1590,8 @@ int xscale_assert_reset(target_t *target)
        armv4_5_common_t *armv4_5 = target->arch_info;
        xscale_common_t *xscale = armv4_5->arch_info;
 
-       LOG_DEBUG("target->state: %s", target_state_strings[target->state]);
+       LOG_DEBUG("target->state: %s", 
+                 Jim_Nvp_value2name_simple( nvp_target_state, target->state )->name);
 
        /* select DCSR instruction (set endstate to R-T-I to ensure we don't
         * end up in T-L-R, which would reset JTAG
@@ -2136,6 +2173,7 @@ void xscale_enable_mmu_caches(target_t *target, int mmu, int d_u_cache, int i_ca
 
 int xscale_set_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
 {
+       int retval;
        armv4_5_common_t *armv4_5 = target->arch_info;
        xscale_common_t *xscale = armv4_5->arch_info;
 
@@ -2145,9 +2183,6 @@ int xscale_set_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
                return ERROR_TARGET_NOT_HALTED;
        }
 
-       if (xscale->force_hw_bkpts)
-               breakpoint->type = BKPT_HARD;
-
        if (breakpoint->set)
        {
                LOG_WARNING("breakpoint already set");
@@ -2180,16 +2215,28 @@ int xscale_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);
+                       if((retval = target->type->read_memory(target, breakpoint->address, 4, 1, breakpoint->orig_instr)) != ERROR_OK)
+                       {
+                               return retval;
+                       }
                        /* write the original instruction in target endianness (arm7_9->arm_bkpt is host endian) */
-                       target_write_u32(target, breakpoint->address, xscale->arm_bkpt);
+                       if((retval = target_write_u32(target, breakpoint->address, xscale->arm_bkpt)) != ERROR_OK)
+                       {
+                               return retval;
+                       }
                }
                else
                {
                        /* keep the original instruction in target endianness */
-                       target->type->read_memory(target, breakpoint->address, 2, 1, breakpoint->orig_instr);
+                       if((retval = target->type->read_memory(target, breakpoint->address, 2, 1, breakpoint->orig_instr)) != ERROR_OK)
+                       {
+                               return retval;
+                       }
                        /* write the original instruction in target endianness (arm7_9->arm_bkpt is host endian) */
-                       target_write_u32(target, breakpoint->address, xscale->thumb_bkpt);
+                       if((retval = target_write_u32(target, breakpoint->address, xscale->thumb_bkpt)) != ERROR_OK)
+                       {
+                               return retval;
+                       }
                }
                breakpoint->set = 1;
        }
@@ -2209,12 +2256,6 @@ int xscale_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
                return ERROR_TARGET_NOT_HALTED;
        }
 
-       if (xscale->force_hw_bkpts)
-       {
-               LOG_DEBUG("forcing use of hardware breakpoint at address 0x%8.8x", breakpoint->address);
-               breakpoint->type = BKPT_HARD;
-       }
-
        if ((breakpoint->type == BKPT_HARD) && (xscale->ibcr_available < 1))
        {
                LOG_INFO("no breakpoint unit available for hardware breakpoint");
@@ -2236,6 +2277,7 @@ int xscale_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
 
 int xscale_unset_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
 {
+       int retval;
        armv4_5_common_t *armv4_5 = target->arch_info;
        xscale_common_t *xscale = armv4_5->arch_info;
 
@@ -2270,11 +2312,17 @@ int xscale_unset_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
                /* restore original instruction (kept in target endianness) */
                if (breakpoint->length == 4)
                {
-                       target->type->write_memory(target, breakpoint->address, 4, 1, breakpoint->orig_instr);
+                       if((retval = target->type->write_memory(target, breakpoint->address, 4, 1, breakpoint->orig_instr)) != ERROR_OK)
+                       {
+                               return retval;
+                       }
                }
                else
                {
-                       target->type->write_memory(target, breakpoint->address, 2, 1, breakpoint->orig_instr);
+                       if((retval = target->type->write_memory(target, breakpoint->address, 2, 1, breakpoint->orig_instr)) != ERROR_OK)
+                       {
+                               return retval;
+                       }
                }
                breakpoint->set = 0;
        }
@@ -2995,7 +3043,7 @@ int xscale_quit(void)
        return ERROR_OK;
 }
 
-int xscale_init_arch_info(target_t *target, xscale_common_t *xscale, int chain_pos, char *variant)
+int xscale_init_arch_info(target_t *target, xscale_common_t *xscale, int chain_pos, const char *variant)
 {
        armv4_5_common_t *armv4_5;
        u32 high_reset_branch, low_reset_branch;
@@ -3064,8 +3112,6 @@ int xscale_init_arch_info(target_t *target, xscale_common_t *xscale, int chain_p
        xscale->hold_rst = 0;
        xscale->external_debug_break = 0;
 
-       xscale->force_hw_bkpts = 1;
-
        xscale->ibcr_available = 2;
        xscale->ibcr0_used = 0;
        xscale->ibcr1_used = 0;
@@ -3106,24 +3152,11 @@ int xscale_init_arch_info(target_t *target, xscale_common_t *xscale, int chain_p
 }
 
 /* target xscale <endianess> <startup_mode> <chain_pos> <variant> */
-int xscale_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target)
+int xscale_target_create(struct target_s *target, Jim_Interp *interp)
 {
-       int chain_pos;
-       char *variant = NULL;
-       xscale_common_t *xscale = malloc(sizeof(xscale_common_t));
-       memset(xscale, 0, sizeof(*xscale));
+       xscale_common_t *xscale = calloc(1,sizeof(xscale_common_t));
 
-       if (argc < 5)
-       {
-               LOG_ERROR("'target xscale' requires four arguments: <endianess> <startup_mode> <chain_pos> <variant>");
-               return ERROR_OK;
-       }
-
-       chain_pos = strtoul(args[3], NULL, 0);
-
-       variant = args[4];
-
-       xscale_init_arch_info(target, xscale, chain_pos, variant);
+       xscale_init_arch_info(target, xscale, target->chain_position, target->variant);
        xscale_build_reg_cache(target);
 
        return ERROR_OK;
@@ -3378,34 +3411,6 @@ int xscale_handle_vector_catch_command(command_context_t *cmd_ctx, char *cmd, ch
        return ERROR_OK;
 }
 
-int xscale_handle_force_hw_bkpts_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;
-       xscale_common_t *xscale;
-
-       if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
-       {
-               return ERROR_OK;
-       }
-
-       if ((argc >= 1) && (strcmp("enable", args[0]) == 0))
-       {
-               xscale->force_hw_bkpts = 1;
-       }
-       else if ((argc >= 1) && (strcmp("disable", args[0]) == 0))
-       {
-               xscale->force_hw_bkpts = 0;
-       }
-       else
-       {
-               command_print(cmd_ctx, "usage: xscale force_hw_bkpts <enable|disable>");
-       }
-
-       command_print(cmd_ctx, "force hardware breakpoints %s", (xscale->force_hw_bkpts) ? "enabled" : "disabled");
-
-       return ERROR_OK;
-}
 
 int xscale_handle_trace_buffer_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
@@ -3616,12 +3621,12 @@ int xscale_handle_cp15(command_context_t *cmd_ctx, char *cmd, char **args, int a
        target_t *target = get_current_target(cmd_ctx);
        armv4_5_common_t *armv4_5;
        xscale_common_t *xscale;
-       
+
        if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
        {
                return ERROR_OK;
        }
-       
+
        if (target->state != TARGET_HALTED)
        {
                command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);