Delete commented out code. Add a bit of error checking.
[openocd.git] / src / target / arm11.c
index 57dcd2f822b91f8bc5684e3bf0fb3e024fc0a8c7..c41adfa3bf779df3f6d1e6ec28437072743a9ca5 100644 (file)
@@ -2,7 +2,7 @@
  *   Copyright (C) 2008 digenius technology GmbH.                          *
  *   Michael Bruck                                                         *
  *                                                                         *
- *   Copyright (C) 2008 Oyvind Harboe oyvind.harboe@zylin.com              *
+ *   Copyright (C) 2008,2009 Oyvind Harboe oyvind.harboe@zylin.com         *
  *                                                                         *
  *   Copyright (C) 2008 Georg Acher <acher@in.tum.de>                      *
  *                                                                         *
@@ -27,6 +27,9 @@
 #endif
 
 #include "arm11.h"
+#include "armv4_5.h"
+#include "arm_simulator.h"
+#include "time_support.h"
 #include "target_type.h"
 
 
@@ -51,8 +54,8 @@ static int arm11_on_enter_debug_state(arm11_common_t * arm11);
 bool   arm11_config_memwrite_burst                             = true;
 bool   arm11_config_memwrite_error_fatal               = true;
 uint32_t               arm11_vcr                                                               = 0;
-bool   arm11_config_memrw_no_increment                 = false;
 bool   arm11_config_step_irq_enable                    = false;
+bool   arm11_config_hardware_step                              = false;
 
 #define ARM11_HANDLER(x)       \
        .x                              = arm11_##x
@@ -371,6 +374,7 @@ int arm11_check_init(arm11_common_t * arm11, uint32_t * dscr)
   */
 static int arm11_on_enter_debug_state(arm11_common_t * arm11)
 {
+       int retval;
        FNC_INFO;
 
        for (size_t i = 0; i < asizeof(arm11->reg_values); i++)
@@ -447,7 +451,9 @@ static int arm11_on_enter_debug_state(arm11_common_t * arm11)
        }
 #endif
 
-       arm11_run_instr_data_prepare(arm11);
+       retval = arm11_run_instr_data_prepare(arm11);
+       if (retval != ERROR_OK)
+               return retval;
 
        /* save r0 - r14 */
 
@@ -456,7 +462,9 @@ static int arm11_on_enter_debug_state(arm11_common_t * arm11)
        for (size_t i = 0; i < 15; i++)
        {
                /* MCR p14,0,R?,c0,c5,0 */
-               arm11_run_instr_data_from_core(arm11, 0xEE000E15 | (i << 12), &R(RX + i), 1);
+               retval = arm11_run_instr_data_from_core(arm11, 0xEE000E15 | (i << 12), &R(RX + i), 1);
+               if (retval != ERROR_OK)
+                       return retval;
        }
 
        /* save rDTR */
@@ -466,7 +474,9 @@ static int arm11_on_enter_debug_state(arm11_common_t * arm11)
        if (R(DSCR) & ARM11_DSCR_RDTR_FULL)
        {
                /* MRC p14,0,R0,c0,c5,0 (move rDTR -> r0 (-> wDTR -> local var)) */
-               arm11_run_instr_data_from_core_via_r0(arm11, 0xEE100E15, &R(RDTR));
+               retval = arm11_run_instr_data_from_core_via_r0(arm11, 0xEE100E15, &R(RDTR));
+               if (retval != ERROR_OK)
+                       return retval;
        }
        else
        {
@@ -476,12 +486,16 @@ static int arm11_on_enter_debug_state(arm11_common_t * arm11)
        /* save CPSR */
 
        /* MRS r0,CPSR (move CPSR -> r0 (-> wDTR -> local var)) */
-       arm11_run_instr_data_from_core_via_r0(arm11, 0xE10F0000, &R(CPSR));
+       retval = arm11_run_instr_data_from_core_via_r0(arm11, 0xE10F0000, &R(CPSR));
+       if (retval != ERROR_OK)
+               return retval;
 
        /* save PC */
 
        /* MOV R0,PC (move PC -> r0 (-> wDTR -> local var)) */
-       arm11_run_instr_data_from_core_via_r0(arm11, 0xE1A0000F, &R(PC));
+       retval = arm11_run_instr_data_from_core_via_r0(arm11, 0xE1A0000F, &R(PC));
+       if (retval != ERROR_OK)
+               return retval;
 
        /* adjust PC depending on ARM state */
 
@@ -507,11 +521,15 @@ static int arm11_on_enter_debug_state(arm11_common_t * arm11)
                /* Write 0 (reset value) to Control register 0 to disable MMU/Cache etc. */
 
                /* MCR p15,0,R0,c1,c0,0 */
-               arm11_run_instr_data_to_core_via_r0(arm11, 0xee010f10, 0);
+               retval = arm11_run_instr_data_to_core_via_r0(arm11, 0xee010f10, 0);
+               if (retval != ERROR_OK)
+                       return retval;
 
        }
 
