ARM11: basic watchpoint support
authorDavid Brownell <dbrownell@users.sourceforge.net>
Sat, 5 Dec 2009 02:57:31 +0000 (18:57 -0800)
committerDavid Brownell <dbrownell@users.sourceforge.net>
Sat, 5 Dec 2009 02:57:31 +0000 (18:57 -0800)
Use the DPM watchpoint support; remove old incomplete stubs.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
NEWS
src/target/arm11.c
src/target/arm11.h
src/target/arm11_dbgtap.c
src/target/arm11_dbgtap.h

diff --git a/NEWS b/NEWS
index 38ae4da6211ff815fad7cc587a9984cb662a62f4..498797b1f4855cd5732f8789330890c487179155 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -24,10 +24,12 @@ Target Layer:
                - accelerated GDB memory checksum
                - support "arm regs" command
                - can access all core modes and registers
+               - watchpoint support
        Cortex-A8
                - support "arm regs" command
                - can access all core modes and registers
                - supports "reset-assert" event (used on OMAP3530)
+               - watchpoint support
        Cortex-M3
                - Exposed DWT registers like cycle counter
 
index b05ef302aa3a14eec65b1be4dfb1346b5f9cbaa9..943ab8ae804d95059cea0a179116ed12d22c3d4e 100644 (file)
@@ -286,6 +286,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 */
@@ -1212,7 +1214,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;
index f3f0644b08b90af0569ea94f078baf0cdd99e3d8..421f8d185c699997cb64ca7b641aa31570c60a7b 100644 (file)
@@ -53,9 +53,10 @@ struct arm11_common
 
        /** Debug module state. */
        struct arm_dpm dpm;
+       struct arm11_sc7_action *bpwp_actions;
+       unsigned bpwp_n;
 
        size_t  brp;                    /**< Number of Breakpoint Register Pairs from DIDR      */
-       size_t  wrp;                    /**< Number of Watchpoint Register Pairs from DIDR      */
        size_t  free_brps;              /**< Number of breakpoints allocated */
 
        uint32_t dscr;                  /**< Last retrieved DSCR value. */
