jtag/tcl.c cleanup -- split out "adapter.c"
[openocd.git] / src / jtag / adapter.c
1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
5 * Copyright (C) 2007-2010 Øyvind Harboe *
6 * oyvind.harboe@zylin.com *
7 * *
8 * Copyright (C) 2009 SoftPLC Corporation *
9 * http://softplc.com *
10 * dick@softplc.com *
11 * *
12 * Copyright (C) 2009 Zachary T Welch *
13 * zw@superlucidity.net *
14 * *
15 * This program is free software; you can redistribute it and/or modify *
16 * it under the terms of the GNU General Public License as published by *
17 * the Free Software Foundation; either version 2 of the License, or *
18 * (at your option) any later version. *
19 * *
20 * This program is distributed in the hope that it will be useful, *
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
23 * GNU General Public License for more details. *
24 * *
25 * You should have received a copy of the GNU General Public License *
26 * along with this program; if not, write to the *
27 * Free Software Foundation, Inc., *
28 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
29 ***************************************************************************/
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif
33
34 #include "jtag.h"
35 #include "minidriver.h"
36 #include "interface.h"
37 #include "interfaces.h"
38
39 #ifdef HAVE_STRINGS_H
40 #include <strings.h>
41 #endif
42
43 /**
44 * @file
45 * Holds support for configuring debug adapters from TCl scripts.
46 */
47
48 extern struct jtag_interface *jtag_interface;
49
50
51
52 static int
53 jim_adapter_name(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
54 {
55 Jim_GetOptInfo goi;
56 Jim_GetOpt_Setup(&goi, interp, argc-1, argv + 1);
57
58 /* return the name of the interface */
59 /* TCL code might need to know the exact type... */
60 /* FUTURE: we allow this as a means to "set" the interface. */
61 if (goi.argc != 0) {
62 Jim_WrongNumArgs(goi.interp, 1, goi.argv-1, "(no params)");
63 return JIM_ERR;
64 }
65 const char *name = jtag_interface ? jtag_interface->name : NULL;
66 Jim_SetResultString(goi.interp, name ? : "undefined", -1);
67 return JIM_OK;
68 }
69
70
71 static int default_khz(int khz, int *jtag_speed)
72 {
73 LOG_ERROR("Translation from khz to jtag_speed not implemented");
74 return ERROR_FAIL;
75 }
76
77 static int default_speed_div(int speed, int *khz)
78 {
79 LOG_ERROR("Translation from jtag_speed to khz not implemented");
80 return ERROR_FAIL;
81 }
82
83 static int default_power_dropout(int *dropout)
84 {
85 *dropout = 0; /* by default we can't detect power dropout */
86 return ERROR_OK;
87 }
88
89 static int default_srst_asserted(int *srst_asserted)
90 {
91 *srst_asserted = 0; /* by default we can't detect srst asserted */
92 return ERROR_OK;
93 }
94
95 COMMAND_HANDLER(handle_interface_list_command)
96 {
97 if (strcmp(CMD_NAME, "interface_list") == 0 && CMD_ARGC > 0)
98 return ERROR_COMMAND_SYNTAX_ERROR;
99
100 command_print(CMD_CTX, "The following debug interfaces are available:");
101 for (unsigned i = 0; NULL != jtag_interfaces[i]; i++)
102 {
103 const char *name = jtag_interfaces[i]->name;
104 command_print(CMD_CTX, "%u: %s", i + 1, name);
105 }
106
107 return ERROR_OK;
108 }
109
110 COMMAND_HANDLER(handle_interface_command)
111 {
112 /* check whether the interface is already configured */
113 if (jtag_interface)
114 {
115 LOG_WARNING("Interface already configured, ignoring");
116 return ERROR_OK;
117 }
118
119 /* interface name is a mandatory argument */
120 if (CMD_ARGC != 1 || CMD_ARGV[0][0] == '\0')
121 return ERROR_COMMAND_SYNTAX_ERROR;
122
123 for (unsigned i = 0; NULL != jtag_interfaces[i]; i++)
124 {
125 if (strcmp(CMD_ARGV[0], jtag_interfaces[i]->name) != 0)
126 continue;
127
128 if (NULL != jtag_interfaces[i]->commands)
129 {
130 int retval = register_commands(CMD_CTX, NULL,
131 jtag_interfaces[i]->commands);
132 if (ERROR_OK != retval)
133 return retval;
134 }
135
136 jtag_interface = jtag_interfaces[i];
137
138 if (jtag_interface->khz == NULL)
139 jtag_interface->khz = default_khz;
140 if (jtag_interface->speed_div == NULL)
141 jtag_interface->speed_div = default_speed_div;
142 if (jtag_interface->power_dropout == NULL)
143 jtag_interface->power_dropout = default_power_dropout;
144 if (jtag_interface->srst_asserted == NULL)
145 jtag_interface->srst_asserted = default_srst_asserted;
146
147 return ERROR_OK;
148 }
149
150 /* no valid interface was found (i.e. the configuration option,
151 * didn't match one of the compiled-in interfaces
152 */
153 LOG_ERROR("The specified debug interface was not found (%s)", CMD_ARGV[0]);
154 CALL_COMMAND_HANDLER(handle_interface_list_command);
155 return ERROR_JTAG_INVALID_INTERFACE;
156 }
157
158 COMMAND_HANDLER(handle_reset_config_command)
159 {
160 int new_cfg = 0;
161 int mask = 0;
162
163 /* Original versions cared about the order of these tokens:
164 * reset_config signals [combination [trst_type [srst_type]]]
165 * They also clobbered the previous configuration even on error.
166 *
167 * Here we don't care about the order, and only change values
168 * which have been explicitly specified.
169 */
170 for (; CMD_ARGC; CMD_ARGC--, CMD_ARGV++) {
171 int tmp = 0;
172 int m;
173
174 /* gating */
175 m = RESET_SRST_NO_GATING;
176 if (strcmp(*CMD_ARGV, "srst_gates_jtag") == 0)
177 /* default: don't use JTAG while SRST asserted */;
178 else if (strcmp(*CMD_ARGV, "srst_nogate") == 0)
179 tmp = RESET_SRST_NO_GATING;
180 else
181 m = 0;
182 if (mask & m) {
183 LOG_ERROR("extra reset_config %s spec (%s)",
184 "gating", *CMD_ARGV);
185 return ERROR_INVALID_ARGUMENTS;
186 }
187 if (m)
188 goto next;
189
190 /* signals */
191 m = RESET_HAS_TRST | RESET_HAS_SRST;
192 if (strcmp(*CMD_ARGV, "none") == 0)
193 tmp = RESET_NONE;
194 else if (strcmp(*CMD_ARGV, "trst_only") == 0)
195 tmp = RESET_HAS_TRST;
196 else if (strcmp(*CMD_ARGV, "srst_only") == 0)
197 tmp = RESET_HAS_SRST;
198 else if (strcmp(*CMD_ARGV, "trst_and_srst") == 0)
199 tmp = RESET_HAS_TRST | RESET_HAS_SRST;
200 else
201 m = 0;
202 if (mask & m) {
203 LOG_ERROR("extra reset_config %s spec (%s)",
204 "signal", *CMD_ARGV);
205 return ERROR_INVALID_ARGUMENTS;
206 }
207 if (m)
208 goto next;
209
210 /* combination (options for broken wiring) */
211 m = RESET_SRST_PULLS_TRST | RESET_TRST_PULLS_SRST;
212 if (strcmp(*CMD_ARGV, "separate") == 0)
213 /* separate reset lines - default */;
214 else if (strcmp(*CMD_ARGV, "srst_pulls_trst") == 0)
215 tmp |= RESET_SRST_PULLS_TRST;
216 else if (strcmp(*CMD_ARGV, "trst_pulls_srst") == 0)
217 tmp |= RESET_TRST_PULLS_SRST;
218 else if (strcmp(*CMD_ARGV, "combined") == 0)
219 tmp |= RESET_SRST_PULLS_TRST | RESET_TRST_PULLS_SRST;
220 else
221 m = 0;
222 if (mask & m) {
223 LOG_ERROR("extra reset_config %s spec (%s)",
224 "combination", *CMD_ARGV);
225 return ERROR_INVALID_ARGUMENTS;
226 }
227 if (m)
228 goto next;
229
230 /* trst_type (NOP without HAS_TRST) */
231 m = RESET_TRST_OPEN_DRAIN;
232 if (strcmp(*CMD_ARGV, "trst_open_drain") == 0)
233 tmp |= RESET_TRST_OPEN_DRAIN;
234 else if (strcmp(*CMD_ARGV, "trst_push_pull") == 0)
235 /* push/pull from adapter - default */;
236 else
237 m = 0;
238 if (mask & m) {
239 LOG_ERROR("extra reset_config %s spec (%s)",
240 "trst_type", *CMD_ARGV);
241 return ERROR_INVALID_ARGUMENTS;
242 }
243 if (m)
244 goto next;
245
246 /* srst_type (NOP without HAS_SRST) */
247 m |= RESET_SRST_PUSH_PULL;
248 if (strcmp(*CMD_ARGV, "srst_push_pull") == 0)
249 tmp |= RESET_SRST_PUSH_PULL;
250 else if (strcmp(*CMD_ARGV, "srst_open_drain") == 0)
251 /* open drain from adapter - default */;
252 else
253 m = 0;
254 if (mask & m) {
255 LOG_ERROR("extra reset_config %s spec (%s)",
256 "srst_type", *CMD_ARGV);
257 return ERROR_INVALID_ARGUMENTS;
258 }
259 if (m)
260 goto next;
261
262 /* caller provided nonsense; fail */
263 LOG_ERROR("unknown reset_config flag (%s)", *CMD_ARGV);
264 return ERROR_INVALID_ARGUMENTS;
265
266 next:
267 /* Remember the bits which were specified (mask)
268 * and their new values (new_cfg).
269 */
270 mask |= m;
271 new_cfg |= tmp;
272 }
273
274 /* clear previous values of those bits, save new values */
275 if (mask) {
276 int old_cfg = jtag_get_reset_config();
277
278 old_cfg &= ~mask;
279 new_cfg |= old_cfg;
280 jtag_set_reset_config(new_cfg);
281 } else
282 new_cfg = jtag_get_reset_config();
283
284
285 /*
286 * Display the (now-)current reset mode
287 */
288 char *modes[5];
289
290 /* minimal JTAG has neither SRST nor TRST (so that's the default) */
291 switch (new_cfg & (RESET_HAS_TRST | RESET_HAS_SRST)) {
292 case RESET_HAS_SRST:
293 modes[0] = "srst_only";
294 break;
295 case RESET_HAS_TRST:
296 modes[0] = "trst_only";
297 break;
298 case RESET_TRST_AND_SRST:
299 modes[0] = "trst_and_srst";
300 break;
301 default:
302 modes[0] = "none";
303 break;
304 }
305
306 /* normally SRST and TRST are decoupled; but bugs happen ... */
307 switch (new_cfg & (RESET_SRST_PULLS_TRST | RESET_TRST_PULLS_SRST)) {
308 case RESET_SRST_PULLS_TRST:
309 modes[1] = "srst_pulls_trst";
310 break;
311 case RESET_TRST_PULLS_SRST:
312 modes[1] = "trst_pulls_srst";
313 break;
314 case RESET_SRST_PULLS_TRST | RESET_TRST_PULLS_SRST:
315 modes[1] = "combined";
316 break;
317 default:
318 modes[1] = "separate";
319 break;
320 }
321
322 /* TRST-less connectors include Altera, Xilinx, and minimal JTAG */
323 if (new_cfg & RESET_HAS_TRST) {
324 if (new_cfg & RESET_TRST_OPEN_DRAIN)
325 modes[3] = " trst_open_drain";
326 else
327 modes[3] = " trst_push_pull";
328 } else
329 modes[3] = "";
330
331 /* SRST-less connectors include TI-14, Xilinx, and minimal JTAG */
332 if (new_cfg & RESET_HAS_SRST) {
333 if (new_cfg & RESET_SRST_NO_GATING)
334 modes[2] = " srst_nogate";
335 else
336 modes[2] = " srst_gates_jtag";
337
338 if (new_cfg & RESET_SRST_PUSH_PULL)
339 modes[4] = " srst_push_pull";
340 else
341 modes[4] = " srst_open_drain";
342 } else {
343 modes[2] = "";
344 modes[4] = "";
345 }
346
347 command_print(CMD_CTX, "%s %s%s%s%s",
348 modes[0], modes[1],
349 modes[2], modes[3], modes[4]);
350
351 return ERROR_OK;
352 }
353
354 COMMAND_HANDLER(handle_adapter_nsrst_delay_command)
355 {
356 if (CMD_ARGC > 1)
357 return ERROR_COMMAND_SYNTAX_ERROR;
358 if (CMD_ARGC == 1)
359 {
360 unsigned delay;
361 COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], delay);
362
363 jtag_set_nsrst_delay(delay);
364 }
365 command_print(CMD_CTX, "adapter_nsrst_delay: %u", jtag_get_nsrst_delay());
366 return ERROR_OK;
367 }
368
369 COMMAND_HANDLER(handle_adapter_khz_command)
370 {
371 if (CMD_ARGC > 1)
372 return ERROR_COMMAND_SYNTAX_ERROR;
373
374 int retval = ERROR_OK;
375 if (CMD_ARGC == 1)
376 {
377 unsigned khz = 0;
378 COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], khz);
379
380 retval = jtag_config_khz(khz);
381 if (ERROR_OK != retval)
382 return retval;
383 }
384
385 int cur_speed = jtag_get_speed_khz();
386 retval = jtag_get_speed_readable(&cur_speed);
387 if (ERROR_OK != retval)
388 return retval;
389
390 if (cur_speed)
391 command_print(CMD_CTX, "%d kHz", cur_speed);
392 else
393 command_print(CMD_CTX, "RCLK - adaptive");
394
395 return retval;
396 }
397
398 static const struct command_registration interface_command_handlers[] = {
399 {
400 .name = "adapter_khz",
401 .handler = handle_adapter_khz_command,
402 .mode = COMMAND_ANY,
403 .help = "With an argument, change to the specified maximum "
404 "jtag speed. For JTAG, 0 KHz signifies adaptive "
405 " clocking. "
406 "With or without argument, display current setting.",
407 .usage = "[khz]",
408 },
409 {
410 .name = "adapter_name",
411 .mode = COMMAND_ANY,
412 .jim_handler = jim_adapter_name,
413 .help = "Returns the name of the currently "
414 "selected adapter (driver)",
415 },
416 {
417 .name = "adapter_nsrst_delay",
418 .handler = handle_adapter_nsrst_delay_command,
419 .mode = COMMAND_ANY,
420 .help = "delay after deasserting SRST in ms",
421 .usage = "[milliseconds]",
422 },
423 {
424 .name = "interface",
425 .handler = handle_interface_command,
426 .mode = COMMAND_CONFIG,
427 .help = "Select a debug adapter interface (driver)",
428 .usage = "driver_name",
429 },
430 {
431 .name = "interface_list",
432 .handler = handle_interface_list_command,
433 .mode = COMMAND_ANY,
434 .help = "List all built-in debug adapter interfaces (drivers)",
435 },
436 {
437 .name = "reset_config",
438 .handler = handle_reset_config_command,
439 .mode = COMMAND_ANY,
440 .help = "configure adapter reset behavior",
441 .usage = "[none|trst_only|srst_only|trst_and_srst] "
442 "[srst_pulls_trst|trst_pulls_srst|combined|separate] "
443 "[srst_gates_jtag|srst_nogate] "
444 "[trst_push_pull|trst_open_drain] "
445 "[srst_push_pull|srst_open_drain]",
446 },
447 COMMAND_REGISTRATION_DONE
448 };
449
450 /**
451 * Register the commands which deal with arbitrary debug adapter drivers.
452 *
453 * @todo Remove internal assumptions that all debug adapters use JTAG for
454 * transport. Various types and data structures are not named generically.
455 */
456 int interface_register_commands(struct command_context *ctx)
457 {
458 return register_commands(ctx, NULL, interface_command_handlers);
459 }

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)