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

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)