diff options
author | David Brownell <dbrownell@users.sourceforge.net> | 2009-12-01 21:47:45 -0800 |
---|---|---|
committer | David Brownell <dbrownell@users.sourceforge.net> | 2009-12-01 21:47:45 -0800 |
commit | f4b52e1ceb2818d7a388c7aa0a3a7ab9b78f68be (patch) | |
tree | bb2e71a55408e2fcbf6b1c1fb575b02f9994722f /src/target | |
parent | 66ca84b58114ad73b5843f62f9f5fbead1126fca (diff) | |
download | riscv-openocd-f4b52e1ceb2818d7a388c7aa0a3a7ab9b78f68be.zip riscv-openocd-f4b52e1ceb2818d7a388c7aa0a3a7ab9b78f68be.tar.gz riscv-openocd-f4b52e1ceb2818d7a388c7aa0a3a7ab9b78f68be.tar.bz2 |
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/target')
-rw-r--r-- | src/target/cortex_a8.c | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/src/target/cortex_a8.c b/src/target/cortex_a8.c index 81402d7..a289d96 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 */ |