ADIv5 transport support moves to separate files
authorDavid Brownell <dbrownell@users.sourceforge.net>
Tue, 16 Mar 2010 21:12:00 +0000 (14:12 -0700)
committerDavid Brownell <dbrownell@users.sourceforge.net>
Tue, 16 Mar 2010 21:12:00 +0000 (14:12 -0700)
Unclutter arm_adi_v5.c by moving most transport-specific code
to a transport-specific files adi_v5_{jtag,swd}.c ... it's not
a full cleanup, because of some issues which need to be addressed
as part of SWD support (along with implementing the DAP operations
on top of SWD transport):

 - The mess where mem_ap_read_buf_u32() is currently coded to
   know about JTAG scan chains, and thus needs rewriting before
   it will work with SWD;

 - Initialization is still JTAG-specific

Also  move JTAG_{DP,ACK}_* constants from adi_v5.h to the JTAG
file; no other code should care about those values.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
src/target/Makefile.am
src/target/adi_v5_jtag.c [new file with mode: 0644]
src/target/adi_v5_swd.c [new file with mode: 0644]
src/target/arm_adi_v5.c
src/target/arm_adi_v5.h

index ad0ff7c0263f817d1c661dc1d9f1d37b3f8d530d..ea6d88fce9f005c7b55f5f261cd887fe6e7022aa 100644 (file)
@@ -83,6 +83,8 @@ ARM_DEBUG_SRC = \
        arm_simulator.c \
        arm_semihosting.c \
        arm_adi_v5.c \
+       adi_v5_jtag.c \
+       adi_v5_swd.c \
        embeddedice.c \
        trace.c \
        etb.c \