-       arm11_run_instr_data_finish(arm11);
+       retval = arm11_run_instr_data_finish(arm11);
+       if (retval != ERROR_OK)
+               return retval;
 
        arm11_dump_reg_changes(arm11);
 
@@ -556,8 +574,11 @@ void arm11_dump_reg_changes(arm11_common_t * arm11)
 int arm11_leave_debug_state(arm11_common_t * arm11)
 {
        FNC_INFO;
+       int retval;
 
-       arm11_run_instr_data_prepare(arm11);
+       retval = arm11_run_instr_data_prepare(arm11);
+       if (retval != ERROR_OK)
+               return retval;
 
        /** \todo TODO: handle other mode registers */
 
@@ -574,7 +595,9 @@ int arm11_leave_debug_state(arm11_common_t * arm11)
                //      LOG_DEBUG("RESTORE R" ZU " %08x", i, R(RX + i));
        }
 
-       arm11_run_instr_data_finish(arm11);
+       retval = arm11_run_instr_data_finish(arm11);
+       if (retval != ERROR_OK)
+               return retval;
 
        /* spec says clear wDTR and rDTR; we assume they are clear as
           otherwise our programming would be sloppy */
@@ -585,36 +608,56 @@ int arm11_leave_debug_state(arm11_common_t * arm11)
 
                if (DSCR & (ARM11_DSCR_RDTR_FULL | ARM11_DSCR_WDTR_FULL))
                {
+                       /*
+                       The wDTR/rDTR two registers that are used to send/receive data to/from
+                       the core in tandem with corresponding instruction codes that are
+                       written into the core. The RDTR FULL/WDTR FULL flag indicates that the
+                       registers hold data that was written by one side (CPU or JTAG) and not
+                       read out by the other side.
+                       */
                        LOG_ERROR("wDTR/rDTR inconsistent (DSCR %08" PRIx32 ")", DSCR);
+                       return ERROR_FAIL;
                }
        }
 
-       arm11_run_instr_data_prepare(arm11);
+       retval = arm11_run_instr_data_prepare(arm11);
+       if (retval != ERROR_OK)
+               return retval;
 
        /* restore original wDTR */
 
        if ((R(DSCR) & ARM11_DSCR_WDTR_FULL) || arm11->reg_list[ARM11_RC_WDTR].dirty)
        {
                /* MCR p14,0,R0,c0,c5,0 */
-               arm11_run_instr_data_to_core_via_r0(arm11, 0xee000e15, R(WDTR));
+               retval = arm11_run_instr_data_to_core_via_r0(arm11, 0xee000e15, R(WDTR));
+               if (retval != ERROR_OK)
+                       return retval;
        }
 
        /* restore CPSR */
 
        /* MSR CPSR,R0*/
-       arm11_run_instr_data_to_core_via_r0(arm11, 0xe129f000, R(CPSR));
+       retval = arm11_run_instr_data_to_core_via_r0(arm11, 0xe129f000, R(CPSR));
+       if (retval != ERROR_OK)
+               return retval;
+
 
        /* restore PC */
 
        /* MOV PC,R0 */
-       arm11_run_instr_data_to_core_via_r0(arm11, 0xe1a0f000, R(PC));
+       retval = arm11_run_instr_data_to_core_via_r0(arm11, 0xe1a0f000, R(PC));
+       if (retval != ERROR_OK)
+               return retval;
+
 
        /* restore R0 */
 
        /* MRC p14,0,r0,c0,c5,0 */
        arm11_run_instr_data_to_core1(arm11, 0xee100e15, R(R0));
 
-       arm11_run_instr_data_finish(arm11);
+       retval = arm11_run_instr_data_finish(arm11);
+       if (retval != ERROR_OK)
+               return retval;
 
        /* restore DSCR */
 
@@ -662,12 +705,10 @@ void arm11_record_register_history(arm11_common_t * arm11)
 int arm11_poll(struct target_s *target)
 {
        FNC_INFO;
+       int retval;
 
        arm11_common_t * arm11 = target->arch_info;
 
-       if (arm11->trst_active)
-               return ERROR_OK;
-
        uint32_t        dscr;
 
        CHECK_RETVAL(arm11_read_DSCR(arm11, &dscr));
@@ -685,7 +726,9 @@ int arm11_poll(struct target_s *target)
                        LOG_DEBUG("enter TARGET_HALTED");
                        target->state                   = TARGET_HALTED;
                        target->debug_reason    = arm11_get_DSCR_debug_reason(dscr);
-                       arm11_on_enter_debug_state(arm11);
+                       retval = arm11_on_enter_debug_state(arm11);
+                       if (retval != ERROR_OK)
+                               return retval;
 
                        target_call_event_callbacks(target,
                                old_state == TARGET_DEBUG_RUNNING ? TARGET_EVENT_DEBUG_HALTED : TARGET_EVENT_HALTED);
@@ -732,7 +775,7 @@ int arm11_halt(struct target_s *target)
        arm11_common_t * arm11 = target->arch_info;
 
        LOG_DEBUG("target->state: %s",
-               Jim_Nvp_value2name_simple(nvp_target_state, target->state)->name);
+               target_state_name(target));
 
        if (target->state == TARGET_UNKNOWN)
        {
@@ -745,24 +788,35 @@ int arm11_halt(struct target_s *target)
                return ERROR_OK;
        }
 
