summaryrefslogtreecommitdiff
path: root/gdb/arc-jtag-ops.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/arc-jtag-ops.c')
-rw-r--r--gdb/arc-jtag-ops.c2215
1 files changed, 1241 insertions, 974 deletions
diff --git a/gdb/arc-jtag-ops.c b/gdb/arc-jtag-ops.c
index 0a237f69d30..54631b92efd 100644
--- a/gdb/arc-jtag-ops.c
+++ b/gdb/arc-jtag-ops.c
@@ -1,1229 +1,1496 @@
-/* Target dependent code for ARC700, for GDB, the GNU debugger.
+/* Target dependent code for ARC processor family, for GDB, the GNU debugger.
- Copyright 2005 Free Software Foundation, Inc.
+ Copyright 2005, 2008, 2009 Free Software Foundation, Inc.
- Contributed by Codito Technologies Pvt. Ltd. (www.codito.com)
+ Contributed by ARC International (www.arc.com)
- Authors:
- Sameer Dhavale <sameer.dhavale@codito.com>
- Soam Vasani <soam.vasani@codito.com>
+ Author:
+ Sameer Dhavale <sameer.dhavale@codito.com>
+ Soam Vasani <soam.vasani@codito.com>
+ Richard Stuckey <richard.stuckey@arc.com>
This file is part of GDB.
-
+
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
+ the Free Software Foundation; either version 3 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.
-*/
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/******************************************************************************/
+/* */
+/* Outline: */
+/* This module implements debug access to an ARC processor via its JTAG */
+/* interface. */
+/* */
+/* See */
+/* ARCompact Instruction Set Architecture */
+/* Programmer's Reference (5115-018) */
+/* */
+/* for a description of ARC processor architecture (in particular */
+/* the auxiliary registers and the halting procedure); */
+/* */
+/* ARC 700 External Interfaces */
+/* Reference (5117-013) */
+/* */
+/* for a description of the JTAG interface (in particular the Test */
+/* Access Port Controller (TAPC) state machine). */
+/* */
+/* The JTAG interface is accessed by three parallel ports: control, data */
+/* and status. Data is read from or written to these ports one byte at a */
+/* at a time, using a GPIO (General Purpose Input/Output) driver. */
+/* */
+/* The TDI and TMS signals are written to the data port. */
+/* The TCK signal is written to the control port. */
+/* The TDO signal is read from the status port. */
+/* */
+/* Host/Target Byte Order: */
+/* The core and auxiliary register contents read from or written to the */
+/* JTAG interface are ALWAYS in little-endian format, regardless of the */
+/* endianness of the target processor. */
+/* */
+/******************************************************************************/
+
+/* system header files */
#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
+#include <string.h>
#include <errno.h>
-#include <sys/io.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <assert.h>
+#include <unistd.h>
+#include <byteswap.h>
+
+/* gdb header files */
+#include "defs.h"
+#include "gdb_assert.h"
+
+/* ARC header files */
+#include "arc-gpio.h"
+#include "arc-jtag.h"
#include "arc-jtag-ops.h"
-#include "gpio.h"
-#include <signal.h>
-#include <defs.h>
-#include <sys/ioctl.h>
-#include "arc-tdep.h"
-#define printf printf_filtered
+#include "arc-support.h"
-unsigned int arcjtag_retry_count = 50;
+/* -------------------------------------------------------------------------- */
+/* conditional compilation flags */
+/* -------------------------------------------------------------------------- */
+/* We would really like to optimise the use of the JTAG Data Register by
+ loading a word into it only if that word differs from the last word loaded;
+ but there seems to be undocumented behaviour of the JTAG mechanism in that
+ the Data Register is altered after a write operation! See ARC Bug #93814. */
+#define JTAG_DATA_REGISTER_IS_CORRUPTED_BY_WRITE
-/* ------------------------------------ */
-/* For ARC jtag Cable */
-/* */
-/* Pin no. Signal Word , Bit */
-/* */
-/* - TRST */
-/* 8 TMS Data 6 */
-/* 1 TCK Control 0 */
-/* 9 TDI Data 7 */
-/* 13 TDO Status 4 */
+/* Define this if you wish to check the whether the contents of the JTAG Data
+ Register are corrupted by write operations. */
+//#define CHECK_JTAG_DATA_REGISTER
+/* Define this if you wish to perform low-level debugging of the JTAG state
+ machine emulated in this module (this should not be necessary). */
+//#define STATE_MACHINE_DEBUG
-#define JTAG_TRST 0x00 /* not there */
-#define JTAG_TMS 0x40 /* data port */
-#define JTAG_TCK 0x01 /* control port. Driven Low. */
-#define JTAG_TDI 0x80 /* data port */
-#define JTAG_TDO 0x10 /* status port */
+/* -------------------------------------------------------------------------- */
+/* local types */
+/* -------------------------------------------------------------------------- */
-/* ------------------------------------ */
+/* Sizes of quantities. */
+#define BITS_IN_COMMAND_CODE 4
+#define BITS_IN_REGISTER_CODE 4
-/* */
-#define A4_HALT_VALUE 0x02000000
-#define ARC700_HALT_VALUE 0x1
+typedef unsigned int Bit; /* Only LSB of word is used. */
+typedef unsigned int JTAG_RegisterContents;
-/* Parallel port i/o addr. (LPT1) */
-#define DATA_PORT 0x378
-#define STATUS_PORT 0x379
-#define CONTROL_PORT 0x37A
+typedef enum
+{
+ MSB_FIRST,
+ MSB_LAST
+} Order;
-unsigned char tapc_dataport=0, tapc_statusport=0, tapc_controlport=0x1;
-int fd;
-struct GPIO_ioctl jtag_ioctl;
-sigset_t block_mask;
-enum AA3SSPinState
- {
- READ_FROM_AA3 = 0,
- WRITE_TO_AA3 = 1
- };
-enum AA3SSPinState rw_flag;
+typedef enum
+{
+ Memory,
+ Register
+} JTAG_TransactionType;
+typedef enum
+{
+ STALLED,
+ FAILURE,
+ READY,
+ NOT_READY
+} JTAG_TransactionStatus;
-struct jtag_ops arc_jtag_ops;
-static enum ARCProcessorVersion ARCProcessor = UNSUPPORTED;
+/* Only these JTAG registers are currently used. */
+typedef enum
+{
+ JTAG_STATUS_REGISTER = 0x8,
+ JTAG_TRANSACTION_COMMAND_REGISTER = 0x9,
+ JTAG_ADDRESS_REGISTER = 0xA,
+ JTAG_DATA_REGISTER = 0xB,
+} JTAG_Register;
-/* Sanity check to give error if jtag is not opened at all. */
-static void
-check_and_raise_error_if_jtag_closed (void)
+#ifdef STATE_MACHINE_DEBUG
+typedef enum
+{
+ UNDEFINED,
+ TEST_LOGIC_RESET,
+ RUN_TEST_IDLE,
+ SELECT_DR_SCAN,
+ CAPTURE_DR,
+ SHIFT_DR,
+ EXIT1_DR,
+ PAUSE_DR,
+ EXIT2_DR,
+ UPDATE_DR,
+ SELECT_IR_SCAN,
+ CAPTURE_IR,
+ SHIFT_IR,
+ EXIT1_IR,
+ PAUSE_IR,
+ EXIT2_IR,
+ UPDATE_IR,
+ NUMBER_OF_STATES /* An end-marker, not a state. */
+} JTAG_ControllerState;
+#endif
+
+
+/* -------------------------------------------------------------------------- */
+/* local data */
+/* -------------------------------------------------------------------------- */
+
+/* -------------------------------------- */
+/* For ARC JTAG Cable */
+/* */
+/* Pin no. Signal Port Bit */
+/* */
+/* - TRST */
+/* 8 TMS Data 6 */
+/* 1 TCK Control 0 */
+/* 9 TDI Data 7 */
+/* 13 TDO Status 4 */
+/* -------------------------------------- */
+
+/* Bit masks for signals written to parallel ports. */
+
+#define JTAG_TRST 0 /* not there */
+#define JTAG_TMS (1 << 6) /* on Data port */
+#define JTAG_TCK (1 << 0) /* on Control port (driven low) */
+#define JTAG_TDI (1 << 7) /* on Data port */
+#define JTAG_TDO (1 << 4) /* on Status port */
+
+
+/* Commands which can be written to the JTAG Transaction Command Register. */
+#define WRITE_MEMORY_LOCATION 0x0
+#define WRITE_CORE_REGISTER 0x1
+#define WRITE_AUX_REGISTER 0x2
+#define NOP 0x3
+#define READ_MEMORY_LOCATION 0x4
+#define READ_CORE_REGISTER 0x5
+#define READ_AUX_REGISTER 0x6
+
+
+/* Gives the endianness of the target processor. */
+static Boolean target_is_big_endian;
+
+/* These accumulate the bit masks to be written to the data and control ports. */
+static Byte data_port_value, control_port_value;
+
+/* Variables for tracking the contents of the JTAG Address and Transaction
+ Command registers. */
+static JTAG_RegisterContents address_register_contents;
+static JTAG_RegisterContents command_register_contents;
+static Boolean address_register_contents_known;
+static Boolean command_register_contents_known;
+
+
+#ifdef STATE_MACHINE_DEBUG
+/* This table encodes all possible transitions of the JTAG Test Access Port
+ (TAP) Controller State Machine: for each state, the transition to one of two
+ possible next states is determined by whether a 0 bit or a 1 bit is written
+ as the JTAG TMS interface signal. */
+static const JTAG_ControllerState transitions[NUMBER_OF_STATES][2] =
{
- if( arc_jtag_ops.jtag_status == JTAG_CLOSED )
- error ("JTAG connection is closed. Use target arcjtag first\n");
+/* 0 1 */
+/* UNDEFINED */ { UNDEFINED, UNDEFINED },
+/* TEST_LOGIC_RESET */ { RUN_TEST_IDLE, TEST_LOGIC_RESET },
+/* RUN_TEST_IDLE */ { RUN_TEST_IDLE, SELECT_DR_SCAN },
+/* SELECT_DR_SCAN */ { CAPTURE_DR, SELECT_IR_SCAN },
+/* CAPTURE_DR */ { SHIFT_DR, EXIT1_DR },
+/* SHIFT_DR */ { SHIFT_DR, EXIT1_DR },
+/* EXIT1_DR */ { PAUSE_DR, UPDATE_DR },
+/* PAUSE_DR */ { PAUSE_DR, EXIT2_DR },
+/* EXIT2_DR */ { SHIFT_DR, UPDATE_DR },
+/* UPDATE_DR */ { RUN_TEST_IDLE, SELECT_DR_SCAN },
+/* SELECT_IR_SCAN */ { CAPTURE_IR, TEST_LOGIC_RESET },
+/* CAPTURE_IR */ { SHIFT_IR, EXIT1_IR },
+/* SHIFT_IR */ { SHIFT_IR, EXIT1_IR },
+/* EXIT1_IR */ { PAUSE_IR, UPDATE_IR },
+/* PAUSE_IR */ { PAUSE_IR, EXIT2_IR },
+/* EXIT2_IR */ { SHIFT_IR, UPDATE_IR },
+/* UPDATE_IR */ { RUN_TEST_IDLE, SELECT_DR_SCAN },
+};
+
+/* The current state of the TAP Controller State Machine. */
+static JTAG_ControllerState current_state = UNDEFINED;
+#endif
+
+
+/* -------------------------------------------------------------------------- */
+/* externally visible data */
+/* -------------------------------------------------------------------------- */
+
+/* This structure holds the operations and data exported by this module. */
+JTAG_Operations arc_jtag_ops;
+
+
+/* -------------------------------------------------------------------------- */
+/* local macros */
+/* -------------------------------------------------------------------------- */
+
+#ifdef DEBUG
+#undef DEBUG
+#endif
+
+#define DEBUG(...) \
+ if (arc_jtag_ops.state_machine_debug) fprintf_unfiltered(gdb_stdlog, __VA_ARGS__)
+
+
+#ifdef STATE_MACHINE_DEBUG
+#define SET_STATE(s) set_state(s)
+#define NEXT_STATE(b) next_state(b)
+#define CHANGE_STATE(x, s) change_state(x, s)
+#define STATE_IS(s) gdb_assert(current_state == s)
+#define STATE_IS_EITHER(s1, s2) gdb_assert(current_state == s1 || \
+ current_state == s2)
+#define STATE_IS_ONE_OF(s1, s2, s3) gdb_assert(current_state == s1 || \
+ current_state == s2 || \
+ current_state == s3)
+#else
+#define SET_STATE(s)
+#define NEXT_STATE(b)
+#define CHANGE_STATE(x, s) tapc_TMS(x)
+#define STATE_IS(s)
+#define STATE_IS_EITHER(s1, s2)
+#define STATE_IS_ONE_OF(s1, s2, s3)
+#endif
+
+
+#define IS_WORD_ALIGNED(addr) ((addr) % BYTES_IN_WORD == 0)
+#define BYTE(val) (Byte) ((val) & 0xFF)
+
+/* This is more efficient than memcpy(to, from, BYTES_IN_WORD). */
+#define COPY_WORD(to, from) { ((Byte*) to)[0] = ((Byte*) from)[0]; \
+ ((Byte*) to)[1] = ((Byte*) from)[1]; \
+ ((Byte*) to)[2] = ((Byte*) from)[2]; \
+ ((Byte*) to)[3] = ((Byte*) from)[3]; }
+
+
+/* -------------------------------------------------------------------------- */
+/* forward declarations */
+/* -------------------------------------------------------------------------- */
+
+static void tapc_TMS (Bit x);
+static void set_interface (JTAG_Status status);
+static void interface_is_closed (void);
+static JTAG_RegisterContents read_jtag_reg (JTAG_Register regnum,
+ unsigned int num_data_bits);
+
+
+/* -------------------------------------------------------------------------- */
+/* local functions */
+/* -------------------------------------------------------------------------- */
+
+/* -------------------------------------------------------------------------- */
+/* 1) debug functions */
+/* -------------------------------------------------------------------------- */
+
+/* Debug function. */
+
+static const char*
+JTAG_register_name (JTAG_Register r)
+{
+ switch (r)
+ {
+ case JTAG_STATUS_REGISTER : return "Status";
+ case JTAG_TRANSACTION_COMMAND_REGISTER : return "Transaction Command";
+ case JTAG_ADDRESS_REGISTER : return "Address";
+ case JTAG_DATA_REGISTER : return "Data";
+ default: internal_error(__FILE__, __LINE__, _("invalid JTAG register %d"), r);
+ }
}
-/* Initializations for GPIO interface */
-static int
-gpio_setup (void)
+/* Debug function. */
+
+static const char*
+JTAG_TransactionStatus_Image (JTAG_TransactionStatus value)
{
- fd=open("//dev//gpio",O_RDWR);
- ioctl(fd,GPIO_IOC_HARDRESET);
- ioctl(fd,GPIO_IOC_SET_PORT_BASE,0x378);
- jtag_ioctl.inlen=0;
- jtag_ioctl.outlen=0;
- jtag_ioctl.inbuf=(unsigned char *)xmalloc(2*sizeof(unsigned char));
- jtag_ioctl.outbuf=(unsigned char *)xmalloc(2*sizeof(unsigned char));
- return 0;
+ switch (value)
+ {
+ case STALLED : return "STALLED";
+ case FAILURE : return "FAILURE";
+ case READY : return "READY";
+ case NOT_READY: return "NOT READY";
+ default: internal_error(__FILE__, __LINE__, _("invalid JTAG transaction status %d"), value);
+ }
}
-void gpio_write(unsigned int port, unsigned char *data)
+
+#ifdef STATE_MACHINE_DEBUG
+/* Debug function. */
+
+static const char*
+JTAG_ControllerState_Image (JTAG_ControllerState state)
{
- jtag_ioctl.inlen=2;
- jtag_ioctl.inbuf[1]=*data;
- switch(port)
+ switch (state)
{
- case DATA_PORT:
- jtag_ioctl.inbuf[0]=0;
- break;
-
- case STATUS_PORT:
- jtag_ioctl.inbuf[0]=1;
- break;
-
- case CONTROL_PORT:
- jtag_ioctl.inbuf[0]=2;
- break;
-
- default:
- error("Invalid port\n");
+ case UNDEFINED : return "<undefined> ";
+ case TEST_LOGIC_RESET: return "Test-Logic-Reset";
+ case RUN_TEST_IDLE : return "Run-Test/Idle ";
+ case SELECT_DR_SCAN : return "Select-DR-Scan ";
+ case CAPTURE_DR : return "Capture-DR ";
+ case SHIFT_DR : return "Shift-DR ";
+ case EXIT1_DR : return "Exit1-DR ";
+ case PAUSE_DR : return "Pause-DR ";
+ case EXIT2_DR : return "Exit2-DR ";
+ case UPDATE_DR : return "Update-DR ";
+ case SELECT_IR_SCAN : return "Select-IR-Scan ";
+ case CAPTURE_IR : return "Capture-IR ";
+ case SHIFT_IR : return "Shift-IR ";
+ case EXIT1_IR : return "Exit1-IR ";
+ case PAUSE_IR : return "Pause-IR ";
+ case EXIT2_IR : return "Exit2-IR ";
+ case UPDATE_IR : return "Update-IR ";
+ default : return "<invalid> ";
}
+}
+#endif
-
- if(ioctl(fd,GPIO_IOC_DO_IO,&jtag_ioctl))
- error("Failure writing to port 0x%x\n",port);
+#ifdef CHECK_JTAG_DATA_REGISTER
+/* Read back the contents of the JTAG Data Register, and check that the value
+ is what is expected, i.e. the last value that was written to that register. */
+
+static void
+check_Data_Register (ARC_Word expected)
+{
+ /* Read the data from the JTAG Data Register. */
+ ARC_Word actual = (ARC_Word) read_jtag_reg(JTAG_DATA_REGISTER, BITS_IN_WORD);
+
+ /* Is the data still in the register? */
+ if (actual != expected)
+ warning(_("JTAG Data Register: expected = %08X, actual = %08X\n"), expected, actual);
+ else
+ printf_unfiltered(_("word %08X is still in JTAG Data Register\n"), expected);
}
+#endif
-unsigned char gpio_read(unsigned int port)
-{
- //jtag_ioctl.inbuf[1]=tapc_statusport;
- jtag_ioctl.inlen=2;
- jtag_ioctl.outlen=1;
+/* -------------------------------------------------------------------------- */
+/* 2) helper functions for setting TMS / TCK / TDI */
+/* -------------------------------------------------------------------------- */
- switch(port)
- {
- case DATA_PORT:
- jtag_ioctl.inbuf[0]=0x80;
- break;
-
- case STATUS_PORT:
- jtag_ioctl.inbuf[0]=0x81;
- break;
-
- case CONTROL_PORT:
- jtag_ioctl.inbuf[0]=0x82;
- break;
-
- default:
- error("Invalid port\n");
- }
-
- if(ioctl(fd,GPIO_IOC_DO_IO,&jtag_ioctl))
- error("Failure reading from port 0x%x\n",port);
-
- return jtag_ioctl.outbuf[0];
+/* These functions set the accumulated values to be written out to the ports.
+ The final values are written only by doing the pulse, e.g. if TDI and TMS
+ are set/unset by subsequent calls, the last GPIO write operation performed
+ by those calls before the pulse writes the accumulated bit mask value to
+ the port (overwriting the values written by the preceding calls), and it
+ is this bit mask that is significant when the JTAG is clocked. */
+static void
+tapc_set_TMS (Bit x)
+{
+ Byte current_value = data_port_value;
+
+ if (x)
+ data_port_value |= JTAG_TMS;
+ else
+ data_port_value &= ~JTAG_TMS;
+ if (data_port_value != current_value)
+ gpio_write(DATA_PORT, data_port_value);
}
-/* Helper functions for setting
- TMS / TCK / TDI. Valid inputs
- are 1 and 0. The tapc_<tms/tck/tdi>
- functions set the internal values
- to be written out to the port. The
- final values are written only by doing
- the pulse.
- */
static void
-tapc_set_tms (char x)
+tapc_set_TDI (Bit x)
{
- if(x)
- tapc_dataport |= JTAG_TMS;
+ Byte current_value = data_port_value;
+
+ if (x)
+ data_port_value |= JTAG_TDI;
else
- tapc_dataport &= ~JTAG_TMS;
+ data_port_value &= ~JTAG_TDI;
- /* outb(tapc_dataport, DATA_PORT); */
- gpio_write(DATA_PORT,&tapc_dataport);
+ if (data_port_value != current_value)
+ gpio_write(DATA_PORT, data_port_value);
}
-/* Set TCK. */
static void
-tapc_set_tck (char x)
+tapc_set_TCK (Bit x)
{
- /* active low. The clock is active low. */
- if(!x)
- tapc_controlport |= JTAG_TCK;
+ /* The clock is active low. */
+ if (x)
+ control_port_value &= ~JTAG_TCK;
else
- tapc_controlport &= ~JTAG_TCK;
-
- if(rw_flag == READ_FROM_AA3)
- tapc_controlport |= 0x4;
- else
- tapc_controlport &= ~(0x4);
-
- /* outb(tapc_controlport, CONTROL_PORT); */
- gpio_write(CONTROL_PORT,&tapc_controlport);
+ control_port_value |= JTAG_TCK;
+
+ gpio_write(CONTROL_PORT, control_port_value);
}
+/* -------------------------------------------------------------------------- */
+/* 3) JTAG state machine handlers */
+/* -------------------------------------------------------------------------- */
+
+#ifdef STATE_MACHINE_DEBUG
+/* Debug function. Perform a state change to the given state. */
+
static void
-tapc_set_tdi (char x)
+set_state (JTAG_ControllerState new_state)
{
- if(x)
- tapc_dataport |= JTAG_TDI;
- else
- tapc_dataport &= ~JTAG_TDI;
-
- /* outb(tapc_dataport, DATA_PORT); */
- gpio_write(DATA_PORT,&tapc_dataport);
+ DEBUG("TAPC state: %s ====> %s\n",
+ JTAG_ControllerState_Image(current_state),
+ JTAG_ControllerState_Image(new_state));
+
+ current_state = new_state;
+
+ gdb_assert(current_state != UNDEFINED);
+}
+
+
+/* Debug function. Perform a state change from the current state according to
+ the transition specified by the given bit. */
+
+static void
+next_state (Bit x)
+{
+ current_state = (transitions[current_state][x]);
}
-/* Unused function clockdelay. Why not add a command
- that allows the user to set the clock delay ? */
+
+/* Debug function. Perform a state change from the current state according to
+ the transition specified by the given bit, and check that the new state is
+ as expected. */
static void
-clockdelay (void)
+change_state (Bit x, JTAG_ControllerState new_state)
{
- int i;
- //for (i=0; i<10; ++i)
-
- // usleep(0);
+ tapc_TMS(x);
+
+ gdb_assert(current_state == new_state);
}
+#endif /* STATE_MACHINE_DEBUG */
+
+
+/* Clock the JTAG on the ARC platform. */
-/* Clock the JTAG on the ARC platform. */
static void
tapc_pulse (void)
{
- /* Control 0 bit is active low */
- unsigned char temp;
- assert( (tapc_controlport & JTAG_TCK) ); // clock should be zero on entry
-
- /* outb(tapc_controlport & ~JTAG_TCK, CONTROL_PORT); */
- temp = tapc_controlport & ~JTAG_TCK;
- gpio_write(CONTROL_PORT,&temp);
- /* outb(tapc_controlport, CONTROL_PORT); */
- gpio_write(CONTROL_PORT,&tapc_controlport);
-
+ /* TCK control bit is active low. */
+ gdb_assert((control_port_value & JTAG_TCK) != (Byte) 0); /* Clock should be zero on entry. */
+
+ gpio_write(CONTROL_PORT, control_port_value & ~JTAG_TCK);
+ gpio_write(CONTROL_PORT, control_port_value);
}
-/* All the JTAG state machine handlers. */
-/* Reset the TAPC controller on the JTAG.
- */
+/* Reset the TAP Controller on the JTAG. */
+
static void
tapc_reset (void)
{
- /* from any state, these many ones should get us into "test-logic reset"
- */
- tapc_set_tms(1);
- tapc_set_tck(0); /* want rising edge */
+ ENTERMSG;
+
+ /* The Test Clock signal is active low (i.e. the signal is active when the
+ corresponding bit written to the control bit is 0; so initialize the bit
+ in the control port value to 1 so that the signal is initially not active. */
+ control_port_value = (Byte) JTAG_TCK;
+ data_port_value = (Byte) 0;
+
+ /* From any state, this many TCK pulses should get the controller into state
+ Test-Logic-Reset. */
+ tapc_set_TMS(1);
+ tapc_set_TCK(0); /* We want the rising edge. */
tapc_pulse();
tapc_pulse();
tapc_pulse();
tapc_pulse();
tapc_pulse();
tapc_pulse();
+
+ SET_STATE(TEST_LOGIC_RESET);
+
+ DEBUG("TAPC has been reset\n");
+
+ /* The reset has re-initialized all the JTAG registers. */
+ address_register_contents_known = FALSE;
+ command_register_contents_known = FALSE;
+
+ CHANGE_STATE(0, RUN_TEST_IDLE);
+
+ LEAVEMSG;
}
-/* Set the tms to the value of the bit and
- clock the jtag. */
+
+/* Set the TMS to the value of the bit and clock the JTAG.
+ This will cause the TAP Controller State Machine to move to another state. */
static void
-tapc_tms (char x)
+tapc_TMS (Bit x)
{
- tapc_set_tms(x);
+ tapc_set_TMS(x);
tapc_pulse();
+ NEXT_STATE(x);
}
-/* Read bit from the TDO of the JTAG. */
-static char
-tapc_readbit (void)
+
+/* Read a bit from the TDO of the JTAG. */
+
+static Bit
+tapc_readTDO (void)
{
- if(gpio_read(STATUS_PORT) & JTAG_TDO)
- return 1;
- else
- return 0;
+ Byte byte = gpio_read(STATUS_PORT);
+
+ /* Read from the status port. */
+ return ((byte & JTAG_TDO) != (Byte) 0) ? (Bit) 1 : (Bit) 0;
}
-/* Interface functions that use the below mentioned
- JTAG state machine handler functions.
-*/
+/* -------------------------------------------------------------------------- */
+/* 4) interface functions that use the JTAG state machine handler functions */
+/* -------------------------------------------------------------------------- */
-/* Shift one bit out on the JTAG TDI. */
-static char
-tapc_shiftbit (char x)
-{
- char read;
+/* Shift one bit out on the JTAG TDO and one bit in on the JTAG TDI. */
- //printf("tapc_shiftbit: Shifted %d\n", x);
+static Bit
+tapc_shift_bit (Bit out)
+{
+ Bit in = tapc_readTDO();
- read = tapc_readbit();
- tapc_set_tdi(x);
+ tapc_set_TDI(out);
tapc_pulse();
- return read;
+// DEBUG("%u (out) >>> %u (in)\n", out, in);
+
+ return in;
}
-/*
- * Shift N bits from to_write into TDI, and out from TDO into read.
- *
- * If msb_first=0, shift LSB first, starting from to_write[0], to_write[1],
- * etc.
-
- * If msb_first=1, shift to_write[-1] MSB first, then to_write[-2] etc.
- *
- * Must be called in Shift DR/IR state.
- * Leaves in Exit1 DR/IR state.
- */
+/* Shift N bits from to_write into TDI, and out from TDO into to_read.
+
+ If order == MSB_LAST, shift LSB first, starting from to_write[0], to_write[1],
+ etc.
+
+ If order == MSB_FIRST, shift to_write[N-1] MSB first, then to_write[N-2] etc.
+
+ Must be called in Shift DR/IR state.
+ Leaves in Exit1-DR/IR state. */
+
static void
-tapc_shiftnbits (int n,
- unsigned char *to_write,
- unsigned char *read,
- char msb_first)
+tapc_shift_N_bits (unsigned int n,
+ Byte *to_write,
+ Byte *to_read,
+ Order order)
{
- unsigned char outbyte, inbyte;
- int nbytes = (n-1)/8 + 1,limit=8;
- int i, j;
+ unsigned int nbytes = (n - 1) / BITS_IN_BYTE + 1;
+ unsigned int nbits = BITS_IN_BYTE;
+ unsigned int i, j;
+
+ ENTERARGS("shift %u bits", n);
- for(i=0; i < nbytes; ++i)
+ STATE_IS_EITHER(SHIFT_DR, SHIFT_IR);
+
+ for (i = 0; i < nbytes; i++)
{
- if(msb_first)
- outbyte = to_write[-1-i];
- else
- outbyte = to_write[i];
-
- inbyte = 0;
- /* should write a maximum of 8 bits */
- if(i == nbytes-1)
- limit = ((n-1) % 8) + 1;
-
- for(j = 0; j < limit; ++j)
- {
- unsigned char outbit, inbit;
-
- if(msb_first)
- outbit = !!(outbyte & 0x80);
- else
- outbit = outbyte & 1;
- /* the last bit of the last byte */
- /* transition to EXIT-1 state before last bit */
- if((i == nbytes-1)&&(j == limit-1))
- tapc_set_tms(1);
-
- inbit = tapc_shiftbit(outbit);
-
- if(msb_first)
- {
- inbyte |= (inbit << (7-j));
- outbyte <<= 1;
- }
- else
- {
- inbyte |= inbit << j;
- outbyte >>= 1;
- }
- }
-
- //tapc_tms(1);
- if(msb_first)
- read[-1-i] = inbyte;
- else
- read[i] = inbyte;
+ Boolean is_last_byte = (i == nbytes - 1);
+ Byte inbyte = (Byte) 0;
+ Byte outbyte;
+
+ if (order == MSB_FIRST)
+ outbyte = to_write[nbytes - 1 - i];
+ else
+ outbyte = to_write[i];
+
+ if (is_last_byte)
+ {
+ /* How many significant bits are in this byte? */
+ nbits = ((n - 1) % BITS_IN_BYTE) + 1;
+ }
+
+ /* gdb_assert (nbits <= BITS_IN_BYTE); */
+
+ for (j = 0; j < nbits; j++)
+ {
+ Bit outbit, inbit;
+
+// DEBUG("byte %u, bit %u\n", i, j);
+
+ /* Get the next bit to be output from the current byte. */
+ if (order == MSB_FIRST)
+ {
+ /* Get MSB from byte. */
+ outbit = (Bit) ((outbyte >> BITS_IN_BYTE) & 1);
+ outbyte <<= 1;
+ }
+ else
+ {
+ /* Get LSB from byte. */
+ outbit = (Bit) (outbyte & 1);
+ outbyte >>= 1;
+ }
+
+ /* The last bit of the last byte. */
+ if (is_last_byte && (j == nbits - 1))
+ {
+ /* Change to Exit1-DR/IR state before the last bit is shifted:
+ this is necessary because the TAP Controller performs the
+ last sample of TDI when exiting the Shift-DR/IR state. */
+ tapc_set_TMS(1);
+ NEXT_STATE(1);
+ }
+
+ /* Shift one bit in from the JTAG TDO and one bit out to the JTAG TDI. */
+ inbit = tapc_shift_bit(outbit);
+
+ /* Add the bit read into the input byte.
+ N.B. the shift amount will always be positive, as 0 <= j < BITS_IN_BYTE */
+ if (order == MSB_FIRST)
+ inbyte |= (Byte) (inbit << (BITS_IN_BYTE - 1 - j));
+ else
+ inbyte |= (Byte) (inbit << j);
+ }
+
+ if (order == MSB_FIRST)
+ to_read[nbytes - 1 - i] = inbyte;
+ else
+ to_read[i] = inbyte;
}
-}
+ STATE_IS_EITHER(EXIT1_DR, EXIT1_IR);
-/* Read the JTAG status register. This indicates
- the status of the JTAG for the user.
-*/
-static unsigned int
-read_jtag_status_reg (void)
-{
- unsigned int wr, rd;
- int x;
- //rw_flag=0;
- //tapc_tms(0); // runtest/idle
- tapc_tms(1); // select dr
- tapc_tms(1); // select ir
- tapc_tms(0); // capture ir
- tapc_tms(0); // shift ir
-
- wr = 0x8; // IR = status register
-
- tapc_shiftnbits(4, (unsigned char *)&wr, (unsigned char*)&rd, 0);
-
-
-
- // goto shift DR
- tapc_tms(1); // update ir
- //tapc_tms(0); // runtest/idle
- tapc_tms(1); // select dr
- tapc_tms(0); // capture dr
- tapc_tms(0); // shift dr
-
- rd = 0;
-
- // read 1 bit, if it is zero then keep reading
- rd = tapc_shiftbit(0);
- if (rd)
- return rd;
-
- rd |= tapc_shiftbit(0) << 1;
- if (rd)
- return rd;
-
- rd |= tapc_shiftbit(0) << 2;
-
- /* the last bit is optional */
- /*rd |= tapc_shiftbit(0) << 3;*/
-
- return rd;
+ LEAVEMSG;
}
-/* Interpret the status message. */
-static void
-print_jtag_status_reg_val (unsigned int status)
+/* Read the JTAG Status Register.
+ This indicates the status of the JTAG transaction that has been attempted. */
+
+static JTAG_TransactionStatus
+read_jtag_status_register( void)
{
- int i ;
- char * messages [] = { "Stalled" , "Failure", "Ready", "PC Selected" };
- for(i=0;i<=3;i++)
- {
- printf_filtered("%s %s \t",(status & 1)?"":"Not",messages[i]);
- status = status >> 1;
- }
- printf_filtered("\n");
+ JTAG_RegisterContents rd, wr;
+ Bit bit;
+
+ ENTERMSG;
+
+ STATE_IS_EITHER(RUN_TEST_IDLE, UPDATE_DR);
+
+ CHANGE_STATE(1, SELECT_DR_SCAN);
+ CHANGE_STATE(1, SELECT_IR_SCAN);
+ CHANGE_STATE(0, CAPTURE_IR);
+ CHANGE_STATE(0, SHIFT_IR);
+
+ wr = JTAG_STATUS_REGISTER;
+
+ tapc_shift_N_bits(BITS_IN_REGISTER_CODE, (Byte*) &wr, (Byte*) &rd, MSB_LAST);
+
+ CHANGE_STATE(1, UPDATE_IR);
+// CHANGE_STATE(0, RUN_TEST_IDLE);
+ CHANGE_STATE(1, SELECT_DR_SCAN);
+ CHANGE_STATE(0, CAPTURE_DR);
+ CHANGE_STATE(0, SHIFT_DR);
+
+ /* The JTAG Status Register is read-only, and any bits shifted in are
+ ignored - hence the parameter to tapc_shift_bit is irrelevant here. */
+
+ /* Read Stalled bit; if it is zero then keep reading. */
+ bit = tapc_shift_bit(0);
+ if (bit)
+ return STALLED;
+
+ /* Read Failed bit; if it is zero then keep reading. */
+ bit = tapc_shift_bit(0);
+ if (bit)
+ return FAILURE;
+
+ /* Read Ready bit. */
+ bit = tapc_shift_bit(0);
+ if (bit)
+ return READY;
+
+ /* The last bit (PC_SEL) is optional. */
+
+ return NOT_READY;
}
+/* Write a value to a JTAG register.
+ enter in Update-DR/IR state or Run-Test/Idle.
+ exit in Update-DR */
-/* Write a JTAG Command to a JTAG register.
- enter in update dr/ir state
- or Test-Logic-Reset.
- exit in update dr
-*/
static void
-write_jtag_reg (char regnum, unsigned int data, int ndatabits)
+write_jtag_reg (JTAG_Register regnum,
+ JTAG_RegisterContents data,
+ unsigned int num_data_bits)
{
- unsigned int wr=0,rd=0;
- rw_flag = WRITE_TO_AA3 ;
- // tapc_tms(0); // runtest/idle
- tapc_tms(1); // select dr
- tapc_tms(1); // select ir
- tapc_tms(0); // capture ir
- tapc_tms(0); // shift ir
-
-
- tapc_shiftnbits(4, (unsigned char *)&regnum, (unsigned char *)&rd, 0);
-
-
- tapc_tms(1); // update ir
-
- tapc_tms(1); // select dr
- tapc_tms(0); // capture dr
- tapc_tms(0); // shift dr
-
- tapc_shiftnbits(ndatabits, (unsigned char *)&data,
- (unsigned char *)&rd, 0);
- tapc_tms(1); // update dr
+ Byte num = (Byte) regnum;
+ JTAG_RegisterContents rd = 0;
+
+ ENTERARGS("regnum %d <== 0x%08X (:%d)", regnum, data, num_data_bits);
+
+ STATE_IS_ONE_OF(UPDATE_DR, UPDATE_IR, RUN_TEST_IDLE);
+
+// CHANGE_STATE(0, RUN_TEST_IDLE);
+ CHANGE_STATE(1, SELECT_DR_SCAN);
+ CHANGE_STATE(1, SELECT_IR_SCAN);
+ CHANGE_STATE(0, CAPTURE_IR);
+ CHANGE_STATE(0, SHIFT_IR);
+
+ tapc_shift_N_bits(BITS_IN_REGISTER_CODE, &num, (Byte*) &rd, MSB_LAST);
+
+ CHANGE_STATE(1, UPDATE_IR);
+ CHANGE_STATE(1, SELECT_DR_SCAN);
+ CHANGE_STATE(0, CAPTURE_DR);
+ CHANGE_STATE(0, SHIFT_DR);
+
+ tapc_shift_N_bits(num_data_bits, (Byte*) &data, (Byte*) &rd, MSB_LAST);
+
+ CHANGE_STATE(1, UPDATE_DR);
+
+ DEBUG("written 0x%08X to JTAG %s register\n", data, JTAG_register_name(regnum));
+
+ LEAVEMSG;
}
-
-// enter in update dr/ir state
-// exit in update dr
-static unsigned int
-read_jtag_reg (char regnum, int ndatabits)
+
+/* Read a value from a JTAG register.
+ enter in Update-DR/IR state
+ exit in Update-DR */
+
+static JTAG_RegisterContents
+read_jtag_reg (JTAG_Register regnum, unsigned int num_data_bits)
{
- unsigned int wr=0x0,rd=0;
- rw_flag = READ_FROM_AA3;
- // tapc_tms(0); // runtest/idle
- tapc_tms(1); // select dr
- tapc_tms(1); // select ir
- tapc_tms(0); // capture ir
- tapc_tms(0); // shift ir
-
- tapc_shiftnbits(4, (unsigned char *)&regnum, (unsigned char *)&rd, 0);
- tapc_tms(1); // update ir
-
- /* JTAG registers can be read without going to run-test/idle state.
-
- Doing tapc_tms(0) will take us to run-test/idle state.
- This will make JTAG perform the transaction as per TCR.
- We dont want this.
- */
- // tapc_tms(0); // runtest/idle
- tapc_tms(1); // select dr
- tapc_tms(0); // capture dr
- tapc_tms(0); // shift dr
-
- tapc_shiftnbits(ndatabits, (unsigned char *)&wr, (unsigned char *)&rd, 0);
- tapc_tms(1); // update dr
+ Byte num = (Byte) regnum;
+ JTAG_RegisterContents wr = 0, rd = 0;
+
+ ENTERARGS("regnum %u, %u bits", regnum, num_data_bits);
+
+ STATE_IS_EITHER(UPDATE_DR, UPDATE_IR);
+
+// CHANGE_STATE(0, RUN_TEST_IDLE);
+ CHANGE_STATE(1, SELECT_DR_SCAN);
+ CHANGE_STATE(1, SELECT_IR_SCAN);
+ CHANGE_STATE(0, CAPTURE_IR);
+ CHANGE_STATE(0, SHIFT_IR);
+
+ tapc_shift_N_bits(BITS_IN_REGISTER_CODE, &num, (Byte*) &rd, MSB_LAST);
+
+ CHANGE_STATE(1, UPDATE_IR);
+
+ /* JTAG registers can be read without going to Run-Test/Idle state.
+
+ Doing CHANGE_STATE(0) would take us to Run-Test/Idle state. This would
+ make JTAG perform the transaction in the Transaction Command Register.
+ We don't want that! */
+// CHANGE_STATE(0, RUN_TEST_IDLE);
+ CHANGE_STATE(1, SELECT_DR_SCAN);
+ CHANGE_STATE(0, CAPTURE_DR);
+ CHANGE_STATE(0, SHIFT_DR);
+
+ tapc_shift_N_bits(num_data_bits, (Byte*) &wr, (Byte*) &rd, MSB_LAST);
+ CHANGE_STATE(1, UPDATE_DR);
+
+ DEBUG("read 0x%08X from JTAG %s register\n", rd, JTAG_register_name(regnum));
return rd;
}
+/* -------------------------------------------------------------------------- */
+/* 5) JTAG transaction functions */
+/* -------------------------------------------------------------------------- */
-
-
-
+/* Start a JTAG transaction.
+ Parameters:
+ command: the JTAG command to be performed
+ address: the address (memory address or register number) for the command
+*/
-static int
-arc_jtag_read_core_reg (unsigned int regnum, unsigned int *readbuf)
+static void
+start_jtag_transaction (JTAG_RegisterContents command,
+ JTAG_RegisterContents address)
{
- unsigned int rd, wr, data, i;
- check_and_raise_error_if_jtag_closed();
- tapc_reset();
- tapc_tms(0);//run-test idle
- write_jtag_reg(0xA, regnum, 32);//update dr
+ ENTERARGS("command = %d, address = 0x%x", command, address);
-
+ STATE_IS_ONE_OF(UPDATE_DR, UPDATE_IR, RUN_TEST_IDLE);
- // Setup instruction register to 0x9 indicating
- // a JTAG instruction is being downloaded.
- // jtag transaction command reg = 0x5 (read core reg)
- write_jtag_reg(0x9, 0x5, 4);//update dr
+ /* N.B. do NOT reset the TAP Controller at the start of each transaction, as
+ that would re-initialize the JTAG registers to their default values
+ (whatever those might be), so invalidating the optimisation of the
+ use of the Address and Transaction Command registers performed by
+ this module. */
- /* Perform the transaction.
- */
- tapc_tms(0); // run-test idle
-
- // poll the status
+ if (command == READ_MEMORY_LOCATION || command == WRITE_MEMORY_LOCATION)
+ {
+ gdb_assert(IS_WORD_ALIGNED(address));
+ }
- for (i=0;i<arcjtag_retry_count;i++)
+ /* Load the command that is required into the JTAG Transaction Command
+ Register, and the address into the JTAG Address Register; by keeping
+ track of the values that these registers contain, we can avoid re-loading
+ them unnecessarily, which can save time when transferring a stream of data. */
+
+ if (!command_register_contents_known ||
+ (command_register_contents != command))
{
- unsigned int status = read_jtag_status_reg();
- //if( !(status & 1) && (status & 4) )
- if(status == 4)
- break;
- if(status == 2)
- return JTAG_READ_FAILURE;
- tapc_tms(1);//exit1-dr
- tapc_tms(1);//update-dr
- /* Do not redo the transaction. Pause and re-try.
- */
- //tapc_tms(0);//run-test-idle
+ write_jtag_reg(JTAG_TRANSACTION_COMMAND_REGISTER, command, BITS_IN_COMMAND_CODE);
+
+ command_register_contents_known = TRUE;
+ command_register_contents = command;
}
- if (i==arcjtag_retry_count)
- return JTAG_READ_FAILURE;
-
- /* JTAG status register leaves us in Shift DR */
- tapc_tms(1); /* Move to Exit-1 DR */
- tapc_tms(1); /* Move to Update DR */
-
- // data = jtag data reg
- data = read_jtag_reg(0xB, 32);
-
- *readbuf = data;
-
- return sizeof(data);
+
+ if (!address_register_contents_known ||
+ (address_register_contents != address))
+ {
+ write_jtag_reg(JTAG_ADDRESS_REGISTER, address, BITS_IN_WORD);
+
+ address_register_contents_known = TRUE;
+ address_register_contents = address;
+ }
+
+ LEAVEMSG;
}
-static int
-arc_jtag_write_core_reg (unsigned int regnum, unsigned int data)
-{
- unsigned int rd, wr, i;
- check_and_raise_error_if_jtag_closed();
- tapc_reset();
- tapc_tms(0);//run-test idle
+/* Perform the given JTAG transaction (a mmeory or register operation).
+ If the transaction fails, this function returns the given error. */
- // data = jtag data reg
- write_jtag_reg(0xB, data, 32);//update dr
+static JTAG_OperationStatus
+perform_jtag_transaction (JTAG_TransactionType transaction,
+ JTAG_OperationStatus error)
+{
+ JTAG_OperationStatus result = error;
+ unsigned int tries = 0;
- // jtag addr register = regnum:
- write_jtag_reg(0xA, regnum, 32);//update dr
-
-
+ ENTERARGS("transaction: %u", transaction);
- // jtag transaction command reg = 0x1(write core reg)
- write_jtag_reg(0x9, 0x1, 4);//update dr
+ /* This causes the TAP Controller to perform the transaction, according to
+ the contents of the JTAG Transaction Command, Address and Data registers. */
+ CHANGE_STATE(0, RUN_TEST_IDLE);
- /* Perform the transaction.
- */
- tapc_tms(0); // run-test idle
-
- for (i=0;i<arcjtag_retry_count;i++)
+ /* Poll the JTAG Status Register. */
+ do
{
- unsigned int status = read_jtag_status_reg();
- if(status == 4)
- break;
- if(status == 2)
- return JTAG_WRITE_FAILURE;
- tapc_tms(1);//exit1-dr
- tapc_tms(1);//update-dr
- /* Do not redo the transaction. Pause and re-try.
- */
- //tapc_tms(0);//run-test-idle
+ JTAG_TransactionStatus status = read_jtag_status_register();
+
+ DEBUG("status: %s\n", JTAG_TransactionStatus_Image(status));
+
+ /* The read has left the TAP Controller FSM in state Shift-DR. */
+ STATE_IS(SHIFT_DR);
+
+ CHANGE_STATE(1, EXIT1_DR);
+ CHANGE_STATE(1, UPDATE_DR);
+
+ /* If the transaction is complete. */
+ if (status == READY)
+ {
+ /* The value in the JTAG Address Register is incremented by four
+ (a memory access) or one (a register access) when a read/write
+ transaction has completed. */
+ address_register_contents += (transaction == Memory) ? BYTES_IN_WORD : 1;
+
+ result = JTAG_SUCCESS;
+ break;
+ }
+
+ if (status == FAILURE)
+ break;
+
+ /* Pause and re-try. */
+ usleep(1);
}
- if (i==arcjtag_retry_count)
- return JTAG_READ_FAILURE;
-
- tapc_tms(1);//exit1-dr
- tapc_tms(1);//update-dr
- /* This should have been done earlier i.e. before
- reading the JTAG status register.
- */
- //tapc_tms(0);//rn-test-idle
- return sizeof(data);
+ while (++tries <= arc_jtag_ops.retry_count);
+
+ LEAVEMSG;
+ return result;
}
-static int
-arc_jtag_read_aux_reg (unsigned int regnum, unsigned int *readbuf)
-{
- unsigned int rd, wr, data, i;
- if(arc_jtag_ops.arc_jtag_state_machine_debug)
- printf_filtered("\nEntered arc_jtag_read_aux_reg()\
- \n Regnum:%d \n",regnum);
- check_and_raise_error_if_jtag_closed();
- check_and_raise_error_if_jtag_closed();
- tapc_reset();
- tapc_tms(0);//run-test idle
- write_jtag_reg(0xA, regnum, 32);//update dr
+/* -------------------------------------------------------------------------- */
+/* 6) read/write helper functions */
+/* -------------------------------------------------------------------------- */
+/* These functions aid in reading/writing registers/memory. */
- // Setup instruction register to 0x9 indicating
- // a JTAG instruction is being downloaded.
- // jtag transaction command reg = 0x6 (read aux reg)
- write_jtag_reg(0x9, 0x6, 4);//update dr
+/* Read a processor register (core or auxiliary). */
- /* Perform the transaction.
- */
- tapc_tms(0); // run-test idle
+static JTAG_OperationStatus
+read_processor_register (ARC_RegisterNumber regnum,
+ JTAG_RegisterContents command,
+ ARC_RegisterContents *contents)
+{
+ JTAG_OperationStatus status;
- // poll the status
+ /* Load the number of the register that is to be read into the JTAG Address
+ Register. */
+ start_jtag_transaction(command, regnum);
- for (i=0;i<arcjtag_retry_count;i++)
- {
- unsigned int status = read_jtag_status_reg();
-
- if(status == 4)
- break;
- if(status == 2)
- return JTAG_READ_FAILURE;
- tapc_tms(1);//exit1-dr
- tapc_tms(1);//update-dr
- /* Do not redo the transaction. Pause and re-try.
- */
- //tapc_tms(0);//run-test-idle
+ status = perform_jtag_transaction(Register, JTAG_READ_FAILURE);
+ if (status == JTAG_SUCCESS)
+ {
+ /* Read the register contents from the JTAG Data Register. */
+ *contents = (ARC_RegisterContents) read_jtag_reg(JTAG_DATA_REGISTER, BITS_IN_REGISTER);
}
- if (i==arcjtag_retry_count)
- return JTAG_READ_FAILURE;
-
-
-/* JTAG status register leaves us in Shift DR */
- tapc_tms(1); /* Move to Exit-1 IR */
- tapc_tms(1); /* Move to Update IR */
-
- // data = jtag data reg
- data = read_jtag_reg(0xB, 32);
- *readbuf = data;
- if(arc_jtag_ops.arc_jtag_state_machine_debug)
- printf(" Data: %d\n",data);
- return sizeof(data);
+
+ return status;
}
-static int
-arc_jtag_write_aux_reg (unsigned int regnum, unsigned int data)
+
+/* Write a processor register (core or auxiliary). */
+
+static JTAG_OperationStatus
+write_processor_register (ARC_RegisterNumber regnum,
+ JTAG_RegisterContents command,
+ ARC_RegisterContents contents)
{
- unsigned int rd, wr, i;
- if(arc_jtag_ops.arc_jtag_state_machine_debug)
- printf_filtered("\nEntered arc_jtag_write_aux_reg()\n Regnum:%d\nData:%d\n",regnum,data);
- check_and_raise_error_if_jtag_closed();
- tapc_reset();
- tapc_tms(0);//run-test idle
-
- // data = jtag data reg
- write_jtag_reg(0xB, data, 32);//update dr
+ /* Load the number of the register that is to be written into the JTAG
+ Address Register. */
+ start_jtag_transaction(command, regnum);
+
+ /* Load the new register contents into the JTAG Data Register. */
+ write_jtag_reg(JTAG_DATA_REGISTER, contents, BITS_IN_REGISTER);
- // jtag addr register = regnum:
- write_jtag_reg(0xA, regnum, 32);//update dr
-
-
+ return perform_jtag_transaction(Register, JTAG_WRITE_FAILURE);
+}
- // jtag transaction command reg = 0x2 (write aux reg)
- write_jtag_reg(0x9, 0x2, 4);//update dr
- /* Perform the transaction.
- */
- tapc_tms(0); // run-test idle
+/* Write a processor core register. */
- for (i=0;i<arcjtag_retry_count;i++)
- {
- unsigned int status = read_jtag_status_reg();
- if(status == 4)
- break;
- if(status == 2)
- return JTAG_WRITE_FAILURE;
- tapc_tms(1);//exit1-dr
- tapc_tms(1);//update-dr
- /* Do not redo the transaction. Pause and re-try.
- */
- //tapc_tms(0);//run-test-idle
- }
- if (i==arcjtag_retry_count)
- return JTAG_READ_FAILURE;
-
- tapc_tms(1);//exit1-dr
- tapc_tms(1);//update-dr
- /* This should have been done earlier i.e. before
- reading the JTAG status register.
- */
- //tapc_tms(0);//run-test-idle
- return sizeof(data);
+static JTAG_OperationStatus
+jtag_write_core_reg (ARC_RegisterNumber regnum, ARC_RegisterContents contents)
+{
+ ENTERARGS("regnum %d", regnum);
+
+ return write_processor_register(regnum, WRITE_CORE_REGISTER, contents);
}
-static int
-read_mem (unsigned int addr, unsigned int *readbuf)
+/* Read a processor auxiliary register. */
+
+static JTAG_OperationStatus
+jtag_read_aux_reg (ARC_RegisterNumber regnum, ARC_RegisterContents *contents)
{
- unsigned int rd, wr, data, i;
+ ENTERARGS("regnum %d", regnum);
+
+ return read_processor_register(regnum, READ_AUX_REGISTER, contents);
+}
- rw_flag = READ_FROM_AA3;
- if(arc_jtag_ops.arc_jtag_state_machine_debug)
- printf_filtered("\nEntered read_mem() 0x%x\n",addr);
- // jtag addr register = regnum:
- tapc_reset();
- tapc_tms(0);//run-test idle
- write_jtag_reg(0xA, addr, 32);//update dr
-
+/* Write a processor auxiliary register. */
- // Setup instruction register to 0x9 indicating
- // a JTAG instruction is being downloaded.
- // jtag transaction command reg = 0x5 (read core reg)
- write_jtag_reg(0x9, 0x4, 4);//update dr
+static JTAG_OperationStatus
+jtag_write_aux_reg (ARC_RegisterNumber regnum, ARC_RegisterContents contents)
+{
+ ENTERARGS("regnum %d", regnum);
+
+ return write_processor_register(regnum, WRITE_AUX_REGISTER, contents);
+}
+
+
+/* Read a word of data from memory; the given address must be word-aligned.
+ Returns number of bytes read. */
+
+static unsigned int
+jtag_read_word (ARC_Address addr, ARC_Word *data)
+{
+ JTAG_OperationStatus status;
+
+ ENTERARGS("addr 0x%08X", addr);
- /* Perform the transaction.
- */
- tapc_tms(0); // run-test idle
+ gdb_assert(IS_WORD_ALIGNED(addr));
- // poll the status
+ /* Load the address of the memory word that is to be read into the JTAG
+ Address Register. */
+ start_jtag_transaction(READ_MEMORY_LOCATION, addr);
- for (i=0;i<arcjtag_retry_count;i++)
+ status = perform_jtag_transaction(Memory, JTAG_READ_FAILURE);
+
+ if (status == JTAG_SUCCESS)
{
- unsigned int status = read_jtag_status_reg();
- if(status == 4)
- break;
- if(status == 2)
- return JTAG_READ_FAILURE;
- tapc_tms(1);//exit1-dr
- tapc_tms(1);//update-dr
- /* Do not redo the transaction. Pause and re-try.
- */
- //tapc_tms(0); // run-test-idle
+ /* Read the data from the JTAG Data Register. */
+ ARC_Word word = (ARC_Word) read_jtag_reg(JTAG_DATA_REGISTER, BITS_IN_WORD);
+
+ /* N.B. this assumes that the host is little-endian! */
+ if (target_is_big_endian)
+ word = __bswap_32(word);
+
+ DEBUG("read 0x%08X\n", word);
+
+ *data = word;
+
+ return BYTES_IN_WORD;
}
- if (i==arcjtag_retry_count)
- return JTAG_READ_FAILURE;
-
- /* JTAG status register leaves us in Shift DR */
- tapc_tms(1); /* Move to Exit-1 DR */
- tapc_tms(1); /* Move to Update DR */
-
- // data = jtag data reg
- data = read_jtag_reg(0xB, 32);
- *readbuf = data;
- if(arc_jtag_ops.arc_jtag_state_machine_debug)
- printf_filtered("\n Read rd =0x%x in read_mem",data);
-
- return sizeof(data);
+
+ /* Failed: no data read. */
+ return 0;
}
-static int
-write_mem (unsigned int addr, unsigned int data)
+/* Write a word of data to memory; the given address must be word-aligned.
+ Returns number of bytes written. */
+
+static unsigned int
+jtag_write_word (ARC_Address addr, ARC_Word data)
{
- unsigned int rd, wr, i;
- if(arc_jtag_ops.arc_jtag_state_machine_debug)
- printf_filtered("\nEntered write_mem() to write 0x%x at 0x%x\n",data,addr);
- tapc_reset();
- tapc_tms(0);//run-test idle
-
- // data = jtag data reg
- write_jtag_reg(0xB, data, 32);//update dr
+ ENTERARGS("addr 0x%08X, data 0x%08X", addr, data);
- // jtag addr register = regnum:
- write_jtag_reg(0xA, addr, 32);//update dr
-
-
+ gdb_assert(IS_WORD_ALIGNED(addr));
- // jtag transaction command reg = 0x0(write mem)
- write_jtag_reg(0x9, 0x0, 4);//update dr
+ /* Load the address of the memory word that is to be written into the JTAG
+ Address Register. */
+ start_jtag_transaction(WRITE_MEMORY_LOCATION, addr);
- /* Perform the transaction.
- */
- tapc_tms(0); // run-test idle
+ /* N.B. this assumes that the host is little-endian! */
+ if (target_is_big_endian)
+ data = __bswap_32(data);
- for (i=0;i<arcjtag_retry_count;i++)
- {
- unsigned int status = read_jtag_status_reg();
- if(status == 4)
- break;
- if(status == 2)
- return JTAG_WRITE_FAILURE;
- tapc_tms(1);//exit1-dr
- tapc_tms(1);//update-dr
- /* Do not redo the transaction. Pause and re-try.
- */
- //tapc_tms(0);//run-tes-idle
- }
- if (i==arcjtag_retry_count)
- return JTAG_READ_FAILURE;
-
- tapc_tms(1);//exit1-dr
- tapc_tms(1);//update-dr
- /* This should have been done earlier i.e. before
- reading the JTAG status register.
- */
- //tapc_tms(0);//run-test-idle
- return sizeof(data);
+ /* Load the data to be written into the JTAG Data Register. */
+ write_jtag_reg(JTAG_DATA_REGISTER, data, BITS_IN_WORD);
+
+ if (perform_jtag_transaction(Memory, JTAG_WRITE_FAILURE) == JTAG_SUCCESS)
+ return BYTES_IN_WORD;
+
+ /* Failed: no data written. */
+ return 0;
}
-static int
-arc_jtag_write_chunk (unsigned int addr, unsigned int *write_buf, int len)
+/* Read a number of words of data from target memory starting at the given address.
+ Returns number of bytes read. */
+
+static unsigned int
+jtag_read_chunk (ARC_Address address, ARC_Byte *data, unsigned int words)
{
- unsigned int rd, wr;
- unsigned int status;
- check_and_raise_error_if_jtag_closed();
-
- rw_flag = WRITE_TO_AA3 ;
- int i = 0;
- int len_mod = len % 4;
- len = len - len_mod;
-
- tapc_reset();
- if(arc_jtag_ops.arc_jtag_state_machine_debug)
- printf_filtered("Entered arc_jtag_write_chunk()......0x%x\n",*write_buf);
- tapc_tms(0);//run-test idle
-
- // jtag addr register = regnum:
- write_jtag_reg(0xA, addr, 32);//update dr
-
-
-
- // jtag transaction command reg = 0x0(write mem)
- write_jtag_reg(0x9, 0x0, 4);//update dr
-
- while(len)
- {
-
- // data = jtag data reg
- write_jtag_reg(0xB, write_buf[i++], 32);//update dr
-
- /* Perform the transaction.
- */
- tapc_tms(0); // run-test idle
-
-
- while(1)
- {
- status = read_jtag_status_reg();
- if(status == 4)
- break;
- if(status == 2)
- return (i-1) * 4;
-
- tapc_tms(1);//exit1-dr
- tapc_tms(1);//update-dr
- /* Do not redo the transaction. Pause and re-try.
- */
- //tapc_tms(0);//run-tes-idle
- }
-
- tapc_tms(1);//exit1-dr
- tapc_tms(1);//update-dr
- /* This should have been done earlier i.e. before
- reading the JTAG status register.
- */
- //tapc_tms(0);//run-test idle
- len = len - 4;
- }
+ unsigned int total_read = 0;
+
+ ENTERARGS("address 0x%08X, words %u", address, words);
- if(arc_jtag_ops.arc_jtag_state_machine_debug)
- printf_filtered("leaving arc_jtag_write_chunk() with return value %d",i*4);
-
- // added support for writing no of bytes those are not exact mutiple of four
-
- if(!len_mod)
- return i*4;
- else
+ /* Load the start address of the memory chunk that is to be read
+ into the JTAG Address Register. */
+ start_jtag_transaction(READ_MEMORY_LOCATION, address);
+
+ /* Read all the words of data. */
+ while (words--)
{
-
- addr=addr+(i*4);
- if(read_mem(addr,&rd)==JTAG_READ_FAILURE)
- return i*4;
- if(arc_jtag_ops.arc_jtag_state_machine_debug)
- printf_filtered("\nrd=0x%x and wr=0x%x\n",rd,write_buf[i]);
-
- switch(len_mod)
- {
-
- case 1:
- wr = (rd & 0xffffff00)|(write_buf[i] & 0xff);
- break;
-
- case 2:
- wr = (rd & 0xffff0000)|(write_buf[i] & 0xffff);
- break;
-
- case 3:
- wr = (rd & 0xff000000)|(write_buf[i] & 0xffffff);
- break;
-
- }
- if(arc_jtag_ops.arc_jtag_state_machine_debug)
- printf_filtered("\nwrite_mem writing 0x%x at 0x%x",wr,addr);
- arc_jtag_write_chunk(addr,&wr,4);
- return (i*4 + len_mod);
- }
-
-
+ ARC_Word word;
+
+ /* Read the next word of data - this increments the address in
+ the JTAG Address Register by the word size, so the register
+ does not have to be re-loaded with the next address. */
+ if (perform_jtag_transaction(Memory, JTAG_READ_FAILURE) != JTAG_SUCCESS)
+ {
+ DEBUG("FAIL: read %u bytes\n", total_read);
+
+ /* Failed - just return amount of data read so far. */
+ return total_read;
+ }
+
+ /* Read the word of data from the JTAG Data Register. */
+ word = (ARC_Word) read_jtag_reg(JTAG_DATA_REGISTER, BITS_IN_WORD);
+
+ /* N.B. this assumes that the host is little-endian! */
+ if (target_is_big_endian)
+ word = __bswap_32(word);
+
+ /* Copy it into the buffer (byte-by-byte copy means that alignment does not matter). */
+ COPY_WORD(data, &word);
+
+ total_read += BYTES_IN_WORD;
+ data += BYTES_IN_WORD;
+ }
+
+ return total_read;
}
-static int
-arc_jtag_read_chunk (unsigned int addr, unsigned int *read_buf, int len)
+
+/* Write a number of words of data to target memory starting at the given address.
+ Returns number of bytes written. */
+
+static unsigned int
+jtag_write_chunk (ARC_Address address, ARC_Byte *data, unsigned int words)
{
- unsigned int rd, wr, data;
- int i=0;
- rw_flag = READ_FROM_AA3 ;
- int len_mod=len%4;
- len=len-len_mod;
- if(arc_jtag_ops.arc_jtag_state_machine_debug)
- printf_filtered("\nEntered arc_jtag_read_chunk() 0x%x\n",addr);
- check_and_raise_error_if_jtag_closed();
-
- // jtag addr register = regnum:
- tapc_reset();
- tapc_tms(0);//run-test idle
-
- write_jtag_reg(0xA, addr, 32);//update dr
+ unsigned int total_written = 0;
-
- while(len)
- {
- // Setup instruction register to 0x9 indicating
- // a JTAG instruction is being downloaded.
- // jtag transaction command reg = 0x5 (read core reg)
- write_jtag_reg(0x9, 0x4, 4);//update dr
+#ifndef JTAG_DATA_REGISTER_IS_CORRUPTED_BY_WRITE
+ ARC_Word last_word;
- /* Perform the transaction.
- */
- tapc_tms(0); // run-test idle
+ /* Initialise last_word with a value that is different from the
+ first word to be written. */
+ COPY_WORD(&last_word, data);
+ last_word++;
+#endif
- // poll the status
+ ENTERARGS("address 0x%08X, words %u", address, words);
- while(1)
+ /* Load the start address of the memory chunk that is to be written
+ into the JTAG Address Register. */
+ start_jtag_transaction(WRITE_MEMORY_LOCATION, address);
+
+ /* write all the words of data */
+ while (words--)
{
- unsigned int status = read_jtag_status_reg();
- if(status == 4)
- break;
- if(status == 2)
- return (i-1)*4;
- tapc_tms(1);//exit1-dr
- tapc_tms(1);//update-dr
- /* Do not redo the transaction. Pause and re-try.
- */
- //tapc_tms(0);//run-test-idle
+ ARC_Word word;
- }
+ /* Copy the next word of data from the buffer
+ (byte-by-byte copy means that alignment does not matter). */
+ COPY_WORD(&word, data);
+
+ /* N.B. this assumes that the host is little-endian! */
+ if (target_is_big_endian)
+ word = __bswap_32(word);
+
+#ifndef JTAG_DATA_REGISTER_IS_CORRUPTED_BY_WRITE
+ if (word != last_word)
+ {
+#endif
+ write_jtag_reg(JTAG_DATA_REGISTER, word, BITS_IN_WORD);
- /* JTAG status register leaves us in Shift DR */
- tapc_tms(1); /* Move to Exit-1 DR */
- tapc_tms(1); /* Move to Update DR */
-
- // data = jtag data reg
- read_buf[i++] = read_jtag_reg(0xB, 32);// exits in Update DR
- len= len-4;
- //tapc_tms(0);/* Move to run-test-idle */
+#ifdef CHECK_JTAG_DATA_REGISTER
+ check_Data_Register(word);
+#endif
+#ifndef JTAG_DATA_REGISTER_IS_CORRUPTED_BY_WRITE
+ last_word = word;
+ }
+#endif
+
+ data += BYTES_IN_WORD;
+
+ /* Write the word - this increments the address in the JTAG
+ Address Register by the word size, so the register does not
+ have to be re-loaded with the next address. */
+ if (perform_jtag_transaction(Memory, JTAG_WRITE_FAILURE) != JTAG_SUCCESS)
+ {
+ DEBUG("FAIL: written %u bytes\n", total_written);
+
+ /* Failed - just return amount of data written so far. */
+ return total_written;
+ }
+
+ total_written += BYTES_IN_WORD;
}
- // added support for reading no of bytes those are not exact mutiple of four
+ return total_written;
+}
- if(!len_mod)
- return i*4;
- else
+
+/* Write a number of copies of a word-sized pattern of data to memory starting
+ at the given address.
+ Returns number of bytes written. */
+
+static unsigned int
+jtag_write_pattern (ARC_Address address, ARC_Word pattern, unsigned int words)
+{
+ unsigned int total_written = 0;
+
+ ENTERARGS("address 0x%08X, pattern 0x%08X, words %u", address, pattern, words);
+
+ /* Load the start address of the memory chunk that is to be written
+ into the JTAG Address Register. */
+ start_jtag_transaction(WRITE_MEMORY_LOCATION, address);
+
+ /* N.B. this assumes that the host is little-endian! */
+ if (target_is_big_endian)
+ pattern = __bswap_32(pattern);
+
+#ifndef JTAG_DATA_REGISTER_IS_CORRUPTED_BY_WRITE
+ /* Load the pattern into the JTAG Data Register. */
+ write_jtag_reg(JTAG_DATA_REGISTER, pattern, BITS_IN_WORD);
+#endif
+
+ /* Write all the complete words of data. */
+ while (words--)
{
- char *ptr = (char *)read_buf + i*4;
- addr=addr+(i*4);
- if(read_mem(addr,&rd)==JTAG_READ_FAILURE)
- return i*4;
-
- switch(len_mod)
- {
- case 1:
- ptr[0] = rd & 0xff;
- break;
-
- case 2:
- ptr[0] = rd & 0xff;
- ptr[1] = (rd>>8) & 0xff;
- break;
-
- case 3:
- ptr[0] = rd & 0xff;
- ptr[1] = (rd>>8) & 0xff;
- ptr[2] = (rd>>16) & 0xff;
- break;
- }
-
- return ((i*4)+len_mod);
-
+#ifdef JTAG_DATA_REGISTER_IS_CORRUPTED_BY_WRITE
+ /* Load the pattern into the JTAG Data Register. */
+ write_jtag_reg(JTAG_DATA_REGISTER, pattern, BITS_IN_WORD);
+#endif
+
+#ifdef CHECK_JTAG_DATA_REGISTER
+ check_Data_Register(pattern);
+#endif
+
+ /* Write the word - this increments the address in the JTAG
+ Address Register by the word size, so the register does not
+ have to be re-loaded with the next address. */
+ if (perform_jtag_transaction(Memory, JTAG_WRITE_FAILURE) != JTAG_SUCCESS)
+ {
+ DEBUG("FAIL: written %u bytes\n", total_written);
+
+ /* Failed - just return amount of data written so far. */
+ return total_written;
+ }
+
+ total_written += BYTES_IN_WORD;
}
-
+ return total_written;
}
+/* -------------------------------------------------------------------------- */
+/* 7) main operations */
+/* -------------------------------------------------------------------------- */
+
+/* These are the functions that are called from outside this module via the
+ pointers in the arc_jtag_ops global object.
+ N.B. none of these functions are called from within this module. */
-/*
- * Return the Processor Variant that is connected.
- */
-int
-arc_get_architecture()
+
+/* Read a processor core register. */
+
+static JTAG_OperationStatus
+jtag_read_core_reg (ARC_RegisterNumber regnum, ARC_RegisterContents *contents)
{
- if (ARCProcessor == UNSUPPORTED) {
- unsigned int value;
-
- /* Read the Identity Register. */
- if (arc_jtag_read_aux_reg(4, &value) == JTAG_READ_FAILURE)
- error("Failure reading from auxillary IDENTITY register");
-
- /* Get Identity Mask. */
- value &= 0xff ;
-
- if((value >= 0x30) && (value <= 0x3f))
- ARCProcessor = ARC700;
- else if((value >= 0x20) && (value <= 0x2f))
- ARCProcessor = ARC600;
- else if((value >= 0x10) && (value <= 0x1f))
- ARCProcessor = A5;
- else if ((value >= 0x00) && (value <= 0x0f))
- ARCProcessor = A4;
- else
- error("Unsupported Processor Version 0x%x\n", value);
- }
-
- return ARCProcessor;
+ ENTERARGS("regnum %d", regnum);
+
+ return read_processor_register(regnum, READ_CORE_REGISTER, contents);
}
+/* Try to open the JTAG interface.
+ Returns TRUE for success. */
-static void
-arc_jtag_open (void)
+static Boolean
+jtag_open (ARC_RegisterNumber mem_subsys)
{
- int retval;
- unsigned int read_status = 0;
- sigaddset(&block_mask,SIGINT);
- retval = gpio_setup();
- if(retval != 0)
+ ENTERMSG;
+
+ if (arc_jtag_ops.status == JTAG_CLOSED)
{
- error("Unable to open JTAG Port .%s \n",(retval == EINVAL)?
- "Invalid Params":"Permission Denied" );
- arc_jtag_ops.jtag_status = JTAG_CLOSED;
- return ;
+ JTAG_OperationStatus status;
+
+ /* Make sure that the GPIO driver is open. */
+ if (!gpio_open())
+ return FALSE;
+
+ set_interface(JTAG_OPENED);
+
+ tapc_reset();
+
+ /* Load the number of the MEMSUBSYS BCR that is to be read into the JTAG
+ Address Register. */
+ start_jtag_transaction(READ_AUX_REGISTER, mem_subsys);
+
+ status = perform_jtag_transaction(Register, JTAG_READ_FAILURE);
+
+ if (status == JTAG_SUCCESS)
+ {
+ /* Read the register contents from the JTAG Data Register. */
+ ARC_RegisterContents contents =
+ (ARC_RegisterContents) read_jtag_reg(JTAG_DATA_REGISTER, BITS_IN_REGISTER);
+
+ DEBUG("MEMSUBSYS BCR: 0x%08X\n", contents);
+
+ target_is_big_endian = ((contents & 4) != 0);
+ }
+ else
+ {
+ warning(_("can not discover endianness of target\n"));
+ return FALSE;
+ }
+
+ DEBUG("arcjtag opened\n");
}
- arc_jtag_ops.jtag_status = JTAG_OPENED;
- tapc_reset();
- //Writing debug bit of debug register
-
- do
- {
- /* Note: Reading the status/status32 register here to
- check if halt bit is set*/
- if (IS_A4) {
- if(arc_jtag_read_aux_reg( 0x0, &read_status) == JTAG_READ_FAILURE)
- error("Failure reading auxillary register 0xA\n");
- if(read_status & A4_HALT_VALUE)
- break;
- }
- else {
- if(arc_jtag_read_aux_reg( 0xA, &read_status) == JTAG_READ_FAILURE)
- error("Failure reading auxillary register 0xA\n");
- if(read_status & ARC700_HALT_VALUE)
- break;
- }
- printf_filtered("Processor running. Trying to halt.....\n");
- if(arc_jtag_write_aux_reg(0x5,0x2)==JTAG_WRITE_FAILURE)
- error("Failure writing 0x2 to auxillary register 0x5:debug register\n");
- }while(1);
- if (arc_jtag_ops.arc_jtag_state_machine_debug)
- printf_filtered("Processor halted.....\n");
+ LEAVEMSG;
+ return TRUE;
}
-static void
-arc_jtag_close (void)
+
+/* Close the JTAG interface. */
+
+static void
+jtag_close (void)
{
- ARCProcessor = UNSUPPORTED;
+ ENTERMSG;
- if(arc_jtag_ops.jtag_status != JTAG_CLOSED)
+ if (arc_jtag_ops.status == JTAG_OPENED)
{
- tapc_reset();
- /* closing file descriptor opened for communication with gpio driver */
- close(fd);
- if(arc_jtag_ops.arc_jtag_state_machine_debug)
- printf_filtered("arc-jtag closed\n");
- arc_jtag_ops.jtag_status = JTAG_CLOSED;
+ tapc_reset();
+
+ /* Close the file descriptor opened for communication with gpio driver. */
+ gpio_close();
+
+ set_interface(JTAG_CLOSED);
+
+#ifdef STATE_MACHINE_DEBUG
+ current_state = UNDEFINED;
+#endif
+
+ DEBUG("arcjtag closed\n");
}
+ LEAVEMSG;
}
-static void
-arc_jtag_wait(void)
+
+/* Reset the target JTAG controller. */
+
+static void
+jtag_reset (void)
{
- unsigned int read_status;
- check_and_raise_error_if_jtag_closed();
- do
- {
- sigprocmask(SIG_BLOCK,&block_mask, NULL);
-
- if (IS_A4) {
- if(arc_jtag_read_aux_reg( 0x0, &read_status) == JTAG_READ_FAILURE)
- error("Failure reading auxillary register 0x0\n");
- //FIXMEA: if(debug_arc_jtag_target_message)
- // printf_filtered ("\n Read Status: 0x%x,%d\n", read_status, read_status);
-
- if(read_status & A4_HALT_VALUE)
- {
- sigprocmask(SIG_BLOCK,&block_mask, NULL);
- break;
- }
- }
- else {
- if(arc_jtag_read_aux_reg( 0xA, &read_status) == JTAG_READ_FAILURE)
- error("Failure reading auxillary register 0xA\n");
- if(read_status & ARC700_HALT_VALUE)
- {
- sigprocmask(SIG_BLOCK,&block_mask, NULL);
- break;
-
- }
- }
- sigprocmask(SIG_UNBLOCK,&block_mask, NULL);
- }while(1);
-
- while (1)
+ ENTERMSG;
+ tapc_reset();
+ LEAVEMSG;
+}
+
+
+/* Reset the target board. */
+
+static void
+jtag_reset_board (void)
+{
+ ENTERMSG;
+
+ /* Make sure that the GPIO driver is open. */
+ if (gpio_open())
{
- if (arc_jtag_read_aux_reg (0x5,&read_status) == JTAG_READ_FAILURE)
- error ("Failure reading Debug register \n");
- if (!(read_status & 0x80000000))
- break;
+ /* Writing 9 did not work. But that's what the manual says. Hmmm. */
+// gpio_write (CONTROL_PORT, 9);
+
+ /* What is this for? */
+ gpio_write(CONTROL_PORT, (Byte) JTAG_TCK);
+ gpio_write(CONTROL_PORT, (Byte) 0xD);
+ gpio_write(CONTROL_PORT, (Byte) JTAG_TCK);
+ gpio_write(DATA_PORT, (Byte) 0);
+ gpio_write(DATA_PORT, (Byte) JTAG_TMS);
+ gpio_write(DATA_PORT, (Byte) 0);
+
+ tapc_reset();
}
+
+ LEAVEMSG;
+}
+
+
+/* Check that the JTAG interface is open.
+ If it is closed, 'error' is called. */
+
+static void jtag_check_open (void)
+{
+ if (arc_jtag_ops.status == JTAG_CLOSED)
+ interface_is_closed();
}
+
+/* -------------------------------------------------------------------------- */
+/* 8) interface management */
+/* -------------------------------------------------------------------------- */
+
+/* Report that the JTAG interface is closed. */
+
static void
-arc_jtag_reset_board (void)
+interface_is_closed (void)
{
- char c = 5;
- int auxval = 2 ;
- check_and_raise_error_if_jtag_closed ();
-
- /*
- Writing 9 did not work. But thats
- what the manual says. Hmmm.
- gpio_write (CONTROL_PORT, &c);
- */
-
- gpio_write ( CONTROL_PORT, &c);
- c = 0xd;
- gpio_write ( CONTROL_PORT, &c);
- c = 5;
- gpio_write ( CONTROL_PORT, &c);
-
- if (arc_jtag_write_aux_reg(0x5 , 2) == JTAG_WRITE_FAILURE)
- error ("Failure writing to auxiliary register Debug\n");
-
- c = 0;
- gpio_write ( 0x378, &c);
- c = 0x40;
- gpio_write ( 0x378, &c);
- c = 0;
- gpio_write ( 0x378, &c);
-
- tapc_reset();
+ error(_("JTAG connection is closed. "
+ "Use command 'target " ARC_TARGET_NAME "' first."));
}
+/* Set up the function pointers in the arc_jtag_ops structure according to
+ whether the JTAG interface is open or closed. Note that if the interface is
+ closed, all the pointers point to the 'interface_is_closed' function - so any
+ attempt to invoke one of those operations results in an error; but if the
+ interface is open, they point to the appropriate operations (which may be
+ called without incurring the overhead of a check on the interface status). */
+
+static void
+set_interface (JTAG_Status status)
+{
+ arc_jtag_ops.status = status;
+
+ if (status == JTAG_OPENED)
+ {
+ arc_jtag_ops.memory_read_word = jtag_read_word;
+ arc_jtag_ops.memory_write_word = jtag_write_word;
+ arc_jtag_ops.memory_read_chunk = jtag_read_chunk;
+ arc_jtag_ops.memory_write_chunk = jtag_write_chunk;
+ arc_jtag_ops.memory_write_pattern = jtag_write_pattern;
+ arc_jtag_ops.read_aux_reg = jtag_read_aux_reg;
+ arc_jtag_ops.write_aux_reg = jtag_write_aux_reg;
+ arc_jtag_ops.read_core_reg = jtag_read_core_reg;
+ arc_jtag_ops.write_core_reg = jtag_write_core_reg;
+ arc_jtag_ops.reset = jtag_reset;
+ }
+ else
+ {
+ typedef unsigned int (*Read_Word) (ARC_Address, ARC_Word*);
+ typedef unsigned int (*Write_Word) (ARC_Address, ARC_Word);
+ typedef unsigned int (*Transfer_Chunk) (ARC_Address, ARC_Byte*, unsigned int);
+ typedef unsigned int (*Write_Pattern) (ARC_Address, ARC_Word, unsigned int);
+ typedef JTAG_OperationStatus (*Read_Register) (ARC_RegisterNumber, ARC_RegisterContents*);
+ typedef JTAG_OperationStatus (*Write_Register) (ARC_RegisterNumber, ARC_RegisterContents);
+
+ /* The type casts avoid "assignment from incompatible pointer type" warnings
+ at compile-time. */
+ arc_jtag_ops.memory_read_word = (Read_Word) interface_is_closed;
+ arc_jtag_ops.memory_write_word = (Write_Word) interface_is_closed;
+ arc_jtag_ops.memory_read_chunk = (Transfer_Chunk) interface_is_closed;
+ arc_jtag_ops.memory_write_chunk = (Transfer_Chunk) interface_is_closed;
+ arc_jtag_ops.memory_write_pattern = (Write_Pattern) interface_is_closed;
+ arc_jtag_ops.read_aux_reg = (Read_Register) interface_is_closed;
+ arc_jtag_ops.write_aux_reg = (Write_Register) interface_is_closed;
+ arc_jtag_ops.read_core_reg = (Read_Register) interface_is_closed;
+ arc_jtag_ops.write_core_reg = (Write_Register) interface_is_closed;
+ arc_jtag_ops.reset = interface_is_closed;
+ }
+}
+
+
+/* -------------------------------------------------------------------------- */
+/* externally visible functions */
+/* -------------------------------------------------------------------------- */
+
+/* Initialize the module. This function is called from the gdb core on start-up. */
+
void
_initialize_arc_jtag_ops (void)
{
- arc_jtag_ops.name=NULL;
- arc_jtag_ops.jtag_open = arc_jtag_open;
- arc_jtag_ops.jtag_close = arc_jtag_close;
- arc_jtag_ops.jtag_memory_write = arc_jtag_write_chunk;
- arc_jtag_ops.jtag_memory_read = arc_jtag_read_chunk;
- arc_jtag_ops.jtag_memory_chunk_write = arc_jtag_write_chunk;
- arc_jtag_ops.jtag_memory_chunk_read = arc_jtag_read_chunk;
- arc_jtag_ops.jtag_write_aux_reg = arc_jtag_write_aux_reg;
- arc_jtag_ops.jtag_read_aux_reg = arc_jtag_read_aux_reg;
- arc_jtag_ops.jtag_read_core_reg = arc_jtag_read_core_reg;
- arc_jtag_ops.jtag_write_core_reg = arc_jtag_write_core_reg;
- arc_jtag_ops.jtag_wait = arc_jtag_wait;
- arc_jtag_ops.jtag_reset_board = arc_jtag_reset_board;
- arc_jtag_ops.jtag_status = JTAG_CLOSED ;
+ ENTERMSG;
+
+ /* Initialize the arc_jtag_ops global variable. */
+
+ arc_jtag_ops.state_machine_debug = FALSE;
+ arc_jtag_ops.retry_count = 50;
+
+ /* We want to be able to reset the board, and check whether it is connected,
+ regardless of the connection state. */
+ arc_jtag_ops.open = jtag_open;
+ arc_jtag_ops.close = jtag_close;
+ arc_jtag_ops.check_open = jtag_check_open;
+ arc_jtag_ops.reset_board = jtag_reset_board;
+
+ /* The JTAG interface is initially closed. */
+ set_interface(JTAG_CLOSED);
}
+
+/******************************************************************************/