tcl.c 44.3 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
#include "interfaces.h"
38

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

43
static const Jim_Nvp nvp_jtag_tap_event[] = {
44
45
	{ .value = JTAG_TRST_ASSERTED,		.name = "post-reset" },
	{ .value = JTAG_TAP_EVENT_SETUP,	.name = "setup" },
46
47
48
49
50
	{ .value = JTAG_TAP_EVENT_ENABLE,       .name = "tap-enable" },
	{ .value = JTAG_TAP_EVENT_DISABLE,      .name = "tap-disable" },

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

52
extern jtag_interface_t *jtag_interface;
53

54
55
56
57
58
59
/* 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);
60
static int handle_jtag_rclk_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
61
62
63
64
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
65
66
static int handle_jtag_nsrst_assert_width_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_jtag_ntrst_assert_width_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
oharboe's avatar
oharboe committed
67

68
static int handle_scan_chain_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
69

70
71
72
73
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
74
static int Jim_Command_pathmove(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
75
static int Jim_Command_flush_count(Jim_Interp *interp, int argc, Jim_Obj *const *args);
76

77
78
79
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);
80

81

82
83
84
85
86
87
88
89
90
91
enum jtag_tap_cfg_param {
	JCFG_EVENT
};

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

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

92
static int jtag_tap_configure_cmd(Jim_GetOptInfo *goi, jtag_tap_t * tap)
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
{
	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) {
111
					Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name? ...");
112
113
114
					return JIM_ERR;
				}

115
				e = Jim_GetOpt_Nvp(goi, nvp_jtag_tap_event, &n);
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
				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
139
						if (jteap->event == (enum jtag_event)n->value) {
140
141
142
143
144
145
							break;
						}
						jteap = jteap->next;
					}

					if (goi->isconfigure) {
146
						bool replace = true;
147
148
149
						if (jteap == NULL) {
							/* create new */
							jteap = calloc(1, sizeof (*jteap));
150
							replace = false;
151
152
						}
						jteap->event = n->value;
153
						Jim_GetOpt_Obj(goi, &o);
154
155
156
157
158
159
						if (jteap->body) {
							Jim_DecrRefCount(interp, jteap->body);
						}
						jteap->body = Jim_DuplicateObj(goi->interp, o);
						Jim_IncrRefCount(jteap->body);

160
161
162
163
164
165
						if (!replace)
						{
							/* add to head of event list */
							jteap->next = tap->event_action;
							tap->event_action = jteap;
						}
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
						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;
}
183

zwelch's avatar
zwelch committed
184
185
186
187
188
189
190
191
192
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;
}
193

194
static int jim_newtap_cmd(Jim_GetOptInfo *goi)
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
{
	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
211
		{ .name = "-enable"			,	.value = NTAP_OPT_ENABLED },
212
#define NTAP_OPT_DISABLED  4
213
		{ .name = "-disable"		,	.value = NTAP_OPT_DISABLED },
214
#define NTAP_OPT_EXPECTED_ID 5
215
216
		{ .name = "-expected-id"	,	.value = NTAP_OPT_EXPECTED_ID },
		{ .name = NULL				,	.value = -1 },
217
218
	};

zwelch's avatar
zwelch committed
219
220
221
	pTap = calloc(1, sizeof(jtag_tap_t));
	if (!pTap) {
		Jim_SetResult_sprintf(goi->interp, "no memory");
222
223
		return JIM_ERR;
	}
zwelch's avatar
zwelch committed
224

225
226
227
	/*
	 * we expect CHIP + TAP + OPTIONS
	 * */
zwelch's avatar
zwelch committed
228
	if (goi->argc < 3) {
229
		Jim_SetResult_sprintf(goi->interp, "Missing CHIP TAP OPTIONS ....");
230
		free(pTap);
231
232
		return JIM_ERR;
	}
233
	Jim_GetOpt_String(goi, &cp, NULL);
234
235
	pTap->chip = strdup(cp);

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

