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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.0/] [gdb/] [jtag.c] - Diff between revs 118 and 122

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 118 Rev 122
/* Remote debugging interface for JTAG debugging protocol.
/* Remote debugging interface for JTAG debugging protocol.
   JTAG connects to or1k target ops. See or1k-tdep.c
   JTAG connects to or1k target ops. See or1k-tdep.c
 
 
   Copyright 1993-1995, 2000 Free Software Foundation, Inc.
   Copyright 1993-1995, 2000 Free Software Foundation, Inc.
   Contributed by Cygnus Support.  Written by Marko Mlinar
   Contributed by Cygnus Support.  Written by Marko Mlinar
   <markom@opencores.org>
   <markom@opencores.org>
 
 
   This file is part of GDB.
   This file is part of GDB.
 
 
   This program is free software; you can redistribute it and/or modify
   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
   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 2 of the License, or
   (at your option) any later version.
   (at your option) any later version.
 
 
   This program is distributed in the hope that it will be useful,
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   GNU General Public License for more details.
 
 
   You should have received a copy of the GNU General Public License
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330,
   Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.  */
   Boston, MA 02111-1307, USA.  */
 
 
#include "defs.h"
#include "defs.h"
#include "inferior.h"
#include "inferior.h"
#include "bfd.h"
#include "bfd.h"
#include "symfile.h"
#include "symfile.h"
#include "gdb_wait.h"
#include "gdb_wait.h"
#include "gdbcmd.h"
#include "gdbcmd.h"
#include "gdbcore.h"
#include "gdbcore.h"
#include "serial.h"
#include "serial.h"
#include "target.h"
#include "target.h"
#include "remote-utils.h"
#include "remote-utils.h"
#include "gdb_string.h"
#include "gdb_string.h"
#include "tm.h"
#include "tm.h"
 
 
#include <signal.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <fcntl.h>
 
 
#define TCLK (0x01)
#define TCLK (0x01)
#define TRST (0x02)
#define TRST (0x02)
#define JTAG_WAIT()
#define JTAG_WAIT()
#define NUM_RETRIES (16)
#define NUM_RETRIES (16)
#define JTAG_RETRY_WAIT() usleep (100)
#define JTAG_RETRY_WAIT() usleep (100)
 
 
/* Selects crc trailer size in bits. Currently supported: 8 */
/* Selects crc trailer size in bits. Currently supported: 8 */
#define CRC_SIZE (8)
#define CRC_SIZE (8)
 
 
/* Scan chain size in bits.  */
/* Scan chain size in bits.  */
#define SC_SIZE (4)
#define SC_SIZE (4)
 
 
/* Scan chain info. */
/* Scan chain info. */
/* *INDENT-OFF* */
/* *INDENT-OFF* */
static int chain_addr_size[] = { 0,  32, 0,  0,  5  };
static int chain_addr_size[] = { 0,  32, 0,  0,  5  };
static int chain_data_size[] = { 0,  32, 0,  32, 32 };
static int chain_data_size[] = { 0,  32, 0,  32, 32 };
static int chain_is_valid[]  = { 0,  1,  0,  1,  1  };
static int chain_is_valid[]  = { 0,  1,  0,  1,  1  };
static int chain_has_crc[]   = { 0,  1,  0,  1,  1  };
static int chain_has_crc[]   = { 0,  1,  0,  1,  1  };
static int chain_has_rw[]    = { 0,  1,  0,  0,  1  };
static int chain_has_rw[]    = { 0,  1,  0,  0,  1  };
/* *INDENT-OFF* */
/* *INDENT-OFF* */
 
 
/* Currently selected scan chain - just to prevent unnecessary
/* Currently selected scan chain - just to prevent unnecessary
   transfers. */
   transfers. */
static int current_chain;
static int current_chain;
 
 
/* Designates whether we are in SELECT_DR state, otherwise in
/* Designates whether we are in SELECT_DR state, otherwise in
   RUN TEST/IDLE */
   RUN TEST/IDLE */
