ARM11: help/usage updates
[fw/openocd] / src / target / arm11.c
index 44c9ad300e9d0219324e993fe4a990b8fc04f637..082930a90691a40c33ee8f7754da7738c55e03ad 100644 (file)
@@ -6,6 +6,8 @@
  *                                                                         *
  *   Copyright (C) 2008 Georg Acher <acher@in.tum.de>                      *
  *                                                                         *
+ *   Copyright (C) 2009 David Brownell                                     *
+ *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
  *   it under the terms of the GNU General Public License as published by  *
  *   the Free Software Foundation; either version 2 of the License, or     *
 #include "breakpoints.h"
 #include "arm11_dbgtap.h"
 #include "arm_simulator.h"
-#include "time_support.h"
+#include <helper/time_support.h>
 #include "target_type.h"
 #include "algorithm.h"
 #include "register.h"
+#include "arm_opcodes.h"
 
 
 #if 0
 #define _DEBUG_INSTRUCTION_EXECUTION_
 #endif
 
+
+/* FIXME none of these flags should be global to all ARM11 cores!
+ * Most of them shouldn't exist at all, once the code works...
+ */
 static bool arm11_config_memwrite_burst = true;
 static bool arm11_config_memwrite_error_fatal = true;
 static uint32_t arm11_vcr = 0;
@@ -59,18 +66,18 @@ static int arm11_check_init(struct arm11_common *arm11)
        CHECK_RETVAL(arm11_read_DSCR(arm11));
        LOG_DEBUG("DSCR %08x", (unsigned) arm11->dscr);
 
