summaryrefslogtreecommitdiff
path: root/src/target/arm11_dbgtap.c
diff options
context:
space:
mode:
authorDavid Brownell <dbrownell@users.sourceforge.net>2009-12-04 18:57:31 -0800
committerDavid Brownell <dbrownell@users.sourceforge.net>2009-12-04 18:57:31 -0800
commita0edb8a328ceea23186ab74c941454fb146c9a48 (patch)
tree93e1e4f78240e40ba2ae5627055dde51b5b737a5 /src/target/arm11_dbgtap.c
parentf4651c869fb0bbe00495a09470af0a934814c92a (diff)
downloadopenocd+libswd-a0edb8a328ceea23186ab74c941454fb146c9a48.tar.gz
openocd+libswd-a0edb8a328ceea23186ab74c941454fb146c9a48.tar.bz2
openocd+libswd-a0edb8a328ceea23186ab74c941454fb146c9a48.tar.xz
openocd+libswd-a0edb8a328ceea23186ab74c941454fb146c9a48.zip
ARM11: basic watchpoint support
Use the DPM watchpoint support; remove old incomplete stubs. Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Diffstat (limited to 'src/target/arm11_dbgtap.c')
-rw-r--r--src/target/arm11_dbgtap.c102
1 files changed, 95 insertions, 7 deletions
diff --git a/src/target/arm11_dbgtap.c b/src/target/arm11_dbgtap.c
index e37ad56c..9ad56622 100644
--- a/src/target/arm11_dbgtap.c
+++ b/src/target/arm11_dbgtap.c
@@ -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);
}