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

Subversion Repositories adv_debug_sys

[/] [adv_debug_sys/] [tags/] [ADS_RELEASE_1_1_0/] [Software/] [adv_jtag_bridge/] [adv_jtag_bridge.c] - Blame information for rev 4

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

Line No. Rev Author Line
1 4 nyawn
/* adv_jtag_bridge.c -- JTAG protocol bridge between GDB and Advanced debug module.
2
   Copyright(C) 2001 Marko Mlinar, markom@opencores.org
3
   Code for TCP/IP copied from gdb, by Chris Ziomkowski
4
   Refactoring by Nathan Yawn, nyawn@opencores.org
5
 
6
   This file was part of the OpenRISC 1000 Architectural Simulator.
7
   It is now also used to connect GDB to a running hardware OpenCores / OR1200
8
   advanced debug unit.
9
 
10
   This program is free software; you can redistribute it and/or modify
11
   it under the terms of the GNU General Public License as published by
12
   the Free Software Foundation; either version 2 of the License, or
13
   (at your option) any later version.
14
 
15
   This program is distributed in the hope that it will be useful,
16
   but WITHOUT ANY WARRANTY; without even the implied warranty of
17
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
   GNU General Public License for more details.
19
 
20
   You should have received a copy of the GNU General Public License
21
   along with this program; if not, write to the Free Software
22
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
23
 
24
/* Establishes jtag proxy server and communicates with parallel
25
   port directly.  Requires root access. */
26
 
27
#include <stdio.h>
28
#include <stdlib.h>  // for exit(), atoi(), strtoul()
29
#include <unistd.h>
30
#include <stdarg.h>
31
#include <string.h>  // for strstr()
32
#include <sys/types.h>
33
 
34
 
35
#include "adv_jtag_bridge.h"
36
#include "rsp-server.h"
37
#include "chain_commands.h"
38
#include "cable_common.h"
39
#include "or32_selftest.h"
40
#include "bsdl.h"
41
#include "errcodes.h"
42
 
43
#define debug(...) //fprintf(stderr, __VA_ARGS__ )
44
 
45
// How many command-line IR length settings to create by default
46
#define IR_START_SETS 16
47
 
48
//////////////////////////////////////////////////
49
// Command line option flags / values
50
 
51
/* Which device in the scan chain we want to target.
52
 * 0 is the first device we find, which is nearest the data input of the cable.
53
 */
54
unsigned int target_dev_pos = 0;
55
 
56
// Do test before setting up server?
57
unsigned char do_selftest = 0;
58
 
59
// IR register length in TAP of 
60
// Can override autoprobe, or set if IDCODE not supported
61
typedef struct {
62
  int dev_index;
63
  int ir_length;
64
} irset;
65
 
66
#define START_IR_SETS 16
67
int reallocs = 0;
68
int num_ir_sets = 0;
69
irset * cmd_line_ir_sizes = NULL;
70
 
71
// DEBUG command for target device TAP
72
// May actually be USER1, for Xilinx devices using internal BSCAN modules
73
// Can override autoprobe, or set if unable to find in BSDL files
74
int cmd_line_cmd_debug = -1;  // 0 is a valid debug command, so use -1
75
 
76
// TCP port to set up the server for GDB on
77
char *port;
78
char default_port[] = "9999";
79
 
80
// Force altera virtual jtag mode on(1) or off(-1)
81
int force_alt_vjtag = 0;
82
 
83
 
84
// Pointer to the command line arg used as the cable name
85
char * cable_name = NULL;
86
 
87
////////////////////////////////////////////////////////
88
// List of IDCODES of devices on the JTAG scan chain
89
// The array is dynamically allocated in chain_commands/jtag_enumerate_chain()
90
 
91
uint32_t *idcodes = NULL;
92
int num_devices = 0;
93
 
94
 
95
const char *name_not_found = "(unknown)";
96
 
97
///////////////////////////////////////////////////////////
98
// JTAG constants
99
 
100
// Defines for Altera JTAG constants
101
#define ALTERA_MANUFACTURER_ID   0x6E
102
 
103
// Defines for Xilinx JTAG constants
104
#define XILINX_MANUFACTURER_ID   0x49
105
 
106
 