-       if (!(arm11->dscr & ARM11_DSCR_MODE_SELECT))
+       if (!(arm11->dscr & DSCR_HALT_DBG_MODE))
        {
                LOG_DEBUG("Bringing target into debug mode");
 
-               arm11->dscr |= ARM11_DSCR_MODE_SELECT;          /* Halt debug-mode */
+               arm11->dscr |= DSCR_HALT_DBG_MODE;
                arm11_write_DSCR(arm11, arm11->dscr);
 
                /* add further reset initialization here */
 
                arm11->simulate_reset_on_next_halt = true;
 
-               if (arm11->dscr & ARM11_DSCR_CORE_HALTED)
+               if (arm11->dscr & DSCR_CORE_HALTED)
                {
                        /** \todo TODO: this needs further scrutiny because
                          * arm11_debug_entry() never gets called.  (WHY NOT?)
@@ -79,8 +86,7 @@ static int arm11_check_init(struct arm11_common *arm11)
                          */
 
                        arm11->arm.target->state = TARGET_HALTED;
-                       arm11->arm.target->debug_reason =
-                                       arm11_get_DSCR_debug_reason(arm11->dscr);
+                       arm_dpm_report_dscr(arm11->arm.dpm, arm11->dscr);
                }
                else
                {
@@ -104,8 +110,7 @@ static int arm11_debug_entry(struct arm11_common *arm11)
        int retval;
 
        arm11->arm.target->state = TARGET_HALTED;
-       arm11->arm.target->debug_reason =
-                       arm11_get_DSCR_debug_reason(arm11->dscr);
+       arm_dpm_report_dscr(arm11->arm.dpm, arm11->dscr);
 
        /* REVISIT entire cache should already be invalid !!! */
        register_cache_invalidate(arm11->arm.core_cache);
@@ -113,7 +118,7 @@ static int arm11_debug_entry(struct arm11_common *arm11)
        /* See e.g. ARM1136 TRM, "14.8.4 Entering Debug state" */
 
        /* maybe save wDTR (pending DCC write to debug SW, e.g. libdcc) */
-       arm11->is_wdtr_saved = !!(arm11->dscr & ARM11_DSCR_WDTR_FULL);
+       arm11->is_wdtr_saved = !!(arm11->dscr & DSCR_DTR_TX_FULL);
        if (arm11->is_wdtr_saved)
        {
                arm11_add_debug_SCAN_N(arm11, 0x05, ARM11_TAP_DEFAULT);
@@ -131,15 +136,13 @@ static int arm11_debug_entry(struct arm11_common *arm11)
 
        }
 
-       /* DSCR: set ARM11_DSCR_EXECUTE_ARM_INSTRUCTION_ENABLE
+       /* DSCR: set the Execute ARM instruction enable bit.
         *
         * ARM1176 spec says this is needed only for wDTR/rDTR's "ITR mode",
-        * but not to issue ITRs. ARM1136 seems to require this to issue
-        * ITR's as well...
+        * but not to issue ITRs(?).  The ARMv7 arch spec says it's required
+        * for executing instructions via ITR.
         */
-
-       arm11_write_DSCR(arm11, ARM11_DSCR_EXECUTE_ARM_INSTRUCTION_ENABLE
-                               | arm11->dscr);
+       arm11_write_DSCR(arm11, DSCR_ITR_EN | arm11->dscr);
 
 
        /* From the spec:
@@ -188,7 +191,7 @@ static int arm11_debug_entry(struct arm11_common *arm11)
                return retval;
 
        /* maybe save rDTR (pending DCC read from debug SW, e.g. libdcc) */
-       arm11->is_rdtr_saved = !!(arm11->dscr & ARM11_DSCR_RDTR_FULL);
+       arm11->is_rdtr_saved = !!(arm11->dscr & DSCR_DTR_RX_FULL);
        if (arm11->is_rdtr_saved)
        {
                /* MRC p14,0,R0,c0,c5,0 (move rDTR -> r0 (-> wDTR -> local var)) */
@@ -217,6 +220,19 @@ static int arm11_debug_entry(struct arm11_common *arm11)
 
        }
 
+       if (arm11->arm.target->debug_reason == DBG_REASON_WATCHPOINT) {
+               uint32_t wfar;
+
+               /* MRC p15, 0, <Rd>, c6, c0, 1 ; Read WFAR */
+               retval = arm11_run_instr_data_from_core_via_r0(arm11,
+                               ARMV4_5_MRC(15, 0, 0, 6, 0, 1),
+                               &wfar);
+               if (retval != ERROR_OK)
+                       return retval;
+               arm_dpm_report_wfar(arm11->arm.dpm, wfar);
+       }
+
+
        retval = arm11_run_instr_data_finish(arm11);
        if (retval != ERROR_OK)
                return retval;
@@ -248,7 +264,7 @@ static int arm11_leave_debug_state(struct arm11_common *arm11, bool bpwp)
        {
                CHECK_RETVAL(arm11_read_DSCR(arm11));
 
-               if (arm11->dscr & (ARM11_DSCR_RDTR_FULL | ARM11_DSCR_WDTR_FULL))
+               if (arm11->dscr & (DSCR_DTR_RX_FULL | DSCR_DTR_TX_FULL))
                {
                        /*
                        The wDTR/rDTR two registers that are used to send/receive data to/from
@@ -286,6 +302,8 @@ static int arm11_leave_debug_state(struct arm11_common *arm11, bool bpwp)
         */
        retval = arm_dpm_write_dirty_registers(&arm11->dpm, bpwp);
 
+       retval = arm11_bpwp_flush(arm11);
+
        register_cache_invalidate(arm11->arm.core_cache);
 
        /* restore DSCR */
@@ -324,7 +342,7 @@ static int arm11_poll(struct target *target)
 
        CHECK_RETVAL(arm11_check_init(arm11));
 
-       if (arm11->dscr & ARM11_DSCR_CORE_HALTED)
+       if (arm11->dscr & DSCR_CORE_HALTED)
        {
                if (target->state != TARGET_HALTED)
                {
@@ -336,7 +354,9 @@ static int arm11_poll(struct target *target)
                                return retval;
 
                        target_call_event_callbacks(target,
-                               old_state == TARGET_DEBUG_RUNNING ? TARGET_EVENT_DEBUG_HALTED : TARGET_EVENT_HALTED);
+                               (old_state == TARGET_DEBUG_RUNNING)
+                                       ? TARGET_EVENT_DEBUG_HALTED
+                                       : TARGET_EVENT_HALTED);
                }
        }
        else
@@ -354,12 +374,17 @@ static int arm11_poll(struct target *target)
 /* architecture specific status reply */
 static int arm11_arch_state(struct target *target)
 {
+       struct arm11_common *arm11 = target_to_arm11(target);
        int retval;
 
-       retval = armv4_5_arch_state(target);
+       retval = arm_arch_state(target);
 
        /* REVISIT also display ARM11-specific MMU and cache status ... */
 
+       if (target->debug_reason == DBG_REASON_WATCHPOINT)
+               LOG_USER("Watchpoint triggered at PC %#08x",
+                               (unsigned) arm11->dpm.wp_pc);
+
        return retval;
 }
 
@@ -401,7 +426,7 @@ static int arm11_halt(struct target *target)
        {
                CHECK_RETVAL(arm11_read_DSCR(arm11));
 
-               if (arm11->dscr & ARM11_DSCR_CORE_HALTED)
+               if (arm11->dscr & DSCR_CORE_HALTED)
                        break;
 
 
@@ -513,7 +538,8 @@ static int arm11_resume(struct target *target, int current,
                        brp_num++;
                }
 
-               arm11_sc7_set_vcr(arm11, arm11_vcr);
+               if (arm11_vcr)
+                       arm11_sc7_set_vcr(arm11, arm11_vcr);
        }
 
        arm11_leave_debug_state(arm11, handle_breakpoints);
@@ -529,7 +555,7 @@ static int arm11_resume(struct target *target, int current,
 
                LOG_DEBUG("DSCR %08x", (unsigned) arm11->dscr);
 
-               if (arm11->dscr & ARM11_DSCR_CORE_RESTARTED)
+               if (arm11->dscr & DSCR_CORE_RESTARTED)
                        break;
 
 
@@ -549,20 +575,12 @@ static int arm11_resume(struct target *target, int current,
                i++;
        }
 
+       target->debug_reason = DBG_REASON_NOTHALTED;
        if (!debug_execution)
-       {
-               target->state                   = TARGET_RUNNING;
-               target->debug_reason    = DBG_REASON_NOTHALTED;
-
-               CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_RESUMED));
-       }
+               target->state = TARGET_RUNNING;
        else
-       {
-               target->state                   = TARGET_DEBUG_RUNNING;
-               target->debug_reason    = DBG_REASON_NOTHALTED;
-
-               CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_RESUMED));
-       }
+               target->state = TARGET_DEBUG_RUNNING;
+       CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_RESUMED));
 
        return ERROR_OK;
 }