static int select_dr = 0;
static int select_dr = 0;
 
 
/* Printer compatible device we have open.  */
/* Printer compatible device we have open.  */
static int lp;
static int lp;
 
 
/* Crc of current read or written data.  */
/* Crc of current read or written data.  */
static int crc_r, crc_w = 0;
static int crc_r, crc_w = 0;
 
 
/* Generates new crc, sending in new bit input_bit */
/* Generates new crc, sending in new bit input_bit */
 
 
static int
static int
crc_calc (int crc, int input_bit)
crc_calc (int crc, int input_bit)
{
{
  int c;
  int c;
  int new_crc;
  int new_crc;
  int d;
  int d;
 
 
#if (CRC_SIZE == 8)
#if (CRC_SIZE == 8)
  d = input_bit&1;
  d = input_bit&1;
  c = crc;
  c = crc;
 
 
  /* Move queue left.  */
  /* Move queue left.  */
  new_crc = crc << 1;
  new_crc = crc << 1;
 
 
  /* Mask upper five bits.  */
  /* Mask upper five bits.  */
  new_crc &= 0xF8;
  new_crc &= 0xF8;
 
 
  /* Set lower three bits */
  /* Set lower three bits */
  new_crc |= (d ^ ((c >> 7)&1));
  new_crc |= (d ^ ((c >> 7)&1));
  new_crc |= (d ^ ((c >> 0)&1) ^ ((c >> 7)&1)) << 1;
  new_crc |= (d ^ ((c >> 0)&1) ^ ((c >> 7)&1)) << 1;
  new_crc |= (d ^ ((c >> 1)&1) ^ ((c >> 7)&1)) << 2;
  new_crc |= (d ^ ((c >> 1)&1) ^ ((c >> 7)&1)) << 2;
  return new_crc;
  return new_crc;
#else
#else
  return 0;
  return 0;
#endif
#endif
}
}
 
 
/* Resets JTAG.
/* Resets JTAG.
   Writes TRST=0
   Writes TRST=0
   and    TRST=1 */
   and    TRST=1 */
 
 
static void
static void
jp1_reset_JTAG ()
jp1_reset_JTAG ()
{
{
  unsigned char data;
  unsigned char data;
  data = 0;
  data = 0;
  write (lp, &data, sizeof (data));
  write (lp, &data, sizeof (data));
  JTAG_WAIT();
  JTAG_WAIT();
  data = TRST;
  data = TRST;
  write (lp, &data, sizeof (data));
  write (lp, &data, sizeof (data));
  JTAG_WAIT();
  JTAG_WAIT();
}
}
 
 
/* Writes TCLK=0, TRST=1, TMS=bit0, TDI=bit1
/* Writes TCLK=0, TRST=1, TMS=bit0, TDI=bit1
   and    TCLK=1, TRST=1, TMS=bit0, TDI=bit1 */
   and    TCLK=1, TRST=1, TMS=bit0, TDI=bit1 */
 
 
