Hi all,

I am working with an xscale target.  The debug hardware on xscale supports
watchpoints (data breakpoints) with an optional address mask.  This very useful
feature allows breaks upon an access across a range of addresses.  However,
theOpenOCD wp command does not support this, and to complicate matters further,
supports optional 'value' and 'mask' arguments that refer to the value that
crosses the data bus (which xscale does not support and quietly ignores).

Just wondering if any consideration has been given to perhaps modify the wp
interface to accomodate this functionality.  If so, I might be able to crawl out
of my little xscale corner of the sandbox to help with implementation (though
currently I only have xscale target hardware to test on).  Just thought I'd ask.

I have patched my source to take advantage of this xscale functionality by
essentially re-defining the meaning of the arguments to wp such that the mask is
defined in xscale terms (an address mask).  The argument 'value' remains as a
placeholder, but is ignored by the xscale code.  Patch is below if anyone is
curious.  To help explain the contents of the patch: xscale hardware resources
are such that you can have two watchpoints at specific singular addresses, or
one watchpoint with a mask.

Thanks,
Mike

---
 src/target/xscale.c |   41 ++++++++++++++++++++++++++++++++++++-----
 1 files changed, 36 insertions(+), 5 deletions(-)

diff --git a/src/target/xscale.c b/src/target/xscale.c
index ddc73d2..0ccd38a 100644
--- a/src/target/xscale.c
+++ b/src/target/xscale.c
@@ -2266,7 +2266,7 @@ static int xscale_set_watchpoint(struct target *target,
                struct watchpoint *watchpoint)
 {
        struct xscale_common *xscale = target_to_xscale(target);
-       uint8_t enable = 0;
+       uint32_t enable = 0;
        struct reg *dbcon = &xscale->reg_cache->reg_list[XSCALE_DBCON];
        uint32_t dbcon_value = buf_get_u32(dbcon->value, 0, 32);
 @@ -2276,8 +2276,6 @@ static int xscale_set_watchpoint(struct target *target,
                return ERROR_TARGET_NOT_HALTED;
        }
 -      xscale_get_reg(dbcon);
-
        switch (watchpoint->rw)
        {
                case WPT_READ:
@@ -2293,6 +2291,20 @@ static int xscale_set_watchpoint(struct target *target,
                        LOG_ERROR("BUG: watchpoint->rw neither read, write nor 
access");
        }
 +      /* watchpoint with address mask requires both DBR registers */
+       if (watchpoint->mask != 0xffffffff)
+       {
+          if (xscale->dbr0_used || xscale->dbr1_used) +           {
+                 LOG_ERROR("BUG: sufficient hardware comparators unavailable");
+                 return ERROR_OK;
+          }
+
+          xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_DBR1],
watchpoint->mask);
+          xscale->dbr1_used = 1;
+          enable |= 0x100;                     /* DBCON[M] */
+       }
+
        if (!xscale->dbr0_used)
        {
                xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_DBR0],
watchpoint->address);
@@ -2333,8 +2345,17 @@ static int xscale_add_watchpoint(struct target *target,
                return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
        }
 -      xscale->dbr_available--;
+       if (watchpoint->mask == 0xffffffff)
+       {
+          xscale->dbr_available--;
+          return ERROR_OK;
+       }
 +      /* watchpoint with addr mask requires both DBR registers */
+       if (xscale->dbr_available < 2)
+          return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+       
+       xscale->dbr_available = 0;
        return ERROR_OK;
 }
 @@ -2359,7 +2380,14 @@ static int xscale_unset_watchpoint(struct target 
*target,
        if (watchpoint->set == 1)
        {
-               dbcon_value &= ~0x3;
+          if (watchpoint->mask != 0xffffffff)
+          {
+                 dbcon_value &= ~0x103; /* clear DBCON[M] as well */
+                 xscale->dbr1_used = 0; /* DBR1 was used for mask */
+          }
+          else
+                 dbcon_value &= ~0x3;
+
                xscale_set_reg_u32(dbcon, dbcon_value);
                xscale->dbr0_used = 0;
        }
@@ -2389,6 +2417,9 @@ static int xscale_remove_watchpoint(struct target *target,
struct watchpoint *wa
                xscale_unset_watchpoint(target, watchpoint);
        }
 +      if (watchpoint->mask != 0xffffffff)
+          xscale->dbr_available++;     /* both DBR regs now available */
+       
        xscale->dbr_available++;
        return ERROR_OK;
-- 
1.6.4.4


_______________________________________________
Openocd-development mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/openocd-development

Reply via email to