arm_adi_v5: Make the DAP API stateless 65/3165/3
authorAndreas Fritiofson <andreas.fritiofson@gmail.com>
Tue, 8 Dec 2015 18:35:15 +0000 (19:35 +0100)
committerAndreas Fritiofson <andreas.fritiofson@gmail.com>
Tue, 29 Dec 2015 20:33:04 +0000 (20:33 +0000)
Remove entirely the concept of a "selected" AP that has to be maintained
between calls. All the information the DAP ops need are now provided to
each call through the AP/DAP pointer.

Consolidate the cache of the SELECT fields into one single field caching
the entire register.

Change-Id: I2e1c93ac5ee8ac38a7d680ca2c660c30093a6b87
Signed-off-by: Andreas Fritiofson <andreas.fritiofson@gmail.com>
Reviewed-on: http://openocd.zylin.com/3165
Tested-by: jenkins
Reviewed-by: Matthias Welwarsky <matthias@welwarsky.de>
src/target/adi_v5_jtag.c
src/target/adi_v5_swd.c
src/target/arm_adi_v5.c
src/target/arm_adi_v5.h

index 2753713c36f05f16a054bfd5b93aacd6940df5ee..b71fe3820ea53e20d02041a98164b61b1c448612 100644 (file)
@@ -75,11 +75,13 @@ static int jtag_ap_q_abort(struct adiv5_dap *dap, uint8_t *ack);
  * @param outvalue points to a 32-bit (little-endian) integer
  * @param invalue NULL, or points to a 32-bit (little-endian) integer
  * @param ack points to where the three bit JTAG_ACK_* code will be stored
+ * @param memaccess_tck number of idle cycles to add after AP access
  */
 
 static int adi_jtag_dp_scan(struct adiv5_dap *dap,
                uint8_t instr, uint8_t reg_addr, uint8_t RnW,
-               uint8_t *outvalue, uint8_t *invalue, uint8_t *ack)
+               uint8_t *outvalue, uint8_t *invalue, uint8_t *ack,
+               uint32_t memaccess_tck)
 {
        struct jtag_tap *tap = dap->tap;
        struct scan_field fields[2];
@@ -117,9 +119,8 @@ static int adi_jtag_dp_scan(struct adiv5_dap *dap,
        if ((instr == JTAG_DP_APACC)
                        && ((reg_addr == MEM_AP_REG_DRW)
                                || ((reg_addr & 0xF0) == MEM_AP_REG_BD0))
-                       && (dap->ap[dap_ap_get_select(dap)].memaccess_tck != 0))
-               jtag_add_runtest(dap->ap[dap_ap_get_select(dap)].memaccess_tck,
-                               TAP_IDLE);
+                       && memaccess_tck != 0)
+               jtag_add_runtest(memaccess_tck, TAP_IDLE);
 
        return ERROR_OK;
 }
