5db36a122ae943089d54656e57f1f8c9ff102da4
[openocd.git] / src / jtag / drivers / osbdm.c
1 /***************************************************************************
2 * Copyright (C) 2012 by Jan Dakinevich *
3 * jan.dakinevich@gmail.com *
4 * *
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. *
9 * *
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. *
14 * *
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 ***************************************************************************/
18 #ifdef HAVE_CONFIG_H
19 # include "config.h"
20 #endif
21
22 #include <helper/log.h>
23 #include <helper/binarybuffer.h>
24 #include <helper/command.h>
25 #include <jtag/interface.h>
26 #include "libusb_common.h"
27
28 struct sequence {
29 int len;
30 void *tms;
31 void *tdo;
32 const void *tdi;
33 struct sequence *next;
34 };
35
36 struct queue {
37 struct sequence *head;
38 struct sequence *tail;
39 };
40
41 static struct sequence *queue_add_tail(struct queue *queue, int len)
42 {
43 if (len <= 0) {
44 LOG_ERROR("BUG: sequences with zero length are not allowed");
45 return NULL;
46 }
47
48 struct sequence *next;
49 next = malloc(sizeof(*next));
50 if (next) {
51 next->tms = calloc(1, DIV_ROUND_UP(len, 8));
52 if (next->tms) {
53 next->len = len;
54 next->tdo = NULL;
55 next->tdi = NULL;
56 next->next = NULL;
57
58 if (!queue->head) {
59 /* Queue is empty at the moment */
60 queue->head = next;
61 } else {
62 /* Queue already contains at least one sequence */
63 queue->tail->next = next;
64 }
65
66 queue->tail = next;
67 } else {
68 free(next);
69 next = NULL;
70 }
71 }
72
73 if (!next)
74 LOG_ERROR("Not enough memory");
75
76 return next;
77 }
78
79 static void queue_drop_head(struct queue *queue)
80 {
81 struct sequence *head = queue->head->next; /* New head */
82 free(queue->head->tms);
83 free(queue->head);
84 queue->head = head;
85 }
86
87 static void queue_free(struct queue *queue)
88 {
89 if (queue) {
90 while (queue->head)
91 queue_drop_head(queue);
92
93 free(queue);
94 }
95 }
96
97 static struct queue *queue_alloc(void)
98 {
99 struct queue *queue = malloc(sizeof(*queue));
100 if (queue)
101 queue->head = NULL;
102 else
103 LOG_ERROR("Not enough memory");
104
105 return queue;
106 }
107
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
114 /* Read end point */
115 #define OSBDM_USB_EP_READ 0x82
116
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
124 /* Reset control */
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)
128
129 /* Lists of valid VID/PID pairs
130 */
131 static const uint16_t osbdm_vid[] = { 0x15a2, 0x15a2, 0x15a2, 0 };
132 static const uint16_t osbdm_pid[] = { 0x0042, 0x0058, 0x005e, 0 };
133
134 struct osbdm {
135 struct jtag_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 */
138 };
139
140 /* osbdm instance
141 */
142 static struct osbdm osbdm_context;
143
144 static int osbdm_send_and_recv(struct osbdm *osbdm)
145 {
146 /* Send request */
147 int count = jtag_libusb_bulk_write(osbdm->devh, OSBDM_USB_EP_WRITE,
148 (char *)osbdm->buffer, osbdm->count, OSBDM_USB_TIMEOUT);
149
150 if (count != osbdm->count) {
151 LOG_ERROR("OSBDM communication error: can't write");
152 return ERROR_FAIL;
153 }
154
155 /* Save command code for next checking */
156 uint8_t cmd_saved = osbdm->buffer[0];
157
158 /* Reading answer */
159 osbdm->count = jtag_libusb_bulk_read(osbdm->devh, OSBDM_USB_EP_READ,
160 (char *)osbdm->buffer, OSBDM_USB_BUFSIZE, OSBDM_USB_TIMEOUT);
161
162 /* Now perform basic checks for data sent by BDM device
163 */
164
165 if (osbdm->count < 0) {
166 LOG_ERROR("OSBDM communication error: can't read");
167 return ERROR_FAIL;
168 }
169
170 if (osbdm->count < 2) {
171 LOG_ERROR("OSBDM communication error: reply too small");
172 return ERROR_FAIL;
173 }
174
175 if (osbdm->count != osbdm->buffer[1]) {
176 LOG_ERROR("OSBDM communication error: reply size mismatch");
177 return ERROR_FAIL;
178 }
179
180 if (cmd_saved != osbdm->buffer[0]) {
181 LOG_ERROR("OSBDM communication error: reply command mismatch");
182 return ERROR_FAIL;
183 }
184
185 return ERROR_OK;
186 }
187
188 static int osbdm_srst(struct osbdm *osbdm, int srst)
189 {
190 osbdm->count = 0;
191 (void)memset(osbdm->buffer, 0, OSBDM_USB_BUFSIZE);
192
193 /* Composing request
194 */
195 osbdm->buffer[osbdm->count++] = OSBDM_CMD_SPECIAL; /* Command */
196 osbdm->buffer[osbdm->count++] = OSBDM_CMD_SPECIAL_SRST; /* Subcommand */
197 /* Length in bytes - not used */
198 osbdm->buffer[osbdm->count++] = 0;
199 osbdm->buffer[osbdm->count++] = 0;
200 /* SRST state */
201 osbdm->buffer[osbdm->count++] = (srst ? 0 : 0x08);
202
203 /* Sending data
204 */
205 if (osbdm_send_and_recv(osbdm) != ERROR_OK)
206 return ERROR_FAIL;
207
208 return ERROR_OK;
209 }
210
211 static int osbdm_swap(struct osbdm *osbdm, void *tms, void *tdi,
212 void *tdo, int length)
213 {
214 if (length > OSBDM_SWAP_MAX) {
215 LOG_ERROR("BUG: bit sequence too long");
216 return ERROR_FAIL;
217 }
218
219 if (length <= 0) {
220 LOG_ERROR("BUG: bit sequence equal or less than 0");
221 return ERROR_FAIL;
222 }
223
224 int swap_count = DIV_ROUND_UP(length, 16);
225
226 /* cleanup */
227 osbdm->count = 0;
228 (void)memset(osbdm->buffer, 0, OSBDM_USB_BUFSIZE);
229
230 /* Composing request
231 */
232
233 osbdm->buffer[osbdm->count++] = OSBDM_CMD_SPECIAL; /* Command */
234 osbdm->buffer[osbdm->count++] = OSBDM_CMD_SPECIAL_SWAP; /* Subcommand */
235 /* Length in bytes - not used */
236 osbdm->buffer[osbdm->count++] = 0;
237 osbdm->buffer[osbdm->count++] = 0;
238 /* Swap count */
239 osbdm->buffer[osbdm->count++] = 0;
240 osbdm->buffer[osbdm->count++] = (uint8_t)swap_count;
241
242 for (int bit_idx = 0; bit_idx < length; ) {
243 /* Bit count in swap */
244 int bit_count = length - bit_idx;
245 if (bit_count > 16)
246 bit_count = 16;
247
248 osbdm->buffer[osbdm->count++] = (uint8_t)bit_count;
249
250 /* Copying TMS and TDI data to output buffer */
251 uint32_t tms_data = buf_get_u32(tms, bit_idx, bit_count);
252 uint32_t tdi_data = buf_get_u32(tdi, bit_idx, bit_count);
253 osbdm->buffer[osbdm->count++] = (uint8_t)(tdi_data >> 8);
254 osbdm->buffer[osbdm->count++] = (uint8_t)tdi_data;
255 osbdm->buffer[osbdm->count++] = (uint8_t)(tms_data >> 8);
256 osbdm->buffer[osbdm->count++] = (uint8_t)tms_data;
257
258 /* Next bit offset */
259 bit_idx += bit_count;
260 }
261
262 assert(osbdm->count <= OSBDM_USB_BUFSIZE);
263
264 /* Sending data
265 */
266 if (osbdm_send_and_recv(osbdm) != ERROR_OK)
267 return ERROR_FAIL;
268
269 /* Extra check
270 */
271 if (((osbdm->buffer[2] << 8) | osbdm->buffer[3]) != 2 * swap_count) {
272 LOG_ERROR("OSBDM communication error: invalid swap command reply");
273 return ERROR_FAIL;
274 }
275
276 /* Copy TDO responce
277 */
278 uint8_t *buffer = osbdm->buffer + 4;
279 for (int bit_idx = 0; bit_idx < length; ) {
280 int bit_count = length - bit_idx;
281 if (bit_count > 16)
282 bit_count = 16;
283
284 /* Prepare data */
285 uint32_t tdo_data = 0;
286 tdo_data |= (*buffer++) << 8;
287 tdo_data |= (*buffer++);
288 tdo_data >>= (16 - bit_count);
289
290 /* Copy TDO to return */
291 buf_set_u32(tdo, bit_idx, bit_count, tdo_data);
292
293 bit_idx += bit_count;
294 }
295
296 return ERROR_OK;
297 }
298
299 static int osbdm_flush(struct osbdm *osbdm, struct queue* queue)
300 {
301 uint8_t tms[DIV_ROUND_UP(OSBDM_SWAP_MAX, 8)];
302 uint8_t tdi[DIV_ROUND_UP(OSBDM_SWAP_MAX, 8)];
303 uint8_t tdo[DIV_ROUND_UP(OSBDM_SWAP_MAX, 8)];
304
305 int seq_back_len = 0;
306
307 while (queue->head) {
308 (void)memset(tms, 0, sizeof(tms));
309 (void)memset(tdi, 0, sizeof(tdi));
310 (void)memset(tdo, 0, sizeof(tdo));
311
312 int seq_len;
313 int swap_len;
314 struct sequence *seq;
315
316 /* Copy from queue to tms/tdi streams
317 */
318 seq = queue->head;
319 seq_len = seq_back_len;
320 swap_len = 0;
321
322 while (seq && swap_len != OSBDM_SWAP_MAX) {
323 /* Count bit for copy at this iteration.
324 * len should fit into remaining space
325 * in tms/tdo bitstreams
326 */
327 int len = seq->len - seq_len;
328 if (len > OSBDM_SWAP_MAX - swap_len)
329 len = OSBDM_SWAP_MAX - swap_len;
330
331 /* Set tms data */
332 buf_set_buf(seq->tms, seq_len, tms, swap_len, len);
333
334 /* Set tdi data if they exists */
335 if (seq->tdi)
336 buf_set_buf(seq->tdi, seq_len, tdi, swap_len, len);
337
338 swap_len += len;
339 seq_len += len;
340 if (seq_len == seq->len) {
341 seq = seq->next; /* Move to next sequence */
342 seq_len = 0;
343 }
344 }
345
346 if (osbdm_swap(osbdm, tms, tdi, tdo, swap_len))
347 return ERROR_FAIL;
348
349 /* Copy from tdo stream to queue
350 */
351
352 for (int swap_back_len = 0; swap_back_len < swap_len; ) {
353 int len = queue->head->len - seq_back_len;
354 if (len > swap_len - swap_back_len)
355 len = swap_len - swap_back_len;
356
357 if (queue->head->tdo)
358 buf_set_buf(tdo, swap_back_len, queue->head->tdo, seq_back_len, len);
359
360 swap_back_len += len;
361 seq_back_len += len;
362 if (seq_back_len == queue->head->len) {
363 queue_drop_head(queue);
364 seq_back_len = 0;
365 }
366 }
367 }
368
369 return ERROR_OK;
370 }
371
372 /* Basic operation for opening USB device */
373 static int osbdm_open(struct osbdm *osbdm)
374 {
375 (void)memset(osbdm, 0, sizeof(*osbdm));
376 if (jtag_libusb_open(osbdm_vid, osbdm_pid, NULL, &osbdm->devh) != ERROR_OK)
377 return ERROR_FAIL;
378
379 if (jtag_libusb_claim_interface(osbdm->devh, 0) != ERROR_OK)
380 return ERROR_FAIL;
381
382 return ERROR_OK;
383 }
384
385 static int osbdm_quit(void)
386 {
387 jtag_libusb_close(osbdm_context.devh);
388 return ERROR_OK;
389 }
390
391 static int osbdm_add_pathmove(
392 struct queue *queue,
393 tap_state_t *path,
394 int num_states)
395 {
396 assert(num_states <= 32);
397
398 struct sequence *next = queue_add_tail(queue, num_states);
399 if (!next) {
400 LOG_ERROR("BUG: can't allocate bit sequence");
401 return ERROR_FAIL;
402 }
403
404 uint32_t tms = 0;
405 for (int i = 0; i < num_states; i++) {
406 if (tap_state_transition(tap_get_state(), 1) == path[i]) {
407 tms |= (1 << i);
408 } else if (tap_state_transition(tap_get_state(), 0) == path[i]) {
409 tms &= ~(1 << i); /* This line not so needed */
410 } else {
411 LOG_ERROR("BUG: %s -> %s isn't a valid TAP state transition",
412 tap_state_name(tap_get_state()),
413 tap_state_name(path[i]));
414 return ERROR_FAIL;
415 }
416
417 tap_set_state(path[i]);
418 }
419
420 buf_set_u32(next->tms, 0, num_states, tms);
421 tap_set_end_state(tap_get_state());
422
423 return ERROR_OK;
424 }
425
426 static int osbdm_add_statemove(
427 struct queue *queue,
428 tap_state_t new_state,
429 int skip_first)
430 {
431 int len = 0;
432 int tms = 0;
433
434 tap_set_end_state(new_state);
435 if (tap_get_end_state() == TAP_RESET) {
436 /* Ignore current state */
437 tms = 0xff;
438 len = 5;
439 } else if (tap_get_state() != tap_get_end_state()) {
440 tms = tap_get_tms_path(tap_get_state(), new_state);
441 len = tap_get_tms_path_len(tap_get_state(), new_state);
442 }
443
444 if (len && skip_first) {
445 len--;
446 tms >>= 1;
447 }
448
449 if (len) {
450 struct sequence *next = queue_add_tail(queue, len);
451 if (!next) {
452 LOG_ERROR("BUG: can't allocate bit sequence");
453 return ERROR_FAIL;
454 }
455 buf_set_u32(next->tms, 0, len, tms);
456 }
457
458 tap_set_state(tap_get_end_state());
459 return ERROR_OK;
460 }
461
462 static int osbdm_add_stableclocks(
463 struct queue *queue,
464 int count)
465 {
466 if (!tap_is_state_stable(tap_get_state())) {
467 LOG_ERROR("BUG: current state (%s) is not stable",
468 tap_state_name(tap_get_state()));
469 return ERROR_FAIL;
470 }
471
472 struct sequence *next = queue_add_tail(queue, count);
473 if (!next) {
474 LOG_ERROR("BUG: can't allocate bit sequence");
475 return ERROR_FAIL;
476 }
477
478 if (tap_get_state() == TAP_RESET)
479 (void)memset(next->tms, 0xff, DIV_ROUND_UP(count, 8));
480
481 return ERROR_OK;
482 }
483
484 static int osbdm_add_tms(
485 struct queue *queue,
486 const uint8_t *tms,
487 int num_bits)
488 {
489 struct sequence *next = queue_add_tail(queue, num_bits);
490 if (!next) {
491 LOG_ERROR("BUG: can't allocate bit sequence");
492 return ERROR_FAIL;
493 }
494 buf_set_buf(tms, 0, next->tms, 0, num_bits);
495
496 return ERROR_OK;
497 }
498
499 static int osbdm_add_scan(
500 struct queue *queue,
501 struct scan_field *fields,
502 int num_fields,
503 tap_state_t end_state,
504 bool ir_scan)
505 {
506 /* Move to desired shift state */
507 if (ir_scan) {
508 if (tap_get_state() != TAP_IRSHIFT) {
509 if (osbdm_add_statemove(queue, TAP_IRSHIFT, 0) != ERROR_OK)
510 return ERROR_FAIL;
511 }
512 } else {
513 if (tap_get_state() != TAP_DRSHIFT) {
514 if (osbdm_add_statemove(queue, TAP_DRSHIFT, 0) != ERROR_OK)
515 return ERROR_FAIL;
516 }
517 }
518
519 /* Add scan */
520 tap_set_end_state(end_state);
521 for (int idx = 0; idx < num_fields; idx++) {
522 struct sequence *next = queue_add_tail(queue, fields[idx].num_bits);
523 if (!next) {
524 LOG_ERROR("Can't allocate bit sequence");
525 return ERROR_FAIL;
526 }
527
528 (void)memset(next->tms, 0, DIV_ROUND_UP(fields[idx].num_bits, 8));
529 next->tdi = fields[idx].out_value;
530 next->tdo = fields[idx].in_value;
531 }
532
533 /* Move to end state
534 */
535 if (tap_get_state() != tap_get_end_state()) {
536 /* Exit from IRSHIFT/DRSHIFT */
537 buf_set_u32(queue->tail->tms, queue->tail->len - 1, 1, 1);
538
539 /* Move with skip_first flag */
540 if (osbdm_add_statemove(queue, tap_get_end_state(), 1) != ERROR_OK)
541 return ERROR_FAIL;
542 }
543
544 return ERROR_OK;
545 }
546
547 static int osbdm_add_runtest(
548 struct queue *queue,
549 int num_cycles,
550 tap_state_t end_state)
551 {
552 if (osbdm_add_statemove(queue, TAP_IDLE, 0) != ERROR_OK)
553 return ERROR_FAIL;
554
555 if (osbdm_add_stableclocks(queue, num_cycles) != ERROR_OK)
556 return ERROR_FAIL;
557
558 if (osbdm_add_statemove(queue, end_state, 0) != ERROR_OK)
559 return ERROR_FAIL;
560
561 return ERROR_OK;
562 }
563
564 static int osbdm_execute_command(
565 struct osbdm *osbdm,
566 struct queue *queue,
567 struct jtag_command *cmd)
568 {
569 int retval = ERROR_OK;
570
571 switch (cmd->type) {
572 case JTAG_RESET:
573 if (cmd->cmd.reset->trst) {
574 LOG_ERROR("BUG: nTRST signal is not supported");
575 retval = ERROR_FAIL;
576 } else {
577 retval = osbdm_flush(osbdm, queue);
578 if (retval == ERROR_OK)
579 retval = osbdm_srst(osbdm, cmd->cmd.reset->srst);
580 }
581 break;
582
583 case JTAG_PATHMOVE:
584 retval = osbdm_add_pathmove(
585 queue,
586 cmd->cmd.pathmove->path,
587 cmd->cmd.pathmove->num_states);
588 break;
589
590 case JTAG_TLR_RESET:
591 retval = osbdm_add_statemove(
592 queue,
593 cmd->cmd.statemove->end_state,
594 0);
595 break;
596
597 case JTAG_STABLECLOCKS:
598 retval = osbdm_add_stableclocks(
599 queue,
600 cmd->cmd.stableclocks->num_cycles);
601 break;
602
603 case JTAG_TMS:
604 retval = osbdm_add_tms(
605 queue,
606 cmd->cmd.tms->bits,
607 cmd->cmd.tms->num_bits);
608 break;
609
610 case JTAG_SCAN:
611 retval = osbdm_add_scan(
612 queue,
613 cmd->cmd.scan->fields,
614 cmd->cmd.scan->num_fields,
615 cmd->cmd.scan->end_state,
616 cmd->cmd.scan->ir_scan);
617 break;
618
619 case JTAG_SLEEP:
620 retval = osbdm_flush(osbdm, queue);
621 if (retval == ERROR_OK)
622 jtag_sleep(cmd->cmd.sleep->us);
623 break;
624
625 case JTAG_RUNTEST:
626 retval = osbdm_add_runtest(
627 queue,
628 cmd->cmd.runtest->num_cycles,
629 cmd->cmd.runtest->end_state);
630 break;
631
632 default:
633 LOG_ERROR("BUG: unknown JTAG command type encountered");
634 retval = ERROR_FAIL;
635 break;
636 }
637
638 return retval;
639 }
640
641 static int osbdm_execute_queue(void)
642 {
643 int retval = ERROR_OK;
644
645 struct queue *queue = queue_alloc();
646 if (!queue) {
647 LOG_ERROR("BUG: can't allocate bit queue");
648 retval = ERROR_FAIL;
649 } else {
650 struct jtag_command *cmd = jtag_command_queue;
651
652 while (retval == ERROR_OK && cmd) {
653 retval = osbdm_execute_command(&osbdm_context, queue, cmd);
654 cmd = cmd->next;
655 }
656
657 if (retval == ERROR_OK)
658 retval = osbdm_flush(&osbdm_context, queue);
659
660 queue_free(queue);
661 }
662
663 if (retval != ERROR_OK) {
664 LOG_ERROR("FATAL: can't execute jtag command");
665 exit(-1);
666 }
667
668 return retval;
669 }
670
671 static int osbdm_init(void)
672 {
673 /* Open device */
674 if (osbdm_open(&osbdm_context) != ERROR_OK) {
675 LOG_ERROR("Can't open OSBDM device");
676 return ERROR_FAIL;
677 } else {
678 /* Device successfully opened */
679 LOG_DEBUG("OSBDM init");
680 }
681
682 /* Perform initialize command */
683 osbdm_context.count = 0;
684 osbdm_context.buffer[osbdm_context.count++] = OSBDM_CMD_INIT;
685 if (osbdm_send_and_recv(&osbdm_context) != ERROR_OK)
686 return ERROR_FAIL;
687
688 return ERROR_OK;
689 }
690
691 struct jtag_interface osbdm_interface = {
692 .name = "osbdm",
693
694 .transports = jtag_only,
695 .execute_queue = osbdm_execute_queue,
696
697 .init = osbdm_init,
698 .quit = osbdm_quit
699 };

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)