jtag: retire tap field
[openocd.git] / src / jtag / drivers / driver.c
1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
5 * Copyright (C) 2007-2009 Ø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/jtag.h>
35 #include <jtag/interface.h>
36 #include <jtag/commands.h>
37 #include <jtag/minidriver.h>
38 #include <helper/command.h>
39
40 struct jtag_callback_entry
41 {
42 struct jtag_callback_entry *next;
43
44 jtag_callback_t callback;
45 jtag_callback_data_t data0;
46 jtag_callback_data_t data1;
47 jtag_callback_data_t data2;
48 jtag_callback_data_t data3;
49 };
50
51 static struct jtag_callback_entry *jtag_callback_queue_head = NULL;
52 static struct jtag_callback_entry *jtag_callback_queue_tail = NULL;
53
54 static void jtag_callback_queue_reset(void)
55 {
56 jtag_callback_queue_head = NULL;
57 jtag_callback_queue_tail = NULL;
58 }
59
60 /**
61 * Copy a struct scan_field for insertion into the queue.
62 *
63 * This allocates a new copy of out_value using cmd_queue_alloc.
64 */
65 static void cmd_queue_scan_field_clone(struct scan_field * dst, const struct scan_field * src)
66 {
67 dst->num_bits = src->num_bits;
68 dst->out_value = buf_cpy(src->out_value, cmd_queue_alloc(DIV_ROUND_UP(src->num_bits, 8)), src->num_bits);
69 dst->in_value = src->in_value;
70 }
71
72
73 /**
74 * see jtag_add_ir_scan()
75 *
76 */
77 int interface_jtag_add_ir_scan(struct jtag_tap* active, int in_num_fields, const struct scan_field *in_fields, tap_state_t state)
78 {
79 size_t num_taps = jtag_tap_count_enabled();
80
81 struct jtag_command * cmd = cmd_queue_alloc(sizeof(struct jtag_command));
82 struct scan_command * scan = cmd_queue_alloc(sizeof(struct scan_command));
83 struct scan_field * out_fields = cmd_queue_alloc(num_taps * sizeof(struct scan_field));
84
85 jtag_queue_command(cmd);
86
87 cmd->type = JTAG_SCAN;
88 cmd->cmd.scan = scan;
89
90 scan->ir_scan = true;
91 scan->num_fields = num_taps; /* one field per device */
92 scan->fields = out_fields;
93 scan->end_state = state;
94
95
96 struct scan_field * field = out_fields; /* keep track where we insert data */
97
98 /* loop over all enabled TAPs */
99
100 for (struct jtag_tap * tap = jtag_tap_next_enabled(NULL); tap != NULL; tap = jtag_tap_next_enabled(tap))
101 {
102 /* search the input field list for fields for the current TAP */
103
104 if (tap == active)
105 {
106 /* if TAP is listed in input fields, copy the value */
107 tap->bypass = 0;
108
109 for (int j = 0; j < in_num_fields; j++)
110 cmd_queue_scan_field_clone(field, in_fields + j);
111 } else
112 {
113 /* if a TAP isn't listed in input fields, set it to BYPASS */
114
115 tap->bypass = 1;
116
117 field->num_bits = tap->ir_length;
118 field->out_value = buf_set_ones(cmd_queue_alloc(DIV_ROUND_UP(tap->ir_length, 8)), tap->ir_length);
119 field->in_value = NULL; /* do not collect input for tap's in bypass */
120 }
121
122 /* update device information */
123 buf_cpy(field->out_value, tap->cur_instr, tap->ir_length);
124
125 field++;
126 }
127
128 assert(field == out_fields + num_taps); /* paranoia: jtag_tap_count_enabled() and jtag_tap_next_enabled() not in sync */
129
130 return ERROR_OK;
131 }
132
133 /**
134 * see jtag_add_plain_ir_scan()
135 *
136 */
137 int interface_jtag_add_plain_ir_scan(int in_num_fields, const struct scan_field *in_fields, tap_state_t state)
138 {
139
140 struct jtag_command * cmd = cmd_queue_alloc(sizeof(struct jtag_command));
141 struct scan_command * scan = cmd_queue_alloc(sizeof(struct scan_command));
142 struct scan_field * out_fields = cmd_queue_alloc(in_num_fields * sizeof(struct scan_field));
143
144 jtag_queue_command(cmd);
145
146 cmd->type = JTAG_SCAN;
147 cmd->cmd.scan = scan;
148
149 scan->ir_scan = true;
150 scan->num_fields = in_num_fields;
151 scan->fields = out_fields;
152 scan->end_state = state;
153
154 for (int i = 0; i < in_num_fields; i++)
155 cmd_queue_scan_field_clone(out_fields + i, in_fields + i);
156
157 return ERROR_OK;
158 }
159
160
161
162 /**
163 * see jtag_add_dr_scan()
164 *
165 */
166 int interface_jtag_add_dr_scan(struct jtag_tap* active, int in_num_fields, const struct scan_field *in_fields, tap_state_t state)
167 {
168 /* count devices in bypass */
169
170 size_t bypass_devices = 0;
171
172 for (struct jtag_tap * tap = jtag_tap_next_enabled(NULL); tap != NULL; tap = jtag_tap_next_enabled(tap))
173 {
174 if (tap->bypass)
175 bypass_devices++;
176 }
177
178 struct jtag_command * cmd = cmd_queue_alloc(sizeof(struct jtag_command));
179 struct scan_command * scan = cmd_queue_alloc(sizeof(struct scan_command));
180 struct scan_field * out_fields = cmd_queue_alloc((in_num_fields + bypass_devices) * sizeof(struct scan_field));
181
182 jtag_queue_command(cmd);
183
184 cmd->type = JTAG_SCAN;
185 cmd->cmd.scan = scan;
186
187 scan->ir_scan = false;
188 scan->num_fields = in_num_fields + bypass_devices;
189 scan->fields = out_fields;
190 scan->end_state = state;
191
192
193 struct scan_field * field = out_fields; /* keep track where we insert data */
194
195 /* loop over all enabled TAPs */
196
197 for (struct jtag_tap * tap = jtag_tap_next_enabled(NULL); tap != NULL; tap = jtag_tap_next_enabled(tap))
198 {
199 /* if TAP is not bypassed insert matching input fields */
200
201 if (!tap->bypass)
202 {
203 assert(active == tap);
204 #ifndef NDEBUG
205 /* remember initial position for assert() */
206 struct scan_field *start_field = field;
207 #endif /* NDEBUG */
208
209 for (int j = 0; j < in_num_fields; j++)
210 {
211 cmd_queue_scan_field_clone(field, in_fields + j);
212
213 field++;
214 }
215
216 assert(field > start_field); /* must have at least one input field per not bypassed TAP */
217 }
218
219 /* if a TAP is bypassed, generated a dummy bit*/
220 else
221 {
222 field->num_bits = 1;
223 field->out_value = NULL;
224 field->in_value = NULL;
225
226 field++;
227 }
228 }
229
230 assert(field == out_fields + scan->num_fields); /* no superfluous input fields permitted */
231
232 return ERROR_OK;
233 }
234
235
236
237 /**
238 * Generate a DR SCAN using the array of output values passed to the function
239 *
240 * This function assumes that the parameter target_tap specifies the one TAP
241 * that is not bypassed. All other TAPs must be bypassed and the function will
242 * generate a dummy 1bit field for them.
243 *
244 * For the target_tap a sequence of output-only fields will be generated where
245 * each field has the size num_bits and the field's values are taken from
246 * the array value.
247 *
248 * The bypass status of TAPs is set by jtag_add_ir_scan().
249 *
250 */
251 void interface_jtag_add_dr_out(struct jtag_tap *target_tap,
252 int in_num_fields,
253 const int *num_bits,
254 const uint32_t *value,
255 tap_state_t end_state)
256 {
257 /* count devices in bypass */
258
259 size_t bypass_devices = 0;
260
261 for (struct jtag_tap * tap = jtag_tap_next_enabled(NULL); tap != NULL; tap = jtag_tap_next_enabled(tap))
262 {
263 if (tap->bypass)
264 bypass_devices++;
265 }
266
267
268 struct jtag_command * cmd = cmd_queue_alloc(sizeof(struct jtag_command));
269 struct scan_command * scan = cmd_queue_alloc(sizeof(struct scan_command));
270 struct scan_field * out_fields = cmd_queue_alloc((in_num_fields + bypass_devices) * sizeof(struct scan_field));
271
272 jtag_queue_command(cmd);
273
274 cmd->type = JTAG_SCAN;
275 cmd->cmd.scan = scan;
276
277 scan->ir_scan = false;
278 scan->num_fields = in_num_fields + bypass_devices;
279 scan->fields = out_fields;
280 scan->end_state = end_state;
281
282
283 bool target_tap_match = false;
284
285 struct scan_field * field = out_fields; /* keep track where we insert data */
286
287 /* loop over all enabled TAPs */
288
289 for (struct jtag_tap * tap = jtag_tap_next_enabled(NULL); tap != NULL; tap = jtag_tap_next_enabled(tap))
290 {
291 /* if TAP is not bypassed insert matching input fields */
292
293 if (!tap->bypass)
294 {
295 assert(tap == target_tap); /* target_tap must match the one not bypassed TAP */
296
297 target_tap_match = true;
298
299 for (int j = 0; j < in_num_fields; j++)
300 {
301 uint8_t out_value[4];
302 size_t scan_size = num_bits[j];
303 buf_set_u32(out_value, 0, scan_size, value[j]);
304
305 field->num_bits = scan_size;
306 field->out_value = buf_cpy(out_value, cmd_queue_alloc(DIV_ROUND_UP(scan_size, 8)), scan_size);
307 field->in_value = NULL;
308
309 field++;
310 }
311 }
312
313 /* if a TAP is bypassed, generated a dummy bit*/
314 else
315 {
316
317 field->num_bits = 1;
318 field->out_value = NULL;
319 field->in_value = NULL;
320
321 field++;
322 }
323 }
324
325 assert(target_tap_match); /* target_tap should be enabled and not bypassed */
326 }
327
328 /**
329 * see jtag_add_plain_dr_scan()
330 *
331 */
332 int interface_jtag_add_plain_dr_scan(int in_num_fields, const struct scan_field *in_fields, tap_state_t state)
333 {
334 struct jtag_command * cmd = cmd_queue_alloc(sizeof(struct jtag_command));
335 struct scan_command * scan = cmd_queue_alloc(sizeof(struct scan_command));
336 struct scan_field * out_fields = cmd_queue_alloc(in_num_fields * sizeof(struct scan_field));
337
338 jtag_queue_command(cmd);
339
340 cmd->type = JTAG_SCAN;
341 cmd->cmd.scan = scan;
342
343 scan->ir_scan = false;
344 scan->num_fields = in_num_fields;
345 scan->fields = out_fields;
346 scan->end_state = state;
347
348 for (int i = 0; i < in_num_fields; i++)
349 cmd_queue_scan_field_clone(out_fields + i, in_fields + i);
350
351 return ERROR_OK;
352 }
353
354 int interface_jtag_add_tlr(void)
355 {
356 tap_state_t state = TAP_RESET;
357
358 /* allocate memory for a new list member */
359 struct jtag_command * cmd = cmd_queue_alloc(sizeof(struct jtag_command));
360
361 jtag_queue_command(cmd);
362
363 cmd->type = JTAG_STATEMOVE;
364
365 cmd->cmd.statemove = cmd_queue_alloc(sizeof(struct statemove_command));
366 cmd->cmd.statemove->end_state = state;
367
368 return ERROR_OK;
369 }
370
371 int interface_add_tms_seq(unsigned num_bits, const uint8_t *seq, enum tap_state state)
372 {
373 struct jtag_command *cmd;
374
375 cmd = cmd_queue_alloc(sizeof(struct jtag_command));
376 if (cmd == NULL)
377 return ERROR_FAIL;
378
379 cmd->type = JTAG_TMS;
380 cmd->cmd.tms = cmd_queue_alloc(sizeof(*cmd->cmd.tms));
381 if (!cmd->cmd.tms)
382 return ERROR_FAIL;
383
384 /* copy the bits; our caller doesn't guarantee they'll persist */
385 cmd->cmd.tms->num_bits = num_bits;
386 cmd->cmd.tms->bits = buf_cpy(seq,
387 cmd_queue_alloc(DIV_ROUND_UP(num_bits, 8)), num_bits);
388 if (!cmd->cmd.tms->bits)
389 return ERROR_FAIL;
390
391 jtag_queue_command(cmd);
392
393 return ERROR_OK;
394 }
395
396 int interface_jtag_add_pathmove(int num_states, const tap_state_t *path)
397 {
398 /* allocate memory for a new list member */
399 struct jtag_command * cmd = cmd_queue_alloc(sizeof(struct jtag_command));
400
401 jtag_queue_command(cmd);
402
403 cmd->type = JTAG_PATHMOVE;
404
405 cmd->cmd.pathmove = cmd_queue_alloc(sizeof(struct pathmove_command));
406 cmd->cmd.pathmove->num_states = num_states;
407 cmd->cmd.pathmove->path = cmd_queue_alloc(sizeof(tap_state_t) * num_states);
408
409 for (int i = 0; i < num_states; i++)
410 cmd->cmd.pathmove->path[i] = path[i];
411
412 return ERROR_OK;
413 }
414
415 int interface_jtag_add_runtest(int num_cycles, tap_state_t state)
416 {
417 /* allocate memory for a new list member */
418 struct jtag_command * cmd = cmd_queue_alloc(sizeof(struct jtag_command));
419
420 jtag_queue_command(cmd);
421
422 cmd->type = JTAG_RUNTEST;
423
424 cmd->cmd.runtest = cmd_queue_alloc(sizeof(struct runtest_command));
425 cmd->cmd.runtest->num_cycles = num_cycles;
426 cmd->cmd.runtest->end_state = state;
427
428 return ERROR_OK;
429 }
430
431 int interface_jtag_add_clocks(int num_cycles)
432 {
433 /* allocate memory for a new list member */
434 struct jtag_command * cmd = cmd_queue_alloc(sizeof(struct jtag_command));
435
436 jtag_queue_command(cmd);
437
438 cmd->type = JTAG_STABLECLOCKS;
439
440 cmd->cmd.stableclocks = cmd_queue_alloc(sizeof(struct stableclocks_command));
441 cmd->cmd.stableclocks->num_cycles = num_cycles;
442
443 return ERROR_OK;
444 }
445
446 int interface_jtag_add_reset(int req_trst, int req_srst)
447 {
448 /* allocate memory for a new list member */
449 struct jtag_command * cmd = cmd_queue_alloc(sizeof(struct jtag_command));
450
451 jtag_queue_command(cmd);
452
453 cmd->type = JTAG_RESET;
454
455 cmd->cmd.reset = cmd_queue_alloc(sizeof(struct reset_command));
456 cmd->cmd.reset->trst = req_trst;
457 cmd->cmd.reset->srst = req_srst;
458
459 return ERROR_OK;
460 }
461
462 int interface_jtag_add_sleep(uint32_t us)
463 {
464 /* allocate memory for a new list member */
465 struct jtag_command * cmd = cmd_queue_alloc(sizeof(struct jtag_command));
466
467 jtag_queue_command(cmd);
468
469 cmd->type = JTAG_SLEEP;
470
471 cmd->cmd.sleep = cmd_queue_alloc(sizeof(struct sleep_command));
472 cmd->cmd.sleep->us = us;
473
474 return ERROR_OK;
475 }
476
477 /* add callback to end of queue */
478 void interface_jtag_add_callback4(jtag_callback_t callback, jtag_callback_data_t data0, jtag_callback_data_t data1, jtag_callback_data_t data2, jtag_callback_data_t data3)
479 {
480 struct jtag_callback_entry *entry = cmd_queue_alloc(sizeof(struct jtag_callback_entry));
481
482 entry->next = NULL;
483 entry->callback = callback;
484 entry->data0 = data0;
485 entry->data1 = data1;
486 entry->data2 = data2;
487 entry->data3 = data3;
488
489 if (jtag_callback_queue_head == NULL)
490 {
491 jtag_callback_queue_head = entry;
492 jtag_callback_queue_tail = entry;
493 } else
494 {
495 jtag_callback_queue_tail->next = entry;
496 jtag_callback_queue_tail = entry;
497 }
498 }
499
500 int interface_jtag_execute_queue(void)
501 {
502 static int reentry = 0;
503
504 assert(reentry==0);
505 reentry++;
506
507 int retval = default_interface_jtag_execute_queue();
508 if (retval == ERROR_OK)
509 {
510 struct jtag_callback_entry *entry;
511 for (entry = jtag_callback_queue_head; entry != NULL; entry = entry->next)
512 {
513 retval = entry->callback(entry->data0, entry->data1, entry->data2, entry->data3);
514 if (retval != ERROR_OK)
515 break;
516 }
517 }
518
519 jtag_command_queue_reset();
520 jtag_callback_queue_reset();
521
522 reentry--;
523
524 return retval;
525 }
526
527 static int jtag_convert_to_callback4(jtag_callback_data_t data0, jtag_callback_data_t data1, jtag_callback_data_t data2, jtag_callback_data_t data3)
528 {
529 ((jtag_callback1_t)data1)(data0);
530 return ERROR_OK;
531 }
532
533 void interface_jtag_add_callback(jtag_callback1_t callback, jtag_callback_data_t data0)
534 {
535 jtag_add_callback4(jtag_convert_to_callback4, data0, (jtag_callback_data_t)callback, 0, 0);
536 }
537
538
539 /* A minidriver can use use an inline versions of this API level fn */
540 void jtag_add_dr_out(struct jtag_tap* tap,
541 int num_fields, const int* num_bits, const uint32_t* value,
542 tap_state_t end_state)
543 {
544 assert(end_state != TAP_RESET);
545 assert(end_state != TAP_INVALID);
546
547 cmd_queue_cur_state = end_state;
548
549 interface_jtag_add_dr_out(tap,
550 num_fields, num_bits, value,
551 end_state);
552 }
553
554 void jtag_add_callback(jtag_callback1_t f, jtag_callback_data_t data0)
555 {
556 interface_jtag_add_callback(f, data0);
557 }
558
559 void jtag_add_callback4(jtag_callback_t f, jtag_callback_data_t data0,
560 jtag_callback_data_t data1, jtag_callback_data_t data2,
561 jtag_callback_data_t data3)
562 {
563 interface_jtag_add_callback4(f, data0, data1, data2, data3);
564 }

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)