@@ -674,9 +692,9 @@ static int arm11_step(struct target *target, int current,
 
                if (arm11_config_step_irq_enable)
                        /* this disable should be redundant ... */
-                       arm11->dscr &= ~ARM11_DSCR_INTERRUPTS_DISABLE;
+                       arm11->dscr &= ~DSCR_INT_DIS;
                else
-                       arm11->dscr |= ARM11_DSCR_INTERRUPTS_DISABLE;
+                       arm11->dscr |= DSCR_INT_DIS;
 
 
                CHECK_RETVAL(arm11_leave_debug_state(arm11, handle_breakpoints));
@@ -690,8 +708,8 @@ static int arm11_step(struct target *target, int current,
 
                while (1)
                {
-                       const uint32_t mask = ARM11_DSCR_CORE_RESTARTED
-                                       | ARM11_DSCR_CORE_HALTED;
+                       const uint32_t mask = DSCR_CORE_RESTARTED
+                                       | DSCR_CORE_HALTED;
 
                        CHECK_RETVAL(arm11_read_DSCR(arm11));
                        LOG_DEBUG("DSCR %08x e", (unsigned) arm11->dscr);
@@ -722,11 +740,11 @@ static int arm11_step(struct target *target, int current,
                CHECK_RETVAL(arm11_debug_entry(arm11));
 
                /* restore default state */
-               arm11->dscr &= ~ARM11_DSCR_INTERRUPTS_DISABLE;
+               arm11->dscr &= ~DSCR_INT_DIS;
 
        }
 
-       target->debug_reason    = DBG_REASON_SINGLESTEP;
+       target->debug_reason = DBG_REASON_SINGLESTEP;
 
        CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_HALTED));
 
@@ -735,67 +753,72 @@ static int arm11_step(struct target *target, int current,
 
 static int arm11_assert_reset(struct target *target)
 {
-       int retval;
        struct arm11_common *arm11 = target_to_arm11(target);
 
-       retval = arm11_check_init(arm11);
-       if (retval != ERROR_OK)
-               return retval;
+       /* optionally catch reset vector */
+       if (target->reset_halt && !(arm11_vcr & 1))
+               arm11_sc7_set_vcr(arm11, arm11_vcr | 1);
+
+       /* Issue some kind of warm reset. */
+       if (target_has_event_action(target, TARGET_EVENT_RESET_ASSERT)) {
+               target_handle_event(target, TARGET_EVENT_RESET_ASSERT);
+       } else if (jtag_get_reset_config() & RESET_HAS_SRST) {
+               /* REVISIT handle "pulls" cases, if there's
+                * hardware that needs them to work.
+                */
+               jtag_add_reset(0, 1);
+       } else {
+               LOG_ERROR("%s: how to reset?", target_name(target));
+               return ERROR_FAIL;
+       }
 
-       target->state = TARGET_UNKNOWN;
+       /* registers are now invalid */
+       register_cache_invalidate(arm11->arm.core_cache);
 
-       /* we would very much like to reset into the halted, state,
-        * but resetting and halting is second best... */
-       if (target->reset_halt)
-       {
-               CHECK_RETVAL(target_halt(target));
-       }
+       target->state = TARGET_RESET;
 
+       return ERROR_OK;
+}
 
-       /* srst is funny. We can not do *anything* else while it's asserted
-        * and it has unkonwn side effects. Make sure no other code runs
-        * meanwhile.
-        *
-        * Code below assumes srst:
-        *
-        * - Causes power-on-reset (but of what parts of the system?). Bug
-        * in arm11?
-        *
-        * - Messes us TAP state without asserting trst.
-        *
-        * - There is another bug in the arm11 core. When you generate an access to
-        * external logic (for example ddr controller via AHB bus) and that block
-        * is not configured (perhaps it is still held in reset), that transaction
-        * will never complete. This will hang arm11 core but it will also hang
-        * JTAG controller. Nothing, short of srst assertion will bring it out of
-        * this.
-        *
-        * Mysteries:
-        *
-        * - What should the PC be after an srst reset when starting in the halted
-        * state?
-        */
+/*
+ * - There is another bug in the arm11 core.  (iMX31 specific again?)
+ *   When you generate an access to external logic (for example DDR
+ *   controller via AHB bus) and that block is not configured (perhaps
+ *   it is still held in reset), that transaction will never complete.
+ *   This will hang arm11 core but it will also hang JTAG controller.
+ *   Nothing short of srst assertion will bring it out of this.
+ */
 
-       jtag_add_reset(0, 1);
-       jtag_add_reset(0, 0);
+static int arm11_deassert_reset(struct target *target)
+{
+       struct arm11_common *arm11 = target_to_arm11(target);
+       int retval;
 
-       /* How long do we have to wait? */
-       jtag_add_sleep(5000);
+       /* be certain SRST is off */
+       jtag_add_reset(0, 0);
 
-       /* un-mess up TAP state */
+       /* WORKAROUND i.MX31 problems:  SRST goofs the TAP, and resets
+        * at least DSCR.  OMAP24xx doesn't show that problem, though
+        * SRST-only reset seems to be problematic for other reasons.
+        * (Secure boot sequences being one likelihood!)
+        */
        jtag_add_tlr();
 
-       retval = jtag_execute_queue();
-       if (retval != ERROR_OK)
-       {
-               return retval;
+       retval = arm11_poll(target);
+
+       if (target->reset_halt) {
+               if (target->state != TARGET_HALTED) {
+                       LOG_WARNING("%s: ran after reset and before halt ...",
+                                       target_name(target));
+                       if ((retval = target_halt(target)) != ERROR_OK)
+                               return retval;
+               }
        }
 
-       return ERROR_OK;
-}
+       /* maybe restore vector catch config */
+       if (target->reset_halt && !(arm11_vcr & 1))
+               arm11_sc7_set_vcr(arm11, arm11_vcr);
 
-static int arm11_deassert_reset(struct target *target)
-{
        return ERROR_OK;
 }
 
@@ -998,27 +1021,25 @@ static int arm11_write_memory_inner(struct target *target,
                }
 
        case 4: {
+               /* increment:           STC p14,c5,[R0],#4 */
+               /* no increment:        STC p14,c5,[R0]*/
                uint32_t instr = !no_increment ? 0xeca05e01 : 0xed805e00;
 
                /** \todo TODO: buffer cast to uint32_t* causes alignment warnings */
                uint32_t *words = (uint32_t*)buffer;
 
+               /* "burst" here just means trusting each instruction executes
+                * fully before we run the next one:  per-word roundtrips, to
+                * check the Ready flag, are not used.
+                */
                if (!burst)
-               {
-                       /* STC p14,c5,[R0],#4 */
-                       /* STC p14,c5,[R0]*/
-                       retval = arm11_run_instr_data_to_core(arm11, instr, words, count);
-                       if (retval != ERROR_OK)
-                               return retval;
-               }
+                       retval = arm11_run_instr_data_to_core(arm11,
+                                       instr, words, count);
                else
-               {
-                       /* STC p14,c5,[R0],#4 */
-                       /* STC p14,c5,[R0]*/
-                       retval = arm11_run_instr_data_to_core_noack(arm11, instr, words, count);
-                       if (retval != ERROR_OK)
-                               return retval;
-               }
+                       retval = arm11_run_instr_data_to_core_noack(arm11,
+                                       instr, words, count);
+               if (retval != ERROR_OK)
+                       return retval;
 
                break;
        }
@@ -1136,12 +1157,12 @@ static int arm11_target_create(struct target *target, Jim_Interp *interp)
        if (!arm11)
                return ERROR_FAIL;
 
-       armv4_5_init_arch_info(target, &arm11->arm);
+       arm_init_arch_info(target, &arm11->arm);
 
        arm11->jtag_info.tap = target->tap;
        arm11->jtag_info.scann_size = 5;
        arm11->jtag_info.scann_instr = ARM11_SCAN_N;
-       /* cur_scan_chain == 0 */
+       arm11->jtag_info.cur_scan_chain = ~0;   /* invalid/unknown */
        arm11->jtag_info.intest_instr = ARM11_INTEST;
 
        return ERROR_OK;
@@ -1190,20 +1211,24 @@ static int arm11_examine(struct target *target)
 
        CHECK_RETVAL(jtag_execute_queue());
 
-       switch (device_id & 0x0FFFF000)
+       /* assume the manufacturer id is ok; check the part # */
+       switch ((device_id >> 12) & 0xFFFF)
        {
-       case 0x07B36000:
+       case 0x7B36:
                type = "ARM1136";
                break;
-       case 0x07B56000:
+       case 0x7B37:
+               type = "ARM11 MPCore";
+               break;
+       case 0x7B56:
                type = "ARM1156";
                break;
-       case 0x07B76000:
+       case 0x7B76:
                arm11->arm.core_type = ARM_MODE_MON;
                type = "ARM1176";
                break;
        default:
-               LOG_ERROR("'target arm11' expects IDCODE 0x*7B*7****");
+               LOG_ERROR("unexpected ARM11 ID code");
                return ERROR_FAIL;
        }
        LOG_INFO("found %s", type);
@@ -1219,7 +1244,6 @@ static int arm11_examine(struct target *target)
        }
 
        arm11->brp = ((didr >> 24) & 0x0F) + 1;
-       arm11->wrp = ((didr >> 28) & 0x0F) + 1;
 
        /** \todo TODO: reserve one brp slot if we allow breakpoints during step */
        arm11->free_brps = arm11->brp;
@@ -1294,17 +1318,20 @@ COMMAND_HANDLER(arm11_handle_vcr)
 static const struct command_registration arm11_mw_command_handlers[] = {
        {
                .name = "burst",
-               .handler = &arm11_handle_bool_memwrite_burst,
+               .handler = arm11_handle_bool_memwrite_burst,
                .mode = COMMAND_ANY,
-               .help = "Enable/Disable non-standard but fast burst mode"
-                       " (default: enabled)",
+               .help = "Display or modify flag controlling potentially "
+                       "risky fast burst mode (default: enabled)",
+               .usage = "['enable'|'disable']",
        },
        {
                .name = "error_fatal",
-               .handler = &arm11_handle_bool_memwrite_error_fatal,
+               .handler = arm11_handle_bool_memwrite_error_fatal,
                .mode = COMMAND_ANY,
-               .help = "Terminate program if transfer error was found"
+               .help = "Display or modify flag controlling transfer "
+                       "termination on transfer errors"
                        " (default: enabled)",
+               .usage = "['enable'|'disable']",
        },
        COMMAND_REGISTRATION_DONE
 };
@@ -1314,11 +1341,11 @@ static const struct command_registration arm11_any_command_handlers[] = {
                 * simulate + breakpoint implementation is broken.
                 * TEMPORARY! NOT DOCUMENTED! */
                .name = "hardware_step",
-               .handler = &arm11_handle_bool_hardware_step,
+               .handler = arm11_handle_bool_hardware_step,
                .mode = COMMAND_ANY,
                .help = "DEBUG ONLY - Hardware single stepping"
                        " (default: disabled)",
-               .usage = "(enable|disable)",
+               .usage = "['enable'|'disable']",
        },
        {
                .name = "memwrite",
@@ -1328,16 +1355,18 @@ static const struct command_registration arm11_any_command_handlers[] = {
        },
        {
                .name = "step_irq_enable",
-               .handler = &arm11_handle_bool_step_irq_enable,
+               .handler = arm11_handle_bool_step_irq_enable,
                .mode = COMMAND_ANY,
-               .help = "Enable interrupts while stepping"
-                       " (default: disabled)",
+               .help = "Display or modify flag controlling interrupt "
+                       "enable while stepping (default: disabled)",
+               .usage = "['enable'|'disable']",
        },
        {
                .name = "vcr",
-               .handler = &arm11_handle_vcr,
+               .handler = arm11_handle_vcr,
                .mode = COMMAND_ANY,
-               .help = "Control (Interrupt) Vector Catch Register",
+               .help = "Display or modify Vector Catch Register",
+               .usage = "[value]",
        },
        COMMAND_REGISTRATION_DONE
 };
@@ -1374,7 +1403,7 @@ struct target_type arm11_target = {
        .deassert_reset =       arm11_deassert_reset,
        .soft_reset_halt =      arm11_soft_reset_halt,
 
-       .get_gdb_reg_list =     armv4_5_get_gdb_reg_list,
+       .get_gdb_reg_list =     arm_get_gdb_reg_list,
 
        .read_memory =          arm11_read_memory,
        .write_memory =         arm11_write_memory,