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

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)