adi_v5_swd: Read RDBUFF once after a sequence of AP reads
authorAndreas Fritiofson <andreas.fritiofson@gmail.com>
Sun, 16 Feb 2014 08:29:01 +0000 (09:29 +0100)
committerAndreas Fritiofson <andreas.fritiofson@gmail.com>
Sat, 28 Jun 2014 09:26:12 +0000 (09:26 +0000)
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>
src/target/adi_v5_swd.c
src/target/arm_adi_v5.c
src/target/arm_adi_v5.h

index c9c3ae586591de1189927b7a24a32c9c84acd336..c78aef27aecc7933c84524667c56dc2263ae8b5b 100644 (file)
 /* 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 = {
index 2e56396ced0bfc02cf34e54b65c18491f8dcaf4b..a18101daff380b390d3d288207d3289b9c3bc136 100644 (file)
@@ -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 */
 
index d132c57cb690078e5a6819943769c7a7219f0c2d..c51e8f81b7d03cef3c5af0494b3c05dd70e87015 100644 (file)
@@ -187,6 +187,12 @@ struct adiv5_dap {
        /* information about current pending SWjDP-AHBAP transaction */
        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).