1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright (C) 2005 by Dominic Rath *
5 * Dominic.Rath@gmx.de *
7 * Copyright (C) 2007-2010 Øyvind Harboe *
8 * oyvind.harboe@zylin.com *
10 * Copyright (C) 2009 SoftPLC Corporation *
11 * http://softplc.com *
14 * Copyright (C) 2009 Zachary T Welch *
15 * zw@superlucidity.net *
16 ***************************************************************************/
22 #include <jtag/jtag.h>
23 #include <jtag/interface.h>
24 #include <jtag/commands.h>
25 #include <jtag/minidriver.h>
26 #include <helper/command.h>
28 struct jtag_callback_entry
{
29 struct jtag_callback_entry
*next
;
31 jtag_callback_t callback
;
32 jtag_callback_data_t data0
;
33 jtag_callback_data_t data1
;
34 jtag_callback_data_t data2
;
35 jtag_callback_data_t data3
;
38 static struct jtag_callback_entry
*jtag_callback_queue_head
;
39 static struct jtag_callback_entry
*jtag_callback_queue_tail
;
41 static void jtag_callback_queue_reset(void)
43 jtag_callback_queue_head
= NULL
;
44 jtag_callback_queue_tail
= NULL
;
48 * see jtag_add_ir_scan()
51 int interface_jtag_add_ir_scan(struct jtag_tap
*active
,
52 const struct scan_field
*in_fields
, tap_state_t state
)
54 size_t num_taps
= jtag_tap_count_enabled();
56 struct jtag_command
*cmd
= cmd_queue_alloc(sizeof(struct jtag_command
));
57 struct scan_command
*scan
= cmd_queue_alloc(sizeof(struct scan_command
));
58 struct scan_field
*out_fields
= cmd_queue_alloc(num_taps
* sizeof(struct scan_field
));
60 jtag_queue_command(cmd
);
62 cmd
->type
= JTAG_SCAN
;
66 scan
->num_fields
= num_taps
; /* one field per device */
67 scan
->fields
= out_fields
;
68 scan
->end_state
= state
;
70 struct scan_field
*field
= out_fields
; /* keep track where we insert data */
72 /* loop over all enabled TAPs */
74 for (struct jtag_tap
*tap
= jtag_tap_next_enabled(NULL
); tap
; tap
= jtag_tap_next_enabled(tap
)) {
75 /* search the input field list for fields for the current TAP */
78 /* if TAP is listed in input fields, copy the value */
81 jtag_scan_field_clone(field
, in_fields
);
83 /* if a TAP isn't listed in input fields, set it to BYPASS */
87 field
->num_bits
= tap
->ir_length
;
88 if (tap
->ir_bypass_value
) {
89 uint8_t *v
= cmd_queue_alloc(DIV_ROUND_UP(tap
->ir_length
, 8));
90 buf_set_u64(v
, 0, tap
->ir_length
, tap
->ir_bypass_value
);
93 field
->out_value
= buf_set_ones(cmd_queue_alloc(DIV_ROUND_UP(tap
->ir_length
, 8)), tap
->ir_length
);
95 field
->in_value
= NULL
; /* do not collect input for tap's in bypass */
98 /* update device information */
99 buf_cpy(field
->out_value
, tap
->cur_instr
, tap
->ir_length
);
103 /* paranoia: jtag_tap_count_enabled() and jtag_tap_next_enabled() not in sync */
104 assert(field
== out_fields
+ num_taps
);
110 * see jtag_add_dr_scan()
113 int interface_jtag_add_dr_scan(struct jtag_tap
*active
, int in_num_fields
,
114 const struct scan_field
*in_fields
, tap_state_t state
)
116 /* count devices in bypass */
118 size_t bypass_devices
= 0;
119 size_t all_devices
= 0;
121 for (struct jtag_tap
*tap
= jtag_tap_next_enabled(NULL
); tap
; tap
= jtag_tap_next_enabled(tap
)) {
128 if (all_devices
== bypass_devices
) {
129 LOG_ERROR("At least one TAP shouldn't be in BYPASS mode");
134 struct jtag_command
*cmd
= cmd_queue_alloc(sizeof(struct jtag_command
));
135 struct scan_command
*scan
= cmd_queue_alloc(sizeof(struct scan_command
));
136 struct scan_field
*out_fields
= cmd_queue_alloc((in_num_fields
+ bypass_devices
) * sizeof(struct scan_field
));
138 jtag_queue_command(cmd
);
140 cmd
->type
= JTAG_SCAN
;
141 cmd
->cmd
.scan
= scan
;
143 scan
->ir_scan
= false;
144 scan
->num_fields
= in_num_fields
+ bypass_devices
;
145 scan
->fields
= out_fields
;
146 scan
->end_state
= state
;
148 struct scan_field
*field
= out_fields
; /* keep track where we insert data */
150 /* loop over all enabled TAPs */
152 for (struct jtag_tap
*tap
= jtag_tap_next_enabled(NULL
); tap
; tap
= jtag_tap_next_enabled(tap
)) {
153 /* if TAP is not bypassed insert matching input fields */
156 assert(active
== tap
);
158 /* remember initial position for assert() */
159 struct scan_field
*start_field
= field
;
162 for (int j
= 0; j
< in_num_fields
; j
++) {
163 jtag_scan_field_clone(field
, in_fields
+ j
);
168 assert(field
> start_field
); /* must have at least one input field per not bypassed TAP */
171 /* if a TAP is bypassed, generated a dummy bit*/
174 field
->out_value
= NULL
;
175 field
->in_value
= NULL
;
181 assert(field
== out_fields
+ scan
->num_fields
); /* no superfluous input fields permitted */
186 static int jtag_add_plain_scan(int num_bits
, const uint8_t *out_bits
,
187 uint8_t *in_bits
, tap_state_t state
, bool ir_scan
)
189 struct jtag_command
*cmd
= cmd_queue_alloc(sizeof(struct jtag_command
));
190 struct scan_command
*scan
= cmd_queue_alloc(sizeof(struct scan_command
));
191 struct scan_field
*out_fields
= cmd_queue_alloc(sizeof(struct scan_field
));
193 jtag_queue_command(cmd
);
195 cmd
->type
= JTAG_SCAN
;
196 cmd
->cmd
.scan
= scan
;
198 scan
->ir_scan
= ir_scan
;
199 scan
->num_fields
= 1;
200 scan
->fields
= out_fields
;
201 scan
->end_state
= state
;
203 out_fields
->num_bits
= num_bits
;
204 out_fields
->out_value
= buf_cpy(out_bits
, cmd_queue_alloc(DIV_ROUND_UP(num_bits
, 8)), num_bits
);
205 out_fields
->in_value
= in_bits
;
210 int interface_jtag_add_plain_dr_scan(int num_bits
, const uint8_t *out_bits
, uint8_t *in_bits
, tap_state_t state
)
212 return jtag_add_plain_scan(num_bits
, out_bits
, in_bits
, state
, false);
215 int interface_jtag_add_plain_ir_scan(int num_bits
, const uint8_t *out_bits
, uint8_t *in_bits
, tap_state_t state
)
217 return jtag_add_plain_scan(num_bits
, out_bits
, in_bits
, state
, true);
220 int interface_jtag_add_tlr(void)
222 tap_state_t state
= TAP_RESET
;
224 /* allocate memory for a new list member */
225 struct jtag_command
*cmd
= cmd_queue_alloc(sizeof(struct jtag_command
));
227 jtag_queue_command(cmd
);
229 cmd
->type
= JTAG_TLR_RESET
;
231 cmd
->cmd
.statemove
= cmd_queue_alloc(sizeof(struct statemove_command
));
232 cmd
->cmd
.statemove
->end_state
= state
;
237 int interface_add_tms_seq(unsigned num_bits
, const uint8_t *seq
, enum tap_state state
)
239 struct jtag_command
*cmd
;
241 cmd
= cmd_queue_alloc(sizeof(struct jtag_command
));
245 cmd
->type
= JTAG_TMS
;
246 cmd
->cmd
.tms
= cmd_queue_alloc(sizeof(*cmd
->cmd
.tms
));
250 /* copy the bits; our caller doesn't guarantee they'll persist */
251 cmd
->cmd
.tms
->num_bits
= num_bits
;
252 cmd
->cmd
.tms
->bits
= buf_cpy(seq
,
253 cmd_queue_alloc(DIV_ROUND_UP(num_bits
, 8)), num_bits
);
254 if (!cmd
->cmd
.tms
->bits
)
257 jtag_queue_command(cmd
);
262 int interface_jtag_add_pathmove(int num_states
, const tap_state_t
*path
)
264 /* allocate memory for a new list member */
265 struct jtag_command
*cmd
= cmd_queue_alloc(sizeof(struct jtag_command
));
267 jtag_queue_command(cmd
);
269 cmd
->type
= JTAG_PATHMOVE
;
271 cmd
->cmd
.pathmove
= cmd_queue_alloc(sizeof(struct pathmove_command
));
272 cmd
->cmd
.pathmove
->num_states
= num_states
;
273 cmd
->cmd
.pathmove
->path
= cmd_queue_alloc(sizeof(tap_state_t
) * num_states
);
275 for (int i
= 0; i
< num_states
; i
++)
276 cmd
->cmd
.pathmove
->path
[i
] = path
[i
];
281 int interface_jtag_add_runtest(int num_cycles
, tap_state_t state
)
283 /* allocate memory for a new list member */
284 struct jtag_command
*cmd
= cmd_queue_alloc(sizeof(struct jtag_command
));
286 jtag_queue_command(cmd
);
288 cmd
->type
= JTAG_RUNTEST
;
290 cmd
->cmd
.runtest
= cmd_queue_alloc(sizeof(struct runtest_command
));
291 cmd
->cmd
.runtest
->num_cycles
= num_cycles
;
292 cmd
->cmd
.runtest
->end_state
= state
;
297 int interface_jtag_add_clocks(int num_cycles
)
299 /* allocate memory for a new list member */
300 struct jtag_command
*cmd
= cmd_queue_alloc(sizeof(struct jtag_command
));
302 jtag_queue_command(cmd
);
304 cmd
->type
= JTAG_STABLECLOCKS
;
306 cmd
->cmd
.stableclocks
= cmd_queue_alloc(sizeof(struct stableclocks_command
));
307 cmd
->cmd
.stableclocks
->num_cycles
= num_cycles
;
312 int interface_jtag_add_reset(int req_trst
, int req_srst
)
314 /* allocate memory for a new list member */
315 struct jtag_command
*cmd
= cmd_queue_alloc(sizeof(struct jtag_command
));
317 jtag_queue_command(cmd
);
319 cmd
->type
= JTAG_RESET
;
321 cmd
->cmd
.reset
= cmd_queue_alloc(sizeof(struct reset_command
));
322 cmd
->cmd
.reset
->trst
= req_trst
;
323 cmd
->cmd
.reset
->srst
= req_srst
;
328 int interface_jtag_add_sleep(uint32_t us
)
330 /* allocate memory for a new list member */
331 struct jtag_command
*cmd
= cmd_queue_alloc(sizeof(struct jtag_command
));
333 jtag_queue_command(cmd
);
335 cmd
->type
= JTAG_SLEEP
;
337 cmd
->cmd
.sleep
= cmd_queue_alloc(sizeof(struct sleep_command
));
338 cmd
->cmd
.sleep
->us
= us
;
343 /* add callback to end of queue */
344 void interface_jtag_add_callback4(jtag_callback_t callback
,
345 jtag_callback_data_t data0
, jtag_callback_data_t data1
,
346 jtag_callback_data_t data2
, jtag_callback_data_t data3
)
348 struct jtag_callback_entry
*entry
= cmd_queue_alloc(sizeof(struct jtag_callback_entry
));
351 entry
->callback
= callback
;
352 entry
->data0
= data0
;
353 entry
->data1
= data1
;
354 entry
->data2
= data2
;
355 entry
->data3
= data3
;
357 if (!jtag_callback_queue_head
) {
358 jtag_callback_queue_head
= entry
;
359 jtag_callback_queue_tail
= entry
;
361 jtag_callback_queue_tail
->next
= entry
;
362 jtag_callback_queue_tail
= entry
;
366 int interface_jtag_execute_queue(void)
370 assert(reentry
== 0);
373 int retval
= default_interface_jtag_execute_queue();
374 if (retval
== ERROR_OK
) {
375 struct jtag_callback_entry
*entry
;
376 for (entry
= jtag_callback_queue_head
; entry
; entry
= entry
->next
) {
377 retval
= entry
->callback(entry
->data0
, entry
->data1
, entry
->data2
, entry
->data3
);
378 if (retval
!= ERROR_OK
)
383 jtag_command_queue_reset();
384 jtag_callback_queue_reset();
391 static int jtag_convert_to_callback4(jtag_callback_data_t data0
,
392 jtag_callback_data_t data1
, jtag_callback_data_t data2
, jtag_callback_data_t data3
)
394 ((jtag_callback1_t
)data1
)(data0
);
398 void interface_jtag_add_callback(jtag_callback1_t callback
, jtag_callback_data_t data0
)
400 jtag_add_callback4(jtag_convert_to_callback4
, data0
, (jtag_callback_data_t
)callback
, 0, 0);
403 void jtag_add_callback(jtag_callback1_t f
, jtag_callback_data_t data0
)
405 interface_jtag_add_callback(f
, data0
);
408 void jtag_add_callback4(jtag_callback_t f
, jtag_callback_data_t data0
,
409 jtag_callback_data_t data1
, jtag_callback_data_t data2
,
410 jtag_callback_data_t data3
)
412 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)