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 #define INCLUDE_JTAG_INTERFACE_H
35 #include "interface.h"
36 #include "minidriver.h"
39 struct jtag_callback_entry
41 struct jtag_callback_entry
*next
;
43 jtag_callback_t callback
;
45 jtag_callback_data_t data1
;
46 jtag_callback_data_t data2
;
47 jtag_callback_data_t data3
;
50 static struct jtag_callback_entry
*jtag_callback_queue_head
= NULL
;
51 static struct jtag_callback_entry
*jtag_callback_queue_tail
= NULL
;
53 static void jtag_callback_queue_reset(void)
55 jtag_callback_queue_head
= NULL
;
56 jtag_callback_queue_tail
= NULL
;
60 * Copy a scan_field_t for insertion into the queue.
62 * This allocates a new copy of out_value using cmd_queue_alloc.
64 static void cmd_queue_scan_field_clone(scan_field_t
* dst
, const scan_field_t
* src
)
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
;
74 * see jtag_add_ir_scan()
77 int interface_jtag_add_ir_scan(int in_num_fields
, const scan_field_t
*in_fields
, tap_state_t state
)
79 size_t num_taps
= jtag_NumEnabledTaps();
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
));
85 jtag_queue_command(cmd
);
87 cmd
->type
= JTAG_SCAN
;
91 scan
->num_fields
= num_taps
; /* one field per device */
92 scan
->fields
= out_fields
;
93 scan
->end_state
= state
;
96 scan_field_t
* field
= out_fields
; /* keep track where we insert data */
98 /* loop over all enabled TAPs */
100 for (jtag_tap_t
* tap
= jtag_NextEnabledTap(NULL
); tap
!= NULL
; tap
= jtag_NextEnabledTap(tap
))
102 /* search the input field list for fields for the current TAP */
106 for (int j
= 0; j
< in_num_fields
; j
++)
108 if (tap
!= in_fields
[j
].tap
)
111 /* if TAP is listed in input fields, copy the value */
117 assert(in_fields
[j
].num_bits
== tap
->ir_length
); /* input fields must have the same length as the TAP's IR */
119 cmd_queue_scan_field_clone(field
, in_fields
+ j
);
126 /* if a TAP isn't listed in input fields, set it to BYPASS */
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 */
136 /* update device information */
137 buf_cpy(field
->out_value
, tap
->cur_instr
, tap
->ir_length
);
142 assert(field
== out_fields
+ num_taps
); /* paranoia: jtag_NumEnabledTaps() and jtag_NextEnabledTap() not in sync */
148 * see jtag_add_plain_ir_scan()
151 int interface_jtag_add_plain_ir_scan(int in_num_fields
, const scan_field_t
*in_fields
, tap_state_t state
)
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
));
158 jtag_queue_command(cmd
);
160 cmd
->type
= JTAG_SCAN
;
161 cmd
->cmd
.scan
= scan
;
163 scan
->ir_scan
= true;
164 scan
->num_fields
= in_num_fields
;
165 scan
->fields
= out_fields
;
166 scan
->end_state
= state
;
168 for (int i
= 0; i
< in_num_fields
; i
++)
169 cmd_queue_scan_field_clone(out_fields
+ i
, in_fields
+ i
);
177 * see jtag_add_dr_scan()
180 int interface_jtag_add_dr_scan(int in_num_fields
, const scan_field_t
*in_fields
, tap_state_t state
)
182 /* count devices in bypass */
184 size_t bypass_devices
= 0;
186 for (jtag_tap_t
* tap
= jtag_NextEnabledTap(NULL
); tap
!= NULL
; tap
= jtag_NextEnabledTap(tap
))
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
));
196 jtag_queue_command(cmd
);
198 cmd
->type
= JTAG_SCAN
;
199 cmd
->cmd
.scan
= scan
;
201 scan
->ir_scan
= false;
202 scan
->num_fields
= in_num_fields
+ bypass_devices
;
203 scan
->fields
= out_fields
;
204 scan
->end_state
= state
;
207 scan_field_t
* field
= out_fields
; /* keep track where we insert data */
209 /* loop over all enabled TAPs */
211 for (jtag_tap_t
* tap
= jtag_NextEnabledTap(NULL
); tap
!= NULL
; tap
= jtag_NextEnabledTap(tap
))
213 /* if TAP is not bypassed insert matching input fields */
217 scan_field_t
* start_field
= field
; /* keep initial position for assert() */
219 for (int j
= 0; j
< in_num_fields
; j
++)
221 if (tap
!= in_fields
[j
].tap
)
224 cmd_queue_scan_field_clone(field
, in_fields
+ j
);
229 assert(field
> start_field
); /* must have at least one input field per not bypassed TAP */
232 /* if a TAP is bypassed, generated a dummy bit*/
237 field
->out_value
= NULL
;
238 field
->in_value
= NULL
;
244 assert(field
== out_fields
+ scan
->num_fields
); /* no superfluous input fields permitted */
252 * Generate a DR SCAN using the array of output values passed to the function
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.
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
262 * The bypass status of TAPs is set by jtag_add_ir_scan().
265 void interface_jtag_add_dr_out(jtag_tap_t
*target_tap
,
269 tap_state_t end_state
)
271 /* count devices in bypass */
273 size_t bypass_devices
= 0;
275 for (jtag_tap_t
* tap
= jtag_NextEnabledTap(NULL
); tap
!= NULL
; tap
= jtag_NextEnabledTap(tap
))
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
));
286 jtag_queue_command(cmd
);
288 cmd
->type
= JTAG_SCAN
;
289 cmd
->cmd
.scan
= scan
;
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
;
297 bool target_tap_match
= false;
299 scan_field_t
* field
= out_fields
; /* keep track where we insert data */
301 /* loop over all enabled TAPs */
303 for (jtag_tap_t
* tap
= jtag_NextEnabledTap(NULL
); tap
!= NULL
; tap
= jtag_NextEnabledTap(tap
))
305 /* if TAP is not bypassed insert matching input fields */
309 assert(tap
== target_tap
); /* target_tap must match the one not bypassed TAP */
311 target_tap_match
= true;
313 for (int j
= 0; j
< in_num_fields
; j
++)
316 size_t scan_size
= num_bits
[j
];
317 buf_set_u32(out_value
, 0, scan_size
, value
[j
]);
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
;
328 /* if a TAP is bypassed, generated a dummy bit*/
334 field
->out_value
= NULL
;
335 field
->in_value
= NULL
;
341 assert(target_tap_match
); /* target_tap should be enabled and not bypassed */
345 * see jtag_add_plain_dr_scan()
348 int interface_jtag_add_plain_dr_scan(int in_num_fields
, const scan_field_t
*in_fields
, tap_state_t state
)
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
));
354 jtag_queue_command(cmd
);
356 cmd
->type
= JTAG_SCAN
;
357 cmd
->cmd
.scan
= scan
;
359 scan
->ir_scan
= false;
360 scan
->num_fields
= in_num_fields
;
361 scan
->fields
= out_fields
;
362 scan
->end_state
= state
;
364 for (int i
= 0; i
< in_num_fields
; i
++)
365 cmd_queue_scan_field_clone(out_fields
+ i
, in_fields
+ i
);
370 int interface_jtag_add_tlr(void)
372 tap_state_t state
= TAP_RESET
;
374 /* allocate memory for a new list member */
375 jtag_command_t
* cmd
= cmd_queue_alloc(sizeof(jtag_command_t
));
377 jtag_queue_command(cmd
);
379 cmd
->type
= JTAG_STATEMOVE
;
381 cmd
->cmd
.statemove
= cmd_queue_alloc(sizeof(statemove_command_t
));
382 cmd
->cmd
.statemove
->end_state
= state
;
387 int interface_jtag_add_pathmove(int num_states
, const tap_state_t
*path
)
389 /* allocate memory for a new list member */
390 jtag_command_t
* cmd
= cmd_queue_alloc(sizeof(jtag_command_t
));
392 jtag_queue_command(cmd
);
394 cmd
->type
= JTAG_PATHMOVE
;
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
);
400 for (int i
= 0; i
< num_states
; i
++)
401 cmd
->cmd
.pathmove
->path
[i
] = path
[i
];
406 int interface_jtag_add_runtest(int num_cycles
, tap_state_t state
)
408 /* allocate memory for a new list member */
409 jtag_command_t
* cmd
= cmd_queue_alloc(sizeof(jtag_command_t
));
411 jtag_queue_command(cmd
);
413 cmd
->type
= JTAG_RUNTEST
;
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
;
422 int interface_jtag_add_clocks( int num_cycles
)
424 /* allocate memory for a new list member */
425 jtag_command_t
* cmd
= cmd_queue_alloc(sizeof(jtag_command_t
));
427 jtag_queue_command(cmd
);
429 cmd
->type
= JTAG_STABLECLOCKS
;
431 cmd
->cmd
.stableclocks
= cmd_queue_alloc(sizeof(stableclocks_command_t
));
432 cmd
->cmd
.stableclocks
->num_cycles
= num_cycles
;
437 int interface_jtag_add_reset(int req_trst
, int req_srst
)
439 /* allocate memory for a new list member */
440 jtag_command_t
* cmd
= cmd_queue_alloc(sizeof(jtag_command_t
));
442 jtag_queue_command(cmd
);
444 cmd
->type
= JTAG_RESET
;
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
;
453 int interface_jtag_add_sleep(u32 us
)
455 /* allocate memory for a new list member */
456 jtag_command_t
* cmd
= cmd_queue_alloc(sizeof(jtag_command_t
));
458 jtag_queue_command(cmd
);
460 cmd
->type
= JTAG_SLEEP
;
462 cmd
->cmd
.sleep
= cmd_queue_alloc(sizeof(sleep_command_t
));
463 cmd
->cmd
.sleep
->us
= us
;
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
)
471 struct jtag_callback_entry
*entry
=cmd_queue_alloc(sizeof(struct jtag_callback_entry
));
474 entry
->callback
=callback
;
480 if (jtag_callback_queue_head
==NULL
)
482 jtag_callback_queue_head
=entry
;
483 jtag_callback_queue_tail
=entry
;
486 jtag_callback_queue_tail
->next
=entry
;
487 jtag_callback_queue_tail
=entry
;
491 int interface_jtag_execute_queue(void)
493 int retval
= default_interface_jtag_execute_queue();
494 if (retval
== ERROR_OK
)
496 struct jtag_callback_entry
*entry
;
497 for (entry
=jtag_callback_queue_head
; entry
!=NULL
; entry
=entry
->next
)
499 retval
=entry
->callback(entry
->in
, entry
->data1
, entry
->data2
, entry
->data3
);
500 if (retval
!=ERROR_OK
)
505 jtag_command_queue_reset();
506 jtag_callback_queue_reset();
511 static int jtag_convert_to_callback4(u8
*in
, jtag_callback_data_t data1
, jtag_callback_data_t data2
, jtag_callback_data_t data3
)
513 ((jtag_callback1_t
)data1
)(in
);
517 void interface_jtag_add_callback(jtag_callback1_t callback
, u8
*in
)
519 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)