tcl.c 40.7 KB
Newer Older
1
2
3
4
/***************************************************************************
 *   Copyright (C) 2005 by Dominic Rath                                    *
 *   Dominic.Rath@gmx.de                                                   *
 *                                                                         *
5
 *   Copyright (C) 2007,2008 yvind Harboe                                 *
6
 *   oyvind.harboe@zylin.com                                               *
ntfreak's avatar
ntfreak committed
7
8
 *                                                                         *
 *   Copyright (C) 2009 SoftPLC Corporation                                *
zwelch's avatar
zwelch committed
9
 *       http://softplc.com                                                *
ntfreak's avatar
ntfreak committed
10
 *   dick@softplc.com                                                      *
11
 *                                                                         *
12
13
14
 *   Copyright (C) 2009 Zachary T Welch                                    *
 *   zw@superlucidity.net                                                  *
 *                                                                         *
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
 *   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.             *
 ***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "jtag.h"
zwelch's avatar
zwelch committed
35
#include "minidriver.h"
36
#include "interface.h"
37

38
39
40
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
41

42
43
44
45
46
47
static const Jim_Nvp nvp_jtag_tap_event[] = {
	{ .value = JTAG_TAP_EVENT_ENABLE,       .name = "tap-enable" },
	{ .value = JTAG_TAP_EVENT_DISABLE,      .name = "tap-disable" },

	{ .name = NULL, .value = -1 }
};
48

49
50
/* jtag interfaces (parport, FTDI-USB, TI-USB, ...)
 */
51

oharboe's avatar
oharboe committed
52
#if BUILD_ZY1000 == 1
53
	extern jtag_interface_t zy1000_interface;
54
#elif defined(BUILD_MINIDRIVER_DUMMY)
55
	extern jtag_interface_t minidummy_interface;
56
#else // standard drivers
57
58
59
#if BUILD_PARPORT == 1
	extern jtag_interface_t parport_interface;
#endif
60

61
62
63
#if BUILD_DUMMY == 1
	extern jtag_interface_t dummy_interface;
#endif
64

65
66
67
68
69
70
71
72
73
74
75
76
#if BUILD_FT2232_FTD2XX == 1
	extern jtag_interface_t ft2232_interface;
#endif

#if BUILD_FT2232_LIBFTDI == 1
	extern jtag_interface_t ft2232_interface;
#endif

#if BUILD_AMTJTAGACCEL == 1
	extern jtag_interface_t amt_jtagaccel_interface;
#endif

77
78
79
#if BUILD_EP93XX == 1
	extern jtag_interface_t ep93xx_interface;
#endif
80

81
82
83
#if BUILD_AT91RM9200 == 1
	extern jtag_interface_t at91rm9200_interface;
#endif
84

85
86
87
#if BUILD_GW16012 == 1
	extern jtag_interface_t gw16012_interface;
#endif
88

89
90
91
#if BUILD_PRESTO_LIBFTDI == 1 || BUILD_PRESTO_FTD2XX == 1
	extern jtag_interface_t presto_interface;
#endif
92

93
94
95
#if BUILD_USBPROG == 1
	extern jtag_interface_t usbprog_interface;
#endif
96

97
98
99
#if BUILD_JLINK == 1
	extern jtag_interface_t jlink_interface;
#endif
100

101
102
103
#if BUILD_VSLLINK == 1
	extern jtag_interface_t vsllink_interface;
#endif
104

105
106
107
#if BUILD_RLINK == 1
	extern jtag_interface_t rlink_interface;
#endif
108

109
110
111
112
#if BUILD_ARMJTAGEW == 1
	extern jtag_interface_t armjtagew_interface;
#endif
#endif // standard drivers
113

114
115
116
117
118
119
120
121
/**
 * The list of built-in JTAG interfaces, containing entries for those
 * drivers that were enabled by the @c configure script.
 *
 * The list should be defined to contain either one minidriver interface
 * or some number of standard driver interfaces, never both.
 */
jtag_interface_t *jtag_interfaces[] = {
oharboe's avatar
oharboe committed
122
#if BUILD_ZY1000 == 1
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
	&zy1000_interface,
#elif defined(BUILD_MINIDRIVER_DUMMY)
	&minidummy_interface,
#else // standard drivers
#if BUILD_PARPORT == 1
	&parport_interface,
#endif
#if BUILD_DUMMY == 1
	&dummy_interface,
#endif
#if BUILD_FT2232_FTD2XX == 1
	&ft2232_interface,
#endif
#if BUILD_FT2232_LIBFTDI == 1
	&ft2232_interface,
#endif
#if BUILD_AMTJTAGACCEL == 1
	&amt_jtagaccel_interface,
#endif
#if BUILD_EP93XX == 1
	&ep93xx_interface,
#endif
#if BUILD_AT91RM9200 == 1
	&at91rm9200_interface,
#endif
#if BUILD_GW16012 == 1
	&gw16012_interface,
#endif
#if BUILD_PRESTO_LIBFTDI == 1 || BUILD_PRESTO_FTD2XX == 1
	&presto_interface,
#endif
#if BUILD_USBPROG == 1
	&usbprog_interface,
#endif
#if BUILD_JLINK == 1
	&jlink_interface,
#endif
#if BUILD_VSLLINK == 1
	&vsllink_interface,
#endif
#if BUILD_RLINK == 1
	&rlink_interface,
#endif
#if BUILD_ARMJTAGEW == 1
	&armjtagew_interface,
#endif
#endif // standard drivers
	NULL,
};
172