239
	/* name + dot + name + null */
240
	x = strlen(pTap->chip) + 1 + strlen(pTap->tapname) + 1;
241
242
	cp = malloc(x);
	sprintf(cp, "%s.%s", pTap->chip, pTap->tapname);
243
244
	pTap->dotted_name = cp;

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

248
249
250
251
252
253
	/* IEEE specifies that the two LSBs of an IR scan are 01, so make
	 * that the default.  The "-irlen" and "-irmask" options are only
	 * needed to cope with nonstandard TAPs, or to specify more bits.
	 */
	pTap->ir_capture_mask = 0x03;
	pTap->ir_capture_value = 0x01;
254

255
256
	/* clear flags for "required options" them as we find them */
	reqbits = 1;
oharboe's avatar
oharboe committed
257

zwelch's avatar
zwelch committed
258
	while (goi->argc) {
259
		e = Jim_GetOpt_Nvp(goi, opts, &n);
zwelch's avatar
zwelch committed
260
		if (e != JIM_OK) {
261
			Jim_GetOpt_NvpUnknown(goi, opts, 0);
262
263
			free((void *)pTap->dotted_name);
			free(pTap);
264
265
			return e;
		}
266
		LOG_DEBUG("Processing option: %s", n->name);
zwelch's avatar
zwelch committed
267
		switch (n->value) {
268
		case NTAP_OPT_ENABLED:
zwelch's avatar
zwelch committed
269
			pTap->disabled_after_reset = false;
270
271
			break;
		case NTAP_OPT_DISABLED:
zwelch's avatar
zwelch committed
272
			pTap->disabled_after_reset = true;
273
274
			break;
		case NTAP_OPT_EXPECTED_ID:
275
		{
276
			uint32_t *new_expected_ids;
277

278
			e = Jim_GetOpt_Wide(goi, &w);
279
			if (e != JIM_OK) {
280
				Jim_SetResult_sprintf(goi->interp, "option: %s bad parameter", n->name);
281
282
				free((void *)pTap->dotted_name);
				free(pTap);
283
284
285
				return e;
			}

286
			new_expected_ids = malloc(sizeof(uint32_t) * (pTap->expected_ids_cnt + 1));
287
			if (new_expected_ids == NULL) {
288
				Jim_SetResult_sprintf(goi->interp, "no memory");
289
290
				free((void *)pTap->dotted_name);
				free(pTap);
291
292
293
				return JIM_ERR;
			}

294
			memcpy(new_expected_ids, pTap->expected_ids, sizeof(uint32_t) * pTap->expected_ids_cnt);
295
296

			new_expected_ids[pTap->expected_ids_cnt] = w;
297
298

			free(pTap->expected_ids);
299
300
			pTap->expected_ids = new_expected_ids;
			pTap->expected_ids_cnt++;
301
			break;
302
		}
303
304
305
		case NTAP_OPT_IRLEN:
		case NTAP_OPT_IRMASK:
		case NTAP_OPT_IRCAPTURE:
306
			e = Jim_GetOpt_Wide(goi, &w);
zwelch's avatar
zwelch committed
307
			if (e != JIM_OK) {
308
				Jim_SetResult_sprintf(goi->interp, "option: %s bad parameter", n->name);
309
310
				free((void *)pTap->dotted_name);
				free(pTap);
311
312
				return e;
			}
zwelch's avatar
zwelch committed
313
			switch (n->value) {
314
			case NTAP_OPT_IRLEN:
zwelch's avatar
zwelch committed
315
				if (w > (jim_wide) (8 * sizeof(pTap->ir_capture_value)))
316
317
318
					LOG_WARNING("%s: huge IR length %d",
							pTap->dotted_name,
							(int) w);
319
				pTap->ir_length = w;
320
				reqbits = 0;
321
322
				break;
			case NTAP_OPT_IRMASK:
zwelch's avatar
zwelch committed
323
				if (is_bad_irval(pTap->ir_length, w)) {
324
325
					LOG_ERROR("%s: IR mask %x too big",
							pTap->dotted_name,
zwelch's avatar
zwelch committed
326
							(int) w);
327
328
					free((void *)pTap->dotted_name);
					free(pTap);
zwelch's avatar
zwelch committed
329
330
					return ERROR_FAIL;
				}
331
332
333
				if ((w & 3) != 3)
					LOG_WARNING("%s: nonstandard IR mask",
							pTap->dotted_name);
334
335
336
				pTap->ir_capture_mask = w;
				break;
			case NTAP_OPT_IRCAPTURE:
zwelch's avatar
zwelch committed
337
				if (is_bad_irval(pTap->ir_length, w)) {
338
339
					LOG_ERROR("%s: IR capture %x too big",
							pTap->dotted_name,
zwelch's avatar
zwelch committed
340
							(int) w);
341
342
					free((void *)pTap->dotted_name);
					free(pTap);
zwelch's avatar
zwelch committed
343
344
					return ERROR_FAIL;
				}
345
346
347
				if ((w & 3) != 1)
					LOG_WARNING("%s: nonstandard IR value",
							pTap->dotted_name);
348
349
350
				pTap->ir_capture_value = w;
				break;
			}
zwelch's avatar
zwelch committed
351
		} /* switch (n->value) */
352
	} /* while (goi->argc) */
