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

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)