107
///////////////////////////////////////////////////
108
// Prototypes for local / helper functions
109
int get_IR_size(int devidx);
110
uint32_t get_debug_cmd(int devidx);
111
void configure_chain(void);
112
void print_usage(char *func);
113
void parse_args(int argc, char **argv);
114
void get_ir_opts(char *optstr, int *idx, int *val);
115
 
116
 
117
//////////////////////////////////////////////////////////////////////////////////////
118
/*----------------------------------------------------------------------------------*/
119
// Functions
120
/////////////////////////////////////////////////////////////////////////////////////
121
 
122
// Resets JTAG, and sets up DEBUG scan chain
123
void configure_chain(void)
124
{
125
  int i;
126
  unsigned int manuf_id;
127
  uint32_t cmd;
128
  const char *name;
129
  int irlen;
130
  int err = APP_ERR_NONE;
131
 
132
  err |= tap_reset();
133
  err |= jtag_enumerate_chain(&idcodes, &num_devices);
134
 
135
  if(err != APP_ERR_NONE) {
136
    printf("Error %s enumerating JTAG chain, aborting.\n", get_err_string(err));
137
    exit(1);
138
  }
139
 
140
  printf("\nDevices on JTAG chain:\n");
141
  printf("Index\tName\t\tID Code\t\tIR Length\n");
142
  printf("----------------------------------------------------------------\n");
143
  for(i = 0; i < num_devices; i++)
144
    {
145
      if(idcodes[i] != IDCODE_INVALID) {
146
        name = bsdl_get_name(idcodes[i]);
147
        irlen = bsdl_get_IR_size(idcodes[i]);
148
        if(name == NULL)
149
          name = name_not_found;
150
      } else {
151
        name = name_not_found;
152
        irlen = -1;
153
      }
154
      printf("%d: \t%s \t0x%08lX \t%d\n", i, name, idcodes[i], irlen);
155
    }
156
  printf("\n");
157
 
158
  if(target_dev_pos >= num_devices) {
159
    printf("ERROR:  Requested target device (%i) beyond highest device index (%i).\n", target_dev_pos, num_devices-1);
160
    exit(1);
161
  } else {
162
    printf("Target device %i, JTAG ID = 0x%08lx\n", target_dev_pos, idcodes[target_dev_pos]);
163
  }
164
 
165
  manuf_id = (idcodes[target_dev_pos] >> 1) & 0x7FF;
166
 
167
  // Use BSDL files to determine prefix bits, postfix bits, debug command, IR length
168
  config_set_IR_size(get_IR_size(target_dev_pos));
169
 
170
  // Set the IR prefix / postfix bits
171
  int total = 0;
172
  for(i = 0; i < num_devices; i++) {
173
    if(i == target_dev_pos) {
174
      config_set_IR_postfix_bits(total);
175
      //debug("Postfix bits: %d\n", total);
176
      total = 0;
177
      continue;
178
    }
179
 
180
    total += get_IR_size(i);
181
    debug("Adding %i to total for devidx %i\n", get_IR_size(i), i);
182
  }
183
  config_set_IR_prefix_bits(total);
184
  debug("Prefix bits: %d\n", total);
185
 
186
 
187
  // Note that there's a little translation here, since device index 0 is actually closest to the cable data input
188
  config_set_DR_prefix_bits(num_devices - target_dev_pos - 1);  // number of devices between cable data out and target device
189
  config_set_DR_postfix_bits(target_dev_pos);  // number of devices between target device and cable data in
190
 
191
  // Set the DEBUG command for the IR of the target device.
192
  // If this is a Xilinx device, use USER1 instead of DEBUG
193
  // If we Altera Virtual JTAG mode, we don't care.
194
  if((force_alt_vjtag == -1) || ((force_alt_vjtag == 0) &&  (manuf_id != ALTERA_MANUFACTURER_ID))) {
195
    cmd = get_debug_cmd(target_dev_pos);
196
    if(cmd == TAP_CMD_INVALID) {
197
      printf("Unable to find DEBUG command, aborting.\n");
198
      exit(1);
199
    }
200
    config_set_debug_cmd(cmd);  // This may have to be USER1 if this is a Xilinx device   
201
  }
202
 
203
  // Enable the kludge for Xilinx BSCAN, if necessary.
204
  // Safe, but slower, for non-BSCAN TAPs.
205
  if(manuf_id == XILINX_MANUFACTURER_ID) {
206
    config_set_xilinx_bscan(1);
207
  }
208
 
209
  // Set Altera Virtual JTAG mode on or off.  If not forced, then enable
210
  // if the target device has an Altera manufacturer IDCODE
211
  if(force_alt_vjtag == 1) {
212
    config_set_alt_vjtag(1);
213
  } else if(force_alt_vjtag == -1) {
214
    config_set_alt_vjtag(0);
215
  } else {
216
    if(manuf_id == ALTERA_MANUFACTURER_ID) {
217
      config_set_alt_vjtag(1);
218
    } else {
219
      config_set_alt_vjtag(0);
220
    }
221
  }
222
 
223
  // Do a sanity test
224
  cmd = bsdl_get_idcode_cmd(idcodes[target_dev_pos]);
225
  if(cmd != TAP_CMD_INVALID) {
226
       uint32_t id_read;
227
       err |= jtag_get_idcode(cmd, &id_read);
228
 
229
       if(err != APP_ERR_NONE) {
230
         printf("Error %s checking IDCODE, aborting.\n", get_err_string(err));
231
         exit(1);
232
       }
233
 
234
       if(id_read == idcodes[target_dev_pos]) {
235
         printf("IDCODE sanity test passed, chain OK!\n");
236
       } else {
237
         printf("Warning: IDCODE sanity test failed.  Read IDCODE 0x%08lX, expected 0x%08lX\n", id_read, idcodes[target_dev_pos]);
238
       }
239
     }
240
 
241
  if(err |= tap_enable_debug_module()) {  // Select the debug unit in the TAP.
242
    printf("Error %s enabling debug module, aborting.\n", get_err_string(err));
243
    exit(1);
244
  }
245
}
246
 
