URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [branches/] [oc/] [gdb-5.0/] [gdb/] [jtag.c] - Rev 104
Go to most recent revision | Compare with Previous | Blame | View Log
/* Remote debugging interface for JTAG debugging protocol. Copyright 1993-1995, 2000 Free Software Foundation, Inc. Contributed by Cygnus Support. Written by Marko Mlinar <markom@opencores.org> 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 (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. */ #include "defs.h" #include "inferior.h" #include "bfd.h" #include "symfile.h" #include "gdb_wait.h" #include "gdbcmd.h" #include "gdbcore.h" #include "serial.h" #include "target.h" #include "remote-utils.h" #include "gdb_string.h" #include "tm.h" #include <signal.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/ioctl.h> #include <fcntl.h> #define TCLK 0x01 #define TRST 0x02 #define JTAG_WAIT() #define NUM_RETRIES 16 #define JTAG_RETRY_WAIT() usleep (100); /* Scan chain for risc debug interface. */ #define SC_RISC_DEBUG 0x1 #define SC_SIZE 4 /* Designates whether we are in SELECT_DR state, otherwise in RUN TEST/IDLE */ static int select_dr = 0; /* Printer compatible device we have open. */ static int lp; /* Crc of current read or written data. */ static int crc_r, crc_w = 0; /* Generates new crc, sending in new bit input_bit */ static int crc_calc (int crc, int input_bit) { int c; int new_crc; int d; d = input_bit&1; c = crc; /* Move queue left. */ new_crc = crc << 1; /* Mask upper five bits. */ new_crc &= 0xF8; /* Set lower three bits */ new_crc |= (d ^ ((c >> 7)&1)); new_crc |= (d ^ ((c >> 0)&1) ^ ((c >> 7)&1)) << 1; new_crc |= (d ^ ((c >> 1)&1) ^ ((c >> 7)&1)) << 2; return new_crc; } /* Resets JTAG. Writes TRST=0 and TRST=1 */ static void jp1_reset_JTAG () { unsigned char data; data = 0; write (lp, &data, sizeof (data)); JTAG_WAIT(); data = TRST; write (lp, &data, sizeof (data)); JTAG_WAIT(); } /* Writes TCLK=0, TRST=1, TMS=bit0, TDI=bit1 and TCLK=1, TRST=1, TMS=bit0, TDI=bit1 */ static void jp1_write_JTAG (packet) unsigned char packet; { unsigned char data; data = ((packet & 3) << 2) | TRST; write (lp, &data, sizeof (data)); JTAG_WAIT(); crc_w = crc_calc (crc_w, (packet >> 1)&1); /* rise clock */ data |= TCLK; write (lp, &data, sizeof (data)); JTAG_WAIT(); } /* Reads TDO, using IOCTL. */ static int jp1_read_JTAG () { int data; ioctl(data, 0x60b, &data); data = ((data & 0x80) != 0); crc_r = crc_calc (crc_r, data); return data; } /* Writes bitstream. MS bit first. */ static void jp1_write_stream (stream, len, set_last_bit) unsigned long stream; int len; int set_last_bit; { int i; if (len <= 0) return; for (i = len - 1; i > 0; i--) jp1_write_JTAG (((stream >> i) & 1) << 1); if (set_last_bit) jp1_write_JTAG (((stream & 1) << 1) | 1); else jp1_write_JTAG ((stream & 1) << 1); } /* Gets bitstream. MS bit first. */ static unsigned long jp1_read_stream (len, stream, set_last_bit) int len; unsigned long stream; int set_last_bit; { int i; unsigned long data; if (len <= 0) return; data = 0; for (i = 0; i < len-1; i++) { jp1_write_JTAG (0 + ((stream & 1) << 1)); stream >>= 1; data <<= 1; data |= jp1_read_JTAG (); } if (set_last_bit) jp1_write_JTAG (1 + (stream & 1) << 1); else jp1_write_JTAG (0 + (stream & 1) << 1); data <<= 1; data |= jp1_read_JTAG (); return data; } /* Goes into SELECT_IR state. Should be called before every control write. */ static void jp1_prepare_control () { if (!select_dr) jp1_write_JTAG (1); /* SELECT_DR SCAN */ jp1_write_JTAG (1); /* SELECT_IR SCAN */ select_dr = 0; } /* Sets register/memory regno to data. */ void jtag_write_reg (regno, data) int regno; unsigned int data; { int crc_read, crc_write, crc_ok, retry; if (!select_dr) jp1_write_JTAG (1); /* SELECT_DR SCAN */ select_dr = 1; for (retry = 0; retry < NUM_RETRIES; retry++) { jp1_write_JTAG (0); /* CAPTURE_DR */ jp1_write_JTAG (0); /* SHIFT_DR */ crc_w = 0; jp1_write_stream (regno, 32, 0); /* addr32 */ jp1_write_JTAG (2); /* write (R/W=1) */ jp1_write_stream (data, 32, 0); /* data32 */ crc_write = crc_w; crc_read = jp1_read_stream (crc_write, 8, 1); /* write CRC, EXIT1_DR */ jp1_write_JTAG (1); /* UPDATE_DR */ crc_ok = jp1_read_JTAG (); /* Did JTAG receive packet correctly? */ jp1_write_JTAG (1); /* SELECT_DR */ if ((crc_read == crc_write) && (crc_ok)) return; JTAG_RETRY_WAIT(); } err = ERR_CRC; } /* Reads register/memory from regno. */ unsigned int jtag_read_reg (regno) unsigned int regno; { unsigned int data; int crc_read, crc_write, crc_actual_read, retry, crc_ok; if (!select_dr) jp1_write_JTAG (1); /* SELECT_DR SCAN */ select_dr = 1; for (retry = 0; retry < NUM_RETRIES; retry++) { jp1_write_JTAG (0); /* CAPTURE_DR */ jp1_write_JTAG (0); /* SHIFT_DR */ crc_w = 0; jp1_write_stream (regno, 32, 0); /* addr32 */ jp1_write_JTAG (0); /* read (R/W=0) */ crc_r = 0; data = jp1_read_stream (0, 32, 0); /* data32=0 */ crc_write = crc_w; crc_actual_read = crc_read; crc_read = jp1_read_stream (crc_write, 8, 1); /* Send my crc, EXIT1_DR */ jp1_write_JTAG (1); /* UPDATE_DR */ crc_ok = jp1_read_JTAG (); /* Did JTAG receive packet correctly? */ jp1_write_JTAG (1); /* SELECT_DR */ if ((crc_read == crc_actual_read) && (crc_ok)) return; JTAG_RETRY_WAIT(); } err = ERR_CRC; } /* Initialize a new connection to the or1k board, and make sure we are really connected. */ void jtag_init (args) char * args; { char *ptype; char *port_name; char **argv; if (args == 0) error ( "To open a or1k remote debugging connection, you need to specify what parallel\n" "port device is attached to the target board (e.g., /dev/lp0).\n"); /* Parse the serial port name. */ if ((argv = buildargv (args)) == NULL) nomem (0); port_name = strsave (argv[0]); make_cleanup_freeargv (argv); /* Open and initialize the parallel port. */ lp = open (port_name, O_WRONLY); if (lp < 0) error ("Cannot open device."); printf_unfiltered ("Remote or1k debugging using %s\n", port_name); jp1_reset_JTAG (); jp1_prepare_control (); jp1_write_stream (SC_RISC_DEBUG, SC_SIZE, 1); free (port_name); } void jtag_done () { close (lp); }
Go to most recent revision | Compare with Previous | Blame | View Log