1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
5 * Copyright (C) 2007-2009 Øyvind Harboe *
6 * oyvind.harboe@zylin.com *
8 * Copyright (C) 2009 SoftPLC Corporation *
12 * Copyright (C) 2009 Zachary T Welch *
13 * zw@superlucidity.net *
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. *
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. *
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 ***************************************************************************/
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>
40 struct jtag_callback_entry
42 struct jtag_callback_entry
*next
;
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
;
51 static struct jtag_callback_entry
*jtag_callback_queue_head
= NULL
;
52 static struct jtag_callback_entry
*jtag_callback_queue_tail
= NULL
;
54 static void jtag_callback_queue_reset(void)
56 jtag_callback_queue_head
= NULL
;
57 jtag_callback_queue_tail
= NULL
;
61 * Copy a struct scan_field for insertion into the queue.
63 * This allocates a new copy of out_value using cmd_queue_alloc.
65 static void cmd_queue_scan_field_clone(struct scan_field
* dst
, const struct scan_field
* src
)
68 dst
->num_bits
= src
->num_bits
;
69 dst
->out_value
= buf_cpy(src
->out_value
, cmd_queue_alloc(DIV_ROUND_UP(src
->num_bits
, 8)), src
->num_bits
);
70 dst
->in_value
= src
->in_value
;
75 * see jtag_add_ir_scan()
78 int interface_jtag_add_ir_scan(int in_num_fields
, const struct scan_field
*in_fields
, tap_state_t state
)
80 size_t num_taps
= jtag_tap_count_enabled();
82 struct jtag_command
* cmd
= cmd_queue_alloc(sizeof(struct jtag_command
));
83 struct scan_command
* scan
= cmd_queue_alloc(sizeof(struct scan_command
));
84 struct scan_field
* out_fields
= cmd_queue_alloc(num_taps
* sizeof(struct scan_field
));
86 jtag_queue_command(cmd
);
88 cmd
->type
= JTAG_SCAN
;
92 scan
->num_fields
= num_taps
; /* one field per device */
93 scan
->fields
= out_fields
;
94 scan
->end_state
= state
;
97 struct scan_field
* field
= out_fields
; /* keep track where we insert data */
99 /* loop over all enabled TAPs */
101 for (struct jtag_tap
* tap
= jtag_tap_next_enabled(NULL
); tap
!= NULL
; tap
= jtag_tap_next_enabled(tap
))
103 /* search the input field list for fields for the current TAP */
107 for (int j
= 0; j
< in_num_fields
; j
++)
109 if (tap
!= in_fields
[j
].tap
)
112 /* if TAP is listed in input fields, copy the value */
118 assert(in_fields
[j
].num_bits
== tap
->ir_length
); /* input fields must have the same length as the TAP's IR */
120 cmd_queue_scan_field_clone(field
, in_fields
+ j
);
127 /* if a TAP isn't listed in input fields, set it to BYPASS */
132 field
->num_bits
= tap
->ir_length
;
133 field
->out_value
= buf_set_ones(cmd_queue_alloc(DIV_ROUND_UP(tap
->ir_length
, 8)), tap
->ir_length
);
134 field
->in_value
= NULL
; /* do not collect input for tap's in bypass */
137 /* update device information */
138 buf_cpy(field
->out_value
, tap
->cur_instr
, tap
->ir_length
);
143 assert(field
== out_fields
+ num_taps
); /* paranoia: jtag_tap_count_enabled() and jtag_tap_next_enabled() not in sync */
149 * see jtag_add_plain_ir_scan()
152 int interface_jtag_add_plain_ir_scan(int in_num_fields
, const struct scan_field
*in_fields
, tap_state_t state
)
155 struct jtag_command
* cmd
= cmd_queue_alloc(sizeof(struct jtag_command
));
156 struct scan_command
* scan
= cmd_queue_alloc(sizeof(struct scan_command
));
157 struct scan_field
* out_fields
= cmd_queue_alloc(in_num_fields
* sizeof(struct scan_field
));
159 jtag_queue_command(cmd
);
161 cmd
->type
= JTAG_SCAN
;
162 cmd
->cmd
.scan
= scan
;
164 scan
->ir_scan
= true;
165 scan
->num_fields
= in_num_fields
;
166 scan
->fields
= out_fields
;
167 scan
->end_state
= state
;
169 for (int i
= 0; i
< in_num_fields
; i
++)
170 cmd_queue_scan_field_clone(out_fields
+ i
, in_fields
+ i
);
178 * see jtag_add_dr_scan()
181 int interface_jtag_add_dr_scan(int in_num_fields
, const struct scan_field
*in_fields
, tap_state_t state
)
183 /* count devices in bypass */
185 size_t bypass_devices
= 0;
187 for (struct jtag_tap
* tap
= jtag_tap_next_enabled(NULL
); tap
!= NULL
; tap
= jtag_tap_next_enabled(tap
))
193 struct jtag_command
* cmd
= cmd_queue_alloc(sizeof(struct jtag_command
));
194 struct scan_command
* scan
= cmd_queue_alloc(sizeof(struct scan_command
));
195 struct scan_field
* out_fields
= cmd_queue_alloc((in_num_fields
+ bypass_devices
) * sizeof(struct scan_field
));
197 jtag_queue_command(cmd
);
199 cmd
->type
= JTAG_SCAN
;
200 cmd
->cmd
.scan
= scan
;
202 scan
->ir_scan
= false;
203 scan
->num_fields
= in_num_fields
+ bypass_devices
;
204 scan
->fields
= out_fields
;
205 scan
->end_state
= state
;
208 struct scan_field
* field
= out_fields
; /* keep track where we insert data */
210 /* loop over all enabled TAPs */
212 for (struct jtag_tap
* tap
= jtag_tap_next_enabled(NULL
); tap
!= NULL
; tap
= jtag_tap_next_enabled(tap
))
214 /* if TAP is not bypassed insert matching input fields */
219 /* remember initial position for assert() */
220 struct scan_field
*start_field
= field
;
223 for (int j
= 0; j
< in_num_fields
; j
++)
225 if (tap
!= in_fields
[j
].tap
)
228 cmd_queue_scan_field_clone(field
, in_fields
+ j
);
233 assert(field
> start_field
); /* must have at least one input field per not bypassed TAP */
236 /* if a TAP is bypassed, generated a dummy bit*/
241 field
->out_value
= NULL
;
242 field
->in_value
= NULL
;
248 assert(field
== out_fields
+ scan
->num_fields
); /* no superfluous input fields permitted */
256 * Generate a DR SCAN using the array of output values passed to the function
258 * This function assumes that the parameter target_tap specifies the one TAP
259 * that is not bypassed. All other TAPs must be bypassed and the function will
260 * generate a dummy 1bit field for them.
262 * For the target_tap a sequence of output-only fields will be generated where
263 * each field has the size num_bits and the field's values are taken from
266 * The bypass status of TAPs is set by jtag_add_ir_scan().
269 void interface_jtag_add_dr_out(struct jtag_tap
*target_tap
,
272 const uint32_t *value
,
273 tap_state_t end_state
)
275 /* count devices in bypass */
277 size_t bypass_devices
= 0;
279 for (struct jtag_tap
* tap
= jtag_tap_next_enabled(NULL
); tap
!= NULL
; tap
= jtag_tap_next_enabled(tap
))
286 struct jtag_command
* cmd
= cmd_queue_alloc(sizeof(struct jtag_command
));
287 struct scan_command
* scan
= cmd_queue_alloc(sizeof(struct scan_command
));
288 struct scan_field
* out_fields
= cmd_queue_alloc((in_num_fields
+ bypass_devices
) * sizeof(struct scan_field
));
290 jtag_queue_command(cmd
);
292 cmd
->type
= JTAG_SCAN
;
293 cmd
->cmd
.scan
= scan
;
295 scan
->ir_scan
= false;
296 scan
->num_fields
= in_num_fields
+ bypass_devices
;
297 scan
->fields
= out_fields
;
298 scan
->end_state
= end_state
;
301 bool target_tap_match
= false;
303 struct scan_field
* field
= out_fields
; /* keep track where we insert data */
305 /* loop over all enabled TAPs */
307 for (struct jtag_tap
* tap
= jtag_tap_next_enabled(NULL
); tap
!= NULL
; tap
= jtag_tap_next_enabled(tap
))
309 /* if TAP is not bypassed insert matching input fields */
313 assert(tap
== target_tap
); /* target_tap must match the one not bypassed TAP */
315 target_tap_match
= true;
317 for (int j
= 0; j
< in_num_fields
; j
++)
319 uint8_t out_value
[4];
320 size_t scan_size
= num_bits
[j
];
321 buf_set_u32(out_value
, 0, scan_size
, value
[j
]);
324 field
->num_bits
= scan_size
;
325 field
->out_value
= buf_cpy(out_value
, cmd_queue_alloc(DIV_ROUND_UP(scan_size
, 8)), scan_size
);
326 field
->in_value
= NULL
;
332 /* if a TAP is bypassed, generated a dummy bit*/
338 field
->out_value
= NULL
;
339 field
->in_value
= NULL
;
345 assert(target_tap_match
); /* target_tap should be enabled and not bypassed */
349 * see jtag_add_plain_dr_scan()
352 int interface_jtag_add_plain_dr_scan(int in_num_fields
, const struct scan_field
*in_fields
, tap_state_t state
)
354 struct jtag_command
* cmd
= cmd_queue_alloc(sizeof(struct jtag_command
));
355 struct scan_command
* scan
= cmd_queue_alloc(sizeof(struct scan_command
));
356 struct scan_field
* out_fields
= cmd_queue_alloc(in_num_fields
* sizeof(struct scan_field
));
358 jtag_queue_command(cmd
);
360 cmd
->type
= JTAG_SCAN
;
361 cmd
->cmd
.scan
= scan
;
363 scan
->ir_scan
= false;
364 scan
->num_fields
= in_num_fields
;
365 scan
->fields
= out_fields
;
366 scan
->end_state
= state
;
368 for (int i
= 0; i
< in_num_fields
; i
++)
369 cmd_queue_scan_field_clone(out_fields
+ i
, in_fields
+ i
);
374 int interface_jtag_add_tlr(void)
376 tap_state_t state
= TAP_RESET
;
378 /* allocate memory for a new list member */
379 struct jtag_command
* cmd
= cmd_queue_alloc(sizeof(struct jtag_command
));
381 jtag_queue_command(cmd
);
383 cmd
->type
= JTAG_STATEMOVE
;
385 cmd
->cmd
.statemove
= cmd_queue_alloc(sizeof(struct statemove_command
));
386 cmd
->cmd
.statemove
->end_state
= state
;
391 int interface_jtag_add_pathmove(int num_states
, const tap_state_t
*path
)
393 /* allocate memory for a new list member */
394 struct jtag_command
* cmd
= cmd_queue_alloc(sizeof(struct jtag_command
));
396 jtag_queue_command(cmd
);
398 cmd
->type
= JTAG_PATHMOVE
;
400 cmd
->cmd
.pathmove
= cmd_queue_alloc(sizeof(struct pathmove_command
));
401 cmd
->cmd
.pathmove
->num_states
= num_states
;
402 cmd
->cmd
.pathmove
->path
= cmd_queue_alloc(sizeof(tap_state_t
) * num_states
);
404 for (int i
= 0; i
< num_states
; i
++)
405 cmd
->cmd
.pathmove
->path
[i
] = path
[i
];
410 int interface_jtag_add_runtest(int num_cycles
, tap_state_t state
)
412 /* allocate memory for a new list member */
413 struct jtag_command
* cmd
= cmd_queue_alloc(sizeof(struct jtag_command
));
415 jtag_queue_command(cmd
);
417 cmd
->type
= JTAG_RUNTEST
;
419 cmd
->cmd
.runtest
= cmd_queue_alloc(sizeof(struct runtest_command
));
420 cmd
->cmd
.runtest
->num_cycles
= num_cycles
;
421 cmd
->cmd
.runtest
->end_state
= state
;
426 int interface_jtag_add_clocks(int num_cycles
)
428 /* allocate memory for a new list member */
429 struct jtag_command
* cmd
= cmd_queue_alloc(sizeof(struct jtag_command
));
431 jtag_queue_command(cmd
);
433 cmd
->type
= JTAG_STABLECLOCKS
;
435 cmd
->cmd
.stableclocks
= cmd_queue_alloc(sizeof(struct stableclocks_command
));
436 cmd
->cmd
.stableclocks
->num_cycles
= num_cycles
;
441 int interface_jtag_add_reset(int req_trst
, int req_srst
)
443 /* allocate memory for a new list member */
444 struct jtag_command
* cmd
= cmd_queue_alloc(sizeof(struct jtag_command
));
446 jtag_queue_command(cmd
);
448 cmd
->type
= JTAG_RESET
;
450 cmd
->cmd
.reset
= cmd_queue_alloc(sizeof(struct reset_command
));
451 cmd
->cmd
.reset
->trst
= req_trst
;
452 cmd
->cmd
.reset
->srst
= req_srst
;
457 int interface_jtag_add_sleep(uint32_t us
)
459 /* allocate memory for a new list member */
460 struct jtag_command
* cmd
= cmd_queue_alloc(sizeof(struct jtag_command
));
462 jtag_queue_command(cmd
);
464 cmd
->type
= JTAG_SLEEP
;
466 cmd
->cmd
.sleep
= cmd_queue_alloc(sizeof(struct sleep_command
));
467 cmd
->cmd
.sleep
->us
= us
;
472 /* add callback to end of queue */
473 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
)
475 struct jtag_callback_entry
*entry
= cmd_queue_alloc(sizeof(struct jtag_callback_entry
));
478 entry
->callback
= callback
;
479 entry
->data0
= data0
;
480 entry
->data1
= data1
;
481 entry
->data2
= data2
;
482 entry
->data3
= data3
;
484 if (jtag_callback_queue_head
== NULL
)
486 jtag_callback_queue_head
= entry
;
487 jtag_callback_queue_tail
= entry
;
490 jtag_callback_queue_tail
->next
= entry
;
491 jtag_callback_queue_tail
= entry
;
495 int interface_jtag_execute_queue(void)
497 static int reentry
= 0;
502 int retval
= default_interface_jtag_execute_queue();
503 if (retval
== ERROR_OK
)
505 struct jtag_callback_entry
*entry
;
506 for (entry
= jtag_callback_queue_head
; entry
!= NULL
; entry
= entry
->next
)
508 retval
= entry
->callback(entry
->data0
, entry
->data1
, entry
->data2
, entry
->data3
);
509 if (retval
!= ERROR_OK
)
514 jtag_command_queue_reset();
515 jtag_callback_queue_reset();
522 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
)
524 ((jtag_callback1_t
)data1
)(data0
);
528 void interface_jtag_add_callback(jtag_callback1_t callback
, jtag_callback_data_t data0
)
530 jtag_add_callback4(jtag_convert_to_callback4
, data0
, (jtag_callback_data_t
)callback
, 0, 0);
534 /* A minidriver can use use an inline versions of this API level fn */
535 void jtag_add_dr_out(struct jtag_tap
* tap
,
536 int num_fields
, const int* num_bits
, const uint32_t* value
,
537 tap_state_t end_state
)
539 assert(end_state
!= TAP_RESET
);
540 assert(end_state
!= TAP_INVALID
);
542 cmd_queue_cur_state
= end_state
;
544 interface_jtag_add_dr_out(tap
,
545 num_fields
, num_bits
, value
,
549 void jtag_add_callback(jtag_callback1_t f
, jtag_callback_data_t data0
)
551 interface_jtag_add_callback(f
, data0
);
554 void jtag_add_callback4(jtag_callback_t f
, jtag_callback_data_t data0
,
555 jtag_callback_data_t data1
, jtag_callback_data_t data2
,
556 jtag_callback_data_t data3
)
558 interface_jtag_add_callback4(f
, data0
, data1
, data2
, data3
);
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)