247
 
248
void print_usage(char *func)
249
{
250
  printf("JTAG connection between GDB and the Advanced Debug Interface.\n");
251
  printf("Copyright (C) 2008 Nathan Yawn, nathan.yawn@opencores.org\n\n");
252
  printf("Usage: %s (options) [cable] (cable options)\n", func);
253
  printf("Options:\n");
254
  printf("\t-g [port]     : port number for GDB (default: 9999)\n");
255
  printf("\t-x [index]    : Position of the target device in the scan chain\n");
256
  printf("\t-a [0 / 1]    : force Altera virtual JTAG mode off (0) or on (1)\n");
257
  printf("\t-l [<index>:<bits>]     : Specify length of IR register for device\n");
258
  printf("\t                <index>, override autodetect (if any)\n");
259
  printf("\t-c [hex cmd]  : Debug command for target TAP, override autodetect\n");
260
  printf("\t                (ignored for Altera targets)\n");
261
  printf("\t-v [hex cmd]  : VIR command for target TAP, override autodetect\n");
262
  printf("\t                (Altera virtual JTAG targets only)\n");
263
  printf("\t-r [hex cmd]  : VDR for target TAP, override autodetect\n");
264
  printf("\t                (Altera virtual JTAG targets only)\n");
265
  printf("\t-b [dirname]  : Add a directory to search for BSDL files\n");
266
  printf("\t-t            : perform CPU / memory self-test before starting server\n");
267
  printf("\t-h            : show help\n\n");
268
  cable_print_help();
269
}
270
 
271
 