diff --git a/src/target/adi_v5_jtag.c b/src/target/adi_v5_jtag.c
new file mode 100644 (file)
index 0000000..eac83b7
--- /dev/null
@@ -0,0 +1,481 @@
+/***************************************************************************
+ *   Copyright (C) 2006 by Magnus Lundin
+ *   lundin@mlu.mine.nu
+ *
+ *   Copyright (C) 2008 by Spencer Oliver
+ *   spen@spen-soft.co.uk
+ *
+ *   Copyright (C) 2009 by Oyvind Harboe
+ *   oyvind.harboe@zylin.com
+ *
+ *   Copyright (C) 2009-2010 by David Brownell
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the
+ *   Free Software Foundation, Inc.,
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ ***************************************************************************/
+
+/**
+ * @file
+ * This file implements JTAG transport support for cores implementing
+ the ARM Debug Interface version 5 (ADIv5).
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "arm.h"
+#include "arm_adi_v5.h"
+#include <helper/time_support.h>
+
+
+/* JTAG instructions/registers for JTAG-DP and SWJ-DP */
+#define JTAG_DP_ABORT          0x8
+#define JTAG_DP_DPACC          0xA
+#define JTAG_DP_APACC          0xB
+#define JTAG_DP_IDCODE         0xE
+
+/* three-bit ACK values for DPACC and APACC reads */
+#define JTAG_ACK_OK_FAULT      0x2
+#define JTAG_ACK_WAIT          0x1
+
+/***************************************************************************
+ *
+ * DPACC and APACC scanchain access through JTAG-DP (or SWJ-DP)
+ *
+***************************************************************************/
+
+/**
+ * Scan DPACC or APACC using target ordered uint8_t buffers.  No endianness
+ * conversions are performed.  See section 4.4.3 of the ADIv5 spec, which
+ * discusses operations which access these registers.
+ *
+ * Note that only one scan is performed.  If RnW is set, a separate scan
+ * will be needed to collect the data which was read; the "invalue" collects
+ * the posted result of a preceding operation, not the current one.
+ *
+ * @param swjdp the DAP
+ * @param instr JTAG_DP_APACC (AP access) or JTAG_DP_DPACC (DP access)
+ * @param reg_addr two significant bits; A[3:2]; for APACC access, the
+ *     SELECT register has more addressing bits.
+ * @param RnW false iff outvalue will be written to the DP or AP
+ * @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
+ */
+
+/* FIXME don't export ... this is a temporary workaround for the
+ * mem_ap_read_buf_u32() mess, until it's no longer JTAG-specific.
+ */
+int adi_jtag_dp_scan(struct adiv5_dap *swjdp,
+               uint8_t instr, uint8_t reg_addr, uint8_t RnW,
+               uint8_t *outvalue, uint8_t *invalue, uint8_t *ack)
+{
+       struct arm_jtag *jtag_info = swjdp->jtag_info;
+       struct scan_field fields[2];
+       uint8_t out_addr_buf;
+
+       jtag_set_end_state(TAP_IDLE);
+       arm_jtag_set_instr(jtag_info, instr, NULL);
+
+       /* Scan out a read or write operation using some DP or AP register.
+        * For APACC access with any sticky error flag set, this is discarded.
+        */
+       fields[0].num_bits = 3;
+       buf_set_u32(&out_addr_buf, 0, 3, ((reg_addr >> 1) & 0x6) | (RnW & 0x1));
+       fields[0].out_value = &out_addr_buf;
+       fields[0].in_value = ack;
+
+       /* NOTE: if we receive JTAG_ACK_WAIT, the previous operation did not
+        * complete; data we write is discarded, data we read is unpredictable.
+        * When overrun detect is active, STICKYORUN is set.
+        */
+
+       fields[1].num_bits = 32;
+       fields[1].out_value = outvalue;
+       fields[1].in_value = invalue;
+
+       jtag_add_dr_scan(jtag_info->tap, 2, fields, jtag_get_end_state());
+
+       /* Add specified number of tck clocks after starting memory bus
+        * access, giving the hardware time to complete the access.
+        * They provide more time for the (MEM) AP to complete the read ...
+        * See "Minimum Response Time" for JTAG-DP, in the ADIv5 spec.
+        */
+       if ((instr == JTAG_DP_APACC)
+                       && ((reg_addr == AP_REG_DRW)
+                               || ((reg_addr & 0xF0) == AP_REG_BD0))
+                       && (swjdp->memaccess_tck != 0))
+               jtag_add_runtest(swjdp->memaccess_tck,
+                               jtag_set_end_state(TAP_IDLE));
+
+       return jtag_get_error();
+}
+
+/**
+ * Scan DPACC or APACC out and in from host ordered uint32_t buffers.
+ * This is exactly like adi_jtag_dp_scan(), except that endianness
+ * conversions are performed (so the types of invalue and outvalue
+ * must be different).
+ */
+static int adi_jtag_dp_scan_u32(struct adiv5_dap *swjdp,
+               uint8_t instr, uint8_t reg_addr, uint8_t RnW,
+               uint32_t outvalue, uint32_t *invalue, uint8_t *ack)
+{
+       uint8_t out_value_buf[4];
+       int retval;
+
+       buf_set_u32(out_value_buf, 0, 32, outvalue);
+
+       retval = adi_jtag_dp_scan(swjdp, instr, reg_addr, RnW,
+                       out_value_buf, (uint8_t *)invalue, ack);
+       if (retval != ERROR_OK)
+               return retval;
+
+       if (invalue)
+               jtag_add_callback(arm_le_to_h_u32,
+                               (jtag_callback_data_t) invalue);
+
+       return retval;
+}
+
+/**
+ * Utility to write AP registers.
+ */
+static inline int adi_jtag_ap_write_check(struct adiv5_dap *dap,
+               uint8_t reg_addr, uint8_t *outvalue)
+{
+       return adi_jtag_dp_scan(dap, JTAG_DP_APACC, reg_addr, DPAP_WRITE,
+                       outvalue, NULL, NULL);
+}
+
+static int adi_jtag_scan_inout_check_u32(struct adiv5_dap *swjdp,
+               uint8_t instr, uint8_t reg_addr, uint8_t RnW,
+               uint32_t outvalue, uint32_t *invalue)
+{
+       int retval;
+
+       /* Issue the read or write */
+       retval = adi_jtag_dp_scan_u32(swjdp, instr, reg_addr,
+                       RnW, outvalue, NULL, NULL);
+       if (retval != ERROR_OK)
+               return retval;
+
+       /* For reads,  collect posted value; RDBUFF has no other effect.
+        * Assumes read gets acked with OK/FAULT, and CTRL_STAT says "OK".
+        */
+       if ((RnW == DPAP_READ) && (invalue != NULL))
+               retval = adi_jtag_dp_scan_u32(swjdp, JTAG_DP_DPACC,
+                               DP_RDBUFF, DPAP_READ, 0, invalue, &swjdp->ack);
+       return retval;
+}
+
+static int jtagdp_transaction_endcheck(struct adiv5_dap *swjdp)
+{
+       int retval;
+       uint32_t ctrlstat;
+
+       /* too expensive to call keep_alive() here */
+
+#if 0
+       /* Danger!!!! BROKEN!!!! */
+       adi_jtag_scan_inout_check_u32(swjdp, JTAG_DP_DPACC,
+                       DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);
+       /* Danger!!!! BROKEN!!!! Why will jtag_execute_queue() fail here????
+       R956 introduced the check on return value here and now Michael Schwingen reports
+       that this code no longer works....
+
+       https://lists.berlios.de/pipermail/openocd-development/2008-September/003107.html
+       */
+       if ((retval = jtag_execute_queue()) != ERROR_OK)
+       {
+               LOG_ERROR("BUG: Why does this fail the first time????");
+       }
+       /* Why??? second time it works??? */
+#endif
+
+       /* Post CTRL/STAT read; discard any previous posted read value
+        * but collect its ACK status.
+        */
+       adi_jtag_scan_inout_check_u32(swjdp, JTAG_DP_DPACC,
+                       DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);
+       if ((retval = jtag_execute_queue()) != ERROR_OK)
+               return retval;
+
+       swjdp->ack = swjdp->ack & 0x7;
+
+       /* common code path avoids calling timeval_ms() */
+       if (swjdp->ack != JTAG_ACK_OK_FAULT)
+       {
+               long long then = timeval_ms();
+
+               while (swjdp->ack != JTAG_ACK_OK_FAULT)
+               {
+                       if (swjdp->ack == JTAG_ACK_WAIT)
+                       {
+                               if ((timeval_ms()-then) > 1000)
+                               {
+                                       /* NOTE:  this would be a good spot
+                                        * to use JTAG_DP_ABORT.
+                                        */
+                                       LOG_WARNING("Timeout (1000ms) waiting "
+                                               "for ACK=OK/FAULT "
+                                               "in JTAG-DP transaction");
+                                       return ERROR_JTAG_DEVICE_ERROR;
+                               }
+                       }
+                       else
+                       {
+                               LOG_WARNING("Invalid ACK %#x "
+                                               "in JTAG-DP transaction",
+                                               swjdp->ack);
+                               return ERROR_JTAG_DEVICE_ERROR;
+                       }
+
+                       adi_jtag_scan_inout_check_u32(swjdp, JTAG_DP_DPACC,
+                                       DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);
+                       if ((retval = dap_run(swjdp)) != ERROR_OK)
+                               return retval;
+                       swjdp->ack = swjdp->ack & 0x7;
+               }
+       }
+
+       /* REVISIT also STICKYCMP, for pushed comparisons (nyet used) */
+
+       /* Check for STICKYERR and STICKYORUN */
+       if (ctrlstat & (SSTICKYORUN | SSTICKYERR))
+       {
+               LOG_DEBUG("jtag-dp: CTRL/STAT error, 0x%" PRIx32, ctrlstat);
+               /* Check power to debug regions */
+               if ((ctrlstat & 0xf0000000) != 0xf0000000)
+                        ahbap_debugport_init(swjdp);
+               else
+               {
+                       uint32_t mem_ap_csw, mem_ap_tar;
+
+                       /* Maybe print information about last intended
+                        * MEM-AP access; but not if autoincrementing.
+                        * *Real* CSW and TAR values are always shown.
+                        */
+                       if (swjdp->ap_tar_value != (uint32_t) -1)
+                               LOG_DEBUG("MEM-AP Cached values: "
+                                       "ap_bank 0x%" PRIx32
+                                       ", ap_csw 0x%" PRIx32
+                                       ", ap_tar 0x%" PRIx32,
+                                       swjdp->ap_bank_value,
+                                       swjdp->ap_csw_value,
+                                       swjdp->ap_tar_value);
+
+                       if (ctrlstat & SSTICKYORUN)
+                               LOG_ERROR("JTAG-DP OVERRUN - check clock, "
+                                       "memaccess, or reduce jtag speed");
+
+                       if (ctrlstat & SSTICKYERR)
+                               LOG_ERROR("JTAG-DP STICKY ERROR");
+
+                       /* Clear Sticky Error Bits */
+                       adi_jtag_scan_inout_check_u32(swjdp, JTAG_DP_DPACC,
+                                       DP_CTRL_STAT, DPAP_WRITE,
+                                       swjdp->dp_ctrl_stat | SSTICKYORUN
+                                               | SSTICKYERR, NULL);
+                       adi_jtag_scan_inout_check_u32(swjdp, JTAG_DP_DPACC,
+                                       DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);
+                       if ((retval = dap_run(swjdp)) != ERROR_OK)
+                               return retval;
+
+                       LOG_DEBUG("jtag-dp: CTRL/STAT 0x%" PRIx32, ctrlstat);
+
+                       retval = dap_queue_ap_read(swjdp,
+                                       AP_REG_CSW, &mem_ap_csw);
+                       if (retval != ERROR_OK)
+                               return retval;
+
+                       retval = dap_queue_ap_read(swjdp,
+                                       AP_REG_TAR, &mem_ap_tar);
+                       if (retval != ERROR_OK)
+                               return retval;
+
+                       if ((retval = dap_run(swjdp)) != ERROR_OK)
+                               return retval;
+                       LOG_ERROR("MEM_AP_CSW 0x%" PRIx32 ", MEM_AP_TAR 0x%"
+                                       PRIx32, mem_ap_csw, mem_ap_tar);
+
+               }
+               if ((retval = dap_run(swjdp)) != ERROR_OK)
+                       return retval;
+               return ERROR_JTAG_DEVICE_ERROR;
+       }
+
+       return ERROR_OK;
+}
+
+/*--------------------------------------------------------------------------*/
+
+static int jtag_idcode_q_read(struct adiv5_dap *dap,
+               uint8_t *ack, uint32_t *data)
+{
+       struct arm_jtag *jtag_info = dap->jtag_info;
+       int retval;
+       struct scan_field fields[1];
+
+       jtag_set_end_state(TAP_IDLE);
+
+       /* This is a standard JTAG operation -- no DAP tweakage */
+       retval = arm_jtag_set_instr(jtag_info, JTAG_DP_IDCODE, NULL);
+       if (retval != ERROR_OK)
+               return retval;
+
+       fields[0].num_bits = 32;
+       fields[0].out_value = NULL;
+       fields[0].in_value = (void *) data;
+
+       jtag_add_dr_scan(jtag_info->tap, 1, fields, jtag_get_end_state());
+       retval = jtag_get_error();
+       if (retval != ERROR_OK)
+               return retval;
+
+       jtag_add_callback(arm_le_to_h_u32,
+                       (jtag_callback_data_t) data);
+
+       return retval;
+}
+
+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);
+}
+
+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);
+}
+
+/** Select the AP register bank matching bits 7:4 of reg. */
+static int jtag_ap_q_bankselect(struct adiv5_dap *dap, unsigned reg)
+{
+       uint32_t select = reg & 0x000000F0;
+
+       if (select == dap->ap_bank_value)
+               return ERROR_OK;
+       dap->ap_bank_value = select;
+
+       select |= dap->apsel;
+
+       return jtag_dp_q_write(dap, DP_SELECT, select);
+}
+
+static int jtag_ap_q_read(struct adiv5_dap *dap, unsigned reg,
+               uint32_t *data)
+{
+       int retval = jtag_ap_q_bankselect(dap, reg);
+
+       if (retval != ERROR_OK)
+               return retval;
+
+       return adi_jtag_scan_inout_check_u32(dap, JTAG_DP_APACC, reg,
+                       DPAP_READ, 0, data);
+}
+
+static int jtag_ap_q_write(struct adiv5_dap *dap, unsigned reg,
+               uint32_t data)
+{
+       uint8_t out_value_buf[4];
+
+       int retval = jtag_ap_q_bankselect(dap, 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);
+}
+
+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);
+}
+
+static int jtag_dp_run(struct adiv5_dap *dap)
+{
+       return jtagdp_transaction_endcheck(dap);
+}
+
+/* FIXME don't export ... just initialize as
+ * part of DAP setup
+*/
+const struct dap_ops jtag_dp_ops = {
+       .queue_idcode_read =    jtag_idcode_q_read,
+       .queue_dp_read =        jtag_dp_q_read,
+       .queue_dp_write =       jtag_dp_q_write,
+       .queue_ap_read =        jtag_ap_q_read,
+       .queue_ap_write =       jtag_ap_q_write,
+       .queue_ap_abort =       jtag_ap_q_abort,
+       .run =                  jtag_dp_run,
+};
+
+
+const uint8_t swd2jtag_bitseq[] = {
+       /* More than 50 TCK/SWCLK cycles with TMS/SWDIO high,
+        * putting both JTAG and SWD logic into reset state.
+        */
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       /* Switching equence disables SWD and enables JTAG
+        * NOTE: bits in the DP's IDCODE can expose the need for
+        * the old/deprecated sequence (0xae 0xde).
+        */
+       0x3c, 0xe7,
+       /* At least 50 TCK/SWCLK cycles with TMS/SWDIO high,
+        * putting both JTAG and SWD logic into reset state.
+        * NOTE:  some docs say "at least 5".
+        */
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+};
+
+/** Put the debug link into JTAG mode, if the target supports it.
+ * The link's initial mode may be either SWD or JTAG.
+ *
+ * @param target Enters JTAG mode (if possible).
+ *
+ * Note that targets implemented with SW-DP do not support JTAG, and
+ * that some targets which could otherwise support it may have been
+ * configured to disable JTAG signaling
+ *
+ * @return ERROR_OK or else a fault code.
+ */
+int dap_to_jtag(struct target *target)
+{
+       int retval;
+
+       LOG_DEBUG("Enter JTAG mode");
+
+       /* REVISIT it's nasty to need to make calls to a "jtag"
+        * subsystem if the link isn't in JTAG mode...
+        */
+
+       retval = jtag_add_tms_seq(8 * sizeof(swd2jtag_bitseq),
+                       swd2jtag_bitseq, TAP_RESET);
+       if (retval == ERROR_OK)
+               retval = jtag_execute_queue();
+
+       /* REVISIT set up the DAP's ops vector for JTAG mode. */
+
+       return retval;
+}
diff --git a/src/target/adi_v5_swd.c b/src/target/adi_v5_swd.c
new file mode 100644 (file)
index 0000000..f103e4b
--- /dev/null
@@ -0,0 +1,92 @@
+/***************************************************************************
+ *
+ *   Copyright (C) 2010 by David Brownell
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the
+ *   Free Software Foundation, Inc.,
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ ***************************************************************************/
+
+/**
+ * @file
+ * This file implements SWD transport support for cores implementing
+ the ARM Debug Interface version 5 (ADIv5).
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "arm.h"
+#include "arm_adi_v5.h"
+#include <helper/time_support.h>
+
+/*
+ * This represents the bits which must be sent out on TMS/SWDIO to
+ * switch a DAP implemented using an SWJ-DP module into SWD mode.
+ * These bits are stored (and transmitted) LSB-first.
+ *
+ * See the DAP-Lite specification, section 2.2.5 for information
+ * about making the debug link select SWD or JTAG.  (Similar info
+ * is in a few other ARM documents.)
+ */
+static const uint8_t jtag2swd_bitseq[] = {
+       /* More than 50 TCK/SWCLK cycles with TMS/SWDIO high,
+        * putting both JTAG and SWD logic into reset state.
+        */
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       /* Switching sequence enables SWD and disables JTAG
+        * NOTE: bits in the DP's IDCODE may expose the need for
+        * an old/deprecated sequence (0xb6 0xed).
+        */
+       0x9e, 0xe7,
+       /* More than 50 TCK/SWCLK cycles with TMS/SWDIO high,
+        * putting both JTAG and SWD logic into reset state.
+        */
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+};
+
+/**
+ * Put the debug link into SWD mode, if the target supports it.
+ * The link's initial mode may be either JTAG (for example,
+ * with SWJ-DP after reset) or SWD.
+ *
+ * @param target Enters SWD mode (if possible).
+ *
+ * Note that targets using the JTAG-DP do not support SWD, and that
+ * some targets which could otherwise support it may have have been
+ * configured to disable SWD signaling
+ *
+ * @return ERROR_OK or else a fault code.
+ */
+int dap_to_swd(struct target *target)
+{
+       int retval;
+
+       LOG_DEBUG("Enter SWD mode");
+
+       /* REVISIT it's nasty to need to make calls to a "jtag"
+        * subsystem if the link isn't in JTAG mode...
+        */
+
+       retval =  jtag_add_tms_seq(8 * sizeof(jtag2swd_bitseq),
+                       jtag2swd_bitseq, TAP_INVALID);
+       if (retval == ERROR_OK)
+               retval = jtag_execute_queue();
+
+       /* REVISIT set up the DAP's ops vector for SWD mode. */
+
+       return retval;
+}
+
index 61cf98921880f14faef3d6a3c334c7f35d102ff0..dcad0fbcf9ecdee73ad8658e3f37be4313bd58c5 100644 (file)
@@ -85,272 +85,6 @@ static uint32_t max_tar_block_size(uint32_t tar_autoincr_block, uint32_t address
        return (tar_autoincr_block - ((tar_autoincr_block - 1) & address)) >> 2;
 }
 