-       if (arm11->trst_active)
-       {
-               arm11->halt_requested = true;
-               return ERROR_OK;
-       }
-
        arm11_add_IR(arm11, ARM11_HALT, TAP_IDLE);
 
        CHECK_RETVAL(jtag_execute_queue());
 
        uint32_t dscr;
 
+       int i = 0;
        while (1)
        {
                CHECK_RETVAL(arm11_read_DSCR(arm11, &dscr));
 
                if (dscr & ARM11_DSCR_CORE_HALTED)
                        break;
+
+
+               long long then = 0;
+               if (i == 1000)
+               {
+                       then = timeval_ms();
+               }
+               if (i >= 1000)
+               {
+                       if ((timeval_ms()-then) > 1000)
+                       {
+                               LOG_WARNING("Timeout (1000ms) waiting for instructions to complete");
+                               return ERROR_FAIL;
+                       }
+               }
+               i++;
        }
 
        arm11_on_enter_debug_state(arm11);
@@ -789,7 +843,7 @@ int arm11_resume(struct target_s *target, int current, uint32_t address, int han
        arm11_common_t * arm11 = target->arch_info;
 
        LOG_DEBUG("target->state: %s",
-               Jim_Nvp_value2name_simple(nvp_target_state, target->state)->name);
+               target_state_name(target));
 
 
        if (target->state != TARGET_HALTED)
