1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright (C) 2012 by Jan Dakinevich *
5 * jan.dakinevich@gmail.com *
6 ***************************************************************************/
11 #include <helper/log.h>
12 #include <helper/binarybuffer.h>
13 #include <helper/command.h>
14 #include <jtag/interface.h>
15 #include "libusb_helper.h"
22 struct sequence
*next
;
26 struct sequence
*head
;
27 struct sequence
*tail
;
30 static struct sequence
*queue_add_tail(struct queue
*queue
, int len
)
33 LOG_ERROR("BUG: sequences with zero length are not allowed");
37 struct sequence
*next
;
38 next
= malloc(sizeof(*next
));
40 next
->tms
= calloc(1, DIV_ROUND_UP(len
, 8));
48 /* Queue is empty at the moment */
51 /* Queue already contains at least one sequence */
52 queue
->tail
->next
= next
;
63 LOG_ERROR("Not enough memory");
68 static void queue_drop_head(struct queue
*queue
)
70 struct sequence
*head
= queue
->head
->next
; /* New head */
71 free(queue
->head
->tms
);
76 static void queue_free(struct queue
*queue
)
80 queue_drop_head(queue
);
86 static struct queue
*queue_alloc(void)
88 struct queue
*queue
= malloc(sizeof(*queue
));
92 LOG_ERROR("Not enough memory");
97 /* Size of usb communication buffer */
98 #define OSBDM_USB_BUFSIZE 64
99 /* Timeout for USB transfer, ms */
100 #define OSBDM_USB_TIMEOUT 1000
101 /* Write end point */
102 #define OSBDM_USB_EP_WRITE 0x01
104 #define OSBDM_USB_EP_READ 0x82
106 /* Initialize OSBDM device */
107 #define OSBDM_CMD_INIT 0x11
108 /* Execute special, not-BDM command. But only this
109 * command is used for JTAG operation */
110 #define OSBDM_CMD_SPECIAL 0x27
111 /* Execute JTAG swap (tms/tdi -> tdo) */
112 #define OSBDM_CMD_SPECIAL_SWAP 0x05
114 #define OSBDM_CMD_SPECIAL_SRST 0x01
115 /* Maximum bit-length in one swap */
116 #define OSBDM_SWAP_MAX (((OSBDM_USB_BUFSIZE - 6) / 5) * 16)
118 /* Lists of valid VID/PID pairs
120 static const uint16_t osbdm_vid
[] = { 0x15a2, 0x15a2, 0x15a2, 0 };
121 static const uint16_t osbdm_pid
[] = { 0x0042, 0x0058, 0x005e, 0 };
124 struct libusb_device_handle
*devh
; /* USB handle */
125 uint8_t buffer
[OSBDM_USB_BUFSIZE
]; /* Data to send and receive */
126 int count
; /* Count data to send and to read */
131 static struct osbdm osbdm_context
;
133 static int osbdm_send_and_recv(struct osbdm
*osbdm
)
138 ret
= jtag_libusb_bulk_write(osbdm
->devh
, OSBDM_USB_EP_WRITE
,
139 (char *)osbdm
->buffer
, osbdm
->count
,
140 OSBDM_USB_TIMEOUT
, &count
);
141 if (ret
|| count
!= osbdm
->count
) {
142 LOG_ERROR("OSBDM communication error: can't write");
146 /* Save command code for next checking */
147 uint8_t cmd_saved
= osbdm
->buffer
[0];
150 ret
= jtag_libusb_bulk_read(osbdm
->devh
, OSBDM_USB_EP_READ
,
151 (char *)osbdm
->buffer
, OSBDM_USB_BUFSIZE
,
152 OSBDM_USB_TIMEOUT
, &osbdm
->count
);
153 /* Now perform basic checks for data sent by BDM device
156 LOG_ERROR("OSBDM communication error: can't read");
160 if (osbdm
->count
< 2) {
161 LOG_ERROR("OSBDM communication error: reply too small");
165 if (osbdm
->count
!= osbdm
->buffer
[1]) {
166 LOG_ERROR("OSBDM communication error: reply size mismatch");
170 if (cmd_saved
!= osbdm
->buffer
[0]) {
171 LOG_ERROR("OSBDM communication error: reply command mismatch");
178 static int osbdm_srst(struct osbdm
*osbdm
, int srst
)
181 (void)memset(osbdm
->buffer
, 0, OSBDM_USB_BUFSIZE
);
185 osbdm
->buffer
[osbdm
->count
++] = OSBDM_CMD_SPECIAL
; /* Command */
186 osbdm
->buffer
[osbdm
->count
++] = OSBDM_CMD_SPECIAL_SRST
; /* Subcommand */
187 /* Length in bytes - not used */
188 osbdm
->buffer
[osbdm
->count
++] = 0;
189 osbdm
->buffer
[osbdm
->count
++] = 0;
191 osbdm
->buffer
[osbdm
->count
++] = (srst
? 0 : 0x08);
195 if (osbdm_send_and_recv(osbdm
) != ERROR_OK
)
201 static int osbdm_swap(struct osbdm
*osbdm
, void *tms
, void *tdi
,
202 void *tdo
, int length
)
204 if (length
> OSBDM_SWAP_MAX
) {
205 LOG_ERROR("BUG: bit sequence too long");
210 LOG_ERROR("BUG: bit sequence equal or less than 0");
214 int swap_count
= DIV_ROUND_UP(length
, 16);
218 (void)memset(osbdm
->buffer
, 0, OSBDM_USB_BUFSIZE
);
223 osbdm
->buffer
[osbdm
->count
++] = OSBDM_CMD_SPECIAL
; /* Command */
224 osbdm
->buffer
[osbdm
->count
++] = OSBDM_CMD_SPECIAL_SWAP
; /* Subcommand */
225 /* Length in bytes - not used */
226 osbdm
->buffer
[osbdm
->count
++] = 0;
227 osbdm
->buffer
[osbdm
->count
++] = 0;
229 osbdm
->buffer
[osbdm
->count
++] = 0;
230 osbdm
->buffer
[osbdm
->count
++] = (uint8_t)swap_count
;
232 for (int bit_idx
= 0; bit_idx
< length
; ) {
233 /* Bit count in swap */
234 int bit_count
= length
- bit_idx
;
238 osbdm
->buffer
[osbdm
->count
++] = (uint8_t)bit_count
;
240 /* Copying TMS and TDI data to output buffer */
241 uint32_t tms_data
= buf_get_u32(tms
, bit_idx
, bit_count
);
242 uint32_t tdi_data
= buf_get_u32(tdi
, bit_idx
, bit_count
);
243 osbdm
->buffer
[osbdm
->count
++] = (uint8_t)(tdi_data
>> 8);
244 osbdm
->buffer
[osbdm
->count
++] = (uint8_t)tdi_data
;
245 osbdm
->buffer
[osbdm
->count
++] = (uint8_t)(tms_data
>> 8);
246 osbdm
->buffer
[osbdm
->count
++] = (uint8_t)tms_data
;
248 /* Next bit offset */
249 bit_idx
+= bit_count
;
252 assert(osbdm
->count
<= OSBDM_USB_BUFSIZE
);
256 if (osbdm_send_and_recv(osbdm
) != ERROR_OK
)
261 if (((osbdm
->buffer
[2] << 8) | osbdm
->buffer
[3]) != 2 * swap_count
) {
262 LOG_ERROR("OSBDM communication error: invalid swap command reply");
268 uint8_t *buffer
= osbdm
->buffer
+ 4;
269 for (int bit_idx
= 0; bit_idx
< length
; ) {
270 int bit_count
= length
- bit_idx
;
275 uint32_t tdo_data
= 0;
276 tdo_data
|= (*buffer
++) << 8;
277 tdo_data
|= (*buffer
++);
278 tdo_data
>>= (16 - bit_count
);
280 /* Copy TDO to return */
281 buf_set_u32(tdo
, bit_idx
, bit_count
, tdo_data
);
283 bit_idx
+= bit_count
;
289 static int osbdm_flush(struct osbdm
*osbdm
, struct queue
*queue
)
291 uint8_t tms
[DIV_ROUND_UP(OSBDM_SWAP_MAX
, 8)];
292 uint8_t tdi
[DIV_ROUND_UP(OSBDM_SWAP_MAX
, 8)];
293 uint8_t tdo
[DIV_ROUND_UP(OSBDM_SWAP_MAX
, 8)];
295 int seq_back_len
= 0;
297 while (queue
->head
) {
298 (void)memset(tms
, 0, sizeof(tms
));
299 (void)memset(tdi
, 0, sizeof(tdi
));
300 (void)memset(tdo
, 0, sizeof(tdo
));
304 struct sequence
*seq
;
306 /* Copy from queue to tms/tdi streams
309 seq_len
= seq_back_len
;
312 while (seq
&& swap_len
!= OSBDM_SWAP_MAX
) {
313 /* Count bit for copy at this iteration.
314 * len should fit into remaining space
315 * in tms/tdo bitstreams
317 int len
= seq
->len
- seq_len
;
318 if (len
> OSBDM_SWAP_MAX
- swap_len
)
319 len
= OSBDM_SWAP_MAX
- swap_len
;
322 buf_set_buf(seq
->tms
, seq_len
, tms
, swap_len
, len
);
324 /* Set tdi data if they exists */
326 buf_set_buf(seq
->tdi
, seq_len
, tdi
, swap_len
, len
);
330 if (seq_len
== seq
->len
) {
331 seq
= seq
->next
; /* Move to next sequence */
336 if (osbdm_swap(osbdm
, tms
, tdi
, tdo
, swap_len
))
339 /* Copy from tdo stream to queue
342 for (int swap_back_len
= 0; swap_back_len
< swap_len
; ) {
343 int len
= queue
->head
->len
- seq_back_len
;
344 if (len
> swap_len
- swap_back_len
)
345 len
= swap_len
- swap_back_len
;
347 if (queue
->head
->tdo
)
348 buf_set_buf(tdo
, swap_back_len
, queue
->head
->tdo
, seq_back_len
, len
);
350 swap_back_len
+= len
;
352 if (seq_back_len
== queue
->head
->len
) {
353 queue_drop_head(queue
);
362 /* Basic operation for opening USB device */
363 static int osbdm_open(struct osbdm
*osbdm
)
365 (void)memset(osbdm
, 0, sizeof(*osbdm
));
366 if (jtag_libusb_open(osbdm_vid
, osbdm_pid
, &osbdm
->devh
, NULL
) != ERROR_OK
)
369 if (libusb_claim_interface(osbdm
->devh
, 0) != ERROR_OK
)
375 static int osbdm_quit(void)
377 jtag_libusb_close(osbdm_context
.devh
);
381 static int osbdm_add_pathmove(
386 assert(num_states
<= 32);
388 struct sequence
*next
= queue_add_tail(queue
, num_states
);
390 LOG_ERROR("BUG: can't allocate bit sequence");
395 for (int i
= 0; i
< num_states
; i
++) {
396 if (tap_state_transition(tap_get_state(), 1) == path
[i
]) {
398 } else if (tap_state_transition(tap_get_state(), 0) == path
[i
]) {
399 tms
&= ~(1 << i
); /* This line not so needed */
401 LOG_ERROR("BUG: %s -> %s isn't a valid TAP state transition",
402 tap_state_name(tap_get_state()),
403 tap_state_name(path
[i
]));
407 tap_set_state(path
[i
]);
410 buf_set_u32(next
->tms
, 0, num_states
, tms
);
411 tap_set_end_state(tap_get_state());
416 static int osbdm_add_statemove(
418 tap_state_t new_state
,
424 tap_set_end_state(new_state
);
425 if (tap_get_end_state() == TAP_RESET
) {
426 /* Ignore current state */
429 } else if (tap_get_state() != tap_get_end_state()) {
430 tms
= tap_get_tms_path(tap_get_state(), new_state
);
431 len
= tap_get_tms_path_len(tap_get_state(), new_state
);
434 if (len
&& skip_first
) {
440 struct sequence
*next
= queue_add_tail(queue
, len
);
442 LOG_ERROR("BUG: can't allocate bit sequence");
445 buf_set_u32(next
->tms
, 0, len
, tms
);
448 tap_set_state(tap_get_end_state());
452 static int osbdm_add_stableclocks(
456 if (!tap_is_state_stable(tap_get_state())) {
457 LOG_ERROR("BUG: current state (%s) is not stable",
458 tap_state_name(tap_get_state()));
462 struct sequence
*next
= queue_add_tail(queue
, count
);
464 LOG_ERROR("BUG: can't allocate bit sequence");
468 if (tap_get_state() == TAP_RESET
)
469 (void)memset(next
->tms
, 0xff, DIV_ROUND_UP(count
, 8));
474 static int osbdm_add_tms(
479 struct sequence
*next
= queue_add_tail(queue
, num_bits
);
481 LOG_ERROR("BUG: can't allocate bit sequence");
484 buf_set_buf(tms
, 0, next
->tms
, 0, num_bits
);
489 static int osbdm_add_scan(
491 struct scan_field
*fields
,
493 tap_state_t end_state
,
496 /* Move to desired shift state */
498 if (tap_get_state() != TAP_IRSHIFT
) {
499 if (osbdm_add_statemove(queue
, TAP_IRSHIFT
, 0) != ERROR_OK
)
503 if (tap_get_state() != TAP_DRSHIFT
) {
504 if (osbdm_add_statemove(queue
, TAP_DRSHIFT
, 0) != ERROR_OK
)
510 tap_set_end_state(end_state
);
511 for (int idx
= 0; idx
< num_fields
; idx
++) {
512 struct sequence
*next
= queue_add_tail(queue
, fields
[idx
].num_bits
);
514 LOG_ERROR("Can't allocate bit sequence");
518 (void)memset(next
->tms
, 0, DIV_ROUND_UP(fields
[idx
].num_bits
, 8));
519 next
->tdi
= fields
[idx
].out_value
;
520 next
->tdo
= fields
[idx
].in_value
;
525 if (tap_get_state() != tap_get_end_state()) {
526 /* Exit from IRSHIFT/DRSHIFT */
527 buf_set_u32(queue
->tail
->tms
, queue
->tail
->len
- 1, 1, 1);
529 /* Move with skip_first flag */
530 if (osbdm_add_statemove(queue
, tap_get_end_state(), 1) != ERROR_OK
)
537 static int osbdm_add_runtest(
540 tap_state_t end_state
)
542 if (osbdm_add_statemove(queue
, TAP_IDLE
, 0) != ERROR_OK
)
545 if (osbdm_add_stableclocks(queue
, num_cycles
) != ERROR_OK
)
548 if (osbdm_add_statemove(queue
, end_state
, 0) != ERROR_OK
)
554 static int osbdm_execute_command(
557 struct jtag_command
*cmd
)
559 int retval
= ERROR_OK
;
563 if (cmd
->cmd
.reset
->trst
) {
564 LOG_ERROR("BUG: nTRST signal is not supported");
567 retval
= osbdm_flush(osbdm
, queue
);
568 if (retval
== ERROR_OK
)
569 retval
= osbdm_srst(osbdm
, cmd
->cmd
.reset
->srst
);
574 retval
= osbdm_add_pathmove(
576 cmd
->cmd
.pathmove
->path
,
577 cmd
->cmd
.pathmove
->num_states
);
581 retval
= osbdm_add_statemove(
583 cmd
->cmd
.statemove
->end_state
,
587 case JTAG_STABLECLOCKS
:
588 retval
= osbdm_add_stableclocks(
590 cmd
->cmd
.stableclocks
->num_cycles
);
594 retval
= osbdm_add_tms(
597 cmd
->cmd
.tms
->num_bits
);
601 retval
= osbdm_add_scan(
603 cmd
->cmd
.scan
->fields
,
604 cmd
->cmd
.scan
->num_fields
,
605 cmd
->cmd
.scan
->end_state
,
606 cmd
->cmd
.scan
->ir_scan
);
610 retval
= osbdm_flush(osbdm
, queue
);
611 if (retval
== ERROR_OK
)
612 jtag_sleep(cmd
->cmd
.sleep
->us
);
616 retval
= osbdm_add_runtest(
618 cmd
->cmd
.runtest
->num_cycles
,
619 cmd
->cmd
.runtest
->end_state
);
623 LOG_ERROR("BUG: unknown JTAG command type encountered");
631 static int osbdm_execute_queue(void)
633 int retval
= ERROR_OK
;
635 struct queue
*queue
= queue_alloc();
637 LOG_ERROR("BUG: can't allocate bit queue");
640 struct jtag_command
*cmd
= jtag_command_queue
;
642 while (retval
== ERROR_OK
&& cmd
) {
643 retval
= osbdm_execute_command(&osbdm_context
, queue
, cmd
);
647 if (retval
== ERROR_OK
)
648 retval
= osbdm_flush(&osbdm_context
, queue
);
653 if (retval
!= ERROR_OK
) {
654 LOG_ERROR("FATAL: can't execute jtag command");
661 static int osbdm_init(void)
664 if (osbdm_open(&osbdm_context
) != ERROR_OK
) {
665 LOG_ERROR("Can't open OSBDM device");
668 /* Device successfully opened */
669 LOG_DEBUG("OSBDM init");
672 /* Perform initialize command */
673 osbdm_context
.count
= 0;
674 osbdm_context
.buffer
[osbdm_context
.count
++] = OSBDM_CMD_INIT
;
675 if (osbdm_send_and_recv(&osbdm_context
) != ERROR_OK
)
681 static struct jtag_interface osbdm_interface
= {
682 .execute_queue
= osbdm_execute_queue
,
685 struct adapter_driver osbdm_adapter_driver
= {
687 .transports
= jtag_only
,
692 .jtag_ops
= &osbdm_interface
,
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)