@@ -132,7 +133,8 @@ static int adi_jtag_dp_scan(struct adiv5_dap *dap,
  */
 static int adi_jtag_dp_scan_u32(struct adiv5_dap *dap,
                uint8_t instr, uint8_t reg_addr, uint8_t RnW,
-               uint32_t outvalue, uint32_t *invalue, uint8_t *ack)
+               uint32_t outvalue, uint32_t *invalue, uint8_t *ack,
+               uint32_t memaccess_tck)
 {
        uint8_t out_value_buf[4];
        int retval;
@@ -140,7 +142,7 @@ static int adi_jtag_dp_scan_u32(struct adiv5_dap *dap,
        buf_set_u32(out_value_buf, 0, 32, outvalue);
 
        retval = adi_jtag_dp_scan(dap, instr, reg_addr, RnW,
-                       out_value_buf, (uint8_t *)invalue, ack);
+                       out_value_buf, (uint8_t *)invalue, ack, memaccess_tck);
        if (retval != ERROR_OK)
                return retval;
 
@@ -154,22 +156,22 @@ static int adi_jtag_dp_scan_u32(struct adiv5_dap *dap,
 /**
  * Utility to write AP registers.
  */
-static inline int adi_jtag_ap_write_check(struct adiv5_dap *dap,
+static inline int adi_jtag_ap_write_check(struct adiv5_ap *ap,
                uint8_t reg_addr, uint8_t *outvalue)
 {
-       return adi_jtag_dp_scan(dap, JTAG_DP_APACC, reg_addr, DPAP_WRITE,
-                       outvalue, NULL, NULL);
+       return adi_jtag_dp_scan(ap->dap, JTAG_DP_APACC, reg_addr, DPAP_WRITE,
+                       outvalue, NULL, NULL, ap->memaccess_tck);
 }
 
 static int adi_jtag_scan_inout_check_u32(struct adiv5_dap *dap,
                uint8_t instr, uint8_t reg_addr, uint8_t RnW,
-               uint32_t outvalue, uint32_t *invalue)
+               uint32_t outvalue, uint32_t *invalue, uint32_t memaccess_tck)
 {
        int retval;
 
        /* Issue the read or write */
        retval = adi_jtag_dp_scan_u32(dap, instr, reg_addr,
-                       RnW, outvalue, NULL, NULL);
+                       RnW, outvalue, NULL, NULL, memaccess_tck);
        if (retval != ERROR_OK)
                return retval;
 
@@ -178,7 +180,7 @@ static int adi_jtag_scan_inout_check_u32(struct adiv5_dap *dap,
         */
        if ((RnW == DPAP_READ) && (invalue != NULL))
                retval = adi_jtag_dp_scan_u32(dap, JTAG_DP_DPACC,
-                               DP_RDBUFF, DPAP_READ, 0, invalue, &dap->ack);
+                               DP_RDBUFF, DPAP_READ, 0, invalue, &dap->ack, 0);
        return retval;
 }
 
@@ -218,7 +220,7 @@ static int jtagdp_transaction_endcheck(struct adiv5_dap *dap)
         * but collect its ACK status.
         */
        retval = adi_jtag_scan_inout_check_u32(dap, JTAG_DP_DPACC,
-                       DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);
+                       DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat, 0);
        if (retval != ERROR_OK)
                return retval;
        retval = jtag_execute_queue();
@@ -254,7 +256,7 @@ static int jtagdp_transaction_endcheck(struct adiv5_dap *dap)
                        }
 
                        retval = adi_jtag_scan_inout_check_u32(dap, JTAG_DP_DPACC,
-                                       DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);
+                                       DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat, 0);
                        if (retval != ERROR_OK)
                                return retval;
                        retval = jtag_execute_queue();
@@ -285,11 +287,11 @@ static int jtagdp_transaction_endcheck(struct adiv5_dap *dap)
                        retval = adi_jtag_scan_inout_check_u32(dap, JTAG_DP_DPACC,
                                        DP_CTRL_STAT, DPAP_WRITE,
                                        dap->dp_ctrl_stat | SSTICKYORUN
-                                               | SSTICKYERR, NULL);
+                                               | SSTICKYERR, NULL, 0);
                        if (retval != ERROR_OK)
                                return retval;
                        retval = adi_jtag_scan_inout_check_u32(dap, JTAG_DP_DPACC,
-                                       DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);
+                                       DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat, 0);
                        if (retval != ERROR_OK)
                                return retval;
                        retval = jtag_execute_queue();
@@ -313,61 +315,61 @@ static int jtag_dp_q_read(struct adiv5_dap *dap, unsigned reg,
                uint32_t *data)
 {
        return adi_jtag_scan_inout_check_u32(dap, JTAG_DP_DPACC,
-                       reg, DPAP_READ, 0, data);
+                       reg, DPAP_READ, 0, data, 0);
 }
 
 static int jtag_dp_q_write(struct adiv5_dap *dap, unsigned reg,
                uint32_t data)
 {
        return adi_jtag_scan_inout_check_u32(dap, JTAG_DP_DPACC,
-                       reg, DPAP_WRITE, data, NULL);
+                       reg, DPAP_WRITE, data, NULL, 0);
 }
 
 /** Select the AP register bank matching bits 7:4 of reg. */
-static int jtag_ap_q_bankselect(struct adiv5_dap *dap, unsigned reg)
+static int jtag_ap_q_bankselect(struct adiv5_ap *ap, unsigned reg)
 {
-       uint32_t select_ap_bank = reg & 0x000000F0;
+       struct adiv5_dap *dap = ap->dap;
+       uint32_t select = ((uint32_t)ap->ap_num << 24) | (reg & 0x000000F0);
 
-       if (select_ap_bank == dap->ap_bank_value)
+       if (select == dap->select)
                return ERROR_OK;
-       dap->ap_bank_value = select_ap_bank;
 
-       select_ap_bank |= dap->ap_current;
+       dap->select = select;
 
-       return jtag_dp_q_write(dap, DP_SELECT, select_ap_bank);
+       return jtag_dp_q_write(dap, DP_SELECT, select);
 }
 