353

zwelch's avatar
zwelch committed
354
355
356
	/* default is enabled-after-reset */
	pTap->enabled = !pTap->disabled_after_reset;

357
358
359
360
361
	/* Did all the required option bits get cleared? */
	if (0 == reqbits)
	{
		jtag_tap_init(pTap);
		return ERROR_OK;
362
363
	}

364
365
366
	Jim_SetResult_sprintf(goi->interp,
			"newtap: %s missing required parameters",
			pTap->dotted_name);
367
	jtag_tap_free(pTap);
368
369
	return JIM_ERR;
}
370

zwelch's avatar
zwelch committed
371
static void jtag_tap_handle_event(jtag_tap_t *tap, enum jtag_event e)
372
373
374
{
	jtag_tap_event_action_t * jteap;

dbrownell's avatar
dbrownell committed
375
	for (jteap = tap->event_action; jteap != NULL; jteap = jteap->next) {
376
		if (jteap->event == e) {
377
			LOG_DEBUG("JTAG tap: %s event: %d (%s)\n\taction: %s",
378
379
380
					tap->dotted_name,
					e,
					Jim_Nvp_value2name_simple(nvp_jtag_tap_event, e)->name,
381
					Jim_GetString(jteap->body, NULL));
382
383
			if (Jim_EvalObj(interp, jteap->body) != JIM_OK) {
				Jim_PrintErrorMessage(interp);
384
385
386
			} else switch (e) {
			case JTAG_TAP_EVENT_ENABLE:
			case JTAG_TAP_EVENT_DISABLE:
zwelch's avatar
zwelch committed
387
				/* NOTE:  we currently assume the handlers
388
389
				 * can't fail.  Right here is where we should
				 * really be verifying the scan chains ...
zwelch's avatar
zwelch committed
390
				 */
391
				tap->enabled = (e == JTAG_TAP_EVENT_ENABLE);
392
393
				LOG_INFO("JTAG tap: %s %s", tap->dotted_name,
					tap->enabled ? "enabled" : "disabled");
394
395
396
				break;
			default:
				break;
397
398
399
400
401
402
			}
		}
	}
}