-/***************************************************************************
- *                                                                         *
- * DPACC and APACC scanchain access through JTAG-DP                        *
- *                                                                         *
-***************************************************************************/
-
-/**
- * Scan DPACC or APACC using target ordered uint8_t buffers.  No endianness
- * conversions are performed.  See section 4.4.3 of the ADIv5 spec, which
- * discusses operations which access these registers.
- *
- * Note that only one scan is performed.  If RnW is set, a separate scan
- * will be needed to collect the data which was read; the "invalue" collects
- * the posted result of a preceding operation, not the current one.
- *
- * @param swjdp the DAP
- * @param instr JTAG_DP_APACC (AP access) or JTAG_DP_DPACC (DP access)
- * @param reg_addr two significant bits; A[3:2]; for APACC access, the
- *     SELECT register has more addressing bits.
- * @param RnW false iff outvalue will be written to the DP or AP
- * @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
- */
-static int adi_jtag_dp_scan(struct adiv5_dap *swjdp,
-               uint8_t instr, uint8_t reg_addr, uint8_t RnW,
-               uint8_t *outvalue, uint8_t *invalue, uint8_t *ack)
-{
-       struct arm_jtag *jtag_info = swjdp->jtag_info;
-       struct scan_field fields[2];
-       uint8_t out_addr_buf;
-
-       jtag_set_end_state(TAP_IDLE);
-       arm_jtag_set_instr(jtag_info, instr, NULL);
-
-       /* Scan out a read or write operation using some DP or AP register.
-        * For APACC access with any sticky error flag set, this is discarded.
-        */
-       fields[0].num_bits = 3;
-       buf_set_u32(&out_addr_buf, 0, 3, ((reg_addr >> 1) & 0x6) | (RnW & 0x1));
-       fields[0].out_value = &out_addr_buf;
-       fields[0].in_value = ack;
-
-       /* NOTE: if we receive JTAG_ACK_WAIT, the previous operation did not
-        * complete; data we write is discarded, data we read is unpredictable.
-        * When overrun detect is active, STICKYORUN is set.
-        */
-
-       fields[1].num_bits = 32;
-       fields[1].out_value = outvalue;
-       fields[1].in_value = invalue;
-
-       jtag_add_dr_scan(jtag_info->tap, 2, fields, jtag_get_end_state());
-
-       /* Add specified number of tck clocks after starting memory bus
-        * access, giving the hardware time to complete the access.
-        * They provide more time for the (MEM) AP to complete the read ...
-        * See "Minimum Response Time" for JTAG-DP, in the ADIv5 spec.
-        */
-       if ((instr == JTAG_DP_APACC)
-                       && ((reg_addr == AP_REG_DRW)
-                               || ((reg_addr & 0xF0) == AP_REG_BD0))
-                       && (swjdp->memaccess_tck != 0))
-               jtag_add_runtest(swjdp->memaccess_tck,
-                               jtag_set_end_state(TAP_IDLE));
-
-       return jtag_get_error();
-}
-
-/**
- * Scan DPACC or APACC out and in from host ordered uint32_t buffers.
- * This is exactly like adi_jtag_dp_scan(), except that endianness
- * conversions are performed (so the types of invalue and outvalue
- * must be different).
- */
-static int adi_jtag_dp_scan_u32(struct adiv5_dap *swjdp,
-               uint8_t instr, uint8_t reg_addr, uint8_t RnW,
-               uint32_t outvalue, uint32_t *invalue, uint8_t *ack)
-{
-       uint8_t out_value_buf[4];
-       int retval;
-
-       buf_set_u32(out_value_buf, 0, 32, outvalue);
-
-       retval = adi_jtag_dp_scan(swjdp, instr, reg_addr, RnW,
-                       out_value_buf, (uint8_t *)invalue, ack);
-       if (retval != ERROR_OK)
-               return retval;
-
-       if (invalue)
-               jtag_add_callback(arm_le_to_h_u32,
-                               (jtag_callback_data_t) invalue);
-
-       return retval;
-}
-
-/**
- * Utility to write AP registers.
- */
-static inline int adi_jtag_ap_write_check(struct adiv5_dap *dap,
-               uint8_t reg_addr, uint8_t *outvalue)
-{
-       return adi_jtag_dp_scan(dap, JTAG_DP_APACC, reg_addr, DPAP_WRITE,
-                       outvalue, NULL, NULL);
-}
-
-static int adi_jtag_scan_inout_check_u32(struct adiv5_dap *swjdp,
-               uint8_t instr, uint8_t reg_addr, uint8_t RnW,
-               uint32_t outvalue, uint32_t *invalue)
-{
-       int retval;
-
-       /* Issue the read or write */
-       retval = adi_jtag_dp_scan_u32(swjdp, instr, reg_addr,
-                       RnW, outvalue, NULL, NULL);
-       if (retval != ERROR_OK)
-               return retval;
-
-       /* For reads,  collect posted value; RDBUFF has no other effect.
-        * Assumes read gets acked with OK/FAULT, and CTRL_STAT says "OK".
-        */
-       if ((RnW == DPAP_READ) && (invalue != NULL))
-               retval = adi_jtag_dp_scan_u32(swjdp, JTAG_DP_DPACC,
-                               DP_RDBUFF, DPAP_READ, 0, invalue, &swjdp->ack);
-       return retval;
-}
-
-static int jtagdp_transaction_endcheck(struct adiv5_dap *swjdp)
-{
-       int retval;
-       uint32_t ctrlstat;
-
-       /* too expensive to call keep_alive() here */
-
-#if 0
-       /* Danger!!!! BROKEN!!!! */
-       adi_jtag_scan_inout_check_u32(swjdp, JTAG_DP_DPACC,
-                       DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);
-       /* Danger!!!! BROKEN!!!! Why will jtag_execute_queue() fail here????
-       R956 introduced the check on return value here and now Michael Schwingen reports
-       that this code no longer works....
-
-       https://lists.berlios.de/pipermail/openocd-development/2008-September/003107.html
-       */
-       if ((retval = jtag_execute_queue()) != ERROR_OK)
-       {
-               LOG_ERROR("BUG: Why does this fail the first time????");
-       }
-       /* Why??? second time it works??? */
-#endif
-
-       /* Post CTRL/STAT read; discard any previous posted read value
-        * but collect its ACK status.
-        */
-       adi_jtag_scan_inout_check_u32(swjdp, JTAG_DP_DPACC,
-                       DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);
-       if ((retval = jtag_execute_queue()) != ERROR_OK)
-               return retval;
-
-       swjdp->ack = swjdp->ack & 0x7;
-
-       /* common code path avoids calling timeval_ms() */
-       if (swjdp->ack != JTAG_ACK_OK_FAULT)
-       {
-               long long then = timeval_ms();
-
-               while (swjdp->ack != JTAG_ACK_OK_FAULT)
-               {
-                       if (swjdp->ack == JTAG_ACK_WAIT)
-                       {
-                               if ((timeval_ms()-then) > 1000)
-                               {
-                                       /* NOTE:  this would be a good spot
-                                        * to use JTAG_DP_ABORT.
-                                        */
-                                       LOG_WARNING("Timeout (1000ms) waiting "
-                                               "for ACK=OK/FAULT "
-                                               "in JTAG-DP transaction");
-                                       return ERROR_JTAG_DEVICE_ERROR;
-                               }
-                       }
-                       else
-                       {
-                               LOG_WARNING("Invalid ACK %#x "
-                                               "in JTAG-DP transaction",
-                                               swjdp->ack);
-                               return ERROR_JTAG_DEVICE_ERROR;
-                       }
-
-                       adi_jtag_scan_inout_check_u32(swjdp, JTAG_DP_DPACC,
-                                       DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);
-                       if ((retval = dap_run(swjdp)) != ERROR_OK)
-                               return retval;
-                       swjdp->ack = swjdp->ack & 0x7;
-               }
-       }
-
-       /* REVISIT also STICKYCMP, for pushed comparisons (nyet used) */
-
-       /* Check for STICKYERR and STICKYORUN */
-       if (ctrlstat & (SSTICKYORUN | SSTICKYERR))
-       {
-               LOG_DEBUG("jtag-dp: CTRL/STAT error, 0x%" PRIx32, ctrlstat);
-               /* Check power to debug regions */
-               if ((ctrlstat & 0xf0000000) != 0xf0000000)
-                        ahbap_debugport_init(swjdp);
-               else
-               {
-                       uint32_t mem_ap_csw, mem_ap_tar;
-
-                       /* Maybe print information about last intended
-                        * MEM-AP access; but not if autoincrementing.
-                        * *Real* CSW and TAR values are always shown.
-                        */
-                       if (swjdp->ap_tar_value != (uint32_t) -1)
-                               LOG_DEBUG("MEM-AP Cached values: "
-                                       "ap_bank 0x%" PRIx32
-                                       ", ap_csw 0x%" PRIx32
-                                       ", ap_tar 0x%" PRIx32,
-                                       swjdp->ap_bank_value,
-                                       swjdp->ap_csw_value,
-                                       swjdp->ap_tar_value);
-
-                       if (ctrlstat & SSTICKYORUN)
-                               LOG_ERROR("JTAG-DP OVERRUN - check clock, "
-                                       "memaccess, or reduce jtag speed");
-
-                       if (ctrlstat & SSTICKYERR)
-                               LOG_ERROR("JTAG-DP STICKY ERROR");
-
-                       /* Clear Sticky Error Bits */
-                       adi_jtag_scan_inout_check_u32(swjdp, JTAG_DP_DPACC,
-                                       DP_CTRL_STAT, DPAP_WRITE,
-                                       swjdp->dp_ctrl_stat | SSTICKYORUN
-                                               | SSTICKYERR, NULL);
-                       adi_jtag_scan_inout_check_u32(swjdp, JTAG_DP_DPACC,
-                                       DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);
-                       if ((retval = dap_run(swjdp)) != ERROR_OK)
-                               return retval;
-
-                       LOG_DEBUG("jtag-dp: CTRL/STAT 0x%" PRIx32, ctrlstat);
-
-                       retval = dap_queue_ap_read(swjdp,
-                                       AP_REG_CSW, &mem_ap_csw);
-                       if (retval != ERROR_OK)
-                               return retval;
-
-                       retval = dap_queue_ap_read(swjdp,
-                                       AP_REG_TAR, &mem_ap_tar);
-                       if (retval != ERROR_OK)
-                               return retval;
-
-                       if ((retval = dap_run(swjdp)) != ERROR_OK)
-                               return retval;
-                       LOG_ERROR("MEM_AP_CSW 0x%" PRIx32 ", MEM_AP_TAR 0x%"
-                                       PRIx32, mem_ap_csw, mem_ap_tar);
-
-               }
-               if ((retval = dap_run(swjdp)) != ERROR_OK)
-                       return retval;
-               return ERROR_JTAG_DEVICE_ERROR;
-       }
-
-       return ERROR_OK;
-}
-
 /***************************************************************************
  *                                                                         *
  * DP and MEM-AP  register access  through APACC and DPACC                 *
@@ -818,6 +552,13 @@ int mem_ap_write_buf_u8(struct adiv5_dap *swjdp, uint8_t *buffer, int count, uin
        return retval;
 }
 
+/* FIXME don't import ... this is a temporary workaround for the
+ * mem_ap_read_buf_u32() mess, until it's no longer JTAG-specific.
+ */
+extern int adi_jtag_dp_scan(struct adiv5_dap *swjdp,
+               uint8_t instr, uint8_t reg_addr, uint8_t RnW,
+               uint8_t *outvalue, uint8_t *invalue, uint8_t *ack);
+
 /**
  * Synchronously read a block of 32-bit words into a buffer
  * @param swjdp The DAP connected to the MEM-AP.
@@ -1116,110 +857,11 @@ int mem_ap_read_buf_u8(struct adiv5_dap *swjdp, uint8_t *buffer,
 
 /*--------------------------------------------------------------------------*/
 