@@ -854,6 +908,7 @@ int arm11_resume(struct target_s *target, int current, uint32_t address, int han
 
        CHECK_RETVAL(jtag_execute_queue());
 
+       int i = 0;
        while (1)
        {
                uint32_t dscr;
@@ -864,6 +919,22 @@ int arm11_resume(struct target_s *target, int current, uint32_t address, int han
 
                if (dscr & ARM11_DSCR_CORE_RESTARTED)
                        break;
+
+
+               long long then = 0;
+               if (i == 1000)
+               {
+                       then = timeval_ms();
+               }
+               if (i >= 1000)
+               {
+                       if ((timeval_ms()-then) > 1000)
+                       {
+                               LOG_WARNING("Timeout (1000ms) waiting for instructions to complete");
+                               return ERROR_FAIL;
+                       }
+               }
+               i++;
        }
 
        if (!debug_execution)
@@ -884,12 +955,99 @@ int arm11_resume(struct target_s *target, int current, uint32_t address, int han
        return ERROR_OK;
 }
 
+
+static int armv4_5_to_arm11(int reg)
+{
+       if (reg < 16)
+               return reg;
+       switch (reg)
+       {
+       case ARMV4_5_CPSR:
+               return ARM11_RC_CPSR;
+       case 16:
+               /* FIX!!! handle thumb better! */
+               return ARM11_RC_CPSR;
+       default:
+               LOG_ERROR("BUG: register translation from armv4_5 to arm11 not supported %d", reg);
+               exit(-1);
+       }
+}
+
+
+static uint32_t arm11_sim_get_reg(struct arm_sim_interface *sim, int reg)
+{
+       arm11_common_t * arm11 = (arm11_common_t *)sim->user_data;
+
+       reg=armv4_5_to_arm11(reg);
+
+       return buf_get_u32(arm11->reg_list[reg].value, 0, 32);
+}
+
+static void arm11_sim_set_reg(struct arm_sim_interface *sim, int reg, uint32_t value)
+{
+       arm11_common_t * arm11 = (arm11_common_t *)sim->user_data;
+
+       reg=armv4_5_to_arm11(reg);
+
+       buf_set_u32(arm11->reg_list[reg].value, 0, 32, value);
+}
+
+static uint32_t arm11_sim_get_cpsr(struct arm_sim_interface *sim, int pos, int bits)
+{
+       arm11_common_t * arm11 = (arm11_common_t *)sim->user_data;
+
+       return buf_get_u32(arm11->reg_list[ARM11_RC_CPSR].value, pos, bits);
+}
+
+static enum armv4_5_state arm11_sim_get_state(struct arm_sim_interface *sim)
+{
+//     arm11_common_t * arm11 = (arm11_common_t *)sim->user_data;
+
+       /* FIX!!!! we should implement thumb for arm11 */
+       return ARMV4_5_STATE_ARM;
+}
+
+static void arm11_sim_set_state(struct arm_sim_interface *sim, enum armv4_5_state mode)
+{
+//     arm11_common_t * arm11 = (arm11_common_t *)sim->user_data;
+
+       /* FIX!!!! we should implement thumb for arm11 */
+       LOG_ERROR("Not implemetned!");
+}
+
+
+static enum armv4_5_mode arm11_sim_get_mode(struct arm_sim_interface *sim)
+{
+       //arm11_common_t * arm11 = (arm11_common_t *)sim->user_data;
+
+       /* FIX!!!! we should implement something that returns the current mode here!!! */
+       return ARMV4_5_MODE_USR;
+}
+
+static int arm11_simulate_step(target_t *target, uint32_t *dry_run_pc)
+{
+       struct arm_sim_interface sim;
+
+       sim.user_data=target->arch_info;
+       sim.get_reg=&arm11_sim_get_reg;
+       sim.set_reg=&arm11_sim_set_reg;
+       sim.get_reg_mode=&arm11_sim_get_reg;
+       sim.set_reg_mode=&arm11_sim_set_reg;
+       sim.get_cpsr=&arm11_sim_get_cpsr;
+       sim.get_mode=&arm11_sim_get_mode;
+       sim.get_state=&arm11_sim_get_state;
+       sim.set_state=&arm11_sim_set_state;
+
+       return arm_simulate_step_core(target, dry_run_pc, &sim);
+
+}
+
 int arm11_step(struct target_s *target, int current, uint32_t address, int handle_breakpoints)
 {
        FNC_INFO;
 
        LOG_DEBUG("target->state: %s",
-               Jim_Nvp_value2name_simple(nvp_target_state, target->state)->name);
+               target_state_name(target));
 
        if (target->state != TARGET_HALTED)
        {
@@ -904,6 +1062,7 @@ int arm11_step(struct target_s *target, int current, uint32_t address, int handl
 
        LOG_DEBUG("STEP PC %08" PRIx32 "%s", R(PC), !current ? "!" : "");
 
+
        /** \todo TODO: Thumb not supported here */
 
        uint32_t        next_instruction;
@@ -947,10 +1106,30 @@ int arm11_step(struct target_s *target, int current, uint32_t address, int handl
 
                brp[0].write    = 1;
                brp[0].address  = ARM11_SC7_BVR0;
-               brp[0].value    = R(PC);
                brp[1].write    = 1;
                brp[1].address  = ARM11_SC7_BCR0;
-               brp[1].value    = 0x1 | (3 << 1) | (0x0F << 5) | (0 << 14) | (0 << 16) | (0 << 20) | (2 << 21);
+
+               if (arm11_config_hardware_step)
+               {
+                       /* hardware single stepping be used if possible or is it better to
+                        * always use the same code path? Hardware single stepping is not supported
+                        * on all hardware
+                        */
+                        brp[0].value   = R(PC);
+                        brp[1].value   = 0x1 | (3 << 1) | (0x0F << 5) | (0 << 14) | (0 << 16) | (0 << 20) | (2 << 21);
+               } else
+               {
+                       /* sets a breakpoint on the next PC(calculated by simulation),
+                        */
+                       uint32_t next_pc;
+                       int retval;
+                       retval = arm11_simulate_step(target, &next_pc);
+                       if (retval != ERROR_OK)
+                               return retval;
+
+                       brp[0].value    = next_pc;
+                       brp[1].value    = 0x1 | (3 << 1) | (0x0F << 5) | (0 << 14) | (0 << 16) | (0 << 20) | (0 << 21);
+               }
 
                CHECK_RETVAL(arm11_sc7_run(arm11, brp, asizeof(brp)));
 
@@ -969,10 +1148,8 @@ int arm11_step(struct target_s *target, int current, uint32_t address, int handl
 
                CHECK_RETVAL(jtag_execute_queue());
 
-               /** \todo TODO: add a timeout */
-
                /* wait for halt */
-
+               int i = 0;
                while (1)
                {
                        uint32_t dscr;
@@ -984,6 +1161,21 @@ int arm11_step(struct target_s *target, int current, uint32_t address, int handl
                        if ((dscr & (ARM11_DSCR_CORE_RESTARTED | ARM11_DSCR_CORE_HALTED)) ==
                                (ARM11_DSCR_CORE_RESTARTED | ARM11_DSCR_CORE_HALTED))
                                break;
+
+                       long long then = 0;
+                       if (i == 1000)
+                       {
+                               then = timeval_ms();
+                       }
+                       if (i >= 1000)
+                       {
+                               if ((timeval_ms()-then) > 1000)
+                               {
+                                       LOG_WARNING("Timeout (1000ms) waiting for instructions to complete");
+                                       return ERROR_FAIL;
+                               }
+                       }
+                       i++;
                }
 
                /* clear breakpoint */
@@ -1005,22 +1197,16 @@ int arm11_step(struct target_s *target, int current, uint32_t address, int handl
        return ERROR_OK;
 }
 
-/* target reset control */
-int arm11_assert_reset(struct target_s *target)
+int arm11_assert_reset(target_t *target)
 {
        FNC_INFO;
 
-#if 0
-       /* assert reset lines */
-       /* resets only the DBGTAP, not the ARM */
-
-       jtag_add_reset(1, 0);
-       jtag_add_sleep(5000);
-
-       arm11_common_t * arm11 = target->arch_info;
-       arm11->trst_active = true;
-#endif
-
+       /* FIX! we really should assert srst here, but
+        * how do we reset the target into the halted state?
+        * 
+        * Also arm11 behaves "funny" when srst is asserted
+        * (as of writing the rules are not understood).
+        */
        if (target->reset_halt)
        {
                CHECK_RETVAL(target_halt(target));
@@ -1029,25 +1215,8 @@ int arm11_assert_reset(struct target_s *target)
        return ERROR_OK;
 }
 
-int arm11_deassert_reset(struct target_s *target)
+int arm11_deassert_reset(target_t *target)
 {
-       FNC_INFO;
-
-#if 0
-       LOG_DEBUG("target->state: %s",
-               Jim_Nvp_value2name_simple(nvp_target_state, target->state)->name);
-
-
-       /* deassert reset lines */
-       jtag_add_reset(0, 0);
-
-       arm11_common_t * arm11 = target->arch_info;
-       arm11->trst_active = false;
-
-       if (arm11->halt_requested)
-               return arm11_halt(target);
-#endif
-
        return ERROR_OK;
 }
 
@@ -1089,10 +1258,16 @@ int arm11_get_gdb_reg_list(struct target_s *target, struct reg_s **reg_list[], i
 /* target memory access
  * size: 1 = byte (8bit), 2 = half-word (16bit), 4 = word (32bit)
  * count: number of items of <size>
+ *
+ * arm11_config_memrw_no_increment - in the future we may want to be able
+ * to read/write a range of data to a "port". a "port" is an action on
+ * read memory address for some peripheral.
  */
-int arm11_read_memory(struct target_s *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
+int arm11_read_memory_inner(struct target_s *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer,
+               bool arm11_config_memrw_no_increment)
 {
        /** \todo TODO: check if buffer cast to uint32_t* and uint16_t* might cause alignment problems */
+       int retval;
 
        FNC_INFO;
 
@@ -1106,10 +1281,14 @@ int arm11_read_memory(struct target_s *target, uint32_t address, uint32_t size,
 
        arm11_common_t * arm11 = target->arch_info;
 
-       arm11_run_instr_data_prepare(arm11);
+       retval = arm11_run_instr_data_prepare(arm11);
+       if (retval != ERROR_OK)
+               return retval;
 
        /* MRC p14,0,r0,c0,c5,0 */
-       arm11_run_instr_data_to_core1(arm11, 0xee100e15, address);
+       retval = arm11_run_instr_data_to_core1(arm11, 0xee100e15, address);
+       if (retval != ERROR_OK)
+               return retval;
 
        switch (size)
        {
@@ -1149,7 +1328,7 @@ int arm11_read_memory(struct target_s *target, uint32_t address, uint32_t size,
                                arm11_run_instr_data_from_core(arm11, 0xEE001E15, &res, 1);
 
                                uint16_t svalue = res;
-                               memcpy(buffer + count * sizeof(uint16_t), &svalue, sizeof(uint16_t));
+                               memcpy(buffer + i * sizeof(uint16_t), &svalue, sizeof(uint16_t));
                        }
 
                        break;
@@ -1168,13 +1347,23 @@ int arm11_read_memory(struct target_s *target, uint32_t address, uint32_t size,
                }
        }
 
-       arm11_run_instr_data_finish(arm11);
+       return arm11_run_instr_data_finish(arm11);
+}
 
-       return ERROR_OK;
+int arm11_read_memory(struct target_s *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
+{
+       return arm11_read_memory_inner(target, address, size, count, buffer, false);
 }
 
-int arm11_write_memory(struct target_s *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
+/*
+* arm11_config_memrw_no_increment - in the future we may want to be able
+* to read/write a range of data to a "port". a "port" is an action on
+* read memory address for some peripheral.
+*/
+int arm11_write_memory_inner(struct target_s *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer,
+               bool arm11_config_memrw_no_increment)
 {
+       int retval;
        FNC_INFO;
 
        if (target->state != TARGET_HALTED)
@@ -1187,10 +1376,23 @@ int arm11_write_memory(struct target_s *target, uint32_t address, uint32_t size,
 
        arm11_common_t * arm11 = target->arch_info;
 
-       arm11_run_instr_data_prepare(arm11);
+       retval = arm11_run_instr_data_prepare(arm11);
+       if (retval != ERROR_OK)
+               return retval;
 
        /* MRC p14,0,r0,c0,c5,0 */
-       arm11_run_instr_data_to_core1(arm11, 0xee100e15, address);
+       retval = arm11_run_instr_data_to_core1(arm11, 0xee100e15, address);
+       if (retval != ERROR_OK)
+               return retval;
+
+       /* burst writes are not used for single words as those may well be
+        * reset init script writes.
+        *
+        * The other advantage is that as burst writes are default, we'll
+        * now exercise both burst and non-burst code paths with the
+        * default settings, increasing code coverage.
+        */
+       bool burst = arm11_config_memwrite_burst && (count > 1);
 
        switch (size)
        {
@@ -1201,12 +1403,16 @@ int arm11_write_memory(struct target_s *target, uint32_t address, uint32_t size,
                        for (size_t i = 0; i < count; i++)
                        {
                                /* MRC p14,0,r1,c0,c5,0 */
-                               arm11_run_instr_data_to_core1(arm11, 0xee101e15, *buffer++);
+                               retval = arm11_run_instr_data_to_core1(arm11, 0xee101e15, *buffer++);
+                               if (retval != ERROR_OK)
+                                       return retval;
 
                                /* strb    r1, [r0], #1 */
                                /* strb    r1, [r0] */
-                               arm11_run_instr_no_data1(arm11,
+                               retval = arm11_run_instr_no_data1(arm11,
                                        !arm11_config_memrw_no_increment ? 0xe4c01001 : 0xe5c01000);
+                               if (retval != ERROR_OK)
+                                       return retval;
                        }
 
                        break;
@@ -1219,15 +1425,19 @@ int arm11_write_memory(struct target_s *target, uint32_t address, uint32_t size,
                        for (size_t i = 0; i < count; i++)
                        {
                                uint16_t value;
-                               memcpy(&value, buffer + count * sizeof(uint16_t), sizeof(uint16_t));
+                               memcpy(&value, buffer + i * sizeof(uint16_t), sizeof(uint16_t));
 
                                /* MRC p14,0,r1,c0,c5,0 */
-                               arm11_run_instr_data_to_core1(arm11, 0xee101e15, value);
+                               retval = arm11_run_instr_data_to_core1(arm11, 0xee101e15, value);
+                               if (retval != ERROR_OK)
+                                       return retval;
 
                                /* strh    r1, [r0], #2 */
                                /* strh    r1, [r0] */
-                               arm11_run_instr_no_data1(arm11,
+                               retval = arm11_run_instr_no_data1(arm11,
                                        !arm11_config_memrw_no_increment ? 0xe0c010b2 : 0xe1c010b0);
+                               if (retval != ERROR_OK)
+                                       return retval;
                        }
 
                        break;
@@ -1239,50 +1449,59 @@ int arm11_write_memory(struct target_s *target, uint32_t address, uint32_t size,
                /** \todo TODO: buffer cast to uint32_t* causes alignment warnings */
                uint32_t *words = (uint32_t*)buffer;
 
-               if (!arm11_config_memwrite_burst)
+               if (!burst)
                {
                        /* STC p14,c5,[R0],#4 */
                        /* STC p14,c5,[R0]*/
-                       arm11_run_instr_data_to_core(arm11, instr, words, count);
+                       retval = arm11_run_instr_data_to_core(arm11, instr, words, count);
+                       if (retval != ERROR_OK)
+                               return retval;
                }
                else
                {
                        /* STC p14,c5,[R0],#4 */
                        /* STC p14,c5,[R0]*/
-                       arm11_run_instr_data_to_core_noack(arm11, instr, words, count);
+                       retval = arm11_run_instr_data_to_core_noack(arm11, instr, words, count);
+                       if (retval != ERROR_OK)
+                               return retval;
                }
 
                break;
        }
        }
 
-#if 1
        /* r0 verification */
        if (!arm11_config_memrw_no_increment)
        {
                uint32_t r0;
 
                /* MCR p14,0,R0,c0,c5,0 */
-               arm11_run_instr_data_from_core(arm11, 0xEE000E15, &r0, 1);
+               retval = arm11_run_instr_data_from_core(arm11, 0xEE000E15, &r0, 1);
+               if (retval != ERROR_OK)
+                       return retval;
 
                if (address + size * count != r0)
                {
-                       LOG_ERROR("Data transfer failed. (%d)", (int)((r0 - address) - size * count));
+                       LOG_ERROR("Data transfer failed. Expected end "
+                                       "address 0x%08x, got 0x%08x",
+                                       (unsigned) (address + size * count),
+                                       (unsigned) r0);
 
-                       if (arm11_config_memwrite_burst)
+                       if (burst)
                                LOG_ERROR("use 'arm11 memwrite burst disable' to disable fast burst mode");
 
                        if (arm11_config_memwrite_error_fatal)
                                return ERROR_FAIL;
                }
        }
-#endif
 
-       arm11_run_instr_data_finish(arm11);
-
-       return ERROR_OK;
+       return arm11_run_instr_data_finish(arm11);
 }
 
+int arm11_write_memory(struct target_s *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
+{
+       return arm11_write_memory_inner(target, address, size, count, buffer, false);
+}
 
 /* write target memory in multiples of 4 byte, optimized for writing large quantities of data */
 int arm11_bulk_write_memory(struct target_s *target, uint32_t address, uint32_t count, uint8_t *buffer)
@@ -1563,6 +1782,8 @@ int arm11_init_target(struct command_context_s *cmd_ctx, struct target_s *target
 /* talk to the target and set things up */
 int arm11_examine(struct target_s *target)
 {
+       int retval;
+
        FNC_INFO;
 
        arm11_common_t * arm11 = target->arch_info;
@@ -1630,7 +1851,9 @@ int arm11_examine(struct target_s *target)
         * as suggested by the spec.
         */
 
-       arm11_check_init(arm11, NULL);
+       retval = arm11_check_init(arm11, NULL);
+       if (retval != ERROR_OK)
+               return retval;
 
        target_set_examined(target);
 
@@ -1786,23 +2009,10 @@ int arm11_handle_bool_##name(struct command_context_s *cmd_ctx, char *cmd, char
        return arm11_handle_bool(cmd_ctx, cmd, args, argc, &arm11_config_##name, print_name); \
 }
 
-#define RC_TOP(name, descr, more)  \
-{ \
-       command_t * new_cmd = register_command(cmd_ctx, top_cmd, name, NULL, COMMAND_ANY, descr);  \
-       command_t * top_cmd = new_cmd; \
-       more \
-}
-
-#define RC_FINAL(name, descr, handler) \
-       register_command(cmd_ctx, top_cmd, name, handler, COMMAND_ANY, descr);
-
-#define RC_FINAL_BOOL(name, descr, var)  \
-       register_command(cmd_ctx, top_cmd, name, arm11_handle_bool_##var, COMMAND_ANY, descr);
-
 BOOL_WRAPPER(memwrite_burst,                   "memory write burst mode")
 BOOL_WRAPPER(memwrite_error_fatal,             "fatal error mode for memory writes")
-BOOL_WRAPPER(memrw_no_increment,               "\"no increment\" mode for memory transfers")
 BOOL_WRAPPER(step_irq_enable,                  "IRQs while stepping")
+BOOL_WRAPPER(hardware_step,                    "hardware single step")
 
 int arm11_handle_vcr(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
@@ -1829,9 +2039,6 @@ const uint32_t arm11_coproc_instruction_limits[] =
        0xFFFFFFFF,             /* value */
 };
 
-const char arm11_mrc_syntax[] = "Syntax: mrc <jtag_target> <coprocessor> <opcode 1> <CRn> <CRm> <opcode 2>. All parameters are numbers only.";
-const char arm11_mcr_syntax[] = "Syntax: mcr <jtag_target> <coprocessor> <opcode 1> <CRn> <CRm> <opcode 2> <32bit value to write>. All parameters are numbers only.";
-
 arm11_common_t * arm11_find_target(const char * arg)
 {
        jtag_tap_t *    tap;
@@ -1857,20 +2064,20 @@ arm11_common_t * arm11_find_target(const char * arg)
 
 int arm11_handle_mrc_mcr(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, bool read)
 {
+       int retval;
+
        if (argc != (read ? 6 : 7))
        {
-               LOG_ERROR("Invalid number of arguments. %s", read ? arm11_mrc_syntax : arm11_mcr_syntax);
-               return -1;
+               LOG_ERROR("Invalid number of arguments.");
+               return ERROR_COMMAND_SYNTAX_ERROR;
        }
 
        arm11_common_t * arm11 = arm11_find_target(args[0]);
 
        if (!arm11)
        {
-               LOG_ERROR("Parameter 1 is not a the JTAG chain position of an ARM11 device. %s",
-                       read ? arm11_mrc_syntax : arm11_mcr_syntax);
-
-               return -1;
+               LOG_ERROR("Parameter 1 is not a the JTAG chain position of an ARM11 device.");
+               return ERROR_COMMAND_SYNTAX_ERROR;
        }
 
        if (arm11->target->state != TARGET_HALTED)
@@ -1887,11 +2094,10 @@ int arm11_handle_mrc_mcr(struct command_context_s *cmd_ctx, char *cmd, char **ar
 
                if (values[i] > arm11_coproc_instruction_limits[i])
                {
-                       LOG_ERROR("Parameter %ld out of bounds (%" PRId32 " max). %s",
+                       LOG_ERROR("Parameter %ld out of bounds (%" PRId32 " max).",
                                  (long)(i + 2),
-                                 arm11_coproc_instruction_limits[i],
-                               read ? arm11_mrc_syntax : arm11_mcr_syntax);
-                       return -1;
+                                 arm11_coproc_instruction_limits[i]);
+                       return ERROR_COMMAND_SYNTAX_ERROR;
                }
        }
 
@@ -1905,12 +2111,16 @@ int arm11_handle_mrc_mcr(struct command_context_s *cmd_ctx, char *cmd, char **ar
        if (read)
                instr |= 0x00100000;
 
-       arm11_run_instr_data_prepare(arm11);
+       retval = arm11_run_instr_data_prepare(arm11);
+       if (retval != ERROR_OK)
+               return retval;
 
        if (read)
        {
                uint32_t result;
-               arm11_run_instr_data_from_core_via_r0(arm11, instr, &result);
+               retval = arm11_run_instr_data_from_core_via_r0(arm11, instr, &result);
+               if (retval != ERROR_OK)
+                       return retval;
 
                LOG_INFO("MRC p%d, %d, R0, c%d, c%d, %d = 0x%08" PRIx32 " (%" PRId32 ")",
                         (int)(values[0]),
@@ -1921,7 +2131,9 @@ int arm11_handle_mrc_mcr(struct command_context_s *cmd_ctx, char *cmd, char **ar
        }
        else
        {
-               arm11_run_instr_data_to_core_via_r0(arm11, instr, values[5]);
+               retval = arm11_run_instr_data_to_core_via_r0(arm11, instr, values[5]);
+               if (retval != ERROR_OK)
+                       return retval;
 
                LOG_INFO("MRC p%d, %d, R0 (#0x%08" PRIx32 "), c%d, c%d, %d",
                         (int)(values[0]), (int)(values[1]),
@@ -1929,10 +2141,7 @@ int arm11_handle_mrc_mcr(struct command_context_s *cmd_ctx, char *cmd, char **ar
                         (int)(values[2]), (int)(values[3]), (int)(values[4]));
        }
 
-       arm11_run_instr_data_finish(arm11);
-
-
-       return ERROR_OK;
+       return arm11_run_instr_data_finish(arm11);
 }
 
 int arm11_handle_mrc(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
@@ -1949,34 +2158,45 @@ int arm11_register_commands(struct command_context_s *cmd_ctx)
 {
        FNC_INFO;
 
-       command_t * top_cmd = NULL;
+       command_t *top_cmd, *mw_cmd;
 
-       RC_TOP("arm11",                         "arm11 specific commands",
+       top_cmd = register_command(cmd_ctx, NULL, "arm11",
+                       NULL, COMMAND_ANY, NULL);
 
-       RC_TOP("memwrite",                              "Control memory write transfer mode",
-
-               RC_FINAL_BOOL("burst",                          "Enable/Disable non-standard but fast burst mode (default: enabled)",
-                                               memwrite_burst)
-
-               RC_FINAL_BOOL("error_fatal",                    "Terminate program if transfer error was found (default: enabled)",
-                                               memwrite_error_fatal)
-) /* memwrite */
-
-       RC_FINAL_BOOL("no_increment",                   "Don't increment address on multi-read/-write (default: disabled)",
-                                               memrw_no_increment)
-
-       RC_FINAL_BOOL("step_irq_enable",                "Enable interrupts while stepping (default: disabled)",
-                                               step_irq_enable)
-
-       RC_FINAL("vcr",                                 "Control (Interrupt) Vector Catch Register",
-                                               arm11_handle_vcr)
-
-       RC_FINAL("mrc",                                 "Read Coprocessor register",
-                                               arm11_handle_mrc)
-
-       RC_FINAL("mcr",                                 "Write Coprocessor register",
-                                               arm11_handle_mcr)
-) /* arm11 */
+       /* "hardware_step" is only here to check if the default
+        * simulate + breakpoint implementation is broken.
+        * TEMPORARY! NOT DOCUMENTED!
+        */
+       register_command(cmd_ctx, top_cmd, "hardware_step",
+                       arm11_handle_bool_hardware_step, COMMAND_ANY,
+                       "DEBUG ONLY - Hardware single stepping"
+                               " (default: disabled)");
+
+       register_command(cmd_ctx, top_cmd, "mcr",
+                       arm11_handle_mcr, COMMAND_ANY,
+                       "Write Coprocessor register. mcr <jtag_target> <coprocessor> <opcode 1> <CRn> <CRm> <opcode 2> <32bit value to write>. All parameters are numbers only.");
+
+       mw_cmd = register_command(cmd_ctx, top_cmd, "memwrite",
+                       NULL, COMMAND_ANY, NULL);
+       register_command(cmd_ctx, mw_cmd, "burst",
+                       arm11_handle_bool_memwrite_burst, COMMAND_ANY,
+                       "Enable/Disable non-standard but fast burst mode"
+                               " (default: enabled)");
+       register_command(cmd_ctx, mw_cmd, "error_fatal",
+                       arm11_handle_bool_memwrite_error_fatal, COMMAND_ANY,
+                       "Terminate program if transfer error was found"
+                               " (default: enabled)");
+
+       register_command(cmd_ctx, top_cmd, "mrc",
+                       arm11_handle_mrc, COMMAND_ANY,
+                       "Read Coprocessor register. mrc <jtag_target> <coprocessor> <opcode 1> <CRn> <CRm> <opcode 2>. All parameters are numbers only.");
+       register_command(cmd_ctx, top_cmd, "step_irq_enable",
+                       arm11_handle_bool_step_irq_enable, COMMAND_ANY,
+                       "Enable interrupts while stepping"
+                               " (default: disabled)");
+       register_command(cmd_ctx, top_cmd, "vcr",
+                       arm11_handle_vcr, COMMAND_ANY,
+                       "Control (Interrupt) Vector Catch Register");
 
        return ERROR_OK;
 }

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)