1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
5 * Copyright (C) 2007,2008 Ø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 "interface.h"
35 #include "minidriver.h"
38 struct jtag_callback_entry
40 struct jtag_callback_entry
*next
;
42 jtag_callback_t callback
;
44 jtag_callback_data_t data1
;
45 jtag_callback_data_t data2
;
46 jtag_callback_data_t data3
;
49 static struct jtag_callback_entry
*jtag_callback_queue_head
= NULL
;
50 static struct jtag_callback_entry
*jtag_callback_queue_tail
= NULL
;
52 static void jtag_callback_queue_reset(void)
54 jtag_callback_queue_head
= NULL
;
55 jtag_callback_queue_tail
= NULL
;
59 * Copy a scan_field_t for insertion into the queue.
61 * This allocates a new copy of out_value using cmd_queue_alloc.
63 static void cmd_queue_scan_field_clone(scan_field_t
* dst
, const scan_field_t
* src
)
66 dst
->num_bits
= src
->num_bits
;
67 dst
->out_value
= buf_cpy(src
->out_value
, cmd_queue_alloc(CEIL(src
->num_bits
, 8)), src
->num_bits
);
68 dst
->in_value
= src
->in_value
;
73 * see jtag_add_ir_scan()
76 int interface_jtag_add_ir_scan(int in_num_fields
, const scan_field_t
*in_fields
, tap_state_t state
)
78 size_t num_taps
= jtag_tap_count_enabled();
80 jtag_command_t
* cmd
= cmd_queue_alloc(sizeof(jtag_command_t
));
81 scan_command_t
* scan
= cmd_queue_alloc(sizeof(scan_command_t
));
82 scan_field_t
* out_fields
= cmd_queue_alloc(num_taps
* sizeof(scan_field_t
));
84 jtag_queue_command(cmd
);
86 cmd
->type
= JTAG_SCAN
;
90 scan
->num_fields
= num_taps
; /* one field per device */
91 scan
->fields
= out_fields
;
92 scan
->end_state
= state
;
95 scan_field_t
* field
= out_fields
; /* keep track where we insert data */
97 /* loop over all enabled TAPs */
99 for (jtag_tap_t
* tap
= jtag_tap_next_enabled(NULL
); tap
!= NULL
; tap
= jtag_tap_next_enabled(tap
))
101 /* search the input field list for fields for the current TAP */
105 for (int j
= 0; j
< in_num_fields
; j
++)
107 if (tap
!= in_fields
[j
].tap
)
110 /* if TAP is listed in input fields, copy the value */
116 assert(in_fields
[j
].num_bits
== tap
->ir_length
); /* input fields must have the same length as the TAP's IR */
118 cmd_queue_scan_field_clone(field
, in_fields
+ j
);
125 /* if a TAP isn't listed in input fields, set it to BYPASS */
130 field
->num_bits
= tap
->ir_length
;
131 field
->out_value
= buf_set_ones(cmd_queue_alloc(CEIL(tap
->ir_length
, 8)), tap
->ir_length
);
132 field
->in_value
= NULL
; /* do not collect input for tap's in bypass */
135 /* update device information */
136 buf_cpy(field
->out_value
, tap
->cur_instr
, tap
->ir_length
);
141 assert(field
== out_fields
+ num_taps
); /* paranoia: jtag_tap_count_enabled() and jtag_tap_next_enabled() not in sync */
147 * see jtag_add_plain_ir_scan()
150 int interface_jtag_add_plain_ir_scan(int in_num_fields
, const scan_field_t
*in_fields
, tap_state_t state
)
153 jtag_command_t
* cmd
= cmd_queue_alloc(sizeof(jtag_command_t
));
154 scan_command_t
* scan
= cmd_queue_alloc(sizeof(scan_command_t
));
155 scan_field_t
* out_fields
= cmd_queue_alloc(in_num_fields
* sizeof(scan_field_t
));
157 jtag_queue_command(cmd
);
159 cmd
->type
= JTAG_SCAN
;
160 cmd
->cmd
.scan
= scan
;
162 scan
->ir_scan
= true;
163 scan
->num_fields
= in_num_fields
;
164 scan
->fields
= out_fields
;
165 scan
->end_state
= state
;
167 for (int i
= 0; i
< in_num_fields
; i
++)
168 cmd_queue_scan_field_clone(out_fields
+ i
, in_fields
+ i
);
176 * see jtag_add_dr_scan()
179 int interface_jtag_add_dr_scan(int in_num_fields
, const scan_field_t
*in_fields
, tap_state_t state
)
181 /* count devices in bypass */
183 size_t bypass_devices
= 0;
185 for (jtag_tap_t
* tap
= jtag_tap_next_enabled(NULL
); tap
!= NULL
; tap
= jtag_tap_next_enabled(tap
))
191 jtag_command_t
* cmd
= cmd_queue_alloc(sizeof(jtag_command_t
));
192 scan_command_t
* scan
= cmd_queue_alloc(sizeof(scan_command_t
));
193 scan_field_t
* out_fields
= cmd_queue_alloc((in_num_fields
+ bypass_devices
) * sizeof(scan_field_t
));
195 jtag_queue_command(cmd
);
197 cmd
->type
= JTAG_SCAN
;
198 cmd
->cmd
.scan
= scan
;
200 scan
->ir_scan
= false;
201 scan
->num_fields
= in_num_fields
+ bypass_devices
;
202 scan
->fields
= out_fields
;
203 scan
->end_state
= state
;
206 scan_field_t
* field
= out_fields
; /* keep track where we insert data */
208 /* loop over all enabled TAPs */
210 for (jtag_tap_t
* tap
= jtag_tap_next_enabled(NULL
); tap
!= NULL
; tap
= jtag_tap_next_enabled(tap
))
212 /* if TAP is not bypassed insert matching input fields */
216 scan_field_t
* start_field
= field
; /* keep initial position for assert() */
218 for (int j
= 0; j
< in_num_fields
; j
++)
220 if (tap
!= in_fields
[j
].tap
)
223 cmd_queue_scan_field_clone(field
, in_fields
+ j
);
228 assert(field
> start_field
); /* must have at least one input field per not bypassed TAP */
231 /* if a TAP is bypassed, generated a dummy bit*/
236 field
->out_value
= NULL
;
237 field
->in_value
= NULL
;
243 assert(field
== out_fields
+ scan
->num_fields
); /* no superfluous input fields permitted */
251 * Generate a DR SCAN using the array of output values passed to the function
253 * This function assumes that the parameter target_tap specifies the one TAP
254 * that is not bypassed. All other TAPs must be bypassed and the function will
255 * generate a dummy 1bit field for them.
257 * For the target_tap a sequence of output-only fields will be generated where
258 * each field has the size num_bits and the field's values are taken from
261 * The bypass status of TAPs is set by jtag_add_ir_scan().
264 void interface_jtag_add_dr_out(jtag_tap_t
*target_tap
,
268 tap_state_t end_state
)
270 /* count devices in bypass */
272 size_t bypass_devices
= 0;
274 for (jtag_tap_t
* tap
= jtag_tap_next_enabled(NULL
); tap
!= NULL
; tap
= jtag_tap_next_enabled(tap
))
281 jtag_command_t
* cmd
= cmd_queue_alloc(sizeof(jtag_command_t
));
282 scan_command_t
* scan
= cmd_queue_alloc(sizeof(scan_command_t
));
283 scan_field_t
* out_fields
= cmd_queue_alloc((in_num_fields
+ bypass_devices
) * sizeof(scan_field_t
));
285 jtag_queue_command(cmd
);
287 cmd
->type
= JTAG_SCAN
;
288 cmd
->cmd
.scan
= scan
;
290 scan
->ir_scan
= false;
291 scan
->num_fields
= in_num_fields
+ bypass_devices
;
292 scan
->fields
= out_fields
;
293 scan
->end_state
= end_state
;
296 bool target_tap_match
= false;
298 scan_field_t
* field
= out_fields
; /* keep track where we insert data */
300 /* loop over all enabled TAPs */
302 for (jtag_tap_t
* tap
= jtag_tap_next_enabled(NULL
); tap
!= NULL
; tap
= jtag_tap_next_enabled(tap
))
304 /* if TAP is not bypassed insert matching input fields */
308 assert(tap
== target_tap
); /* target_tap must match the one not bypassed TAP */
310 target_tap_match
= true;
312 for (int j
= 0; j
< in_num_fields
; j
++)
315 size_t scan_size
= num_bits
[j
];
316 buf_set_u32(out_value
, 0, scan_size
, value
[j
]);
319 field
->num_bits
= scan_size
;
320 field
->out_value
= buf_cpy(out_value
, cmd_queue_alloc(CEIL(scan_size
, 8)), scan_size
);
321 field
->in_value
= NULL
;
327 /* if a TAP is bypassed, generated a dummy bit*/
333 field
->out_value
= NULL
;
334 field
->in_value
= NULL
;
340 assert(target_tap_match
); /* target_tap should be enabled and not bypassed */
344 * see jtag_add_plain_dr_scan()
347 int interface_jtag_add_plain_dr_scan(int in_num_fields
, const scan_field_t
*in_fields
, tap_state_t state
)
349 jtag_command_t
* cmd
= cmd_queue_alloc(sizeof(jtag_command_t
));
350 scan_command_t
* scan
= cmd_queue_alloc(sizeof(scan_command_t
));
351 scan_field_t
* out_fields
= cmd_queue_alloc(in_num_fields
* sizeof(scan_field_t
));
353 jtag_queue_command(cmd
);
355 cmd
->type
= JTAG_SCAN
;
356 cmd
->cmd
.scan
= scan
;
358 scan
->ir_scan
= false;
359 scan
->num_fields
= in_num_fields
;
360 scan
->fields
= out_fields
;
361 scan
->end_state
= state
;
363 for (int i
= 0; i
< in_num_fields
; i
++)
364 cmd_queue_scan_field_clone(out_fields
+ i
, in_fields
+ i
);
369 int interface_jtag_add_tlr(void)
371 tap_state_t state
= TAP_RESET
;
373 /* allocate memory for a new list member */
374 jtag_command_t
* cmd
= cmd_queue_alloc(sizeof(jtag_command_t
));
376 jtag_queue_command(cmd
);
378 cmd
->type
= JTAG_STATEMOVE
;
380 cmd
->cmd
.statemove
= cmd_queue_alloc(sizeof(statemove_command_t
));
381 cmd
->cmd
.statemove
->end_state
= state
;
386 int interface_jtag_add_pathmove(int num_states
, const tap_state_t
*path
)
388 /* allocate memory for a new list member */
389 jtag_command_t
* cmd
= cmd_queue_alloc(sizeof(jtag_command_t
));
391 jtag_queue_command(cmd
);
393 cmd
->type
= JTAG_PATHMOVE
;
395 cmd
->cmd
.pathmove
= cmd_queue_alloc(sizeof(pathmove_command_t
));
396 cmd
->cmd
.pathmove
->num_states
= num_states
;
397 cmd
->cmd
.pathmove
->path
= cmd_queue_alloc(sizeof(tap_state_t
) * num_states
);
399 for (int i
= 0; i
< num_states
; i
++)
400 cmd
->cmd
.pathmove
->path
[i
] = path
[i
];
405 int interface_jtag_add_runtest(int num_cycles
, tap_state_t state
)
407 /* allocate memory for a new list member */
408 jtag_command_t
* cmd
= cmd_queue_alloc(sizeof(jtag_command_t
));
410 jtag_queue_command(cmd
);
412 cmd
->type
= JTAG_RUNTEST
;
414 cmd
->cmd
.runtest
= cmd_queue_alloc(sizeof(runtest_command_t
));
415 cmd
->cmd
.runtest
->num_cycles
= num_cycles
;
416 cmd
->cmd
.runtest
->end_state
= state
;
421 int interface_jtag_add_clocks( int num_cycles
)
423 /* allocate memory for a new list member */
424 jtag_command_t
* cmd
= cmd_queue_alloc(sizeof(jtag_command_t
));
426 jtag_queue_command(cmd
);
428 cmd
->type
= JTAG_STABLECLOCKS
;
430 cmd
->cmd
.stableclocks
= cmd_queue_alloc(sizeof(stableclocks_command_t
));
431 cmd
->cmd
.stableclocks
->num_cycles
= num_cycles
;
436 int interface_jtag_add_reset(int req_trst
, int req_srst
)
438 /* allocate memory for a new list member */
439 jtag_command_t
* cmd
= cmd_queue_alloc(sizeof(jtag_command_t
));
441 jtag_queue_command(cmd
);
443 cmd
->type
= JTAG_RESET
;
445 cmd
->cmd
.reset
= cmd_queue_alloc(sizeof(reset_command_t
));
446 cmd
->cmd
.reset
->trst
= req_trst
;
447 cmd
->cmd
.reset
->srst
= req_srst
;
452 int interface_jtag_add_sleep(u32 us
)
454 /* allocate memory for a new list member */
455 jtag_command_t
* cmd
= cmd_queue_alloc(sizeof(jtag_command_t
));
457 jtag_queue_command(cmd
);
459 cmd
->type
= JTAG_SLEEP
;
461 cmd
->cmd
.sleep
= cmd_queue_alloc(sizeof(sleep_command_t
));
462 cmd
->cmd
.sleep
->us
= us
;
467 /* add callback to end of queue */
468 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 struct jtag_callback_entry
*entry
=cmd_queue_alloc(sizeof(struct jtag_callback_entry
));
473 entry
->callback
=callback
;
479 if (jtag_callback_queue_head
==NULL
)
481 jtag_callback_queue_head
=entry
;
482 jtag_callback_queue_tail
=entry
;
485 jtag_callback_queue_tail
->next
=entry
;
486 jtag_callback_queue_tail
=entry
;
490 int interface_jtag_execute_queue(void)
492 int retval
= default_interface_jtag_execute_queue();
493 if (retval
== ERROR_OK
)
495 struct jtag_callback_entry
*entry
;
496 for (entry
=jtag_callback_queue_head
; entry
!=NULL
; entry
=entry
->next
)
498 retval
=entry
->callback(entry
->in
, entry
->data1
, entry
->data2
, entry
->data3
);
499 if (retval
!=ERROR_OK
)
504 jtag_command_queue_reset();
505 jtag_callback_queue_reset();
510 static int jtag_convert_to_callback4(u8
*in
, jtag_callback_data_t data1
, jtag_callback_data_t data2
, jtag_callback_data_t data3
)
512 ((jtag_callback1_t
)data1
)(in
);
516 void interface_jtag_add_callback(jtag_callback1_t callback
, u8
*in
)
518 jtag_add_callback4(jtag_convert_to_callback4
, in
, (jtag_callback_data_t
)callback
, 0, 0);
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)