-static int jtag_idcode_q_read(struct adiv5_dap *dap,
-               uint8_t *ack, uint32_t *data)
-{
-       struct arm_jtag *jtag_info = dap->jtag_info;
-       int retval;
-       struct scan_field fields[1];
-
-       jtag_set_end_state(TAP_IDLE);
-
-       /* This is a standard JTAG operation -- no DAP tweakage */
-       retval = arm_jtag_set_instr(jtag_info, JTAG_DP_IDCODE, NULL);
-       if (retval != ERROR_OK)
-               return retval;
-
-       fields[0].num_bits = 32;
-       fields[0].out_value = NULL;
-       fields[0].in_value = (void *) data;
-
-       jtag_add_dr_scan(jtag_info->tap, 1, fields, jtag_get_end_state());
-       retval = jtag_get_error();
-       if (retval != ERROR_OK)
-               return retval;
-
-       jtag_add_callback(arm_le_to_h_u32,
-                       (jtag_callback_data_t) data);
-
-       return retval;
-}
-
-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);
-}
-
-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);
-}
-
-/** Select the AP register bank matching bits 7:4 of reg. */
-static int jtag_ap_q_bankselect(struct adiv5_dap *dap, unsigned reg)
-{
-       uint32_t select = reg & 0x000000F0;
-
-       if (select == dap->ap_bank_value)
-               return ERROR_OK;
-       dap->ap_bank_value = select;
-
-       select |= dap->apsel;
-
-       return jtag_dp_q_write(dap, DP_SELECT, select);
-}
-
-static int jtag_ap_q_read(struct adiv5_dap *dap, unsigned reg,
-               uint32_t *data)
-{
-       int retval = jtag_ap_q_bankselect(dap, reg);
-
-       if (retval != ERROR_OK)
-               return retval;
-
-       return adi_jtag_scan_inout_check_u32(dap, JTAG_DP_APACC, reg,
-                       DPAP_READ, 0, data);
-}
-
-static int jtag_ap_q_write(struct adiv5_dap *dap, unsigned reg,
-               uint32_t data)
-{
-       uint8_t out_value_buf[4];
-
-       int retval = jtag_ap_q_bankselect(dap, 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);
-}
-
-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);
-}
-
-static int jtag_dp_run(struct adiv5_dap *dap)
-{
-       return jtagdp_transaction_endcheck(dap);
-}
-
-static const struct dap_ops jtag_dp_ops = {
-       .queue_idcode_read =    jtag_idcode_q_read,
-       .queue_dp_read =        jtag_dp_q_read,
-       .queue_dp_write =       jtag_dp_q_write,
-       .queue_ap_read =        jtag_ap_q_read,
-       .queue_ap_write =       jtag_ap_q_write,
-       .queue_ap_abort =       jtag_ap_q_abort,
-       .run =                  jtag_dp_run,
-};
+/* FIXME don't import ... just initialize as
+ * part of DAP transport setup
+*/
+extern const struct dap_ops jtag_dp_ops;
 
 /*--------------------------------------------------------------------------*/
 
