1 /***************************************************************************
2 * Copyright (C) 2012 by Jan Dakinevich *
3 * jan.dakinevich@gmail.com *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
17 ***************************************************************************/
22 #include <helper/log.h>
23 #include <helper/binarybuffer.h>
24 #include <helper/command.h>
25 #include <jtag/interface.h>
26 #include "libusb_helper.h"
33 struct sequence
*next
;
37 struct sequence
*head
;
38 struct sequence
*tail
;
41 static struct sequence
*queue_add_tail(struct queue
*queue
, int len
)
44 LOG_ERROR("BUG: sequences with zero length are not allowed");
48 struct sequence
*next
;
49 next
= malloc(sizeof(*next
));
51 next
->tms
= calloc(1, DIV_ROUND_UP(len
, 8));
59 /* Queue is empty at the moment */
62 /* Queue already contains at least one sequence */
63 queue
->tail
->next
= next
;
74 LOG_ERROR("Not enough memory");
79 static void queue_drop_head(struct queue
*queue
)
81 struct sequence
*head
= queue
->head
->next
; /* New head */
82 free(queue
->head
->tms
);
87 static void queue_free(struct queue
*queue
)
91 queue_drop_head(queue
);
97 static struct queue
*queue_alloc(void)
99 struct queue
*queue
= malloc(sizeof(*queue
));
103 LOG_ERROR("Not enough memory");
108 /* Size of usb communication buffer */
109 #define OSBDM_USB_BUFSIZE 64
110 /* Timeout for USB transfer, ms */
111 #define OSBDM_USB_TIMEOUT 1000
112 /* Write end point */
113 #define OSBDM_USB_EP_WRITE 0x01
115 #define OSBDM_USB_EP_READ 0x82
117 /* Initialize OSBDM device */
118 #define OSBDM_CMD_INIT 0x11
119 /* Execute special, not-BDM command. But only this
120 * command is used for JTAG operation */
121 #define OSBDM_CMD_SPECIAL 0x27
122 /* Execute JTAG swap (tms/tdi -> tdo) */
123 #define OSBDM_CMD_SPECIAL_SWAP 0x05
125 #define OSBDM_CMD_SPECIAL_SRST 0x01
126 /* Maximum bit-length in one swap */
127 #define OSBDM_SWAP_MAX (((OSBDM_USB_BUFSIZE - 6) / 5) * 16)
129 /* Lists of valid VID/PID pairs
131 static const uint16_t osbdm_vid
[] = { 0x15a2, 0x15a2, 0x15a2, 0 };
132 static const uint16_t osbdm_pid
[] = { 0x0042, 0x0058, 0x005e, 0 };
135 struct libusb_device_handle
*devh
; /* USB handle */
136 uint8_t buffer
[OSBDM_USB_BUFSIZE
]; /* Data to send and receive */
137 int count
; /* Count data to send and to read */
142 static struct osbdm osbdm_context
;
144 static int osbdm_send_and_recv(struct osbdm
*osbdm
)
149 ret
= jtag_libusb_bulk_write(osbdm
->devh
, OSBDM_USB_EP_WRITE
,
150 (char *)osbdm
->buffer
, osbdm
->count
,
151 OSBDM_USB_TIMEOUT
, &count
);
152 if (ret
|| count
!= osbdm
->count
) {
153 LOG_ERROR("OSBDM communication error: can't write");
157 /* Save command code for next checking */
158 uint8_t cmd_saved
= osbdm
->buffer
[0];
161 ret
= jtag_libusb_bulk_read(osbdm
->devh
, OSBDM_USB_EP_READ
,
162 (char *)osbdm
->buffer
, OSBDM_USB_BUFSIZE
,
163 OSBDM_USB_TIMEOUT
, &osbdm
->count
);
164 /* Now perform basic checks for data sent by BDM device
167 LOG_ERROR("OSBDM communication error: can't read");
171 if (osbdm
->count
< 2) {
172 LOG_ERROR("OSBDM communication error: reply too small");
176 if (osbdm
->count
!= osbdm
->buffer
[1]) {
177 LOG_ERROR("OSBDM communication error: reply size mismatch");
181 if (cmd_saved
!= osbdm
->buffer
[0]) {
182 LOG_ERROR("OSBDM communication error: reply command mismatch");
189 static int osbdm_srst(struct osbdm
*osbdm
, int srst
)
192 (void)memset(osbdm
->buffer
, 0, OSBDM_USB_BUFSIZE
);
196 osbdm
->buffer
[osbdm
->count
++] = OSBDM_CMD_SPECIAL
; /* Command */
197 osbdm
->buffer
[osbdm
->count
++] = OSBDM_CMD_SPECIAL_SRST
; /* Subcommand */
198 /* Length in bytes - not used */
199 osbdm
->buffer
[osbdm
->count
++] = 0;
200 osbdm
->buffer
[osbdm
->count
++] = 0;
202 osbdm
->buffer
[osbdm
->count
++] = (srst
? 0 : 0x08);
206 if (osbdm_send_and_recv(osbdm
) != ERROR_OK
)
212 static int osbdm_swap(struct osbdm
*osbdm
, void *tms
, void *tdi
,
213 void *tdo
, int length
)
215 if (length
> OSBDM_SWAP_MAX
) {
216 LOG_ERROR("BUG: bit sequence too long");
221 LOG_ERROR("BUG: bit sequence equal or less than 0");
225 int swap_count
= DIV_ROUND_UP(length
, 16);
229 (void)memset(osbdm
->buffer
, 0, OSBDM_USB_BUFSIZE
);
234 osbdm
->buffer
[osbdm
->count
++] = OSBDM_CMD_SPECIAL
; /* Command */
235 osbdm
->buffer
[osbdm
->count
++] = OSBDM_CMD_SPECIAL_SWAP
; /* Subcommand */
236 /* Length in bytes - not used */
237 osbdm
->buffer
[osbdm
->count
++] = 0;
238 osbdm
->buffer
[osbdm
->count
++] = 0;
240 osbdm
->buffer
[osbdm
->count
++] = 0;
241 osbdm
->buffer
[osbdm
->count
++] = (uint8_t)swap_count
;
243 for (int bit_idx
= 0; bit_idx
< length
; ) {
244 /* Bit count in swap */
245 int bit_count
= length
- bit_idx
;
249 osbdm
->buffer
[osbdm
->count
++] = (uint8_t)bit_count
;
251 /* Copying TMS and TDI data to output buffer */
252 uint32_t tms_data
= buf_get_u32(tms
, bit_idx
, bit_count
);
253 uint32_t tdi_data
= buf_get_u32(tdi
, bit_idx
, bit_count
);
254 osbdm
->buffer
[osbdm
->count
++] = (uint8_t)(tdi_data
>> 8);
255 osbdm
->buffer
[osbdm
->count
++] = (uint8_t)tdi_data
;
256 osbdm
->buffer
[osbdm
->count
++] = (uint8_t)(tms_data
>> 8);
257 osbdm
->buffer
[osbdm
->count
++] = (uint8_t)tms_data
;
259 /* Next bit offset */
260 bit_idx
+= bit_count
;
263 assert(osbdm
->count
<= OSBDM_USB_BUFSIZE
);
267 if (osbdm_send_and_recv(osbdm
) != ERROR_OK
)
272 if (((osbdm
->buffer
[2] << 8) | osbdm
->buffer
[3]) != 2 * swap_count
) {
273 LOG_ERROR("OSBDM communication error: invalid swap command reply");
279 uint8_t *buffer
= osbdm
->buffer
+ 4;
280 for (int bit_idx
= 0; bit_idx
< length
; ) {
281 int bit_count
= length
- bit_idx
;
286 uint32_t tdo_data
= 0;
287 tdo_data
|= (*buffer
++) << 8;
288 tdo_data
|= (*buffer
++);
289 tdo_data
>>= (16 - bit_count
);
291 /* Copy TDO to return */
292 buf_set_u32(tdo
, bit_idx
, bit_count
, tdo_data
);
294 bit_idx
+= bit_count
;
300 static int osbdm_flush(struct osbdm
*osbdm
, struct queue
*queue
)
302 uint8_t tms
[DIV_ROUND_UP(OSBDM_SWAP_MAX
, 8)];
303 uint8_t tdi
[DIV_ROUND_UP(OSBDM_SWAP_MAX
, 8)];
304 uint8_t tdo
[DIV_ROUND_UP(OSBDM_SWAP_MAX
, 8)];
306 int seq_back_len
= 0;
308 while (queue
->head
) {
309 (void)memset(tms
, 0, sizeof(tms
));
310 (void)memset(tdi
, 0, sizeof(tdi
));
311 (void)memset(tdo
, 0, sizeof(tdo
));
315 struct sequence
*seq
;
317 /* Copy from queue to tms/tdi streams
320 seq_len
= seq_back_len
;
323 while (seq
&& swap_len
!= OSBDM_SWAP_MAX
) {
324 /* Count bit for copy at this iteration.
325 * len should fit into remaining space
326 * in tms/tdo bitstreams
328 int len
= seq
->len
- seq_len
;
329 if (len
> OSBDM_SWAP_MAX
- swap_len
)
330 len
= OSBDM_SWAP_MAX
- swap_len
;
333 buf_set_buf(seq
->tms
, seq_len
, tms
, swap_len
, len
);
335 /* Set tdi data if they exists */
337 buf_set_buf(seq
->tdi
, seq_len
, tdi
, swap_len
, len
);
341 if (seq_len
== seq
->len
) {
342 seq
= seq
->next
; /* Move to next sequence */
347 if (osbdm_swap(osbdm
, tms
, tdi
, tdo
, swap_len
))
350 /* Copy from tdo stream to queue
353 for (int swap_back_len
= 0; swap_back_len
< swap_len
; ) {
354 int len
= queue
->head
->len
- seq_back_len
;
355 if (len
> swap_len
- swap_back_len
)
356 len
= swap_len
- swap_back_len
;
358 if (queue
->head
->tdo
)
359 buf_set_buf(tdo
, swap_back_len
, queue
->head
->tdo
, seq_back_len
, len
);
361 swap_back_len
+= len
;
363 if (seq_back_len
== queue
->head
->len
) {
364 queue_drop_head(queue
);
373 /* Basic operation for opening USB device */
374 static int osbdm_open(struct osbdm
*osbdm
)
376 (void)memset(osbdm
, 0, sizeof(*osbdm
));
377 if (jtag_libusb_open(osbdm_vid
, osbdm_pid
, &osbdm
->devh
, NULL
) != ERROR_OK
)
380 if (libusb_claim_interface(osbdm
->devh
, 0) != ERROR_OK
)
386 static int osbdm_quit(void)
388 jtag_libusb_close(osbdm_context
.devh
);
392 static int osbdm_add_pathmove(
397 assert(num_states
<= 32);
399 struct sequence
*next
= queue_add_tail(queue
, num_states
);
401 LOG_ERROR("BUG: can't allocate bit sequence");
406 for (int i
= 0; i
< num_states
; i
++) {
407 if (tap_state_transition(tap_get_state(), 1) == path
[i
]) {
409 } else if (tap_state_transition(tap_get_state(), 0) == path
[i
]) {
410 tms
&= ~(1 << i
); /* This line not so needed */
412 LOG_ERROR("BUG: %s -> %s isn't a valid TAP state transition",
413 tap_state_name(tap_get_state()),
414 tap_state_name(path
[i
]));
418 tap_set_state(path
[i
]);
421 buf_set_u32(next
->tms
, 0, num_states
, tms
);
422 tap_set_end_state(tap_get_state());
427 static int osbdm_add_statemove(
429 tap_state_t new_state
,
435 tap_set_end_state(new_state
);
436 if (tap_get_end_state() == TAP_RESET
) {
437 /* Ignore current state */
440 } else if (tap_get_state() != tap_get_end_state()) {
441 tms
= tap_get_tms_path(tap_get_state(), new_state
);
442 len
= tap_get_tms_path_len(tap_get_state(), new_state
);
445 if (len
&& skip_first
) {
451 struct sequence
*next
= queue_add_tail(queue
, len
);
453 LOG_ERROR("BUG: can't allocate bit sequence");
456 buf_set_u32(next
->tms
, 0, len
, tms
);
459 tap_set_state(tap_get_end_state());
463 static int osbdm_add_stableclocks(
467 if (!tap_is_state_stable(tap_get_state())) {
468 LOG_ERROR("BUG: current state (%s) is not stable",
469 tap_state_name(tap_get_state()));
473 struct sequence
*next
= queue_add_tail(queue
, count
);
475 LOG_ERROR("BUG: can't allocate bit sequence");
479 if (tap_get_state() == TAP_RESET
)
480 (void)memset(next
->tms
, 0xff, DIV_ROUND_UP(count
, 8));
485 static int osbdm_add_tms(
490 struct sequence
*next
= queue_add_tail(queue
, num_bits
);
492 LOG_ERROR("BUG: can't allocate bit sequence");
495 buf_set_buf(tms
, 0, next
->tms
, 0, num_bits
);
500 static int osbdm_add_scan(
502 struct scan_field
*fields
,
504 tap_state_t end_state
,
507 /* Move to desired shift state */
509 if (tap_get_state() != TAP_IRSHIFT
) {
510 if (osbdm_add_statemove(queue
, TAP_IRSHIFT
, 0) != ERROR_OK
)
514 if (tap_get_state() != TAP_DRSHIFT
) {
515 if (osbdm_add_statemove(queue
, TAP_DRSHIFT
, 0) != ERROR_OK
)
521 tap_set_end_state(end_state
);
522 for (int idx
= 0; idx
< num_fields
; idx
++) {
523 struct sequence
*next
= queue_add_tail(queue
, fields
[idx
].num_bits
);
525 LOG_ERROR("Can't allocate bit sequence");
529 (void)memset(next
->tms
, 0, DIV_ROUND_UP(fields
[idx
].num_bits
, 8));
530 next
->tdi
= fields
[idx
].out_value
;
531 next
->tdo
= fields
[idx
].in_value
;
536 if (tap_get_state() != tap_get_end_state()) {
537 /* Exit from IRSHIFT/DRSHIFT */
538 buf_set_u32(queue
->tail
->tms
, queue
->tail
->len
- 1, 1, 1);
540 /* Move with skip_first flag */
541 if (osbdm_add_statemove(queue
, tap_get_end_state(), 1) != ERROR_OK
)
548 static int osbdm_add_runtest(
551 tap_state_t end_state
)
553 if (osbdm_add_statemove(queue
, TAP_IDLE
, 0) != ERROR_OK
)
556 if (osbdm_add_stableclocks(queue
, num_cycles
) != ERROR_OK
)
559 if (osbdm_add_statemove(queue
, end_state
, 0) != ERROR_OK
)
565 static int osbdm_execute_command(
568 struct jtag_command
*cmd
)
570 int retval
= ERROR_OK
;
574 if (cmd
->cmd
.reset
->trst
) {
575 LOG_ERROR("BUG: nTRST signal is not supported");
578 retval
= osbdm_flush(osbdm
, queue
);
579 if (retval
== ERROR_OK
)
580 retval
= osbdm_srst(osbdm
, cmd
->cmd
.reset
->srst
);
585 retval
= osbdm_add_pathmove(
587 cmd
->cmd
.pathmove
->path
,
588 cmd
->cmd
.pathmove
->num_states
);
592 retval
= osbdm_add_statemove(
594 cmd
->cmd
.statemove
->end_state
,
598 case JTAG_STABLECLOCKS
:
599 retval
= osbdm_add_stableclocks(
601 cmd
->cmd
.stableclocks
->num_cycles
);
605 retval
= osbdm_add_tms(
608 cmd
->cmd
.tms
->num_bits
);
612 retval
= osbdm_add_scan(
614 cmd
->cmd
.scan
->fields
,
615 cmd
->cmd
.scan
->num_fields
,
616 cmd
->cmd
.scan
->end_state
,
617 cmd
->cmd
.scan
->ir_scan
);
621 retval
= osbdm_flush(osbdm
, queue
);
622 if (retval
== ERROR_OK
)
623 jtag_sleep(cmd
->cmd
.sleep
->us
);
627 retval
= osbdm_add_runtest(
629 cmd
->cmd
.runtest
->num_cycles
,
630 cmd
->cmd
.runtest
->end_state
);
634 LOG_ERROR("BUG: unknown JTAG command type encountered");
642 static int osbdm_execute_queue(void)
644 int retval
= ERROR_OK
;
646 struct queue
*queue
= queue_alloc();
648 LOG_ERROR("BUG: can't allocate bit queue");
651 struct jtag_command
*cmd
= jtag_command_queue
;
653 while (retval
== ERROR_OK
&& cmd
) {
654 retval
= osbdm_execute_command(&osbdm_context
, queue
, cmd
);
658 if (retval
== ERROR_OK
)
659 retval
= osbdm_flush(&osbdm_context
, queue
);
664 if (retval
!= ERROR_OK
) {
665 LOG_ERROR("FATAL: can't execute jtag command");
672 static int osbdm_init(void)
675 if (osbdm_open(&osbdm_context
) != ERROR_OK
) {
676 LOG_ERROR("Can't open OSBDM device");
679 /* Device successfully opened */
680 LOG_DEBUG("OSBDM init");
683 /* Perform initialize command */
684 osbdm_context
.count
= 0;
685 osbdm_context
.buffer
[osbdm_context
.count
++] = OSBDM_CMD_INIT
;
686 if (osbdm_send_and_recv(&osbdm_context
) != ERROR_OK
)
692 static struct jtag_interface osbdm_interface
= {
693 .execute_queue
= osbdm_execute_queue
,
696 struct adapter_driver osbdm_adapter_driver
= {
698 .transports
= jtag_only
,
703 .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)