-static int jtag_ap_q_read(struct adiv5_dap *dap, unsigned reg,
+static int jtag_ap_q_read(struct adiv5_ap *ap, unsigned reg,
                uint32_t *data)
 {
-       int retval = jtag_ap_q_bankselect(dap, reg);
+       int retval = jtag_ap_q_bankselect(ap, reg);
 
        if (retval != ERROR_OK)
                return retval;
 
-       return adi_jtag_scan_inout_check_u32(dap, JTAG_DP_APACC, reg,
-                       DPAP_READ, 0, data);
+       return adi_jtag_scan_inout_check_u32(ap->dap, JTAG_DP_APACC, reg,
+                       DPAP_READ, 0, data, ap->memaccess_tck);
 }
 
-static int jtag_ap_q_write(struct adiv5_dap *dap, unsigned reg,
+static int jtag_ap_q_write(struct adiv5_ap *ap, unsigned reg,
                uint32_t data)
 {
        uint8_t out_value_buf[4];
 
-       int retval = jtag_ap_q_bankselect(dap, reg);
+       int retval = jtag_ap_q_bankselect(ap, reg);
        if (retval != ERROR_OK)
                return retval;
 
        buf_set_u32(out_value_buf, 0, 32, data);
 
-       return adi_jtag_ap_write_check(dap, reg, out_value_buf);
+       return adi_jtag_ap_write_check(ap, reg, out_value_buf);
 }
 
 static int jtag_ap_q_abort(struct adiv5_dap *dap, uint8_t *ack)
 {
        /* for JTAG, this is the only valid ABORT register operation */
        return adi_jtag_dp_scan_u32(dap, JTAG_DP_ABORT,
-                       0, DPAP_WRITE, 1, NULL, ack);
+                       0, DPAP_WRITE, 1, NULL, ack, 0);
 }
 
 static int jtag_dp_run(struct adiv5_dap *dap)
index 9bd1f93e62c2532e6b702d13ca12b3d902fe0d93..c080964d07a1275840406af7ad0e8a51143542aa 100644 (file)
@@ -114,7 +114,7 @@ static int swd_connect(struct adiv5_dap *dap)
 
        /* Make sure we don't try to perform any other accesses before the DPIDR read. */
        dap->do_reconnect = false;
-       dap->dp_bank_value = 0;
+       dap->select = 0;
 
        swd_queue_dp_read(dap, DP_IDCODE, &idcode);
 
@@ -158,18 +158,19 @@ static int swd_queue_ap_abort(struct adiv5_dap *dap, uint8_t *ack)
 /** Select the DP register bank matching bits 7:4 of reg. */
 static void swd_queue_dp_bankselect(struct adiv5_dap *dap, unsigned reg)
 {
-       uint32_t select_dp_bank = (reg & 0x000000F0) >> 4;
-
        if (reg == DP_SELECT)
                return;
 
-       if (select_dp_bank == dap->dp_bank_value)
+       uint32_t select_dp_bank = (reg & 0x000000F0) >> 4;
+       uint32_t select = select_dp_bank
+                       | (dap->select & (DP_SELECT_APSEL | DP_SELECT_APBANK));
+
+       if (select == dap->select)
                return;
 
-       dap->dp_bank_value = select_dp_bank;
-       select_dp_bank |= dap->ap_current | dap->ap_bank_value;
+       dap->select = select;
 
-       swd_queue_dp_write(dap, DP_SELECT, select_dp_bank);
+       swd_queue_dp_write(dap, DP_SELECT, select);
 }
 
 static int swd_queue_dp_read(struct adiv5_dap *dap, unsigned reg,
@@ -206,49 +207,55 @@ static int swd_queue_dp_write(struct adiv5_dap *dap, unsigned reg,
 }
 
 /** Select the AP register bank matching bits 7:4 of reg. */
-static void swd_queue_ap_bankselect(struct adiv5_dap *dap, unsigned reg)
+static void swd_queue_ap_bankselect(struct adiv5_ap *ap, unsigned reg)
 {
-       uint32_t select_ap_bank = reg & 0x000000F0;
+       struct adiv5_dap *dap = ap->dap;
+       uint32_t select = ((uint32_t)ap->ap_num << 24)
+                       | (reg & 0x000000F0)
+                       | (dap->select & DP_SELECT_DPBANK);
 
-       if (select_ap_bank == dap->ap_bank_value)
+       if (select == dap->select)
                return;
 
-       dap->ap_bank_value = select_ap_bank;
-       select_ap_bank |= dap->ap_current | dap->dp_bank_value;
+       dap->select = select;
 
-       swd_queue_dp_write(dap, DP_SELECT, select_ap_bank);
+       swd_queue_dp_write(dap, DP_SELECT, select);
 }
 
-static int swd_queue_ap_read(struct adiv5_dap *dap, unsigned reg,
+static int swd_queue_ap_read(struct adiv5_ap *ap, unsigned reg,
                uint32_t *data)
 {
        const struct swd_driver *swd = jtag_interface->swd;
        assert(swd);
 
+       struct adiv5_dap *dap = ap->dap;
+
        int retval = swd_check_reconnect(dap);
        if (retval != ERROR_OK)
                return retval;
 
-       swd_queue_ap_bankselect(dap, reg);
-       swd->read_reg(swd_cmd(true,  true, reg), dap->last_read, dap->ap[dap_ap_get_select(dap)].memaccess_tck);
+       swd_queue_ap_bankselect(ap, reg);
+       swd->read_reg(swd_cmd(true,  true, reg), dap->last_read, ap->memaccess_tck);
        dap->last_read = data;
 
        return check_sync(dap);
 }
 
-static int swd_queue_ap_write(struct adiv5_dap *dap, unsigned reg,
+static int swd_queue_ap_write(struct adiv5_ap *ap, unsigned reg,
                uint32_t data)
 {
        const struct swd_driver *swd = jtag_interface->swd;
        assert(swd);
 
+       struct adiv5_dap *dap = ap->dap;
+
        int retval = swd_check_reconnect(dap);
        if (retval != ERROR_OK)
                return retval;
 
        swd_finish_read(dap);
-       swd_queue_ap_bankselect(dap, reg);
-       swd->write_reg(swd_cmd(false,  true, reg), data, dap->ap[dap_ap_get_select(dap)].memaccess_tck);
+       swd_queue_ap_bankselect(ap, reg);
+       swd->write_reg(swd_cmd(false,  true, reg), data, ap->memaccess_tck);
 
        return check_sync(dap);
 }
index e56f595bd89092e53fe8cfcecafaab0aaab818d2..7501149254adbe2a5f2f7ce9ce2be843456635a4 100644 (file)
@@ -94,28 +94,6 @@ static uint32_t max_tar_block_size(uint32_t tar_autoincr_block, uint32_t address
  *                                                                         *
 ***************************************************************************/
 
-/**
- * Select one of the APs connected to the specified DAP.  The
- * selection is implicitly used with future AP transactions.
- * This is a NOP if the specified AP is already selected.
- *
- * @param dap The DAP
- * @param apsel Number of the AP to (implicitly) use with further
- *     transactions.  This normally identifies a MEM-AP.
- */
-void dap_ap_select(struct adiv5_dap *dap, uint8_t ap)
-{
-       uint32_t new_ap = (ap << 24) & 0xFF000000;
-
-       if (new_ap != dap->ap_current) {
-               dap->ap_current = new_ap;
-               /* Switching AP invalidates cached values.
-                * Values MUST BE UPDATED BEFORE AP ACCESS.
-                */
-               dap->ap_bank_value = -1;
-       }
-}
-
 static int mem_ap_setup_csw(struct adiv5_ap *ap, uint32_t csw)
 {
        csw = csw | CSW_DBGSWENABLE | CSW_MASTER_DEBUG | CSW_HPROT |
@@ -608,9 +586,6 @@ struct adiv5_dap *dap_init(void)
                /* Number of bits for tar autoincrement, impl. dep. at least 10 */
                dap->ap[i].tar_autoincr_block = (1<<10);
        }
-       dap->ap_current = -1;
-       dap->ap_bank_value = -1;
-       dap->dp_bank_value = -1;
        return dap;
 }
 
@@ -633,15 +608,12 @@ int dap_dp_init(struct adiv5_dap *dap)
        if (!dap->ops)
                dap->ops = &jtag_dp_ops;
 
-       dap->ap_current = -1;
-       dap->ap_bank_value = -1;
+       dap->select = DP_SELECT_INVALID;
        dap->last_read = NULL;
 
        for (size_t i = 0; i < 10; i++) {
                /* DP initialization */
 
-               dap->dp_bank_value = 0;
-
                retval = dap_queue_dp_read(dap, DP_CTRL_STAT, NULL);
                if (retval != ERROR_OK)
                        continue;
index 63d7f286e8c916727112edc3eff23c1df614289a..fed25ec2ede1a0b95629634cec23da63e0473395 100644 (file)
 
 #define IDR_JEP106_ARM 0x04760000
 
+#define DP_SELECT_APSEL 0xFF000000
+#define DP_SELECT_APBANK 0x000000F0
+#define DP_SELECT_DPBANK 0x0000000F
+#define DP_SELECT_INVALID 0x00FFFF00 /* Reserved bits one */
+
 /**
  * This represents an ARM Debug Interface (v5) Access Port (AP).
  * Most common is a MEM-AP, for memory access.
@@ -211,27 +216,10 @@ struct adiv5_dap {
        uint32_t apsel;
 
        /**
-        * Cache for DP_SELECT bits identifying the current AP.  A DAP may
-        * connect to multiple APs, such as one MEM-AP for general access,
-        * another reserved for accessing debug modules, and a JTAG-DP.
-        * "-1" indicates no cached value.
+        * Cache for DP_SELECT register. A value of DP_SELECT_INVALID
+        * indicates no cached value and forces rewrite of the register.
         */
-       uint32_t ap_current;
-
-       /**
-        * Cache for DP_SELECT bits identifying the current four-word AP
-        * register bank.  This caches AP register addresss bits 7:4; JTAG
-        * and SWD access primitves pass address bits 3:2; bits 1:0 are zero.
-        * "-1" indicates no cached value.
-        */
-       uint32_t ap_bank_value;
-
-       /**
-        * Cache for DP_SELECT bits identifying the current four-word DP
-        * register bank.  This caches DP register addresss bits 7:4; JTAG
-        * and SWD access primitves pass address bits 3:2; bits 1:0 are zero.
-        */
-       uint32_t dp_bank_value;
+       uint32_t select;
 
        /* information about current pending SWjDP-AHBAP transaction */
        uint8_t  ack;
@@ -271,10 +259,10 @@ struct dap_ops {
                        uint32_t data);
 
        /** AP register read. */
-       int (*queue_ap_read)(struct adiv5_dap *dap, unsigned reg,
+       int (*queue_ap_read)(struct adiv5_ap *ap, unsigned reg,
                        uint32_t *data);
        /** AP register write. */
-       int (*queue_ap_write)(struct adiv5_dap *dap, unsigned reg,
+       int (*queue_ap_write)(struct adiv5_ap *ap, unsigned reg,
                        uint32_t data);
 
        /** AP operation abort. */
@@ -302,9 +290,6 @@ enum ap_type {
        AP_TYPE_AXI_AP  = 0x4,  /* AXI Memory-AP */
 };
 
-/* AP selection applies to future AP transactions */
-void dap_ap_select(struct adiv5_dap *dap, uint8_t ap);
-
 /**
  * Queue a DP register read.
  * Note that not all DP registers are readable; also, that JTAG and SWD
@@ -356,8 +341,7 @@ static inline int dap_queue_ap_read(struct adiv5_ap *ap,
                unsigned reg, uint32_t *data)
 {
        assert(ap->dap->ops != NULL);
-       dap_ap_select(ap->dap, ap->ap_num);
-       return ap->dap->ops->queue_ap_read(ap->dap, reg, data);
+       return ap->dap->ops->queue_ap_read(ap, reg, data);
 }
 
 /**
@@ -373,8 +357,7 @@ static inline int dap_queue_ap_write(struct adiv5_ap *ap,
                unsigned reg, uint32_t data)
 {
        assert(ap->dap->ops != NULL);
-       dap_ap_select(ap->dap, ap->ap_num);
-       return ap->dap->ops->queue_ap_write(ap->dap, reg, data);
+       return ap->dap->ops->queue_ap_write(ap, reg, data);
 }
 
 /**
@@ -451,12 +434,6 @@ static inline int dap_dp_poll_register(struct adiv5_dap *dap, unsigned reg,
        }
 }
 
-/** Accessor for currently selected DAP-AP number (0..255) */
-static inline uint8_t dap_ap_get_select(struct adiv5_dap *swjdp)
-{
-       return (uint8_t)(swjdp->ap_current >> 24);
-}
-
 /* Queued MEM-AP memory mapped single word transfers. */
 int mem_ap_read_u32(struct adiv5_ap *ap,
                uint32_t address, uint32_t *value);

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)