@@ -1988,57 +1630,3 @@ int dap_to_swd(struct target *target)
        return retval;
 }
 
-/**
- * This represents the bits which must be sent out on TMS/SWDIO to
- * switch a DAP implemented using an SWJ-DP module into JTAG mode.
- * These bits are stored (and transmitted) LSB-first.
- *
- * These bits are stored (and transmitted) LSB-first.
- */
-static const uint8_t swd2jtag_bitseq[] = {
-       /* More than 50 TCK/SWCLK cycles with TMS/SWDIO high,
-        * putting both JTAG and SWD logic into reset state.
-        */
-       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-       /* Switching equence disables SWD and enables JTAG
-        * NOTE: bits in the DP's IDCODE can expose the need for
-        * the old/deprecated sequence (0xae 0xde).
-        */
-       0x3c, 0xe7,
-       /* At least 50 TCK/SWCLK cycles with TMS/SWDIO high,
-        * putting both JTAG and SWD logic into reset state.
-        * NOTE:  some docs say "at least 5".
-        */
-       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-};
-
-/** Put the debug link into JTAG mode, if the target supports it.
- * The link's initial mode may be either SWD or JTAG.
- *
- * @param target Enters JTAG mode (if possible).
- *
- * Note that targets implemented with SW-DP do not support JTAG, and
- * that some targets which could otherwise support it may have been
- * configured to disable JTAG signaling
- *
- * @return ERROR_OK or else a fault code.
- */
-int dap_to_jtag(struct target *target)
-{
-       int retval;
-
-       LOG_DEBUG("Enter JTAG mode");
-
-       /* REVISIT it's nasty to need to make calls to a "jtag"
-        * subsystem if the link isn't in JTAG mode...
-        */
-
-       retval = jtag_add_tms_seq(8 * sizeof(swd2jtag_bitseq),
-                       swd2jtag_bitseq, TAP_RESET);
-       if (retval == ERROR_OK)
-               retval = jtag_execute_queue();
-
-       /* REVISIT set up the DAP's ops vector for JTAG mode. */
-
-       return retval;
-}
index d207fd9cd54d001a9eca26223c8c45f180b45716..4ee36ff1f8cfbf360e86482e9e82ca8d4e65b01a 100644 (file)
 
 #include "arm_jtag.h"
 
-/* JTAG instructions/registers for JTAG-DP and SWJ-DP */
-#define JTAG_DP_ABORT          0x8
+/* FIXME remove these JTAG-specific decls when mem_ap_read_buf_u32()
+ * is no longer JTAG-specific
+ */
 #define JTAG_DP_DPACC          0xA
 #define JTAG_DP_APACC          0xB
-#define JTAG_DP_IDCODE         0xE
-
-/* three-bit ACK values for DPACC and APACC reads */
-#define JTAG_ACK_OK_FAULT      0x2
-#define JTAG_ACK_WAIT          0x1
 
 /* three-bit ACK values for SWD access (sent LSB first) */
 #define SWD_ACK_OK             0x4

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)