summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDavid Brownell <dbrownell@users.sourceforge.net>2009-12-01 21:47:45 -0800
committerDavid Brownell <dbrownell@users.sourceforge.net>2009-12-01 21:47:45 -0800
commitf4b52e1ceb2818d7a388c7aa0a3a7ab9b78f68be (patch)
treebb2e71a55408e2fcbf6b1c1fb575b02f9994722f /src
parent66ca84b58114ad73b5843f62f9f5fbead1126fca (diff)
downloadopenocd+libswd-f4b52e1ceb2818d7a388c7aa0a3a7ab9b78f68be.tar.gz
openocd+libswd-f4b52e1ceb2818d7a388c7aa0a3a7ab9b78f68be.tar.bz2
openocd+libswd-f4b52e1ceb2818d7a388c7aa0a3a7ab9b78f68be.tar.xz
openocd+libswd-f4b52e1ceb2818d7a388c7aa0a3a7ab9b78f68be.zip
Cortex-A8: basic watchpoint support
Actually this should handle both breakpoints and watchpoints ... but the DPM framework only handles watchpoints for now. Works on Beagle. Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Diffstat (limited to 'src')
-rw-r--r--src/target/cortex_a8.c66
1 files changed, 66 insertions, 0 deletions
diff --git a/src/target/cortex_a8.c b/src/target/cortex_a8.c
index 81402d79..a289d96a 100644
--- a/src/target/cortex_a8.c
+++ b/src/target/cortex_a8.c
@@ -460,6 +460,66 @@ static int cortex_a8_instr_read_data_r0(struct arm_dpm *dpm,
return cortex_a8_read_dcc(a8, data, &dscr);
}
+static int cortex_a8_bpwp_enable(struct arm_dpm *dpm, unsigned index,
+ uint32_t addr, uint32_t control)
+{
+ struct cortex_a8_common *a8 = dpm_to_a8(dpm);
+ uint32_t vr = a8->armv7a_common.debug_base;
+ uint32_t cr = a8->armv7a_common.debug_base;
+ int retval;
+
+ switch (index) {
+ case 0 ... 15: /* breakpoints */
+ vr += CPUDBG_BVR_BASE;
+ cr += CPUDBG_BCR_BASE;
+ break;
+ case 16 ... 31: /* watchpoints */
+ vr += CPUDBG_WVR_BASE;
+ cr += CPUDBG_WCR_BASE;
+ index -= 16;
+ break;
+ default:
+ return ERROR_FAIL;
+ }
+ vr += 4 * index;
+ cr += 4 * index;
+
+ LOG_DEBUG("A8: bpwp enable, vr %08x cr %08x",
+ (unsigned) vr, (unsigned) cr);
+
+ retval = cortex_a8_dap_write_memap_register_u32(dpm->arm->target,
+ vr, addr);
+ if (retval != ERROR_OK)
+ return retval;
+ retval = cortex_a8_dap_write_memap_register_u32(dpm->arm->target,
+ cr, control);
+ return retval;
+}
+
+static int cortex_a8_bpwp_disable(struct arm_dpm *dpm, unsigned index)
+{
+ struct cortex_a8_common *a8 = dpm_to_a8(dpm);
+ uint32_t cr;
+
+ switch (index) {
+ case 0 ... 15:
+ cr = a8->armv7a_common.debug_base + CPUDBG_BCR_BASE;
+ break;
+ case 16 ... 31:
+ cr = a8->armv7a_common.debug_base + CPUDBG_WCR_BASE;
+ index -= 16;
+ break;
+ default:
+ return ERROR_FAIL;
+ }
+ cr += 4 * index;
+
+ LOG_DEBUG("A8: bpwp disable, cr %08x", (unsigned) cr);
+
+ /* clear control register */
+ return cortex_a8_dap_write_memap_register_u32(dpm->arm->target, cr, 0);
+}
+
static int cortex_a8_dpm_setup(struct cortex_a8_common *a8, uint32_t didr)
{
struct arm_dpm *dpm = &a8->armv7a_common.dpm;
@@ -477,6 +537,9 @@ static int cortex_a8_dpm_setup(struct cortex_a8_common *a8, uint32_t didr)
dpm->instr_read_data_dcc = cortex_a8_instr_read_data_dcc;
dpm->instr_read_data_r0 = cortex_a8_instr_read_data_r0;
+ dpm->bpwp_enable = cortex_a8_bpwp_enable;
+ dpm->bpwp_disable = cortex_a8_bpwp_disable;
+
return arm_dpm_setup(dpm);
}
@@ -745,6 +808,7 @@ static int cortex_a8_debug_entry(struct target *target)
case 5: /* vector catch */
target->debug_reason = DBG_REASON_BREAKPOINT;
break;
+ case 2: /* asynch watchpoint */
case 10: /* precise watchpoint */
target->debug_reason = DBG_REASON_WATCHPOINT;
/* REVISIT could collect WFAR later, to see just
@@ -1276,6 +1340,8 @@ static int cortex_a8_write_memory(struct target *target, uint32_t address,
*
* For both ICache and DCache, walk all cache lines in the
* address range. Cortex-A8 has fixed 64 byte line length.
+ *
+ * REVISIT per ARMv7, these may trigger watchpoints ...
*/
/* invalidate I-Cache */