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

Subversion Repositories adv_debug_sys

[/] [adv_debug_sys/] [trunk/] [Software/] [adv_jtag_bridge/] [cable_common.c] - Rev 14

Go to most recent revision | Compare with Previous | Blame | View Log

/* cable_common.c -- Interface to the low-level cable drivers
   Copyright (C) 2001 Marko Mlinar, markom@opencores.org
   Copyright (C) 2004 György Jeney, nog@sdf.lonestar.org
   Copyright (C) 2008 Nathan Yawn, nathan.yawn@opencores.org
 
   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., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
 
 
#include <stdio.h>
#include <string.h>
 
 
#include "cable_common.h"
#include "cable_parallel.h"
#include "cable_sim.h"
#include "cable_usbblaster.h"
#include "cable_xpc_dlc9.h"
#include "errcodes.h"
 
#define debug(...)   //fprintf(stderr, __VA_ARGS__ )
 
static struct jtag_cable {
  const char *name;
  int (*inout_func)(uint8_t, uint8_t *);
  int (*out_func)(uint8_t);
  int (*init_func)();
  void (*wait_func)();
  int (*opt_func)(int, char *);
  int (*bit_out_func)(uint8_t);
  int (*bit_inout_func)(uint8_t, uint8_t *);
  int (*stream_out_func)(uint32_t *, int, int);
  int (*stream_inout_func)(uint32_t *, uint32_t *, int, int);
  const char *opts;
  const char *help;
} jtag_cables[] = {
  { "rtl_sim", 
    cable_rtl_sim_inout, 
    cable_rtl_sim_out, 
    cable_rtl_sim_init, 
    NULL, 
    cable_rtl_sim_opt,
    cable_common_write_bit,
    cable_common_read_write_bit,
    cable_common_write_stream, 
    cable_common_read_stream,
    "d:",
    "-d [directory] Directory in which gdb_in.dat/gdb_out.dat may be found\n" },
  { "vpi", 
    cable_vpi_inout, 
    cable_vpi_out, 
    cable_vpi_init, 
    cable_vpi_wait, 
    cable_vpi_opt,
    cable_common_write_bit,
    cable_common_read_write_bit,
    cable_common_write_stream, 
    cable_common_read_stream,
    "s:p:",
    "-p [port] Port number that the VPI module is listening on\n\t-s [server] Server that the VPI module is running on\n" },
  { "xpc3", 
    cable_xpc3_inout, 
    cable_xpc3_out, 
    cable_parallel_init, 
    cable_parallel_phys_wait, 
    cable_parallel_opt,
    cable_common_write_bit,
    cable_common_read_write_bit,
    cable_common_write_stream, 
    cable_common_read_stream, 
    "p:",
    "-p [port] Which port to use when communicating with the parport hardware (eg. 0x378)\n" },
  { "xess", 
    cable_xess_inout, 
    cable_xess_out, 
    cable_parallel_init, 
    cable_parallel_phys_wait, 
    cable_parallel_opt,
    cable_common_write_bit,
    cable_common_read_write_bit,
    cable_common_write_stream, 
    cable_common_read_stream, 
    "p:",
    "-p [port] Which port to use when communicating with the parport hardware (eg. 0x378)\n" },
  { "usbblaster", 
    cable_usbblaster_inout, 
    cable_usbblaster_out, 
    cable_usbblaster_init, 
    NULL, 
    cable_usbblaster_opt,
    cable_common_write_bit,
    cable_common_read_write_bit,
    cable_usbblaster_write_stream, 
    cable_usbblaster_read_stream,
    "",
    "no options\n" },
  { "xpc_usb", 
    cable_xpcusb_inout, 
    cable_xpcusb_out, 
    cable_xpcusb_init, 
    NULL, 
    cable_xpcusb_opt,
    cable_common_write_bit,
    cable_xpcusb_read_write_bit,
    cable_common_write_stream, 
    cable_common_read_stream, 
    "",
    "no options\n" },
  { NULL, NULL, NULL, NULL } };
 
static struct jtag_cable *jtag_cable_in_use = NULL; /* The currently selected cable */
 
 
/////////////////////////////////////////////////////////////////////////////////////
// Cable subsystem / init functions
 
 
/* Selects a cable for use */
int cable_select(const char *cable)
{
  int i;
 
  for(i = 0; jtag_cables[i].name; i++) {
    if(!strcmp(cable, jtag_cables[i].name)) {
      jtag_cable_in_use = &jtag_cables[i];
      return APP_ERR_NONE;
    }
  }
 
  return APP_ERR_CABLE_INVALID;
}
 
/* Calls the init function of the cable 
 */
int cable_init()
{
  return jtag_cable_in_use->init_func();
}
 
/* Parses command-line options specific to the selected cable */
int cable_parse_opt(int c, char *str)
{
  return jtag_cable_in_use->opt_func(c, str);
}
 
const char *cable_get_args()
{
  if(jtag_cable_in_use != NULL)
    return jtag_cable_in_use->opts;
  else
    return NULL;
}
 
/* Prints a (short) useage message for each available cable */
void cable_print_help()
{
  int i;
  printf("Available cables: ");
 
  for(i = 0; jtag_cables[i].name; i++) {
    if(i)
      printf(", ");
    printf("%s", jtag_cables[i].name);
  }
 
  printf("\n\nOptions availible for the cables:\n");
  for(i = 0; jtag_cables[i].name; i++) {
    if(!jtag_cables[i].help)
      continue;
    printf("  %s:\n    %s", jtag_cables[i].name, jtag_cables[i].help);
  }
}
 
 
/////////////////////////////////////////////////////////////////////////////////
// Cable API Functions
 