static void
static void
jp1_write_JTAG (packet)
jp1_write_JTAG (packet)
     unsigned char packet;
     unsigned char packet;
{
{
  unsigned char data;
  unsigned char data;
  data = ((packet & 3) << 2) | TRST;
  data = ((packet & 3) << 2) | TRST;
  write (lp, &data, sizeof (data));
  write (lp, &data, sizeof (data));
  JTAG_WAIT();
  JTAG_WAIT();
  crc_w = crc_calc (crc_w, (packet >> 1)&1);
  crc_w = crc_calc (crc_w, (packet >> 1)&1);
 
 
  /* rise clock */
  /* rise clock */
  data |= TCLK;
  data |= TCLK;
  write (lp, &data, sizeof (data));
  write (lp, &data, sizeof (data));
  JTAG_WAIT();
  JTAG_WAIT();
}
}
 
 
/* Reads TDO, using IOCTL.  */
/* Reads TDO, using IOCTL.  */
 
 
static int
static int
jp1_read_JTAG ()
jp1_read_JTAG ()
{
{
  int data;
  int data;
  ioctl (data, 0x60b, &data);
  ioctl (data, 0x60b, &data);
  data = ((data & 0x80) != 0);
  data = ((data & 0x80) != 0);
  crc_r = crc_calc (crc_r, data);
  crc_r = crc_calc (crc_r, data);
  return data;
  return data;
}
}
 
 
/* Writes bitstream.  MS bit first.  */
/* Writes bitstream.  MS bit first.  */
 
 
static void
static void
jp1_write_stream (stream, len, set_last_bit)
jp1_write_stream (stream, len, set_last_bit)
     unsigned long long int stream;
     ULONGEST stream;
     int len;
     int len;
     int set_last_bit;
     int set_last_bit;
{
{
  int i;
  int i;
  if (len <= 0) return;
  if (len <= 0) return;
  for (i = len - 1; i > 0; i--)
  for (i = len - 1; i > 0; i--)
    jp1_write_JTAG (((stream >> i) & 1) << 1);
    jp1_write_JTAG (((stream >> i) & 1) << 1);
 
 
  if (set_last_bit)
  if (set_last_bit)
    jp1_write_JTAG (((stream & 1) << 1) | 1);
    jp1_write_JTAG (((stream & 1) << 1) | 1);
  else
  else
    jp1_write_JTAG ((stream & 1) << 1);
    jp1_write_JTAG ((stream & 1) << 1);
}
}
 
 
/* Gets bitstream.  MS bit first.  */
/* Gets bitstream.  MS bit first.  */
 
 
static unsigned long long int
static ULONGEST
jp1_read_stream (len, stream, set_last_bit)
jp1_read_stream (len, stream, set_last_bit)
     int len;
     int len;
     unsigned long stream;
     unsigned long stream;
     int set_last_bit;
     int set_last_bit;
{
{
  int i;
  int i;
  unsigned long long int data;
  ULONGEST data;
 
 
  if (len <= 0) return;
  if (len <= 0) return;
  data = 0;
  data = 0;
  for (i = 0; i < len-1; i++)
  for (i = 0; i < len-1; i++)
    {
    {
      jp1_write_JTAG (0 + ((stream & 1) << 1));
      jp1_write_JTAG (0 + ((stream & 1) << 1));
      stream >>= 1;
      stream >>= 1;
      data <<= 1;
      data <<= 1;
      data |= jp1_read_JTAG ();
      data |= jp1_read_JTAG ();
    }
    }
 
 
  if (set_last_bit)
  if (set_last_bit)
    jp1_write_JTAG (1 + (stream & 1) << 1);
    jp1_write_JTAG (1 + (stream & 1) << 1);
  else
  else
    jp1_write_JTAG (0 + (stream & 1) << 1);
    jp1_write_JTAG (0 + (stream & 1) << 1);
  data <<= 1;
  data <<= 1;
  data |= jp1_read_JTAG ();
  data |= jp1_read_JTAG ();
  return data;
  return data;
}
}
 
 
/* Goes into SELECT_IR state. Should be called before every control write.  */
/* Goes into SELECT_IR state. Should be called before every control write.  */
 
 
static void
static void
jp1_prepare_control ()
jp1_prepare_control ()
{
{
  if (!select_dr)
  if (!select_dr)
    jp1_write_JTAG (1); /* SELECT_DR SCAN */
    jp1_write_JTAG (1); /* SELECT_DR SCAN */
  jp1_write_JTAG (1);   /* SELECT_IR SCAN */
  jp1_write_JTAG (1);   /* SELECT_IR SCAN */
  select_dr = 0;
  select_dr = 0;
}
}
 
 
/* Sets register/memory regno to data.  */
/* Sets register/memory regno to data.  */
 
 
void
void
jtag_write_reg (regno, data)
jtag_write_reg (regno, data)
     int regno;
     int regno;
     unsigned long long int data;
     ULONGEST data;
{
{
  int crc_read, crc_write, crc_ok, retry;
  int crc_read, crc_write, crc_ok, retry;
 
 
  if (!select_dr)
  if (!select_dr)
    jp1_write_JTAG (1); /* SELECT_DR SCAN */
    jp1_write_JTAG (1); /* SELECT_DR SCAN */
  select_dr = 1;
  select_dr = 1;
 
 
  /* If we don't have rw bit, we assume chain
  /* If we don't have rw bit, we assume chain
     is read only. */
     is read only. */
  if (!chain_has_rw[current_chain])
  if (!chain_has_rw[current_chain])
    error ("Internal: Chain not writable.");
    error ("Internal: Chain not writable.");
 
 
  for (retry = 0; retry < NUM_RETRIES; retry++)
  for (retry = 0; retry < NUM_RETRIES; retry++)
    {
    {
      jp1_write_JTAG (0); /* CAPTURE_DR */
      jp1_write_JTAG (0); /* CAPTURE_DR */
      jp1_write_JTAG (0); /* SHIFT_DR */
      jp1_write_JTAG (0); /* SHIFT_DR */
      crc_w = 0;
      crc_w = 0;
 
 
      /* write addr */
      /* write addr */
      jp1_write_stream (regno, chain_addr_size[current_chain], 0);
      jp1_write_stream (regno, chain_addr_size[current_chain], 0);
 
 
      /* write (R/W=1) - we tested that previously. */
      /* write (R/W=1) - we tested that previously. */
      jp1_write_JTAG (2);
      jp1_write_JTAG (2);
 
 
      /* write data */
      /* write data */
      jp1_write_stream (data, chain_data_size[current_chain], 0);
      jp1_write_stream (data, chain_data_size[current_chain], 0);
      if (chain_has_crc[current_chain])
      if (chain_has_crc[current_chain])
        {
        {
          crc_write = crc_w;
          crc_write = crc_w;
 
 
          /* write CRC, EXIT1_DR */
          /* write CRC, EXIT1_DR */
          crc_read = jp1_read_stream (crc_write, CRC_SIZE, 1);
          crc_read = jp1_read_stream (crc_write, CRC_SIZE, 1);
        }
        }
      jp1_write_JTAG (1); /* UPDATE_DR */
      jp1_write_JTAG (1); /* UPDATE_DR */
 
 
       /* Did JTAG receive packet correctly? */
       /* Did JTAG receive packet correctly? */
      if (chain_has_crc[current_chain])
      if (chain_has_crc[current_chain])
        crc_ok = jp1_read_JTAG ();
        crc_ok = jp1_read_JTAG ();
      jp1_write_JTAG (1); /* SELECT_DR */
      jp1_write_JTAG (1); /* SELECT_DR */
      if (chain_has_crc[current_chain])
      if (chain_has_crc[current_chain])
        {
        {
          if ((crc_read == crc_write) && (crc_ok))
          if ((crc_read == crc_write) && (crc_ok))
            return;
            return;
          JTAG_RETRY_WAIT();
          JTAG_RETRY_WAIT();
        }
        }
      else return;
      else return;
    }
    }
  err = ERR_CRC;
  err = ERR_CRC;
}
}
 
 
/* Reads register/memory from regno.  */
/* Reads register/memory from regno.  */
 
 
unsigned long long int
ULONGEST
jtag_read_reg (regno)
jtag_read_reg (regno)
     unsigned int regno;
     unsigned int regno;
{
{
  unsigned long long int data;
  ULONGEST data;
  int crc_read, crc_write, crc_actual_read,  retry, crc_ok;
  int crc_read, crc_write, crc_actual_read,  retry, crc_ok;
 
 
  if (!select_dr)
  if (!select_dr)
    jp1_write_JTAG (1); /* SELECT_DR SCAN */
    jp1_write_JTAG (1); /* SELECT_DR SCAN */
  select_dr = 1;
  select_dr = 1;
 
 
  for (retry = 0; retry < NUM_RETRIES; retry++)
  for (retry = 0; retry < NUM_RETRIES; retry++)
    {
    {
      jp1_write_JTAG (0); /* CAPTURE_DR */
      jp1_write_JTAG (0); /* CAPTURE_DR */
      jp1_write_JTAG (0); /* SHIFT_DR */
      jp1_write_JTAG (0); /* SHIFT_DR */
      crc_w = 0;
      crc_w = 0;
 
 
      /* write addr */
      /* write addr */
      jp1_write_stream (regno, chain_addr_size[current_chain], 0);
      jp1_write_stream (regno, chain_addr_size[current_chain], 0);
 
 
      /* read (R/W=0) */
      /* read (R/W=0) */
      if (chain_has_rw[current_chain])
      if (chain_has_rw[current_chain])
        jp1_write_JTAG (0);
        jp1_write_JTAG (0);
      if (chain_has_crc[current_chain])
      if (chain_has_crc[current_chain])
        {
        {
          crc_r = 0;
          crc_r = 0;
 
 
          /* data = 0 */
          /* data = 0 */
          data = jp1_read_stream (0, chain_data_size[current_chain], 0);
          data = jp1_read_stream (0, chain_data_size[current_chain], 0);
          crc_write = crc_w;
          crc_write = crc_w;
          crc_actual_read = crc_read;
          crc_actual_read = crc_read;
 
 
          /* Send my crc, EXIT1_DR */
          /* Send my crc, EXIT1_DR */
          crc_read = jp1_read_stream (crc_write, CRC_SIZE, 1);
          crc_read = jp1_read_stream (crc_write, CRC_SIZE, 1);
        }
        }
      jp1_write_JTAG (1); /* UPDATE_DR */
      jp1_write_JTAG (1); /* UPDATE_DR */
 
 
       /* Did JTAG receive packet correctly? */
       /* Did JTAG receive packet correctly? */
      if (chain_has_crc[current_chain])
      if (chain_has_crc[current_chain])
        crc_ok = jp1_read_JTAG ();
        crc_ok = jp1_read_JTAG ();
      jp1_write_JTAG (1); /* SELECT_DR */
      jp1_write_JTAG (1); /* SELECT_DR */
      if (chain_has_crc[current_chain])
      if (chain_has_crc[current_chain])
        {
        {
          if ((crc_read == crc_actual_read) && (crc_ok))
          if ((crc_read == crc_actual_read) && (crc_ok))
            return;
            return;
          JTAG_RETRY_WAIT();
          JTAG_RETRY_WAIT();
        }
        }
      else
      else
        return;
        return;
    }
    }
  err = ERR_CRC;
  err = ERR_CRC;
}
}
 
 
/* Sets scan chain.  */
/* Sets scan chain.  */
 
 
void
void
jtag_set_chain (chain)
jtag_set_chain (chain)
     int chain;
     int chain;
{
{
  if (current_chain != chain)
  if (current_chain != chain)
    {
    {
      if (!chain_is_valid[chain])
      if (!chain_is_valid[chain])
        error ("Chain not valid.");
        error ("Chain not valid.");
 
 
      current_chain = chain;
      current_chain = chain;
      jp1_prepare_control ();
      jp1_prepare_control ();
 
 
      jp1_write_JTAG (0); /* CAPTURE_IR */
      jp1_write_JTAG (0); /* CAPTURE_IR */
      jp1_write_JTAG (0); /* SHIFT_IR */
      jp1_write_JTAG (0); /* SHIFT_IR */
 
 
      /* write data, EXIT1_IR */
      /* write data, EXIT1_IR */
      jp1_write_stream (JI_CHAIN_SELECT, JI_SIZE, 4);
      jp1_write_stream (JI_CHAIN_SELECT, JI_SIZE, 4);
 
 
      jp1_write_JTAG (1); /* UPDATE_IR */
      jp1_write_JTAG (1); /* UPDATE_IR */
      jp1_write_JTAG (1); /* SELECT_DR */
      jp1_write_JTAG (1); /* SELECT_DR */
 
 
      jp1_write_JTAG (0); /* CAPTURE_DR */
      jp1_write_JTAG (0); /* CAPTURE_DR */
      jp1_write_JTAG (0); /* SHIFT_DR */
      jp1_write_JTAG (0); /* SHIFT_DR */
 
 
      /* write data, EXIT1_DR */
      /* write data, EXIT1_DR */
      jp1_write_stream (chain, SC_SIZE, 1);
      jp1_write_stream (chain, SC_SIZE, 1);
 
 
      jp1_write_JTAG (1); /* UPDATE_DR */
      jp1_write_JTAG (1); /* UPDATE_DR */
      jp1_write_JTAG (1); /* SELECT_DR */
      jp1_write_JTAG (1); /* SELECT_DR */
 
 
      /* Now we have to go out of SELECT_CHAIN mode.  */
      /* Now we have to go out of SELECT_CHAIN mode.  */
      jp1_write_JTAG (1); /* SELECT_IR */
      jp1_write_JTAG (1); /* SELECT_IR */
      jp1_write_JTAG (0); /* CAPTURE_IR */
      jp1_write_JTAG (0); /* CAPTURE_IR */
      jp1_write_JTAG (0); /* SHIFT_IR */
      jp1_write_JTAG (0); /* SHIFT_IR */
 
 
      /* write data, EXIT1_IR */
      /* write data, EXIT1_IR */
      jp1_write_stream (JI_DEBUG, JI_SIZE,1 );
      jp1_write_stream (JI_DEBUG, JI_SIZE,1 );
 
 
      jp1_write_JTAG (1); /* UPDATE_IR */
      jp1_write_JTAG (1); /* UPDATE_IR */
      jp1_write_JTAG (1); /* SELECT_DR */
      jp1_write_JTAG (1); /* SELECT_DR */
      select_dr = 1;
      select_dr = 1;
    }
    }
}
}
 
 
/* Initialize a new connection to the or1k board, and make sure we are
/* Initialize a new connection to the or1k board, and make sure we are
   really connected.  */
   really connected.  */
 
 
