Line 1... |
Line 1... |
/* adv_jtag_bridge.c -- JTAG protocol bridge between GDB and Advanced debug module.
|
/* adv_jtag_bridge.c -- JTAG protocol bridge between GDB and Advanced debug module.
|
Copyright(C) 2001 Marko Mlinar, markom@opencores.org
|
Copyright(C) 2001 Marko Mlinar, markom@opencores.org
|
Code for TCP/IP copied from gdb, by Chris Ziomkowski
|
Code for TCP/IP copied from gdb, by Chris Ziomkowski
|
Refactoring by Nathan Yawn, nyawn@opencores.org
|
Refactoring by Nathan Yawn <nyawn@opencores.org> (C) 2008 - 2010
|
|
|
This file was part of the OpenRISC 1000 Architectural Simulator.
|
This file was part of the OpenRISC 1000 Architectural Simulator.
|
It is now also used to connect GDB to a running hardware OpenCores / OR1200
|
It is now also used to connect GDB to a running hardware OpenCores / OR1200
|
advanced debug unit.
|
advanced debug unit.
|
|
|
Line 37... |
Line 37... |
#include "chain_commands.h"
|
#include "chain_commands.h"
|
#include "cable_common.h"
|
#include "cable_common.h"
|
#include "or32_selftest.h"
|
#include "or32_selftest.h"
|
#include "bsdl.h"
|
#include "bsdl.h"
|
#include "errcodes.h"
|
#include "errcodes.h"
|
#include "cable_usbblaster.h"
|
|
|
|
#define debug(...) //fprintf(stderr, __VA_ARGS__ )
|
#define debug(...) //fprintf(stderr, __VA_ARGS__ )
|
|
|
// How many command-line IR length settings to create by default
|
// How many command-line IR length settings to create by default
|
#define IR_START_SETS 16
|
#define IR_START_SETS 16
|
Line 83... |
Line 82... |
|
|
|
|
// Pointer to the command line arg used as the cable name
|
// Pointer to the command line arg used as the cable name
|
char * cable_name = NULL;
|
char * cable_name = NULL;
|
|
|
// How many jtag devices in the scan chain.
|
|
unsigned int max_devices = 1;
|
|
|
|
////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////
|
// List of IDCODES of devices on the JTAG scan chain
|
// List of IDCODES of devices on the JTAG scan chain
|
// The array is dynamically allocated in chain_commands/jtag_enumerate_chain()
|
// The array is dynamically allocated in chain_commands/jtag_enumerate_chain()
|
|
|
uint32_t *idcodes = NULL;
|
uint32_t *idcodes = NULL;
|
Line 121... |
Line 117... |
//////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////
|
/*----------------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------------*/
|
// Functions
|
// Functions
|
/////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// If we are using ftdi library for usb-blaster, close the device before we leave
|
|
void close_ftdi_device(void)
|
|
{
|
|
#ifdef __SUPPORT_FTDI_CABLES__
|
|
if (!strcmp(cable_name, "usbblaster_ftdi")) {
|
|
printf("Free ftdi device\n");
|
|
ftdi_usb_blaster_quit();
|
|
}
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
// Resets JTAG, and sets up DEBUG scan chain
|
// Resets JTAG, and sets up DEBUG scan chain
|
void configure_chain(void)
|
void configure_chain(void)
|
{
|
{
|
int i;
|
int i;
|
unsigned int manuf_id;
|
unsigned int manuf_id;
|
Line 181... |
Line 164... |
fprintf(stderr, "*** debug unit, or change your SoC to use the Advanced Debug Unit.\n");
|
fprintf(stderr, "*** debug unit, or change your SoC to use the Advanced Debug Unit.\n");
|
exit(0);
|
exit(0);
|
}
|
}
|
#endif
|
#endif
|
|
|
|
|
if(target_dev_pos >= num_devices) {
|
if(target_dev_pos >= num_devices) {
|
printf("ERROR: Requested target device (%i) beyond highest device index (%i).\n", target_dev_pos, num_devices-1);
|
printf("ERROR: Requested target device (%i) beyond highest device index (%i).\n", target_dev_pos, num_devices-1);
|
exit(1);
|
exit(1);
|
} else {
|
} else {
|
printf("Target device %i, JTAG ID = 0x%08x\n", target_dev_pos, idcodes[target_dev_pos]);
|
printf("Target device %i, JTAG ID = 0x%08x\n", target_dev_pos, idcodes[target_dev_pos]);
|
}
|
}
|
|
|
manuf_id = (idcodes[target_dev_pos] >> 1) & 0x7FF;
|
manuf_id = (idcodes[target_dev_pos] >> 1) & 0x7FF;
|
|
|
// Note that there's a little translation here, since device index 0 is actually closest to the cable data input
|
|
config_set_DR_prefix_bits(num_devices - target_dev_pos - 1); // number of devices between cable data out and target device
|
|
config_set_DR_postfix_bits(target_dev_pos); // number of devices between target device and cable data in
|
|
|
|
// Set Altera Virtual JTAG mode on or off. If not forced, then enable
|
|
// if the target device has an Altera manufacturer IDCODE
|
|
if(force_alt_vjtag == 1 || manuf_id == ALTERA_MANUFACTURER_ID) {
|
|
int ir_size;
|
|
int debug_cmd;
|
|
|
|
ir_size = cmd_line_ir_sizes[target_dev_pos].ir_length > 0 ? cmd_line_ir_sizes[target_dev_pos].ir_length : 10;
|
|
debug_cmd = cmd_line_cmd_debug > 0 ? cmd_line_cmd_debug : 0x8;
|
|
|
|
printf("Working on Altera Virtual JTAG device. IR size = %d, Debeg command = 0x%x\n", ir_size, debug_cmd);
|
|
|
|
config_set_alt_vjtag(1);
|
|
config_set_IR_size(ir_size);
|
|
config_set_debug_cmd(debug_cmd);
|
|
|
|
} else { // Not a Altera JTAG
|
|
|
|
// Use BSDL files to determine prefix bits, postfix bits, debug command, IR length
|
// Use BSDL files to determine prefix bits, postfix bits, debug command, IR length
|
config_set_IR_size(get_IR_size(target_dev_pos));
|
config_set_IR_size(get_IR_size(target_dev_pos));
|
|
|
// Set the IR prefix / postfix bits
|
// Set the IR prefix / postfix bits
|
int total = 0;
|
int total = 0;
|
Line 230... |
Line 193... |
debug("Adding %i to total for devidx %i\n", get_IR_size(i), i);
|
debug("Adding %i to total for devidx %i\n", get_IR_size(i), i);
|
}
|
}
|
config_set_IR_prefix_bits(total);
|
config_set_IR_prefix_bits(total);
|
debug("Prefix bits: %d\n", total);
|
debug("Prefix bits: %d\n", total);
|
|
|
|
|
|
// Note that there's a little translation here, since device index 0 is actually closest to the cable data input
|
|
config_set_DR_prefix_bits(num_devices - target_dev_pos - 1); // number of devices between cable data out and target device
|
|
config_set_DR_postfix_bits(target_dev_pos); // number of devices between target device and cable data in
|
|
|
// Set the DEBUG command for the IR of the target device.
|
// Set the DEBUG command for the IR of the target device.
|
// If this is a Xilinx device, use USER1 instead of DEBUG
|
// If this is a Xilinx device, use USER1 instead of DEBUG
|
// If we Altera Virtual JTAG mode, we don't care.
|
// If we Altera Virtual JTAG mode, we don't care.
|
if((force_alt_vjtag == 0) && (manuf_id != ALTERA_MANUFACTURER_ID)) {
|
if((force_alt_vjtag == -1) || ((force_alt_vjtag == 0) && (manuf_id != ALTERA_MANUFACTURER_ID))) {
|
cmd = get_debug_cmd(target_dev_pos);
|
cmd = get_debug_cmd(target_dev_pos);
|
if(cmd == TAP_CMD_INVALID) {
|
if(cmd == TAP_CMD_INVALID) {
|
printf("Unable to find DEBUG command, aborting.\n");
|
printf("Unable to find DEBUG command, aborting.\n");
|
exit(1);
|
exit(1);
|
}
|
}
|
Line 248... |
Line 216... |
// Safe, but slower, for non-BSCAN TAPs.
|
// Safe, but slower, for non-BSCAN TAPs.
|
if(manuf_id == XILINX_MANUFACTURER_ID) {
|
if(manuf_id == XILINX_MANUFACTURER_ID) {
|
config_set_xilinx_bscan(1);
|
config_set_xilinx_bscan(1);
|
}
|
}
|
|
|
|
// Set Altera Virtual JTAG mode on or off. If not forced, then enable
|
|
// if the target device has an Altera manufacturer IDCODE
|
|
if(force_alt_vjtag == 1) {
|
|
config_set_alt_vjtag(1);
|
|
} else if(force_alt_vjtag == -1) {
|
config_set_alt_vjtag(0);
|
config_set_alt_vjtag(0);
|
|
} else {
|
|
if(manuf_id == ALTERA_MANUFACTURER_ID) {
|
|
config_set_alt_vjtag(1);
|
|
} else {
|
|
config_set_alt_vjtag(0);
|
|
}
|
}
|
}
|
|
|
// Do a sanity test
|
// Do a sanity test
|
cmd = bsdl_get_idcode_cmd(idcodes[target_dev_pos]);
|
cmd = bsdl_get_idcode_cmd(idcodes[target_dev_pos]);
|
if(cmd != TAP_CMD_INVALID) {
|
if(cmd != TAP_CMD_INVALID) {
|
Line 269... |
Line 248... |
} else {
|
} else {
|
printf("Warning: IDCODE sanity test failed. Read IDCODE 0x%08X, expected 0x%08X\n", id_read, idcodes[target_dev_pos]);
|
printf("Warning: IDCODE sanity test failed. Read IDCODE 0x%08X, expected 0x%08X\n", id_read, idcodes[target_dev_pos]);
|
}
|
}
|
}
|
}
|
|
|
printf("Enable Debug Module\n");
|
|
if(err |= tap_enable_debug_module()) { // Select the debug unit in the TAP.
|
if(err |= tap_enable_debug_module()) { // Select the debug unit in the TAP.
|
printf("Error %s enabling debug module, aborting.\n", get_err_string(err));
|
printf("Error %s enabling debug module, aborting.\n", get_err_string(err));
|
close_ftdi_device();
|
|
exit(1);
|
exit(1);
|
}
|
}
|
}
|
}
|
|
|
|
|
Line 290... |
Line 267... |
#endif
|
#endif
|
printf("Copyright (C) 2008 Nathan Yawn, nathan.yawn@opencores.org\n\n");
|
printf("Copyright (C) 2008 Nathan Yawn, nathan.yawn@opencores.org\n\n");
|
printf("Usage: %s (options) [cable] (cable options)\n", func);
|
printf("Usage: %s (options) [cable] (cable options)\n", func);
|
printf("Options:\n");
|
printf("Options:\n");
|
printf("\t-g [port] : port number for GDB (default: 9999)\n");
|
printf("\t-g [port] : port number for GDB (default: 9999)\n");
|
printf("\t-d [num] : Set the maximum devices in the scan chain (default: 1)\n");
|
|
printf("\t-x [index] : Position of the target device in the scan chain\n");
|
printf("\t-x [index] : Position of the target device in the scan chain\n");
|
printf("\t-a [0 / 1] : force Altera virtual JTAG mode off (0) or on (1)\n");
|
printf("\t-a [0 / 1] : force Altera virtual JTAG mode off (0) or on (1)\n");
|
printf("\t-l [<index>:<bits>] : Specify length of IR register for device\n");
|
printf("\t-l [<index>:<bits>] : Specify length of IR register for device\n");
|
printf("\t <index>, override autodetect (if any)\n");
|
printf("\t <index>, override autodetect (if any)\n");
|
printf("\t-c [hex cmd] : Debug command for target TAP, override autodetect\n");
|
printf("\t-c [hex cmd] : Debug command for target TAP, override autodetect\n");
|
Line 319... |
Line 295... |
port = NULL;
|
port = NULL;
|
force_alt_vjtag = 0;
|
force_alt_vjtag = 0;
|
cmd_line_cmd_debug = -1;
|
cmd_line_cmd_debug = -1;
|
|
|
/* Parse the global arguments (if-any) */
|
/* Parse the global arguments (if-any) */
|
while((c = getopt(argc, argv, "+g:d:x:a:l:c:v:r:b:th")) != -1) {
|
while((c = getopt(argc, argv, "+g:x:a:l:c:v:r:b:th")) != -1) {
|
switch(c) {
|
switch(c) {
|
case 'h':
|
case 'h':
|
print_usage(argv[0]);
|
print_usage(argv[0]);
|
exit(0);
|
exit(0);
|
break;
|
break;
|
case 'g':
|
case 'g':
|
port = optarg;
|
port = optarg;
|
break;
|
break;
|
case 'd':
|
|
max_devices = atoi(optarg);
|
|
break;
|
|
case 'x':
|
case 'x':
|
target_dev_pos = atoi(optarg);
|
target_dev_pos = atoi(optarg);
|
break;
|
break;
|
case 'l':
|
case 'l':
|
get_ir_opts(optarg, &idx, &val); // parse the option
|
get_ir_opts(optarg, &idx, &val); // parse the option
|
Line 420... |
Line 393... |
}
|
}
|
}
|
}
|
}
|
}
|
|
|
|
|
|
|
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
char *s;
|
char *s;
|
long int serverPort;
|
long int serverPort;
|
|
|
srand(getpid());
|
srand(getpid());
|
Line 449... |
Line 423... |
if(do_selftest) {
|
if(do_selftest) {
|
// Test the connection.
|
// Test the connection.
|
printf("*** Doing self-test ***\n");
|
printf("*** Doing self-test ***\n");
|
if(dbg_test() != APP_ERR_NONE) {
|
if(dbg_test() != APP_ERR_NONE) {
|
printf("Self-test FAILED *** Bailing out!\n");
|
printf("Self-test FAILED *** Bailing out!\n");
|
close_ftdi_device();
|
|
exit(1);
|
exit(1);
|
}
|
}
|
printf("*** Self-test PASSED ***\n");
|
printf("*** Self-test PASSED ***\n");
|
}
|
}
|
|
|
/* We have a connection. Establish server. */
|
/* We have a connection. Establish server. */
|
serverPort = strtol(port,&s,10);
|
serverPort = strtol(port,&s,10);
|
if(*s) {
|
if(*s) return -1;
|
close_ftdi_device();
|
|
return -1;
|
|
}
|
|
|
|
rsp_init(serverPort);
|
rsp_init(serverPort);
|
|
|
printf("JTAG bridge ready!\n");
|
printf("JTAG bridge ready!\n");
|
|
|
Line 472... |
Line 442... |
// with the select()/poll(), but the or1ksim rsp code (ported for use here) doesn't work
|
// with the select()/poll(), but the or1ksim rsp code (ported for use here) doesn't work
|
// that way, and I don't want to rework that code (to make it easier to import fixes
|
// that way, and I don't want to rework that code (to make it easier to import fixes
|
// written for the or1ksim rsp server). --NAY
|
// written for the or1ksim rsp server). --NAY
|
while(handle_rsp());
|
while(handle_rsp());
|
|
|
close_ftdi_device();
|
|
|
|
return 0;
|
return 0;
|
}
|
}
|
|
|
//////////////////////////////////////////////////
|
//////////////////////////////////////////////////
|
// Helper functions
|
// Helper functions
|