173
extern jtag_interface_t *jtag_interface;
174

175
176
177
178
179
180
181
182
183
184
/* jtag commands */
static int handle_interface_list_command(struct command_context_s *cmd_ctx,
		char *cmd, char **args, int argc);
static int handle_interface_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_jtag_speed_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_jtag_khz_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_jtag_device_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_reset_config_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_jtag_nsrst_delay_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_jtag_ntrst_delay_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
oharboe's avatar
oharboe committed
185

186
static int handle_scan_chain_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
187

188
189
190
191
static int handle_jtag_reset_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_runtest_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_irscan_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int Jim_Command_drscan(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
oharboe's avatar
oharboe committed
192
static int Jim_Command_pathmove(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
193
static int Jim_Command_flush_count(Jim_Interp *interp, int argc, Jim_Obj *const *args);
194

195
196
197
static int handle_verify_ircapture_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_verify_jtag_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_tms_sequence_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
198

199
200
extern int jtag_examine_chain(void);
extern int jtag_validate_chain(void);
201

202
203
204
205
206
207
208
209
210
211
enum jtag_tap_cfg_param {
	JCFG_EVENT
};

static Jim_Nvp nvp_config_opts[] = {
	{ .name = "-event",      .value = JCFG_EVENT },

	{ .name = NULL,          .value = -1 }
};

ntfreak's avatar
ntfreak committed
212
static int jtag_tap_configure_cmd( Jim_GetOptInfo *goi, jtag_tap_t * tap)
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
{
	Jim_Nvp *n;
	Jim_Obj *o;
	int e;

	/* parse config or cget options */
	while (goi->argc > 0) {
		Jim_SetEmptyResult (goi->interp);

		e = Jim_GetOpt_Nvp(goi, nvp_config_opts, &n);
		if (e != JIM_OK) {
			Jim_GetOpt_NvpUnknown(goi, nvp_config_opts, 0);
			return e;
		}

		switch (n->value) {
			case JCFG_EVENT:
				if (goi->argc == 0) {
					Jim_WrongNumArgs( goi->interp, goi->argc, goi->argv, "-event ?event-name? ..." );
					return JIM_ERR;
				}

				e = Jim_GetOpt_Nvp( goi, nvp_jtag_tap_event, &n );
				if (e != JIM_OK) {
					Jim_GetOpt_NvpUnknown(goi, nvp_jtag_tap_event, 1);
					return e;
				}

				if (goi->isconfigure) {
					if (goi->argc != 1) {
						Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name? ?EVENT-BODY?");
						return JIM_ERR;
					}
				} else {
					if (goi->argc != 0) {
						Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name?");
						return JIM_ERR;
					}
				}

				{
					jtag_tap_event_action_t *jteap;

					jteap = tap->event_action;
					/* replace existing? */
					while (jteap) {
zwelch's avatar
zwelch committed
259
						if (jteap->event == (enum jtag_event)n->value) {
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
							break;
						}
						jteap = jteap->next;
					}

					if (goi->isconfigure) {
						if (jteap == NULL) {
							/* create new */
							jteap = calloc(1, sizeof (*jteap));
						}
						jteap->event = n->value;
						Jim_GetOpt_Obj( goi, &o);
						if (jteap->body) {
							Jim_DecrRefCount(interp, jteap->body);
						}
						jteap->body = Jim_DuplicateObj(goi->interp, o);
						Jim_IncrRefCount(jteap->body);

						/* add to head of event list */
						jteap->next = tap->event_action;
						tap->event_action = jteap;
						Jim_SetEmptyResult(goi->interp);
					} else {
						/* get */
						if (jteap == NULL) {
							Jim_SetEmptyResult(goi->interp);
						} else {
							Jim_SetResult(goi->interp, Jim_DuplicateObj(goi->interp, jteap->body));
						}
					}
				}
				/* loop for more */
				break;
		}
	} /* while (goi->argc) */

	return JIM_OK;
}
298

zwelch's avatar
zwelch committed
299
300
301
302
303
304
305
306
307
static int is_bad_irval(int ir_length, jim_wide w)
{
	jim_wide v = 1;

	v <<= ir_length;
	v -= 1;
	v = ~v;
	return (w & v) != 0;
}
308

309
static int jim_newtap_cmd( Jim_GetOptInfo *goi )
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
{
	jtag_tap_t *pTap;
	jim_wide w;
	int x;
	int e;
	int reqbits;
	Jim_Nvp *n;
	char *cp;
	const Jim_Nvp opts[] = {
#define NTAP_OPT_IRLEN     0
		{ .name = "-irlen"			,	.value = NTAP_OPT_IRLEN },
#define NTAP_OPT_IRMASK    1
		{ .name = "-irmask"			,	.value = NTAP_OPT_IRMASK },
#define NTAP_OPT_IRCAPTURE 2
		{ .name = "-ircapture"		,	.value = NTAP_OPT_IRCAPTURE },
#define NTAP_OPT_ENABLED   3
326
		{ .name = "-enable"			,	.value = NTAP_OPT_ENABLED },
327
#define NTAP_OPT_DISABLED  4
328
		{ .name = "-disable"		,	.value = NTAP_OPT_DISABLED },
329
#define NTAP_OPT_EXPECTED_ID 5
330
331
		{ .name = "-expected-id"	,	.value = NTAP_OPT_EXPECTED_ID },
		{ .name = NULL				,	.value = -1 },
332
333
	};

zwelch's avatar
zwelch committed
334
335
336
	pTap = calloc(1, sizeof(jtag_tap_t));
	if (!pTap) {
		Jim_SetResult_sprintf(goi->interp, "no memory");
337
338
		return JIM_ERR;
	}
zwelch's avatar
zwelch committed
339

340
341
342
	/*
	 * we expect CHIP + TAP + OPTIONS
	 * */
zwelch's avatar
zwelch committed
343
	if ( goi->argc < 3 ){
344
345
346
347
348
349
350
351
		Jim_SetResult_sprintf(goi->interp, "Missing CHIP TAP OPTIONS ....");
		return JIM_ERR;
	}
	Jim_GetOpt_String( goi, &cp, NULL );
	pTap->chip = strdup(cp);

	Jim_GetOpt_String( goi, &cp, NULL );
	pTap->tapname = strdup(cp);
oharboe's avatar
oharboe committed
352

353
	/* name + dot + name + null */
354
355
356
357
358
	x = strlen(pTap->chip) + 1 + strlen(pTap->tapname) + 1;
	cp = malloc( x );
	sprintf( cp, "%s.%s", pTap->chip, pTap->tapname );
	pTap->dotted_name = cp;

oharboe's avatar
oharboe committed
359
	LOG_DEBUG("Creating New Tap, Chip: %s, Tap: %s, Dotted: %s, %d params",
360
361
			  pTap->chip, pTap->tapname, pTap->dotted_name, goi->argc);

362
	/* deal with options */
363
364
365
366
#define NTREQ_IRLEN      1
#define NTREQ_IRCAPTURE  2
#define NTREQ_IRMASK     4

367
	/* clear them as we find them */
368
	reqbits = (NTREQ_IRLEN | NTREQ_IRCAPTURE | NTREQ_IRMASK);
oharboe's avatar
oharboe committed
369

zwelch's avatar
zwelch committed
370
	while ( goi->argc ){
371
		e = Jim_GetOpt_Nvp( goi, opts, &n );
zwelch's avatar
zwelch committed
372
		if ( e != JIM_OK ){
373
374
375
376
			Jim_GetOpt_NvpUnknown( goi, opts, 0 );
			return e;
		}
		LOG_DEBUG("Processing option: %s", n->name );
zwelch's avatar
zwelch committed
377
		switch ( n->value ){
378
		case NTAP_OPT_ENABLED:
zwelch's avatar
zwelch committed
379
			pTap->disabled_after_reset = false;
380
381
			break;
		case NTAP_OPT_DISABLED:
zwelch's avatar
zwelch committed
382
			pTap->disabled_after_reset = true;
383
384
			break;
		case NTAP_OPT_EXPECTED_ID:
385
		{
386
			uint32_t *new_expected_ids;
387

388
			e = Jim_GetOpt_Wide( goi, &w );
zwelch's avatar
zwelch committed
389
			if ( e != JIM_OK) {
390
391
392
393
				Jim_SetResult_sprintf(goi->interp, "option: %s bad parameter", n->name);
				return e;
			}

394
			new_expected_ids = malloc(sizeof(uint32_t) * (pTap->expected_ids_cnt + 1));
395
396
397
398
399
			if (new_expected_ids == NULL) {
				Jim_SetResult_sprintf( goi->interp, "no memory");
				return JIM_ERR;
			}

400
			memcpy(new_expected_ids, pTap->expected_ids, sizeof(uint32_t) * pTap->expected_ids_cnt);
401
402

			new_expected_ids[pTap->expected_ids_cnt] = w;
403
404

			free(pTap->expected_ids);
405
406
			pTap->expected_ids = new_expected_ids;
			pTap->expected_ids_cnt++;
407
			break;
408
		}
409
410
411
412
		case NTAP_OPT_IRLEN:
		case NTAP_OPT_IRMASK:
		case NTAP_OPT_IRCAPTURE:
			e = Jim_GetOpt_Wide( goi, &w );
zwelch's avatar
zwelch committed
413
			if ( e != JIM_OK ){
414
415
416
				Jim_SetResult_sprintf( goi->interp, "option: %s bad parameter", n->name );
				return e;
			}
zwelch's avatar
zwelch committed
417
			switch (n->value){
418
			case NTAP_OPT_IRLEN:
zwelch's avatar
zwelch committed
419
				if (w > (jim_wide) (8 * sizeof(pTap->ir_capture_value)))
zwelch's avatar
zwelch committed
420
					LOG_WARNING("huge IR length %d", (int) w);
421
422
423
424
				pTap->ir_length = w;
				reqbits &= (~(NTREQ_IRLEN));
				break;
			case NTAP_OPT_IRMASK:
zwelch's avatar
zwelch committed
425
426
427
428
429
				if (is_bad_irval(pTap->ir_length, w)) {
					LOG_ERROR("IR mask %x too big",
							(int) w);
					return ERROR_FAIL;
				}
430
431
432
433
				pTap->ir_capture_mask = w;
				reqbits &= (~(NTREQ_IRMASK));
				break;
			case NTAP_OPT_IRCAPTURE:
zwelch's avatar
zwelch committed
434
435
436
437
438
				if (is_bad_irval(pTap->ir_length, w)) {
					LOG_ERROR("IR capture %x too big",
							(int) w);
					return ERROR_FAIL;
				}
439
440
441
442
				pTap->ir_capture_value = w;
				reqbits &= (~(NTREQ_IRCAPTURE));
				break;
			}
zwelch's avatar
zwelch committed
443
		} /* switch (n->value) */
zwelch's avatar
zwelch committed
444
	} /* while ( goi->argc ) */
445

zwelch's avatar
zwelch committed
446
447
448
	/* default is enabled-after-reset */
	pTap->enabled = !pTap->disabled_after_reset;

449
450
451
452
453
	/* Did all the required option bits get cleared? */
	if (0 == reqbits)
	{
		jtag_tap_init(pTap);
		return ERROR_OK;
454
455
	}

456
457
458
	Jim_SetResult_sprintf(goi->interp,
			"newtap: %s missing required parameters",
			pTap->dotted_name);
459
	jtag_tap_free(pTap);
460
461
	return JIM_ERR;
}
462

zwelch's avatar
zwelch committed
463
static void jtag_tap_handle_event(jtag_tap_t *tap, enum jtag_event e)
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
{
	jtag_tap_event_action_t * jteap;
	int done;

	jteap = tap->event_action;

	done = 0;
	while (jteap) {
		if (jteap->event == e) {
			done = 1;
			LOG_DEBUG( "JTAG tap: %s event: %d (%s) action: %s\n",
					tap->dotted_name,
					e,
					Jim_Nvp_value2name_simple(nvp_jtag_tap_event, e)->name,
					Jim_GetString(jteap->body, NULL) );
			if (Jim_EvalObj(interp, jteap->body) != JIM_OK) {
				Jim_PrintErrorMessage(interp);
zwelch's avatar
zwelch committed
481
482
483
484
485
486
			} else {
				/* NOTE:  we currently assume the handlers
				 * can't fail.  That presumes later code
				 * will be verifying the scan chains ...
				 */
				tap->enabled = (e == JTAG_TAP_EVENT_ENABLE);
487
488
489
490
491
492
493
494
495
496
497
498
499
500
			}
		}

		jteap = jteap->next;
	}

	if (!done) {
		LOG_DEBUG( "event %d %s - no action",
				e,
				Jim_Nvp_value2name_simple( nvp_jtag_tap_event, e)->name);
	}
}


501
static int jim_jtag_command( Jim_Interp *interp, int argc, Jim_Obj *const *argv )
502
503
504
505
{
	Jim_GetOptInfo goi;
	int e;
	Jim_Nvp *n;
506
	Jim_Obj *o;
507
508
509
510
511
	struct command_context_s *context;

	enum {
		JTAG_CMD_INTERFACE,
		JTAG_CMD_INIT_RESET,
512
513
514
		JTAG_CMD_NEWTAP,
		JTAG_CMD_TAPENABLE,
		JTAG_CMD_TAPDISABLE,
515
516
517
		JTAG_CMD_TAPISENABLED,
		JTAG_CMD_CONFIGURE,
		JTAG_CMD_CGET
518
	};
519

520
521
522
	const Jim_Nvp jtag_cmds[] = {
		{ .name = "interface"     , .value = JTAG_CMD_INTERFACE },
		{ .name = "arp_init-reset", .value = JTAG_CMD_INIT_RESET },
523
524
525
526
		{ .name = "newtap"        , .value = JTAG_CMD_NEWTAP },
		{ .name = "tapisenabled"     , .value = JTAG_CMD_TAPISENABLED },
		{ .name = "tapenable"     , .value = JTAG_CMD_TAPENABLE },
		{ .name = "tapdisable"    , .value = JTAG_CMD_TAPDISABLE },
527
528
		{ .name = "configure"     , .value = JTAG_CMD_CONFIGURE },
		{ .name = "cget"          , .value = JTAG_CMD_CGET },
529

530
531
532
533
		{ .name = NULL, .value = -1 },
	};

	context = Jim_GetAssocData(interp, "context");
534
	/* go past the command */
zwelch's avatar
zwelch committed
535
	Jim_GetOpt_Setup( &goi, interp, argc-1, argv + 1 );
536
537

	e = Jim_GetOpt_Nvp( &goi, jtag_cmds, &n );
zwelch's avatar
zwelch committed
538
	if ( e != JIM_OK ){
539
540
541
542
		Jim_GetOpt_NvpUnknown( &goi, jtag_cmds, 0 );
		return e;
	}
		Jim_SetEmptyResult( goi.interp );
zwelch's avatar
zwelch committed
543
	switch ( n->value ){
544
	case JTAG_CMD_INTERFACE:
545
546
547
		/* return the name of the interface */
		/* TCL code might need to know the exact type... */
		/* FUTURE: we allow this as a means to "set" the interface. */
zwelch's avatar
zwelch committed
548
		if ( goi.argc != 0 ){
549
550
551
552
553
554
			Jim_WrongNumArgs( goi.interp, 1, goi.argv-1, "(no params)");
			return JIM_ERR;
		}
		Jim_SetResultString( goi.interp, jtag_interface->name, -1 );
		return JIM_OK;
	case JTAG_CMD_INIT_RESET:
zwelch's avatar
zwelch committed
555
		if ( goi.argc != 0 ){
556
557
558
559
			Jim_WrongNumArgs( goi.interp, 1, goi.argv-1, "(no params)");
			return JIM_ERR;
		}
		e = jtag_init_reset(context);
zwelch's avatar
zwelch committed
560
		if ( e != ERROR_OK ){
561
562
563
564
			Jim_SetResult_sprintf( goi.interp, "error: %d", e);
			return JIM_ERR;
		}
		return JIM_OK;
565
566
567
568
569
570
	case JTAG_CMD_NEWTAP:
		return jim_newtap_cmd( &goi );
		break;
	case JTAG_CMD_TAPISENABLED:
	case JTAG_CMD_TAPENABLE:
	case JTAG_CMD_TAPDISABLE:
zwelch's avatar
zwelch committed
571
		if ( goi.argc != 1 ){
572
573
574
			Jim_SetResultString( goi.interp, "Too many parameters",-1 );
			return JIM_ERR;
		}
oharboe's avatar
oharboe committed
575
576

		{
577
			jtag_tap_t *t;
zwelch's avatar
zwelch committed
578
579
580

			t = jtag_tap_by_jim_obj(goi.interp, goi.argv[0]);
			if (t == NULL)
581
				return JIM_ERR;
zwelch's avatar
zwelch committed
582
583

			switch (n->value) {
584
585
586
			case JTAG_CMD_TAPISENABLED:
				break;
			case JTAG_CMD_TAPENABLE:
zwelch's avatar
zwelch committed
587
588
589
590
591
592
593
594
595
596
				if (t->enabled)
					break;
				jtag_tap_handle_event(t, JTAG_TAP_EVENT_ENABLE);
				if (!t->enabled)
					break;

				/* FIXME add JTAG sanity checks, w/o TLR
				 *  - scan chain length grew by one (this)
				 *  - IDs and IR lengths are as expected
				 */
zwelch's avatar
zwelch committed
597
598

				jtag_call_event_callbacks(JTAG_TAP_EVENT_ENABLE);
599
600
				break;
			case JTAG_CMD_TAPDISABLE:
zwelch's avatar
zwelch committed
601
602
603
604
605
606
607
608
609
610
				if (!t->enabled)
					break;
				jtag_tap_handle_event(t, JTAG_TAP_EVENT_DISABLE);
				if (t->enabled)
					break;

				/* FIXME add JTAG sanity checks, w/o TLR
				 *  - scan chain length shrank by one (this)
				 *  - IDs and IR lengths are as expected
				 */
zwelch's avatar
zwelch committed
611
612

				jtag_call_event_callbacks(JTAG_TAP_EVENT_DISABLE);
613
614
				break;
			}
zwelch's avatar
zwelch committed
615
616
			e = t->enabled;
			Jim_SetResult(goi.interp, Jim_NewIntObj(goi.interp, e));
617
618
			return JIM_OK;
		}
619
620
621
		break;

	case JTAG_CMD_CGET:
zwelch's avatar
zwelch committed
622
		if ( goi.argc < 2 ){
623
624
625
626
627
628
629
630
			Jim_WrongNumArgs( goi.interp, 0, NULL, "?tap-name? -option ...");
			return JIM_ERR;
		}

		{
			jtag_tap_t *t;

			Jim_GetOpt_Obj(&goi, &o);
631
			t = jtag_tap_by_jim_obj( goi.interp, o );
zwelch's avatar
zwelch committed
632
			if ( t == NULL ){
633
634
635
636
637
638
639
640
641
				return JIM_ERR;
			}

			goi.isconfigure = 0;
			return jtag_tap_configure_cmd( &goi, t);
		}
		break;

	case JTAG_CMD_CONFIGURE:
zwelch's avatar
zwelch committed
642
		if ( goi.argc < 3 ){
643
644
645
646
647
648
649
650
			Jim_WrongNumArgs( goi.interp, 0, NULL, "?tap-name? -option ?VALUE? ...");
			return JIM_ERR;
		}

		{
			jtag_tap_t *t;

			Jim_GetOpt_Obj(&goi, &o);
651
			t = jtag_tap_by_jim_obj( goi.interp, o );
zwelch's avatar
zwelch committed
652
			if ( t == NULL ){
653
654
655
656
657
658
				return JIM_ERR;
			}

			goi.isconfigure = 1;
			return jtag_tap_configure_cmd( &goi, t);
		}
659
	}
660

661
662
663
	return JIM_ERR;
}

664
665
int jtag_register_commands(struct command_context_s *cmd_ctx)
{
666
667
	register_jim( cmd_ctx, "jtag", jim_jtag_command, "perform jtag tap actions");

668
	register_command(cmd_ctx, NULL, "interface", handle_interface_command,
oharboe's avatar
oharboe committed
669
		COMMAND_CONFIG, "try to configure interface");
670
671
672
	register_command(cmd_ctx, NULL,
		"interface_list", &handle_interface_list_command,
		COMMAND_ANY, "list all built-in interfaces");
673
	register_command(cmd_ctx, NULL, "jtag_speed", handle_jtag_speed_command,
zwelch's avatar
zwelch committed
674
		COMMAND_ANY, "(DEPRECATED) set jtag speed (if supported)");
675
	register_command(cmd_ctx, NULL, "jtag_khz", handle_jtag_khz_command,
zwelch's avatar
zwelch committed
676
677
		COMMAND_ANY, "set maximum jtag speed (if supported); "
		"parameter is maximum khz, or 0 for adaptive clocking (RTCK).");
678
	register_command(cmd_ctx, NULL, "jtag_device", handle_jtag_device_command,
zwelch's avatar
zwelch committed
679
		COMMAND_CONFIG, "(DEPRECATED) jtag_device <ir_length> <ir_expected> <ir_mask>");
680
	register_command(cmd_ctx, NULL, "reset_config", handle_reset_config_command,
681
682
		COMMAND_ANY,
		"[none/trst_only/srst_only/trst_and_srst] [srst_pulls_trst/trst_pulls_srst] [combined/separate] [trst_push_pull/trst_open_drain] [srst_push_pull/srst_open_drain]");
683
	register_command(cmd_ctx, NULL, "jtag_nsrst_delay", handle_jtag_nsrst_delay_command,
684
		COMMAND_ANY, "jtag_nsrst_delay <ms> - delay after deasserting srst in ms");
685
	register_command(cmd_ctx, NULL, "jtag_ntrst_delay", handle_jtag_ntrst_delay_command,
686
		COMMAND_ANY, "jtag_ntrst_delay <ms> - delay after deasserting trst in ms");
687

688
689
690
691
692
693
694
695
696
	register_command(cmd_ctx, NULL, "scan_chain", handle_scan_chain_command,
		COMMAND_EXEC, "print current scan chain configuration");

	register_command(cmd_ctx, NULL, "jtag_reset", handle_jtag_reset_command,
		COMMAND_EXEC, "toggle reset lines <trst> <srst>");
	register_command(cmd_ctx, NULL, "runtest", handle_runtest_command,
		COMMAND_EXEC, "move to Run-Test/Idle, and execute <num_cycles>");
	register_command(cmd_ctx, NULL, "irscan", handle_irscan_command,
		COMMAND_EXEC, "execute IR scan <device> <instr> [dev2] [instr2] ...");
697
	register_jim(cmd_ctx, "drscan", Jim_Command_drscan, "execute DR scan <device> <num_bits> <value> <num_bits1> <value2> ...");
698
	register_jim(cmd_ctx, "flush_count", Jim_Command_flush_count, "returns number of times the JTAG queue has been flushed");
oharboe's avatar
oharboe committed
699
	register_jim(cmd_ctx, "pathmove", Jim_Command_pathmove, "move JTAG to state1 then to state2, state3, etc. <state1>,<state2>,<stat3>...");
700
701
702

	register_command(cmd_ctx, NULL, "verify_ircapture", handle_verify_ircapture_command,
		COMMAND_ANY, "verify value captured during Capture-IR <enable|disable>");
oharboe's avatar
oharboe committed
703
704
	register_command(cmd_ctx, NULL, "verify_jtag", handle_verify_jtag_command,
		COMMAND_ANY, "verify value capture <enable|disable>");
705
706
	register_command(cmd_ctx, NULL, "tms_sequence", handle_tms_sequence_command,
		COMMAND_ANY, "choose short(default) or long tms_sequence <short|long>");
707
708
709
	return ERROR_OK;
}

710
711
static int default_khz(int khz, int *jtag_speed)
{
712
	LOG_ERROR("Translation from khz to jtag_speed not implemented");
713
714
715
	return ERROR_FAIL;
}

oharboe's avatar
oharboe committed
716
static int default_speed_div(int speed, int *khz)
717
{
718
	LOG_ERROR("Translation from jtag_speed to khz not implemented");
719
720
721
722
723
	return ERROR_FAIL;
}

static int default_power_dropout(int *dropout)
{
zwelch's avatar
zwelch committed
724
	*dropout = 0; /* by default we can't detect power dropout */
725
726
727
728
729
	return ERROR_OK;
}

static int default_srst_asserted(int *srst_asserted)
{
zwelch's avatar
zwelch committed
730
	*srst_asserted = 0; /* by default we can't detect srst asserted */
731
	return ERROR_OK;
732
733
}

734
735
static int handle_interface_command(struct command_context_s *cmd_ctx,
		char *cmd, char **args, int argc)
736
737
738
739
{
	/* check whether the interface is already configured */
	if (jtag_interface)
	{
740
		LOG_WARNING("Interface already configured, ignoring");
741
742
743
744
		return ERROR_OK;
	}

	/* interface name is a mandatory argument */
745
	if (argc != 1 || args[0][0] == '\0')
746
747
		return ERROR_COMMAND_SYNTAX_ERROR;

748
	for (unsigned i = 0; NULL != jtag_interfaces[i]; i++)
749
	{
750
751
752
753
754
		if (strcmp(args[0], jtag_interfaces[i]->name) != 0)
			continue;

		int retval = jtag_interfaces[i]->register_commands(cmd_ctx);
		if (ERROR_OK != retval)
755
				return retval;
756

757
		jtag_interface = jtag_interfaces[i];
758

759
760
761
762
763
764
765
766
		if (jtag_interface->khz == NULL)
			jtag_interface->khz = default_khz;
		if (jtag_interface->speed_div == NULL)
			jtag_interface->speed_div = default_speed_div;
		if (jtag_interface->power_dropout == NULL)
			jtag_interface->power_dropout = default_power_dropout;
		if (jtag_interface->srst_asserted == NULL)
			jtag_interface->srst_asserted = default_srst_asserted;
767

768
		return ERROR_OK;
769
770
771
772
773
	}

	/* no valid interface was found (i.e. the configuration option,
	 * didn't match one of the compiled-in interfaces
	 */
774
	LOG_ERROR("The specified JTAG interface was not found (%s)", args[0]);
775
776
777
778
779
780
781
782
783
784
785
	handle_interface_list_command(cmd_ctx, cmd, args, argc);
	return ERROR_JTAG_INVALID_INTERFACE;
}

static int handle_interface_list_command(struct command_context_s *cmd_ctx,
		char *cmd, char **args, int argc)
{
	if (strcmp(cmd, "interface_list") == 0 && argc > 0)
		return ERROR_COMMAND_SYNTAX_ERROR;

	command_print(cmd_ctx, "The following JTAG interfaces are available:");
786
	for (unsigned i = 0; NULL != jtag_interfaces[i]; i++)
787
788
789
790
	{
		const char *name = jtag_interfaces[i]->name;
		command_print(cmd_ctx, "%u: %s", i + 1, name);
	}
791

792
	return ERROR_OK;
793
794
}

795
static int handle_jtag_device_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
796
{
797
798
799
	int e;
	char buf[1024];
	Jim_Obj *newargs[ 10 ];
800
801
802
803
804
805
806
807
	/*
	 * CONVERT SYNTAX
	 * argv[-1] = command
	 * argv[ 0] = ir length
	 * argv[ 1] = ir capture
	 * argv[ 2] = ir mask
	 * argv[ 3] = not actually used by anything but in the docs
	 */
oharboe's avatar
oharboe committed
808

zwelch's avatar
zwelch committed
809
	if ( argc < 4 ){
810
		command_print( cmd_ctx, "OLD DEPRECATED SYNTAX: Please use the NEW syntax");
811
		return ERROR_OK;
812
813
814
815
816
817
	}
	command_print( cmd_ctx, "OLD SYNTAX: DEPRECATED - translating to new syntax");
	command_print( cmd_ctx, "jtag newtap CHIP TAP -irlen %s -ircapture %s -irvalue %s",
				   args[0],
				   args[1],
				   args[2] );
818
819
820
	command_print( cmd_ctx, "Example: STM32 has 2 taps, the cortexM3(len4) + boundaryscan(len5)");
	command_print( cmd_ctx, "jtag newtap stm32 cortexm3 ....., thus creating the tap: \"stm32.cortexm3\"");
	command_print( cmd_ctx, "jtag newtap stm32 boundary ....., and the tap: \"stm32.boundary\"");
821
	command_print( cmd_ctx, "And then refer to the taps by the dotted name.");
oharboe's avatar
oharboe committed
822

823
824
	newargs[0] = Jim_NewStringObj( interp, "jtag", -1   );
	newargs[1] = Jim_NewStringObj( interp, "newtap", -1 );
825
	sprintf( buf, "chip%d", jtag_tap_count() );
826
	newargs[2] = Jim_NewStringObj( interp, buf, -1 );
827
	sprintf( buf, "tap%d", jtag_tap_count() );
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
	newargs[3] = Jim_NewStringObj( interp, buf, -1  );
	newargs[4] = Jim_NewStringObj( interp, "-irlen", -1  );
	newargs[5] = Jim_NewStringObj( interp, args[0], -1  );
	newargs[6] = Jim_NewStringObj( interp, "-ircapture", -1  );
	newargs[7] = Jim_NewStringObj( interp, args[1], -1  );
	newargs[8] = Jim_NewStringObj( interp, "-irmask", -1  );
	newargs[9] = Jim_NewStringObj( interp, args[2], -1  );

	command_print( cmd_ctx, "NEW COMMAND:");
	sprintf( buf, "%s %s %s %s %s %s %s %s %s %s",
			 Jim_GetString( newargs[0], NULL ),
			 Jim_GetString( newargs[1], NULL ),
			 Jim_GetString( newargs[2], NULL ),
			 Jim_GetString( newargs[3], NULL ),
			 Jim_GetString( newargs[4], NULL ),
			 Jim_GetString( newargs[5], NULL ),
			 Jim_GetString( newargs[6], NULL ),
			 Jim_GetString( newargs[7], NULL ),
			 Jim_GetString( newargs[8], NULL ),
			 Jim_GetString( newargs[9], NULL ) );

	e = jim_jtag_command( interp, 10, newargs );
zwelch's avatar
zwelch committed
850
	if ( e != JIM_OK ){
851
852
853
		command_print( cmd_ctx, "%s", Jim_GetString( Jim_GetResult(interp), NULL ) );
	}
	return e;
854
855
}

856
static int handle_scan_chain_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
857
{
858
	jtag_tap_t *tap;
859

860
	tap = jtag_all_taps();
861
862
863
	command_print(cmd_ctx, "     TapName            | Enabled |   IdCode      Expected    IrLen IrCap  IrMask Instr     ");
	command_print(cmd_ctx, "---|--------------------|---------|------------|------------|------|------|------|---------");

zwelch's avatar
zwelch committed
864
	while ( tap ){
865
		uint32_t expected, expected_mask, cur_instr, ii;
866
867
868
		expected = buf_get_u32(tap->expected, 0, tap->ir_length);
		expected_mask = buf_get_u32(tap->expected_mask, 0, tap->ir_length);
		cur_instr = buf_get_u32(tap->cur_instr, 0, tap->ir_length);
869

870
871
872
873
874
		command_print(cmd_ctx,
					  "%2d | %-18s |    %c    | 0x%08x | 0x%08x | 0x%02x | 0x%02x | 0x%02x | 0x%02x",
					  tap->abs_chain_position,
					  tap->dotted_name,
					  tap->enabled ? 'Y' : 'n',
875
876
877
878
879
880
					  (unsigned int)(tap->idcode),
					  (unsigned int)(tap->expected_ids_cnt > 0 ? tap->expected_ids[0] : 0),
					  (unsigned int)(tap->ir_length),
					  (unsigned int)(expected),
					  (unsigned int)(expected_mask),
					  (unsigned int)(cur_instr));
881
882
883

		for (ii = 1; ii < tap->expected_ids_cnt; ii++) {
			command_print(cmd_ctx, "   |                    |         |            | 0x%08x |      |      |      |         ",
884
						  (unsigned int)(tap->expected_ids[ii]));
885
886
		}

887
		tap = tap->next_tap;
888
889
890
891
892
	}

	return ERROR_OK;
}

893
static int handle_reset_config_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
894
{
zwelch's avatar
zwelch committed
895
896
897
	int new_cfg = 0;
	int mask = 0;

898
899
	if (argc < 1)
		return ERROR_COMMAND_SYNTAX_ERROR;
900

zwelch's avatar
zwelch committed
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
	/* Original versions cared about the order of these tokens:
	 *   reset_config signals [combination [trst_type [srst_type]]]
	 * They also clobbered the previous configuration even on error.
	 *
	 * Here we don't care about the order, and only change values
	 * which have been explicitly specified.
	 */
	for (; argc; argc--, args++) {
		int tmp = 0;
		int m;

		/* signals */
		m = RESET_HAS_TRST | RESET_HAS_SRST;
		if (strcmp(*args, "none") == 0)
			tmp = RESET_NONE;
		else if (strcmp(*args, "trst_only") == 0)
			tmp = RESET_HAS_TRST;
		else if (strcmp(*args, "srst_only") == 0)
			tmp = RESET_HAS_SRST;
		else if (strcmp(*args, "trst_and_srst") == 0)
			tmp = RESET_HAS_TRST | RESET_HAS_SRST;
922
		else
zwelch's avatar
zwelch committed
923
924
925
926
			m = 0;
		if (mask & m) {
			LOG_ERROR("extra reset_config %s spec (%s)",
					"signal", *args);
927
928
			return ERROR_INVALID_ARGUMENTS;
		}
zwelch's avatar
zwelch committed
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
		if (m)
			goto next;

		/* combination (options for broken wiring) */
		m = RESET_SRST_PULLS_TRST | RESET_TRST_PULLS_SRST;
		if (strcmp(*args, "separate") == 0)
			/* separate reset lines - default */;
		else if (strcmp(*args, "srst_pulls_trst") == 0)
			tmp |= RESET_SRST_PULLS_TRST;
		else if (strcmp(*args, "trst_pulls_srst") == 0)
			tmp |= RESET_TRST_PULLS_SRST;
		else if (strcmp(*args, "combined") == 0)
			tmp |= RESET_SRST_PULLS_TRST | RESET_TRST_PULLS_SRST;
		else
			m = 0;
		if (mask & m) {
			LOG_ERROR("extra reset_config %s spec (%s)",
					"combination", *args);
			return ERROR_INVALID_ARGUMENTS;
948
		}
zwelch's avatar
zwelch committed
949
950
951
952
953
954
955
956
957
		if (m)
			goto next;

		/* trst_type (NOP without HAS_TRST) */
		m = RESET_TRST_OPEN_DRAIN;
		if (strcmp(*args, "trst_open_drain") == 0)
			tmp |= RESET_TRST_OPEN_DRAIN;
		else if (strcmp(*args, "trst_push_pull") == 0)
			/* push/pull from adapter - default */;
958
		else
zwelch's avatar
zwelch committed
959
960
961
962
			m = 0;
		if (mask & m) {
			LOG_ERROR("extra reset_config %s spec (%s)",
					"trst_type", *args);
963
964
			return ERROR_INVALID_ARGUMENTS;
		}
zwelch's avatar
zwelch committed
965
966
967
968
969
970
971
972
973
		if (m)
			goto next;

		/* srst_type (NOP without HAS_SRST) */
		m |= RESET_SRST_PUSH_PULL;
		if (strcmp(*args, "srst_push_pull") == 0)
			tmp |= RESET_SRST_PUSH_PULL;
		else if (strcmp(*args, "srst_open_drain") == 0)
			/* open drain from adapter - default */;
974
		else
zwelch's avatar
zwelch committed
975
976
977
978
			m = 0;
		if (mask & m) {
			LOG_ERROR("extra reset_config %s spec (%s)",
					"srst_type", *args);
979
980
			return ERROR_INVALID_ARGUMENTS;
		}
zwelch's avatar
zwelch committed
981
982
983
984
985
986
987
988
989
990
991
992
993
		if (m)
			goto next;

		/* caller provided nonsense; fail */
		LOG_ERROR("unknown reset_config flag (%s)", *args);
		return ERROR_INVALID_ARGUMENTS;

next:
		/* Remember the bits which were specified (mask)
		 * and their new values (new_cfg).
		 */
		mask |= m;
		new_cfg |= tmp;
994
	}
995

zwelch's avatar
zwelch committed
996
	/* clear previous values of those bits, save new values */
997
998
999
1000
	enum reset_types old_cfg = jtag_get_reset_config();
	old_cfg &= ~mask;
	new_cfg |= old_cfg;
	jtag_set_reset_config(new_cfg);
For faster browsing, not all history is shown. View entire blame