272
void parse_args(int argc, char **argv)
273
{
274
  int c;
275
  int i;
276
  int idx, val;
277
  const char *valid_cable_args = NULL;
278
  port = NULL;
279
  force_alt_vjtag = 0;
280
  cmd_line_cmd_debug = -1;
281
 
282
  /* Parse the global arguments (if-any) */
283
  while((c = getopt(argc, argv, "+g:x:a:l:c:v:r:b:th")) != -1) {
284
    switch(c) {
285
    case 'h':
286
      print_usage(argv[0]);
287
      exit(0);
288
      break;
289
    case 'g':
290
      port = optarg;
291
      break;
292
    case 'x':
293
      target_dev_pos = atoi(optarg);
294
      break;
295
    case 'l':
296
      get_ir_opts(optarg, &idx, &val);        // parse the option
297
      if(num_ir_sets >= (IR_START_SETS<<reallocs)) {
298
        cmd_line_ir_sizes = (irset *) realloc(cmd_line_ir_sizes, (IR_START_SETS<<reallocs)*sizeof(irset));
299
        if(cmd_line_ir_sizes == NULL) {
300
          printf("Error: out of memory while parsing command line.  Aborting.\n");
301
          exit(1);
302
        }
303
      }
304
      cmd_line_ir_sizes[num_ir_sets].dev_index = idx;
305
      cmd_line_ir_sizes[num_ir_sets].ir_length = val;
306
      num_ir_sets++;
307
      break;
308
    case 'c':
309
      cmd_line_cmd_debug = strtoul(optarg, NULL, 16);
310
      break;
311
    case 'v':
312
      config_set_vjtag_cmd_vir(strtoul(optarg, NULL, 16));
313
      break;
314
    case 'r':
315
      config_set_vjtag_cmd_vdr(strtoul(optarg, NULL, 16));
316
      break;
317
    case 't':
318
      do_selftest = 1;
319
      break;
320
     case 'a':
321
       if(atoi(optarg) == 1)
322
        force_alt_vjtag = 1;
323
       else
324
        force_alt_vjtag = -1;
325
       break;
326
    case 'b':
327
       bsdl_add_directory(optarg);
328
      break;
329
    default:
330
      print_usage(argv[0]);
331
      exit(1);
332
    }
333
  }
334
 
335
  if(port == NULL)
336
    port = default_port;
337
 
338
  int found_cable = 0;
339
  char* start_str = argv[optind];
340
  int start_idx = optind;
341
  for(i = optind; i < argc; i++) {
342
    if(cable_select(argv[i]) == APP_ERR_NONE) {
343
      found_cable = 1;
344
      cable_name = argv[i];
345
      argv[optind] = argv[start_idx];  // swap the cable name with the other arg,
346
      argv[start_idx] = start_str;     // keep all cable opts at the end
347
      break;
348
    }
349
  }
350
 
351
 
352
  if(!found_cable) {
353
    fprintf(stderr, "No valid cable specified.\n");
354
    exit(1);
355
  }
356
 
357
  optind = start_idx+1;  // reset the parse index
358
 
359
    /* Get the cable-arguments */
360
  valid_cable_args = cable_get_args();
361
 
362
  /* Parse the remaining options for the cable.
363
   * Note that this will include unrecognized option from before the cable name.
364
   */
365
  while((c = getopt(argc, argv, valid_cable_args)) != -1) {
366
    //printf("Got cable opt %c (0x%X)\n", (char)c, c);
367
    if(c == '?') {
368
      printf("\nERROR:  Unknown cable option \'-%c\'\n\n", optopt);
369
      print_usage(argv[0]);
370
      exit(1);
371
    }
372
    else if(cable_parse_opt(c, optarg) != APP_ERR_NONE) {
373
      printf("\nERROR:  Failed to parse cable option \'-%c\' %s\n\n", (char)c, optarg);
374
      print_usage(argv[0]);
375
      exit(1);
376
    }
377
  }
378
}
379
 
380
 
381
 
382
int main(int argc,  char *argv[]) {
383
  char *s;
384
  long int serverPort;
385
 
386
  srand(getpid());
387
  bsdl_init();
388
  cmd_line_ir_sizes = (irset *) malloc(IR_START_SETS * sizeof(irset));
389
  if(cmd_line_ir_sizes == NULL) {
390
    printf("ERROR: out of memory allocating array for IR sizes.\n");
391
    return 1;
392
  }
393
 
394
  parse_args(argc, argv);
395
 
396
  if(cable_init() != APP_ERR_NONE) {
397
    printf("Failed to initialize cable \'%s\', aborting.\n", cable_name);
398
    exit(1);
399
  }
400
 
401
 
402
  /* Initialize a new connection to the or1k board, and make sure we are
403
     really connected.  */
404
  configure_chain();
405
 
406
  if(do_selftest) {
407
    // Test the connection.
408
    printf("*** Doing self-test ***\n");
409
    if(dbg_test() != APP_ERR_NONE) {
410
      printf("Self-test FAILED *** Bailing out!\n");
411
      exit(1);
412
    }
413
    printf("*** Self-test PASSED ***\n");
414
  }
415
 
416
  /* We have a connection.  Establish server.  */
417
  serverPort = strtol(port,&s,10);
418
  if(*s) return -1;
419
 
420
  rsp_init(serverPort);
421
 
422
  printf("JTAG bridge ready!\n");
423
 
424
  // This handles requests from GDB.  I'd prefer the while() loop to be in the function
425
  // with the select()/poll(), but the or1ksim rsp code (ported for use here) doesn't work 
426
  // that way, and I don't want to rework that code (to make it easier to import fixes
427
  // written for the or1ksim rsp server).  --NAY
428
  while(handle_rsp());
429
 
430
  return 0;
431
}
432
 
