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

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)