index e37ad56ca3567401d7a704500c717c2f162f1647..9ad566222bf5f14a1089af963825ab6ed8d5530f 100644 (file)
@@ -892,7 +892,7 @@ int arm11_sc7_run(struct arm11_common * arm11, struct arm11_sc7_action * actions
  */
 void arm11_sc7_clear_vbw(struct arm11_common * arm11)
 {
-       size_t clear_bw_size = arm11->brp + arm11->wrp + 1;
+       size_t clear_bw_size = arm11->brp + 1;
        struct arm11_sc7_action         *clear_bw = malloc(sizeof(struct arm11_sc7_action) * clear_bw_size);
        struct arm11_sc7_action *       pos = clear_bw;
 
@@ -905,11 +905,6 @@ void arm11_sc7_clear_vbw(struct arm11_common * arm11)
        for (size_t i = 0; i < arm11->brp; i++)
                (pos++)->address = ARM11_SC7_BCR0 + i;
 
-
-       for (size_t i = 0; i < arm11->wrp; i++)
-               (pos++)->address = ARM11_SC7_WCR0 + i;
-
-
        (pos++)->address = ARM11_SC7_VCR;
 
        arm11_sc7_run(arm11, clear_bw, clear_bw_size);
@@ -1013,6 +1008,88 @@ static int arm11_dpm_instr_read_data_r0(struct arm_dpm *dpm,
                        opcode, data);
 }
 
+/* Because arm11_sc7_run() takes a vector of actions, we batch breakpoint
+ * and watchpoint operations instead of running them right away.  Since we
+ * pre-allocated our vector, we don't need to worry about space.
+ */
+static int arm11_bpwp_enable(struct arm_dpm *dpm, unsigned index,
+               uint32_t addr, uint32_t control)
+{
+       struct arm11_common *arm11 = dpm_to_arm11(dpm);
+       struct arm11_sc7_action *action;
+
+       action = arm11->bpwp_actions + arm11->bpwp_n;
+
+       /* Invariant:  this bp/wp is disabled.
+        * It also happens that the core is halted here, but for
+        * DPM-based cores we don't actually care about that.
+        */
+
+       action[0].write = action[1].write = true;
+
+       action[0].value = addr;
+       action[1].value = control;
+
+       switch (index) {
+       case 0 ... 15:
+               action[0].address = ARM11_SC7_BVR0 + index;
+               action[1].address = ARM11_SC7_BCR0 + index;
+               break;
+       case 16 ... 32:
+               index -= 16;
+               action[0].address = ARM11_SC7_WVR0 + index;
+               action[1].address = ARM11_SC7_WCR0 + index;
+               break;
+       default:
+               return ERROR_FAIL;
+       }
+
+       arm11->bpwp_n += 2;
+
+       return ERROR_OK;
+}
+
+static int arm11_bpwp_disable(struct arm_dpm *dpm, unsigned index)
+{
+       struct arm11_common *arm11 = dpm_to_arm11(dpm);
+       struct arm11_sc7_action *action;
+
+       action = arm11->bpwp_actions + arm11->bpwp_n;
+
+       action[0].write = true;
+       action[0].value = 0;
+
+       switch (index) {
+       case 0 ... 15:
+               action[0].address = ARM11_SC7_BCR0 + index;
+               break;
+       case 16 ... 32:
+               index -= 16;
+               action[0].address = ARM11_SC7_WCR0 + index;
+               break;
+       default:
+               return ERROR_FAIL;
+       }
+
+       arm11->bpwp_n += 1;
+
+       return ERROR_OK;
+}
+
+/** Flush any pending breakpoint and watchpoint updates. */
+int arm11_bpwp_flush(struct arm11_common *arm11)
+{
+       int retval;
+
+       if (!arm11->bpwp_n)
+               return ERROR_OK;
+
+       retval = arm11_sc7_run(arm11, arm11->bpwp_actions, arm11->bpwp_n);
+       arm11->bpwp_n = 0;
+
+       return retval;
+}
+
 /** Set up high-level debug module utilities */
 int arm11_dpm_init(struct arm11_common *arm11, uint32_t didr)
 {
@@ -1032,11 +1109,22 @@ int arm11_dpm_init(struct arm11_common *arm11, uint32_t didr)
        dpm->instr_read_data_dcc = arm11_dpm_instr_read_data_dcc;
        dpm->instr_read_data_r0 = arm11_dpm_instr_read_data_r0;
 
+       dpm->bpwp_enable = arm11_bpwp_enable;
+       dpm->bpwp_disable = arm11_bpwp_disable;
+
        retval = arm_dpm_setup(dpm);
        if (retval != ERROR_OK)
                return retval;
 
+       /* alloc enough to enable all breakpoints and watchpoints at once */
+       arm11->bpwp_actions = calloc(2 * (dpm->nbp + dpm->nwp),
+                       sizeof *arm11->bpwp_actions);
+       if (!arm11->bpwp_actions)
+               return ERROR_FAIL;
+
        retval = arm_dpm_initialize(dpm);
+       if (retval != ERROR_OK)
+               return retval;
 
-       return retval;
+       return arm11_bpwp_flush(arm11);
 }
index 2c586cc9fcc4bdc97bdd15d6ffaf04e9fb2de64a..3139a09afe99bc1cb43d620854e03884950fb813 100644 (file)
@@ -59,5 +59,6 @@ int arm11_read_memory_word(struct arm11_common *arm11,
                uint32_t address, uint32_t *result);
 
 int arm11_dpm_init(struct arm11_common *arm11, uint32_t didr);
+int arm11_bpwp_flush(struct arm11_common *arm11);
 
 #endif // ARM11_DBGTAP_H

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)