aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndreas Fritiofson <andreas.fritiofson@gmail.com>2014-02-16 09:29:01 +0100
committerAndreas Fritiofson <andreas.fritiofson@gmail.com>2014-06-28 09:26:12 +0000
commitfd909a5e3dc6d7434bd68bea5c89ffed0f18b586 (patch)
treead71970c66e7f05f5362e4e7bd57d115b705c458 /src
parent9ec211de1ce1f87f0aa424d44fc5b6956a4eb72a (diff)
downloadriscv-openocd-fd909a5e3dc6d7434bd68bea5c89ffed0f18b586.zip
riscv-openocd-fd909a5e3dc6d7434bd68bea5c89ffed0f18b586.tar.gz
riscv-openocd-fd909a5e3dc6d7434bd68bea5c89ffed0f18b586.tar.bz2
adi_v5_swd: Read RDBUFF once after a sequence of AP reads
Increases performance by a factor of two for long reads. Change-Id: I81a7a83835058560c6a53a43c3cc991100f01766 Signed-off-by: Andreas Fritiofson <andreas.fritiofson@gmail.com> Reviewed-on: http://openocd.zylin.com/1954 Tested-by: jenkins Reviewed-by: Paul Fertser <fercerpav@gmail.com>
Diffstat (limited to 'src')
-rw-r--r--src/target/adi_v5_swd.c30
-rw-r--r--src/target/arm_adi_v5.c1
-rw-r--r--src/target/arm_adi_v5.h6
3 files changed, 34 insertions, 3 deletions
diff --git a/src/target/adi_v5_swd.c b/src/target/adi_v5_swd.c
index c9c3ae5..c78aef2 100644
--- a/src/target/adi_v5_swd.c
+++ b/src/target/adi_v5_swd.c
@@ -58,6 +58,17 @@
/* YUK! - but this is currently a global.... */
extern struct jtag_interface *jtag_interface;
+static int swd_finish_read(struct adiv5_dap *dap)
+{
+ const struct swd_driver *swd = jtag_interface->swd;
+ int retval = ERROR_OK;
+ if (dap->last_read != NULL) {
+ retval = swd->read_reg(swd_cmd(true, false, DP_RDBUFF), dap->last_read);
+ dap->last_read = NULL;
+ }
+ return retval;
+}
+
static int (swd_queue_dp_write)(struct adiv5_dap *dap, unsigned reg,
uint32_t data);
@@ -129,6 +140,10 @@ static int (swd_queue_dp_write)(struct adiv5_dap *dap, unsigned reg,
const struct swd_driver *swd = jtag_interface->swd;
assert(swd);
+ retval = swd_finish_read(dap);
+ if (retval != ERROR_OK)
+ return retval;
+
retval = swd_queue_dp_bankselect(dap, reg);
if (retval != ERROR_OK)
return retval;
@@ -169,12 +184,14 @@ static int (swd_queue_ap_read)(struct adiv5_dap *dap, unsigned reg,
if (retval != ERROR_OK)
return retval;
- retval = swd->read_reg(swd_cmd(true, true, reg), data);
+ retval = swd->read_reg(swd_cmd(true, true, reg), dap->last_read);
+ dap->last_read = data;
if (retval != ERROR_OK) {
/* fault response */
uint8_t ack = retval & 0xff;
swd_queue_ap_abort(dap, &ack);
+ return retval;
}
return retval;
@@ -186,8 +203,13 @@ static int (swd_queue_ap_write)(struct adiv5_dap *dap, unsigned reg,
/* REVISIT status return ... */
const struct swd_driver *swd = jtag_interface->swd;
assert(swd);
+ int retval;
- int retval = swd_queue_ap_bankselect(dap, reg);
+ retval = swd_finish_read(dap);
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = swd_queue_ap_bankselect(dap, reg);
if (retval != ERROR_OK)
return retval;
@@ -207,10 +229,12 @@ static int swd_run(struct adiv5_dap *dap)
{
/* for now the SWD interface hard-wires a zero-size queue. */
+ int retval = swd_finish_read(dap);
+
/* FIXME but we still need to check and scrub
* any hardware errors ...
*/
- return ERROR_OK;
+ return retval;
}
const struct dap_ops swd_dap_ops = {
diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c
index 2e56396..a18101d 100644
--- a/src/target/arm_adi_v5.c
+++ b/src/target/arm_adi_v5.c
@@ -661,6 +661,7 @@ int ahbap_debugport_init(struct adiv5_dap *dap)
*/
dap->ap_current = !0;
dap_ap_select(dap, 0);
+ dap->last_read = NULL;
/* DP initialization */
diff --git a/src/target/arm_adi_v5.h b/src/target/arm_adi_v5.h
index d132c57..c51e8f8 100644
--- a/src/target/arm_adi_v5.h
+++ b/src/target/arm_adi_v5.h
@@ -188,6 +188,12 @@ struct adiv5_dap {
uint8_t ack;
/**
+ * Holds the pointer to the destination word for the last queued read,
+ * for use with posted AP read sequence optimization.
+ */
+ uint32_t *last_read;
+
+ /**
* Configures how many extra tck clocks are added after starting a
* MEM-AP access before we try to read its status (and/or result).
*/