void
void
jtag_init (args)
jtag_init (args)
     char * args;
     char * args;
{
{
  char *ptype;
  char *ptype;
  char *port_name;
  char *port_name;
  char **argv;
  char **argv;
 
 
  if (args == 0)
  if (args == 0)
    error ("To open a or1k remote debugging connection, you need to specify what parallel\n"
    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");
           "port device is attached to the target board (e.g., /dev/lp0).\n");
 
 
  /* Parse the port name.  */
  /* Parse the port name.  */
  if ((argv = buildargv (args)) == NULL)
  if ((argv = buildargv (args)) == NULL)
    nomem (0);
    nomem (0);
  port_name = strsave (argv[0]);
  port_name = strsave (argv[0]);
  make_cleanup_freeargv (argv);
  make_cleanup_freeargv (argv);
 
 
  /* Open and initialize the parallel port.  */
  /* Open and initialize the parallel port.  */
  lp = open (port_name, O_WRONLY);
  lp = open (port_name, O_WRONLY);
  if (lp < 0)
  if (lp < 0)
    error ("Cannot open device.");
    error ("Cannot open device.");
 
 
  printf_unfiltered ("Remote or1k debugging using %s\n", port_name);
  printf_unfiltered ("Remote or1k debugging using %s\n", port_name);
 
 
  current_chain = -1;
  current_chain = -1;
  jp1_reset_JTAG ();
  jp1_reset_JTAG ();
  jtag_set_chain (SC_RISC_DEBUG);
  jtag_set_chain (SC_RISC_DEBUG);
  free (port_name);
  free (port_name);
}
}
 
 
void
void
jtag_done ()
jtag_done ()
{
{
  close (lp);
  close (lp);
}
}
 
 

powered by: WebSVN 2.1.0

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