ARMv7-M: make DAP commands verify target is an ARMv7-M
[openocd.git] / src / target / arm11.c
index 20ad22d50235dba2f23e5a670b6d0e720ed87749..671943f2b5b80083b7d122f77ce219ef2b07d4d1 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     *
@@ -34,6 +36,7 @@
 #include "target_type.h"
 #include "algorithm.h"
 #include "register.h"
+#include "arm_opcodes.h"
 
 
 #if 0
@@ -61,10 +64,10 @@ static int arm11_step(struct target *target, int current,
 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 & DSCR_HALT_DBG_MODE))
        {
+               LOG_DEBUG("DSCR %08x", (unsigned) arm11->dscr);
                LOG_DEBUG("Bringing target into debug mode");
 
                arm11->dscr |= DSCR_HALT_DBG_MODE;
@@ -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;
@@ -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 */
@@ -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;
 }
 
@@ -473,12 +498,9 @@ static int arm11_resume(struct target *target, int current,
        if (!debug_execution)
                target_free_all_working_areas(target);
 
-       /* Set up breakpoints */
-       if (handle_breakpoints)
-       {
-               /* check if one matches PC and step over it if necessary */
-
-               struct breakpoint *     bp;
+       /* Should we skip over breakpoints matching the PC? */
+       if (handle_breakpoints) {
+               struct breakpoint *bp;
 
                for (bp = target->breakpoints; bp; bp = bp->next)
                {
@@ -489,9 +511,11 @@ static int arm11_resume(struct target *target, int current,
                                break;
                        }
                }
+       }
 
-               /* set all breakpoints */
-
+       /* activate all breakpoints */
+       if (true) {
+               struct breakpoint *bp;
                unsigned brp_num = 0;
 
                for (bp = target->breakpoints; bp; bp = bp->next)
@@ -513,10 +537,12 @@ 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);
+       /* activate all watchpoints and breakpoints */
+       arm11_leave_debug_state(arm11, true);
 
        arm11_add_IR(arm11, ARM11_RESTART, TAP_IDLE);
 
@@ -727,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;
 }
 
@@ -922,6 +953,7 @@ static int arm11_write_memory_inner(struct target *target,
        if (retval != ERROR_OK)
                return retval;
 
+       /* load r0 with buffer address */
        /* MRC p14,0,r0,c0,c5,0 */
        retval = arm11_run_instr_data_to_core1(arm11, 0xee100e15, address);
        if (retval != ERROR_OK)
@@ -944,11 +976,13 @@ static int arm11_write_memory_inner(struct target *target,
 
                        for (size_t i = 0; i < count; i++)
                        {
+                               /* load r1 from DCC with byte data */
                                /* MRC p14,0,r1,c0,c5,0 */
                                retval = arm11_run_instr_data_to_core1(arm11, 0xee101e15, *buffer++);
                                if (retval != ERROR_OK)
                                        return retval;
 
+                               /* write r1 to memory */
                                /* strb    r1, [r0], #1 */
                                /* strb    r1, [r0] */
                                retval = arm11_run_instr_no_data1(arm11,
@@ -971,11 +1005,13 @@ static int arm11_write_memory_inner(struct target *target,
                                uint16_t value;
                                memcpy(&value, buffer + i * sizeof(uint16_t), sizeof(uint16_t));
 
+                               /* load r1 from DCC with halfword data */
                                /* MRC p14,0,r1,c0,c5,0 */
                                retval = arm11_run_instr_data_to_core1(arm11, 0xee101e15, value);
                                if (retval != ERROR_OK)
                                        return retval;
 
+                               /* write r1 to memory */
                                /* strh    r1, [r0], #2 */
                                /* strh    r1, [r0] */
                                retval = arm11_run_instr_no_data1(arm11,
@@ -990,27 +1026,26 @@ static int arm11_write_memory_inner(struct target *target,
                }
 
        case 4: {
+               /* stream word data through DCC directly to memory */
+               /* 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;
        }
@@ -1128,12 +1163,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;
@@ -1182,20 +1217,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);
@@ -1211,7 +1250,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;
@@ -1286,17 +1324,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
 };
@@ -1306,11 +1347,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",
@@ -1320,16 +1361,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
 };
@@ -1366,7 +1409,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,

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)