int cable_write_stream(uint32_t *stream, int len_bits, int set_last_bit) {
  return jtag_cable_in_use->stream_out_func(stream, len_bits, set_last_bit);
}
 
int cable_read_write_stream(uint32_t *outstream, uint32_t *instream, int len_bits, int set_last_bit) {
  return jtag_cable_in_use->stream_inout_func(outstream, instream, len_bits, set_last_bit);
}
 
int cable_write_bit(uint8_t packet) {
  return jtag_cable_in_use->bit_out_func(packet);
}
 
int cable_read_write_bit(uint8_t packet_out, uint8_t *bit_in) {
  return jtag_cable_in_use->bit_inout_func(packet_out, bit_in);
}
 
 
/////////////////////////////////////////////////////////////////////////////////////
// Common functions which may or may not be used by individual drivers
 
 
/* Note that these make no assumption as to the starting state of the clock,
 * and they leave the clock HIGH.  But, these need to interface with other routines (like
 * the byte-shift mode in the USB-Blaster), which begin by assuming that a new
 * data bit is available at TDO, which only happens after a FALLING edge of TCK.
 * So, routines which assume new data is available will need to start by dropping
 * the clock.
 */
int cable_common_write_bit(uint8_t packet) {
  uint8_t data = TRST_BIT;  // TRST is active low, don't clear unless /set/ in 'packet'
  int err = APP_ERR_NONE;
 
  /* Write data, drop clock */
  if(packet & TDO) data |= TDI_BIT;
  if(packet & TMS) data |= TMS_BIT;
  if(packet & TRST) data &= ~TRST_BIT;
 
  err |= jtag_cable_in_use->out_func(data);
  if (jtag_cable_in_use->wait_func != NULL) jtag_cable_in_use->wait_func();
 
  /* raise clock, to do write */
  err |= jtag_cable_in_use->out_func(data | TCLK_BIT);
   if (jtag_cable_in_use->wait_func != NULL) jtag_cable_in_use->wait_func();  
 
  return err;
}
 
int cable_common_read_write_bit(uint8_t packet_out, uint8_t *bit_in) {
  uint8_t data = TRST_BIT;  //  TRST is active low, don't clear unless /set/ in 'packet'
  int err = APP_ERR_NONE;
 
  /* Write data, drop clock */
  if(packet_out & TDO) data |= TDI_BIT;
  if(packet_out & TMS) data |= TMS_BIT;
  if(packet_out & TRST) data &= ~TRST_BIT;
 
  err |= jtag_cable_in_use->out_func(data);  // drop the clock to make data available, set the out data
  if (jtag_cable_in_use->wait_func != NULL) jtag_cable_in_use->wait_func();
  err |= jtag_cable_in_use->inout_func((data | TCLK_BIT), bit_in);  // read in bit, clock high for out bit.
  if (jtag_cable_in_use->wait_func != NULL) jtag_cable_in_use->wait_func();
 
  return err;
}
 
 
/* Writes bitstream via bit-bang. Can be used by any driver which does not have a high-speed transfer function.
 * Transfers LSB to MSB of stream[0], then LSB to MSB of stream[1], etc.
 */
int cable_common_write_stream(uint32_t *stream, int len_bits, int set_last_bit) {
  int i;
  int index = 0;
  int bits_this_index = 0;
  uint8_t out;
  int err = APP_ERR_NONE;
 
  debug("writeSrrm%d(", len_bits);
  for(i = 0; i < len_bits - 1; i++) {
    out = (stream[index] >> bits_this_index) & 1;
    err |= cable_write_bit(out);
    debug("%i", out);
    bits_this_index++;
    if(bits_this_index >= 32) {
      index++;
      bits_this_index = 0;
    }
  }
 
  out = (stream[index] >>(len_bits - 1)) & 0x1;
  if(set_last_bit) out |= TMS;
  err |= cable_write_bit(out);
  debug("%i)\n", out);
  return err;
}
 
/* Gets bitstream via bit-bang.  Can be used by any driver which does not have a high-speed transfer function.
 * Transfers LSB to MSB of stream[0], then LSB to MSB of stream[1], etc.
 */
int cable_common_read_stream(uint32_t *outstream, uint32_t *instream, int len_bits, int set_last_bit) {
  int i;
  int index = 0;
  int bits_this_index = 0;
  uint8_t inval, outval;
  int err = APP_ERR_NONE;
 
  instream[0] = 0;
 
  debug("readStrm%d(", len_bits);
  for(i = 0; i < (len_bits - 1); i++) {      
    outval = (outstream[index] >> bits_this_index) & 0x1;
    err |= cable_read_write_bit(outval, &inval);
    debug("%i", inval);
    instream[index] |= (inval << bits_this_index);
    bits_this_index++;
    if(bits_this_index >= 32) {
      index++;
      bits_this_index = 0;
      instream[index] = 0;  // It's safe to do this, because there's always at least one more bit
    }   
  }
 
  if (set_last_bit)
    outval = ((outstream[index] >> (len_bits - 1)) & 1) | TMS;
  else
    outval = (outstream[index] >> (len_bits - 1)) & 1; 
 
  err |= cable_read_write_bit(outval, &inval);
  debug("%i", inval);
  instream[index] |= (inval << bits_this_index);  
 
  debug(") = 0x%lX\n", instream[0]);
 
  return err;
}
 
 
 
 

Go to most recent revision | 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.