OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [branches/] [oc/] [gdb-5.0/] [gdb/] [jtag.c] - Rev 1765

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);
}
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.