433
//////////////////////////////////////////////////
434
// Helper functions
435
 
436
int get_IR_size(int devidx)
437
{
438
  int retval = -1;
439
  int i;
440
 
441
  if(idcodes[devidx] != IDCODE_INVALID) {
442
    retval = bsdl_get_IR_size(idcodes[devidx]);
443
  }
444
 
445
  // Search for this devices in the array of command line IR sizes
446
  for(i = 0; i < num_ir_sets; i++) {
447
    if(cmd_line_ir_sizes[i].dev_index == devidx) {
448
      if((retval > 0) && (retval != cmd_line_ir_sizes[i].ir_length))
449
        printf("Warning: overriding autoprobed IR length (%i) with command line value (%i) for device %i\n", retval,
450
                            cmd_line_ir_sizes[i].ir_length, devidx);
451
      retval = cmd_line_ir_sizes[i].ir_length;
452
    }
453
  }
454
 
455
  if(retval < 0) {  // Make sure we have a value
456
    printf("ERROR! Unable to autoprobe IR length for device index %i;  Must set IR size on command line. Aborting.\n", devidx);
457
    exit(1);
458
  }
459
 
460
  return retval;
461
}
462
 
463
 
464
uint32_t get_debug_cmd(int devidx)
465
{
466
  int retval = TAP_CMD_INVALID;
467
  uint32_t manuf_id = (idcodes[devidx] >> 1) & 0x7FF;
468
 
469
  if(idcodes[devidx] != IDCODE_INVALID) {
470
    if(manuf_id == XILINX_MANUFACTURER_ID) {
471
      retval = bsdl_get_user1_cmd(idcodes[devidx]);
472
      if(cmd_line_cmd_debug < 0) printf("Xilinx IDCODE, assuming internal BSCAN mode\n\t(using USER1 instead of DEBUG TAP command)\n");
473
    } else {
474
      retval = bsdl_get_debug_cmd(idcodes[devidx]);
475
    }
476
  }
477
 
478
  if(cmd_line_cmd_debug >= 0) {
479
    if(retval != TAP_CMD_INVALID) {
480
      printf("Warning: overriding autoprobe debug command (0x%X) with command line value (0x%X)\n", retval, cmd_line_cmd_debug);
481
    } else {
482
      printf("Using command-line debug command 0x%X\n", cmd_line_cmd_debug);
483
    }
484
    retval = cmd_line_cmd_debug;
485
  }
486
 
487
  if(retval == TAP_CMD_INVALID) {
488
    printf("ERROR!  Unable to find DEBUG command for device index %i, device ID 0x%0lX\n", devidx, idcodes[devidx]);
489
  }
490
 
491
  return retval;
492
}
493
 
494
 
495
// Extracts two values from an option string
496
// of the form "<index>:<value>", where both args
497
// are in base 10
498
void get_ir_opts(char *optstr, int *idx, int *val)
499
{
500
  char *ptr;
501
 
502
  ptr = strstr(optstr, ":");
503
  if(ptr == NULL) {
504
    printf("Error: badly formatted IR length option.  Use format \'<index>:<value>\', without spaces, where both args are in base 10\n");
505
    exit(1);
506
  }
507
 
508
  *ptr = '\0';
509
  ptr++;  // This now points to the second (value) arg string
510
 
511
  *idx = strtoul(optstr, NULL, 10);
512
  *val = strtoul(ptr, NULL, 10);
513
  // ***CHECK FOR SUCCESS
514
}
515
 

powered by: WebSVN 2.1.0

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