403
static int jim_jtag_command(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
404
405
406
407
{
	Jim_GetOptInfo goi;
	int e;
	Jim_Nvp *n;
408
	Jim_Obj *o;
409
410
411
412
	struct command_context_s *context;

	enum {
		JTAG_CMD_INTERFACE,
413
		JTAG_CMD_INIT,
414
		JTAG_CMD_INIT_RESET,
415
416
417
		JTAG_CMD_NEWTAP,
		JTAG_CMD_TAPENABLE,
		JTAG_CMD_TAPDISABLE,
418
419
		JTAG_CMD_TAPISENABLED,
		JTAG_CMD_CONFIGURE,
zwelch's avatar
zwelch committed
420
421
		JTAG_CMD_CGET,
		JTAG_CMD_NAMES,
422
	};
423

424
425
	const Jim_Nvp jtag_cmds[] = {
		{ .name = "interface"     , .value = JTAG_CMD_INTERFACE },
426
		{ .name = "arp_init"      , .value = JTAG_CMD_INIT },
427
		{ .name = "arp_init-reset", .value = JTAG_CMD_INIT_RESET },
428
429
430
431
		{ .name = "newtap"        , .value = JTAG_CMD_NEWTAP },
		{ .name = "tapisenabled"     , .value = JTAG_CMD_TAPISENABLED },
		{ .name = "tapenable"     , .value = JTAG_CMD_TAPENABLE },
		{ .name = "tapdisable"    , .value = JTAG_CMD_TAPDISABLE },
432
433
		{ .name = "configure"     , .value = JTAG_CMD_CONFIGURE },
		{ .name = "cget"          , .value = JTAG_CMD_CGET },
zwelch's avatar
zwelch committed
434
		{ .name = "names"         , .value = JTAG_CMD_NAMES },
435

436
437
438
439
		{ .name = NULL, .value = -1 },
	};

	context = Jim_GetAssocData(interp, "context");
440
	/* go past the command */
441
	Jim_GetOpt_Setup(&goi, interp, argc-1, argv + 1);
442

443
	e = Jim_GetOpt_Nvp(&goi, jtag_cmds, &n);
zwelch's avatar
zwelch committed
444
	if (e != JIM_OK) {
445
		Jim_GetOpt_NvpUnknown(&goi, jtag_cmds, 0);
446
447
		return e;
	}
448
		Jim_SetEmptyResult(goi.interp);
zwelch's avatar
zwelch committed
449
	switch (n->value) {
450
	case JTAG_CMD_INTERFACE:
451
452
453
		/* 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
454
		if (goi.argc != 0) {
455
			Jim_WrongNumArgs(goi.interp, 1, goi.argv-1, "(no params)");
456
457
			return JIM_ERR;
		}
458
		Jim_SetResultString(goi.interp, jtag_interface->name, -1);
459
		return JIM_OK;
460
461
462
463
464
465
466
467
468
469
470
	case JTAG_CMD_INIT:
		if (goi.argc != 0) {
			Jim_WrongNumArgs(goi.interp, 1, goi.argv-1, "(no params)");
			return JIM_ERR;
		}
		e = jtag_init_inner(context);
		if (e != ERROR_OK) {
			Jim_SetResult_sprintf(goi.interp, "error: %d", e);
			return JIM_ERR;
		}
		return JIM_OK;
471
	case JTAG_CMD_INIT_RESET:
zwelch's avatar
zwelch committed
472
		if (goi.argc != 0) {
473
			Jim_WrongNumArgs(goi.interp, 1, goi.argv-1, "(no params)");
474
475
476
			return JIM_ERR;
		}
		e = jtag_init_reset(context);
zwelch's avatar
zwelch committed
477
		if (e != ERROR_OK) {
478
			Jim_SetResult_sprintf(goi.interp, "error: %d", e);
479
480
481
			return JIM_ERR;
		}
		return JIM_OK;
482
	case JTAG_CMD_NEWTAP:
483
		return jim_newtap_cmd(&goi);
484
485
486
487
		break;
	case JTAG_CMD_TAPISENABLED:
	case JTAG_CMD_TAPENABLE:
	case JTAG_CMD_TAPDISABLE:
zwelch's avatar
zwelch committed
488
		if (goi.argc != 1) {
489
			Jim_SetResultString(goi.interp, "Too many parameters",-1);
490
491
			return JIM_ERR;
		}
oharboe's avatar
oharboe committed
492
493

		{
494
			jtag_tap_t *t;
zwelch's avatar
zwelch committed
495
496
497

			t = jtag_tap_by_jim_obj(goi.interp, goi.argv[0]);
			if (t == NULL)
498
				return JIM_ERR;
zwelch's avatar
zwelch committed
499
500

			switch (n->value) {
501
502
503
			case JTAG_CMD_TAPISENABLED:
				break;
			case JTAG_CMD_TAPENABLE:
zwelch's avatar
zwelch committed
504
505
506
507
508
509
510
511
512
513
				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
514
515

				jtag_call_event_callbacks(JTAG_TAP_EVENT_ENABLE);
516
517
				break;
			case JTAG_CMD_TAPDISABLE:
zwelch's avatar
zwelch committed
518
519
520
521
522
523
524
525
526
527
				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
528
529

				jtag_call_event_callbacks(JTAG_TAP_EVENT_DISABLE);
530
531
				break;
			}
zwelch's avatar
zwelch committed
532
533
			e = t->enabled;
			Jim_SetResult(goi.interp, Jim_NewIntObj(goi.interp, e));
534
535
			return JIM_OK;
		}
536
537
538
		break;

	case JTAG_CMD_CGET:
zwelch's avatar
zwelch committed
539
		if (goi.argc < 2) {
zwelch's avatar
zwelch committed
540
541
			Jim_WrongNumArgs(goi.interp, 0, NULL,
					"cget tap_name queryparm");
542
543
544
545
546
547
548
			return JIM_ERR;
		}

		{
			jtag_tap_t *t;

			Jim_GetOpt_Obj(&goi, &o);
549
			t = jtag_tap_by_jim_obj(goi.interp, o);
zwelch's avatar
zwelch committed
550
			if (t == NULL) {
551
552
553
554
				return JIM_ERR;
			}

			goi.isconfigure = 0;
555
			return jtag_tap_configure_cmd(&goi, t);
556
557
558
559
		}
		break;

	case JTAG_CMD_CONFIGURE:
zwelch's avatar
zwelch committed
560
		if (goi.argc < 3) {
zwelch's avatar
zwelch committed
561
562
			Jim_WrongNumArgs(goi.interp, 0, NULL,
					"configure tap_name attribute value ...");
563
564
565
566
567
568
569
			return JIM_ERR;
		}

		{
			jtag_tap_t *t;

			Jim_GetOpt_Obj(&goi, &o);
570
			t = jtag_tap_by_jim_obj(goi.interp, o);
zwelch's avatar
zwelch committed
571
			if (t == NULL) {
572
573
574
575
				return JIM_ERR;
			}

			goi.isconfigure = 1;
576
			return jtag_tap_configure_cmd(&goi, t);
577
		}
zwelch's avatar
zwelch committed
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
		break;

	case JTAG_CMD_NAMES:
		if (goi.argc != 0) {
			Jim_WrongNumArgs(goi.interp, 1, goi.argv, "Too many parameters");
			return JIM_ERR;
		}
		Jim_SetResult(goi.interp, Jim_NewListObj(goi.interp, NULL, 0));
		{
			jtag_tap_t *tap;

			for (tap = jtag_all_taps(); tap; tap = tap->next_tap) {
				Jim_ListAppendElement(goi.interp,
					Jim_GetResult(goi.interp),
					Jim_NewStringObj(goi.interp,
						tap->dotted_name, -1));
			}
			return JIM_OK;
		}
		break;

599
	}
600

601
602
603
	return JIM_ERR;
}

604

605
void jtag_notify_event(enum jtag_event event)
606
607
{
	jtag_tap_t *tap;
608

609
	for (tap = jtag_all_taps(); tap; tap = tap->next_tap)
610
		jtag_tap_handle_event(tap, event);
611
612
613
}


614
615
int jtag_register_commands(struct command_context_s *cmd_ctx)
{
616
	register_jim(cmd_ctx, "jtag", jim_jtag_command, "perform jtag tap actions");
617

618
	register_command(cmd_ctx, NULL, "interface", handle_interface_command,
oharboe's avatar
oharboe committed
619
		COMMAND_CONFIG, "try to configure interface");
620
621
622
	register_command(cmd_ctx, NULL,
		"interface_list", &handle_interface_list_command,
		COMMAND_ANY, "list all built-in interfaces");
623
	register_command(cmd_ctx, NULL, "jtag_speed", handle_jtag_speed_command,
zwelch's avatar
zwelch committed
624
		COMMAND_ANY, "(DEPRECATED) set jtag speed (if supported)");
625
	register_command(cmd_ctx, NULL, "jtag_khz", handle_jtag_khz_command,
zwelch's avatar
zwelch committed
626
627
		COMMAND_ANY, "set maximum jtag speed (if supported); "
		"parameter is maximum khz, or 0 for adaptive clocking (RTCK).");
628
629
	register_command(cmd_ctx, NULL, "jtag_rclk", handle_jtag_rclk_command,
		COMMAND_ANY, "fallback_speed_khz - set JTAG speed to RCLK or use fallback speed");
630
	register_command(cmd_ctx, NULL, "jtag_device", handle_jtag_device_command,
zwelch's avatar
zwelch committed
631
		COMMAND_CONFIG, "(DEPRECATED) jtag_device <ir_length> <ir_expected> <ir_mask>");
632
	register_command(cmd_ctx, NULL, "reset_config", handle_reset_config_command,
633
		COMMAND_ANY,
dbrownell's avatar
dbrownell committed
634
635
636
637
638
639
		"reset_config "
		"[none|trst_only|srst_only|trst_and_srst] "
		"[srst_pulls_trst|trst_pulls_srst|combined|separate] "
		"[srst_gates_jtag|srst_nogate] "
		"[trst_push_pull|trst_open_drain] "
		"[srst_push_pull|srst_open_drain]");
640
	register_command(cmd_ctx, NULL, "jtag_nsrst_delay", handle_jtag_nsrst_delay_command,
641
		COMMAND_ANY, "jtag_nsrst_delay <ms> - delay after deasserting srst in ms");
642
	register_command(cmd_ctx, NULL, "jtag_ntrst_delay", handle_jtag_ntrst_delay_command,
643
		COMMAND_ANY, "jtag_ntrst_delay <ms> - delay after deasserting trst in ms");
oharboe's avatar
oharboe committed
644
645
646
647
	register_command(cmd_ctx, NULL, "jtag_nsrst_assert_width", handle_jtag_nsrst_assert_width_command,
		COMMAND_ANY, "jtag_nsrst_assert_width <ms> - delay after asserting srst in ms");
	register_command(cmd_ctx, NULL, "jtag_ntrst_assert_width", handle_jtag_ntrst_assert_width_command,
		COMMAND_ANY, "jtag_ntrst_assert_width <ms> - delay after asserting trst in ms");
648

649
650
651
652
653
654
655
656
657
	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] ...");
658
	register_jim(cmd_ctx, "drscan", Jim_Command_drscan, "execute DR scan <device> <num_bits> <value> <num_bits1> <value2> ...");
659
	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
660
	register_jim(cmd_ctx, "pathmove", Jim_Command_pathmove, "move JTAG to state1 then to state2, state3, etc. <state1>,<state2>,<stat3>...");
661
662

	register_command(cmd_ctx, NULL, "verify_ircapture", handle_verify_ircapture_command,
zwelch's avatar
zwelch committed
663
		COMMAND_ANY, "verify value captured during Capture-IR <enable | disable>");
oharboe's avatar
oharboe committed
664
	register_command(cmd_ctx, NULL, "verify_jtag", handle_verify_jtag_command,
zwelch's avatar
zwelch committed
665
		COMMAND_ANY, "verify value capture <enable | disable>");
666
	register_command(cmd_ctx, NULL, "tms_sequence", handle_tms_sequence_command,
zwelch's avatar
zwelch committed
667
		COMMAND_ANY, "choose short(default) or long tms_sequence <short | long>");
668
669
670
	return ERROR_OK;
}

671
672
static int default_khz(int khz, int *jtag_speed)
{
673
	LOG_ERROR("Translation from khz to jtag_speed not implemented");
674
675
676
	return ERROR_FAIL;
}

oharboe's avatar
oharboe committed
677
static int default_speed_div(int speed, int *khz)
678
{
679
	LOG_ERROR("Translation from jtag_speed to khz not implemented");
680
681
682
683
684
	return ERROR_FAIL;
}

static int default_power_dropout(int *dropout)
{
zwelch's avatar
zwelch committed
685
	*dropout = 0; /* by default we can't detect power dropout */
686
687
688
689
690
	return ERROR_OK;
}

static int default_srst_asserted(int *srst_asserted)
{
zwelch's avatar
zwelch committed
691
	*srst_asserted = 0; /* by default we can't detect srst asserted */
692
	return ERROR_OK;
693
694
}

695
696
static int handle_interface_command(struct command_context_s *cmd_ctx,
		char *cmd, char **args, int argc)
697
698
699
700
{
	/* check whether the interface is already configured */
	if (jtag_interface)
	{
701
		LOG_WARNING("Interface already configured, ignoring");
702
703
704
705
		return ERROR_OK;
	}

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

709
	for (unsigned i = 0; NULL != jtag_interfaces[i]; i++)
710
	{
711
712
713
714
715
		if (strcmp(args[0], jtag_interfaces[i]->name) != 0)
			continue;

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

718
		jtag_interface = jtag_interfaces[i];
719

720
721
722
723
724
725
726
727
		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;
728

729
		return ERROR_OK;
730
731
732
733
734
	}

	/* no valid interface was found (i.e. the configuration option,
	 * didn't match one of the compiled-in interfaces
	 */
735
	LOG_ERROR("The specified JTAG interface was not found (%s)", args[0]);
736
737
738
739
740
741
742
743
744
745
746
	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:");
747
	for (unsigned i = 0; NULL != jtag_interfaces[i]; i++)
748
749
750
751
	{
		const char *name = jtag_interfaces[i]->name;
		command_print(cmd_ctx, "%u: %s", i + 1, name);
	}
752

753
	return ERROR_OK;
754
755
}

756
static int handle_jtag_device_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
757
{
758
759
760
	int e;
	char buf[1024];
	Jim_Obj *newargs[ 10 ];
761
762
763
764
765
766
767
768
	/*
	 * 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
769

zwelch's avatar
zwelch committed
770
	if (argc < 4) {
771
		command_print(cmd_ctx, "OLD DEPRECATED SYNTAX: Please use the NEW syntax");
772
		return ERROR_OK;
773
	}
774
775
	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",
776
777
				   args[0],
				   args[1],
778
				   args[2]);
779
780
781
782
783
	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\"");
	command_print(cmd_ctx, "And then refer to the taps by the dotted name.");

784
785
786
787
788
789
790
791
792
793
794
795
	newargs[0] = Jim_NewStringObj(interp, "jtag", -1);
	newargs[1] = Jim_NewStringObj(interp, "newtap", -1);
	sprintf(buf, "chip%d", jtag_tap_count());
	newargs[2] = Jim_NewStringObj(interp, buf, -1);
	sprintf(buf, "tap%d", jtag_tap_count());
	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);
796
797
798

	command_print(cmd_ctx, "NEW COMMAND:");
	sprintf(buf, "%s %s %s %s %s %s %s %s %s %s",
799
800
801
802
803
804
805
806
807
808
809
810
			 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
811
	if (e != JIM_OK) {
812
		command_print(cmd_ctx, "%s", Jim_GetString(Jim_GetResult(interp), NULL));
813
814
	}
	return e;
815
816
}

817
static int handle_scan_chain_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
818
{
819
	jtag_tap_t *tap;
820

821
	tap = jtag_all_taps();
822
823
824
	command_print(cmd_ctx, "     TapName            | Enabled |   IdCode      Expected    IrLen IrCap  IrMask Instr     ");
	command_print(cmd_ctx, "---|--------------------|---------|------------|------------|------|------|------|---------");

zwelch's avatar
zwelch committed
825
	while (tap) {
826
		uint32_t expected, expected_mask, cur_instr, ii;
827
828
829
		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);
830

831
832
833
834
835
		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',
836
837
838
839
840
841
					  (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));
842
843
844

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

848
		tap = tap->next_tap;
849
850
851
852
853
	}

	return ERROR_OK;
}

854
static int handle_reset_config_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
855
{
zwelch's avatar
zwelch committed
856
857
858
859
860
861
862
863
864
865
866
867
868
869
	int new_cfg = 0;
	int mask = 0;

	/* 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;

dbrownell's avatar
dbrownell committed
870
871
		/* gating */
		m = RESET_SRST_NO_GATING;
872
		if (strcmp(*args, "srst_gates_jtag") == 0)
dbrownell's avatar
dbrownell committed
873
874
875
876
877
878
879
880
881
			/* default: don't use JTAG while SRST asserted */;
		else if (strcmp(*args, "srst_nogate") == 0)
			tmp = RESET_SRST_NO_GATING;
		else
			m = 0;
		if (mask & m) {
			LOG_ERROR("extra reset_config %s spec (%s)",
					"gating", *args);
			return ERROR_INVALID_ARGUMENTS;
882
		}
dbrownell's avatar
dbrownell committed
883
884
		if (m)
			goto next;
885

zwelch's avatar
zwelch committed
886
887
888
889
890
891
892
893
894
895
		/* 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;
896
		else
zwelch's avatar
zwelch committed
897
898
899
900
			m = 0;
		if (mask & m) {
			LOG_ERROR("extra reset_config %s spec (%s)",
					"signal", *args);
901
902
			return ERROR_INVALID_ARGUMENTS;
		}
zwelch's avatar
zwelch committed
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
		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;
922
		}
zwelch's avatar
zwelch committed
923
924
925
926
927
928
929
930
931
		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 */;
932
		else
zwelch's avatar
zwelch committed
933
934
935
936
			m = 0;
		if (mask & m) {
			LOG_ERROR("extra reset_config %s spec (%s)",
					"trst_type", *args);
937
938
			return ERROR_INVALID_ARGUMENTS;
		}
zwelch's avatar
zwelch committed
939
940
941
942
943
944
945
946
947
		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 */;
948
		else
zwelch's avatar
zwelch committed
949
950
951
952
			m = 0;
		if (mask & m) {
			LOG_ERROR("extra reset_config %s spec (%s)",
					"srst_type", *args);
953
954
			return ERROR_INVALID_ARGUMENTS;
		}
zwelch's avatar
zwelch committed
955
956
957
958
959
960
961
962
963
964
965
966
967
		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;
968
	}
969

zwelch's avatar
zwelch committed
970
	/* clear previous values of those bits, save new values */
dbrownell's avatar
dbrownell committed
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
	if (mask) {
		int old_cfg = jtag_get_reset_config();

		old_cfg &= ~mask;
		new_cfg |= old_cfg;
		jtag_set_reset_config(new_cfg);
	} else
		new_cfg = jtag_get_reset_config();


	/*
	 * Display the (now-)current reset mode
	 */
	char *modes[5];

	/* minimal JTAG has neither SRST nor TRST (so that's the default) */
	switch (new_cfg & (RESET_HAS_TRST | RESET_HAS_SRST)) {
	case RESET_HAS_SRST:
		modes[0] = "srst_only";
		break;
	case RESET_HAS_TRST:
		modes[0] = "trst_only";
		break;
	case RESET_TRST_AND_SRST:
		modes[0] = "trst_and_srst";
		break;
	default:
		modes[0] = "none";
		break;
	}
For faster browsing, not all history is shown. View entire blame