openocd: src/jtag: replace the GPL-2.0-or-later license tag
[openocd.git] / src / jtag / drivers / vsllink.c
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2
3 /***************************************************************************
4 * Copyright (C) 2009-2010 by Simon Qian <SimonQian@SimonQian.com> *
5 ***************************************************************************/
6
7 /* Versaloon is a programming tool for multiple MCUs.
8 * It's distributed under GPLv3.
9 * You can find it at http://www.Versaloon.com/.
10 */
11
12 #ifdef HAVE_CONFIG_H
13 #include "config.h"
14 #endif
15
16 #include <jtag/adapter.h>
17 #include <jtag/interface.h>
18 #include <jtag/commands.h>
19 #include <jtag/swd.h>
20 #include <libusb.h>
21
22 #include "versaloon/versaloon_include.h"
23 #include "versaloon/versaloon.h"
24
25 static int vsllink_tms_offset;
26
27 struct pending_scan_result {
28 int src_offset;
29 int dest_offset;
30 int length; /* Number of bits to read */
31 struct scan_command *command; /* Corresponding scan command */
32 uint8_t *ack;
33 uint8_t *buffer;
34 bool last; /* indicate the last scan pending */
35 };
36
37 #define MAX_PENDING_SCAN_RESULTS 256
38
39 static int pending_scan_results_length;
40 static struct pending_scan_result
41 pending_scan_results_buffer[MAX_PENDING_SCAN_RESULTS];
42
43 /* Queue command functions */
44 static void vsllink_end_state(tap_state_t state);
45 static void vsllink_state_move(void);
46 static void vsllink_path_move(int num_states, tap_state_t *path);
47 static void vsllink_tms(int num_bits, const uint8_t *bits);
48 static void vsllink_runtest(int num_cycles);
49 static void vsllink_stableclocks(int num_cycles, int tms);
50 static void vsllink_scan(bool ir_scan, enum scan_type type,
51 uint8_t *buffer, int scan_size, struct scan_command *command);
52 static int vsllink_reset(int trst, int srst);
53
54 /* VSLLink tap buffer functions */
55 static void vsllink_tap_append_step(int tms, int tdi);
56 static void vsllink_tap_init(void);
57 static int vsllink_tap_execute(void);
58 static void vsllink_tap_ensure_pending(int scans);
59 static void vsllink_tap_append_scan(int length, uint8_t *buffer,
60 struct scan_command *command);
61
62 /* VSLLink SWD functions */
63 static int_least32_t vsllink_swd_frequency(int_least32_t hz);
64 static int vsllink_swd_switch_seq(enum swd_special_seq seq);
65
66 /* VSLLink lowlevel functions */
67 struct vsllink {
68 struct libusb_context *libusb_ctx;
69 struct libusb_device_handle *usb_device_handle;
70 };
71
72 static int vsllink_usb_open(struct vsllink *vsllink);
73 static void vsllink_usb_close(struct vsllink *vsllink);
74
75 static void vsllink_debug_buffer(uint8_t *buffer, int length);
76
77 static int tap_length;
78 static int tap_buffer_size;
79 static uint8_t *tms_buffer;
80 static uint8_t *tdi_buffer;
81 static uint8_t *tdo_buffer;
82
83 static bool swd_mode;
84
85 static struct vsllink *vsllink_handle;
86
87 static int vsllink_execute_queue(void)
88 {
89 struct jtag_command *cmd = jtag_command_queue;
90 int scan_size;
91 enum scan_type type;
92 uint8_t *buffer;
93
94 LOG_DEBUG_IO("-------------------------------------"
95 " vsllink "
96 "-------------------------------------");
97
98 while (cmd) {
99 switch (cmd->type) {
100 case JTAG_RUNTEST:
101 LOG_DEBUG_IO("runtest %i cycles, end in %s",
102 cmd->cmd.runtest->num_cycles,
103 tap_state_name(cmd->cmd.runtest->end_state));
104
105 vsllink_end_state(cmd->cmd.runtest->end_state);
106 vsllink_runtest(cmd->cmd.runtest->num_cycles);
107 break;
108
109 case JTAG_TLR_RESET:
110 LOG_DEBUG_IO("statemove end in %s",
111 tap_state_name(cmd->cmd.statemove->end_state));
112
113 vsllink_end_state(cmd->cmd.statemove->end_state);
114 vsllink_state_move();
115 break;
116
117 case JTAG_PATHMOVE:
118 LOG_DEBUG_IO("pathmove: %i states, end in %s",
119 cmd->cmd.pathmove->num_states,
120 tap_state_name(cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]));
121
122 vsllink_path_move(cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path);
123 break;
124
125 case JTAG_SCAN:
126 LOG_DEBUG_IO("JTAG Scan...");
127
128 vsllink_end_state(cmd->cmd.scan->end_state);
129
130 scan_size = jtag_build_buffer(
131 cmd->cmd.scan, &buffer);
132
133 if (cmd->cmd.scan->ir_scan)
134 LOG_DEBUG_IO(
135 "JTAG Scan write IR(%d bits), "
136 "end in %s:",
137 scan_size,
138 tap_state_name(cmd->cmd.scan->end_state));
139
140 else
141 LOG_DEBUG_IO(
142 "JTAG Scan write DR(%d bits), "
143 "end in %s:",
144 scan_size,
145 tap_state_name(cmd->cmd.scan->end_state));
146
147 if (LOG_LEVEL_IS(LOG_LVL_DEBUG_IO))
148 vsllink_debug_buffer(buffer, DIV_ROUND_UP(scan_size, 8));
149
150 type = jtag_scan_type(cmd->cmd.scan);
151
152 vsllink_scan(cmd->cmd.scan->ir_scan,
153 type, buffer, scan_size,
154 cmd->cmd.scan);
155 break;
156
157 case JTAG_SLEEP:
158 LOG_DEBUG_IO("sleep %" PRIu32, cmd->cmd.sleep->us);
159 vsllink_tap_execute();
160 jtag_sleep(cmd->cmd.sleep->us);
161 break;
162
163 case JTAG_STABLECLOCKS:
164 LOG_DEBUG_IO("add %d clocks",
165 cmd->cmd.stableclocks->num_cycles);
166
167 switch (tap_get_state()) {
168 case TAP_RESET:
169 /* tms must be '1' to stay
170 * n TAP_RESET mode
171 */
172 scan_size = 1;
173 break;
174 case TAP_DRSHIFT:
175 case TAP_IDLE:
176 case TAP_DRPAUSE:
177 case TAP_IRSHIFT:
178 case TAP_IRPAUSE:
179 /* else, tms should be '0' */
180 scan_size = 0;
181 break;
182 /* above stable states are OK */
183 default:
184 LOG_ERROR("jtag_add_clocks() "
185 "in non-stable state \"%s\"",
186 tap_state_name(tap_get_state())
187 );
188 exit(-1);
189 }
190 vsllink_stableclocks(cmd->cmd.stableclocks->num_cycles, scan_size);
191 break;
192
193 case JTAG_TMS:
194 LOG_DEBUG_IO("add %d jtag tms",
195 cmd->cmd.tms->num_bits);
196
197 vsllink_tms(cmd->cmd.tms->num_bits, cmd->cmd.tms->bits);
198 break;
199
200 default:
201 LOG_ERROR("BUG: unknown JTAG command type "
202 "encountered: %d", cmd->type);
203 exit(-1);
204 }
205 cmd = cmd->next;
206 }
207
208 return vsllink_tap_execute();
209 }
210
211 static int vsllink_speed(int speed)
212 {
213 if (swd_mode) {
214 vsllink_swd_frequency(speed * 1000);
215 return ERROR_OK;
216 }
217
218 versaloon_interface.adaptors.jtag_raw.config(0, (uint16_t)speed);
219 return versaloon_interface.adaptors.peripheral_commit();
220 }
221
222 static int vsllink_khz(int khz, int *jtag_speed)
223 {
224 *jtag_speed = khz;
225
226 return ERROR_OK;
227 }
228
229 static int vsllink_speed_div(int jtag_speed, int *khz)
230 {
231 *khz = jtag_speed;
232
233 return ERROR_OK;
234 }
235
236 static void vsllink_free_buffer(void)
237 {
238 free(tdi_buffer);
239 tdi_buffer = NULL;
240
241 free(tdo_buffer);
242 tdo_buffer = NULL;
243
244 free(tms_buffer);
245 tms_buffer = NULL;
246 }
247
248 static int vsllink_quit(void)
249 {
250 versaloon_interface.adaptors.gpio.config(0, GPIO_SRST | GPIO_TRST,
251 0, 0, GPIO_SRST | GPIO_TRST);
252 versaloon_interface.adaptors.gpio.fini(0);
253
254 if (swd_mode)
255 versaloon_interface.adaptors.swd.fini(0);
256 else
257 versaloon_interface.adaptors.jtag_raw.fini(0);
258
259 versaloon_interface.adaptors.peripheral_commit();
260 versaloon_interface.fini();
261
262 vsllink_free_buffer();
263 vsllink_usb_close(vsllink_handle);
264
265 libusb_exit(vsllink_handle->libusb_ctx);
266 free(vsllink_handle);
267
268 return ERROR_OK;
269 }
270
271 static int vsllink_interface_init(void)
272 {
273 vsllink_handle = malloc(sizeof(struct vsllink));
274 if (!vsllink_handle) {
275 LOG_ERROR("unable to allocate memory");
276 return ERROR_FAIL;
277 }
278
279 libusb_init(&vsllink_handle->libusb_ctx);
280
281 if (vsllink_usb_open(vsllink_handle) != ERROR_OK) {
282 LOG_ERROR("Can't find USB JTAG Interface!"
283 "Please check connection and permissions.");
284 return ERROR_JTAG_INIT_FAILED;
285 }
286 LOG_DEBUG("vsllink found on %04X:%04X",
287 versaloon_interface.usb_setting.vid,
288 versaloon_interface.usb_setting.pid);
289 versaloon_usb_device_handle = vsllink_handle->usb_device_handle;
290
291 if (versaloon_interface.init() != ERROR_OK)
292 return ERROR_FAIL;
293 if (versaloon_interface.usb_setting.buf_size < 32) {
294 versaloon_interface.fini();
295 return ERROR_FAIL;
296 }
297
298 return ERROR_OK;
299 }
300
301 static int vsllink_init(void)
302 {
303 int retval = vsllink_interface_init();
304 if (retval != ERROR_OK)
305 return retval;
306
307 versaloon_interface.adaptors.gpio.init(0);
308 versaloon_interface.adaptors.gpio.config(0, GPIO_SRST, 0, GPIO_SRST,
309 GPIO_SRST);
310 versaloon_interface.adaptors.delay.delayms(100);
311 versaloon_interface.adaptors.peripheral_commit();
312
313 if (swd_mode) {
314 versaloon_interface.adaptors.gpio.config(0, GPIO_TRST, 0,
315 GPIO_TRST, GPIO_TRST);
316 versaloon_interface.adaptors.swd.init(0);
317 vsllink_swd_frequency(adapter_get_speed_khz() * 1000);
318 vsllink_swd_switch_seq(JTAG_TO_SWD);
319
320 } else {
321 /* malloc buffer size for tap */
322 tap_buffer_size = versaloon_interface.usb_setting.buf_size / 2 - 32;
323 vsllink_free_buffer();
324 tdi_buffer = malloc(tap_buffer_size);
325 tdo_buffer = malloc(tap_buffer_size);
326 tms_buffer = malloc(tap_buffer_size);
327 if ((!tdi_buffer) || (!tdo_buffer) || (!tms_buffer)) {
328 vsllink_quit();
329 return ERROR_FAIL;
330 }
331
332 versaloon_interface.adaptors.jtag_raw.init(0);
333 versaloon_interface.adaptors.jtag_raw.config(0, adapter_get_speed_khz());
334 versaloon_interface.adaptors.gpio.config(0, GPIO_SRST | GPIO_TRST,
335 GPIO_TRST, GPIO_SRST, GPIO_SRST);
336 }
337
338 if (versaloon_interface.adaptors.peripheral_commit() != ERROR_OK)
339 return ERROR_FAIL;
340
341 vsllink_reset(0, 0);
342 vsllink_tap_init();
343 return ERROR_OK;
344 }
345
346 /**************************************************************************
347 * Queue command implementations */
348
349 static void vsllink_end_state(tap_state_t state)
350 {
351 if (tap_is_state_stable(state))
352 tap_set_end_state(state);
353 else {
354 LOG_ERROR("BUG: %i is not a valid end state", state);
355 exit(-1);
356 }
357 }
358
359 /* Goes to the end state. */
360 static void vsllink_state_move(void)
361 {
362 int i;
363 uint8_t tms_scan = tap_get_tms_path(tap_get_state(),
364 tap_get_end_state());
365 uint8_t tms_scan_bits = tap_get_tms_path_len(tap_get_state(),
366 tap_get_end_state());
367
368 for (i = 0; i < tms_scan_bits; i++)
369 vsllink_tap_append_step((tms_scan >> i) & 1, 0);
370
371 tap_set_state(tap_get_end_state());
372 }
373
374 static void vsllink_path_move(int num_states, tap_state_t *path)
375 {
376 for (int i = 0; i < num_states; i++) {
377 if (path[i] == tap_state_transition(tap_get_state(), false))
378 vsllink_tap_append_step(0, 0);
379 else if (path[i] == tap_state_transition(tap_get_state(), true))
380 vsllink_tap_append_step(1, 0);
381 else {
382 LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition",
383 tap_state_name(tap_get_state()),
384 tap_state_name(path[i]));
385 exit(-1);
386 }
387
388 tap_set_state(path[i]);
389 }
390
391 tap_set_end_state(tap_get_state());
392 }
393
394 static void vsllink_tms(int num_bits, const uint8_t *bits)
395 {
396 for (int i = 0; i < num_bits; i++)
397 vsllink_tap_append_step((bits[i / 8] >> (i % 8)) & 1, 0);
398 }
399
400 static void vsllink_stableclocks(int num_cycles, int tms)
401 {
402 while (num_cycles > 0) {
403 vsllink_tap_append_step(tms, 0);
404 num_cycles--;
405 }
406 }
407
408 static void vsllink_runtest(int num_cycles)
409 {
410 tap_state_t saved_end_state = tap_get_end_state();
411
412 if (tap_get_state() != TAP_IDLE) {
413 /* enter IDLE state */
414 vsllink_end_state(TAP_IDLE);
415 vsllink_state_move();
416 }
417
418 vsllink_stableclocks(num_cycles, 0);
419
420 /* post-process */
421 /* set end_state */
422 vsllink_end_state(saved_end_state);
423 if (tap_get_end_state() != tap_get_end_state())
424 vsllink_state_move();
425 }
426
427 static void vsllink_scan(bool ir_scan, enum scan_type type, uint8_t *buffer,
428 int scan_size, struct scan_command *command)
429 {
430 tap_state_t saved_end_state;
431
432 saved_end_state = tap_get_end_state();
433
434 /* Move to appropriate scan state */
435 vsllink_end_state(ir_scan ? TAP_IRSHIFT : TAP_DRSHIFT);
436
437 if (tap_get_state() != tap_get_end_state())
438 vsllink_state_move();
439 vsllink_end_state(saved_end_state);
440
441 /* Scan */
442 vsllink_tap_append_scan(scan_size, buffer, command);
443
444 /* Goto Pause and record position to insert tms:0 */
445 vsllink_tap_append_step(0, 0);
446 vsllink_tms_offset = tap_length;
447
448 tap_set_state(ir_scan ? TAP_IRPAUSE : TAP_DRPAUSE);
449
450 if (tap_get_state() != tap_get_end_state())
451 vsllink_state_move();
452 }
453
454 static int vsllink_reset(int trst, int srst)
455 {
456 LOG_DEBUG("trst: %i, srst: %i", trst, srst);
457
458 if (!srst)
459 versaloon_interface.adaptors.gpio.config(0, GPIO_SRST, 0, GPIO_SRST, GPIO_SRST);
460 else
461 versaloon_interface.adaptors.gpio.config(0, GPIO_SRST, GPIO_SRST, 0, 0);
462
463 if (!swd_mode) {
464 if (!trst)
465 versaloon_interface.adaptors.gpio.out(0, GPIO_TRST, GPIO_TRST);
466 else
467 versaloon_interface.adaptors.gpio.out(0, GPIO_TRST, 0);
468 }
469
470 return versaloon_interface.adaptors.peripheral_commit();
471 }
472
473 COMMAND_HANDLER(vsllink_handle_usb_vid_command)
474 {
475 if (CMD_ARGC != 1)
476 return ERROR_COMMAND_SYNTAX_ERROR;
477
478 COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0],
479 versaloon_interface.usb_setting.vid);
480 return ERROR_OK;
481 }
482
483 COMMAND_HANDLER(vsllink_handle_usb_pid_command)
484 {
485 if (CMD_ARGC != 1)
486 return ERROR_COMMAND_SYNTAX_ERROR;
487 COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0],
488 versaloon_interface.usb_setting.pid);
489 return ERROR_OK;
490 }
491
492 COMMAND_HANDLER(vsllink_handle_usb_bulkin_command)
493 {
494 if (CMD_ARGC != 1)
495 return ERROR_COMMAND_SYNTAX_ERROR;
496
497 COMMAND_PARSE_NUMBER(u8, CMD_ARGV[0],
498 versaloon_interface.usb_setting.ep_in);
499
500 versaloon_interface.usb_setting.ep_in |= 0x80;
501
502 return ERROR_OK;
503 }
504
505 COMMAND_HANDLER(vsllink_handle_usb_bulkout_command)
506 {
507 if (CMD_ARGC != 1)
508 return ERROR_COMMAND_SYNTAX_ERROR;
509
510 COMMAND_PARSE_NUMBER(u8, CMD_ARGV[0],
511 versaloon_interface.usb_setting.ep_out);
512
513 versaloon_interface.usb_setting.ep_out &= ~0x80;
514
515 return ERROR_OK;
516 }
517
518 COMMAND_HANDLER(vsllink_handle_usb_interface_command)
519 {
520 if (CMD_ARGC != 1)
521 return ERROR_COMMAND_SYNTAX_ERROR;
522
523 COMMAND_PARSE_NUMBER(u8, CMD_ARGV[0],
524 versaloon_interface.usb_setting.interface);
525 return ERROR_OK;
526 }
527
528 /**************************************************************************
529 * VSLLink tap functions */
530
531 static void vsllink_tap_init(void)
532 {
533 tap_length = 0;
534 pending_scan_results_length = 0;
535 vsllink_tms_offset = 0;
536 }
537
538 static void vsllink_tap_ensure_pending(int scans)
539 {
540 int available_scans =
541 MAX_PENDING_SCAN_RESULTS - pending_scan_results_length;
542
543 if (scans > available_scans)
544 vsllink_tap_execute();
545 }
546
547 static void vsllink_tap_append_step(int tms, int tdi)
548 {
549 int index_var = tap_length / 8;
550
551 int bit_index = tap_length % 8;
552 uint8_t bit = 1 << bit_index;
553
554 if (tms)
555 tms_buffer[index_var] |= bit;
556 else
557 tms_buffer[index_var] &= ~bit;
558
559 if (tdi)
560 tdi_buffer[index_var] |= bit;
561 else
562 tdi_buffer[index_var] &= ~bit;
563
564 tap_length++;
565
566 if (tap_buffer_size * 8 <= tap_length)
567 vsllink_tap_execute();
568 }
569
570 static void vsllink_tap_append_scan(int length, uint8_t *buffer,
571 struct scan_command *command)
572 {
573 struct pending_scan_result *pending_scan_result;
574 int len_tmp, len_all, i;
575
576 len_all = 0;
577 while (len_all < length) {
578 vsllink_tap_ensure_pending(1);
579 pending_scan_result =
580 &pending_scan_results_buffer[
581 pending_scan_results_length];
582
583 if ((length - len_all) > (tap_buffer_size * 8 - tap_length)) {
584 /* Use all memory available
585 vsllink_tap_append_step will commit automatically */
586 len_tmp = tap_buffer_size * 8 - tap_length;
587 pending_scan_result->last = false;
588 } else {
589 len_tmp = length - len_all;
590 pending_scan_result->last = true;
591 }
592 pending_scan_result->src_offset = tap_length;
593 pending_scan_result->dest_offset = len_all;
594 pending_scan_result->length = len_tmp;
595 pending_scan_result->command = command;
596 pending_scan_result->buffer = buffer;
597 pending_scan_results_length++;
598
599 for (i = 0; i < len_tmp; i++) {
600 vsllink_tap_append_step(((len_all + i) < length-1
601 ? 0 : 1),
602 (buffer[(len_all + i)/8]
603 >> ((len_all + i)%8)) & 1);
604 }
605
606 len_all += len_tmp;
607 }
608 }
609
610 static int vsllink_jtag_execute(void)
611 {
612 int i;
613 int result;
614
615 if (tap_length <= 0)
616 return ERROR_OK;
617
618 versaloon_interface.adaptors.jtag_raw.execute(0, tdi_buffer, tms_buffer,
619 tdo_buffer, tap_length);
620
621 result = versaloon_interface.adaptors.peripheral_commit();
622
623 if (result == ERROR_OK) {
624 for (i = 0; i < pending_scan_results_length; i++) {
625 struct pending_scan_result *pending_scan_result =
626 &pending_scan_results_buffer[i];
627 uint8_t *buffer = pending_scan_result->buffer;
628 int length = pending_scan_result->length;
629 int src_first = pending_scan_result->src_offset;
630 int dest_first = pending_scan_result->dest_offset;
631 bool last = pending_scan_result->last;
632
633 struct scan_command *command;
634
635 command = pending_scan_result->command;
636 buf_set_buf(tdo_buffer, src_first, buffer, dest_first, length);
637
638 LOG_DEBUG_IO(
639 "JTAG scan read(%d bits, from src %d bits to dest %d bits):",
640 length, src_first, dest_first);
641 if (LOG_LEVEL_IS(LOG_LVL_DEBUG_IO))
642 vsllink_debug_buffer(buffer + dest_first / 8, DIV_ROUND_UP(length, 7));
643
644 if (last) {
645 if (jtag_read_buffer(buffer, command)
646 != ERROR_OK) {
647 vsllink_tap_init();
648 return ERROR_JTAG_QUEUE_FAILED;
649 }
650
651 free(pending_scan_result->buffer);
652 }
653 }
654 } else {
655 LOG_ERROR("vsllink_jtag_execute failure");
656 return ERROR_JTAG_QUEUE_FAILED;
657 }
658
659 vsllink_tap_init();
660
661 return ERROR_OK;
662 }
663
664 static int vsllink_tap_execute(void)
665 {
666 if (swd_mode)
667 return ERROR_OK;
668
669 return vsllink_jtag_execute();
670 }
671
672 static int vsllink_swd_init(void)
673 {
674 LOG_INFO("VSLLink SWD mode enabled");
675 swd_mode = true;
676
677 return ERROR_OK;
678 }
679
680 static int_least32_t vsllink_swd_frequency(int_least32_t hz)
681 {
682 const int_least32_t delay2hz[] = {
683 1850000, 235000, 130000, 102000, 85000, 72000
684 };
685
686 if (hz > 0) {
687 uint16_t delay = UINT16_MAX;
688
689 for (uint16_t i = 0; i < ARRAY_SIZE(delay2hz); i++) {
690 if (hz >= delay2hz[i]) {
691 hz = delay2hz[i];
692 delay = i;
693 break;
694 }
695 }
696
697 if (delay == UINT16_MAX)
698 delay = (500000 / hz) - 1;
699
700 /* Calculate retry count after a WAIT response. This will give
701 * a retry timeout at about ~250 ms. 54 is the number of bits
702 * found in a transaction. */
703 uint16_t retry_count = 250 * hz / 1000 / 54;
704
705 LOG_DEBUG("SWD delay: %d, retry count: %d", delay, retry_count);
706
707 versaloon_interface.adaptors.swd.config(0, 2, retry_count, delay);
708 }
709
710 return hz;
711 }
712
713 static int vsllink_swd_switch_seq(enum swd_special_seq seq)
714 {
715 switch (seq) {
716 case LINE_RESET:
717 LOG_DEBUG("SWD line reset");
718 versaloon_interface.adaptors.swd.seqout(0, swd_seq_line_reset,
719 swd_seq_line_reset_len);
720 break;
721 case JTAG_TO_SWD:
722 LOG_DEBUG("JTAG-to-SWD");
723 versaloon_interface.adaptors.swd.seqout(0, swd_seq_jtag_to_swd,
724 swd_seq_jtag_to_swd_len);
725 break;
726 case SWD_TO_JTAG:
727 LOG_DEBUG("SWD-to-JTAG");
728 versaloon_interface.adaptors.swd.seqout(0, swd_seq_swd_to_jtag,
729 swd_seq_swd_to_jtag_len);
730 break;
731 default:
732 LOG_ERROR("Sequence %d not supported", seq);
733 return ERROR_FAIL;
734 }
735
736 return ERROR_OK;
737 }
738
739 static void vsllink_swd_read_reg(uint8_t cmd, uint32_t *value, uint32_t ap_delay_clk)
740 {
741 versaloon_interface.adaptors.swd.transact(0, cmd, value, NULL);
742 }
743
744 static void vsllink_swd_write_reg(uint8_t cmd, uint32_t value, uint32_t ap_delay_clk)
745 {
746 versaloon_interface.adaptors.swd.transact(0, cmd, &value, NULL);
747 }
748
749 static int vsllink_swd_run_queue(void)
750 {
751 return versaloon_interface.adaptors.peripheral_commit();
752 }
753
754 /****************************************************************************
755 * VSLLink USB low-level functions */
756
757 static int vsllink_check_usb_strings(
758 struct libusb_device_handle *usb_device_handle,
759 struct libusb_device_descriptor *usb_desc)
760 {
761 char desc_string[256];
762 int retval;
763
764 if (adapter_get_required_serial()) {
765 retval = libusb_get_string_descriptor_ascii(usb_device_handle,
766 usb_desc->iSerialNumber, (unsigned char *)desc_string,
767 sizeof(desc_string));
768 if (retval < 0)
769 return ERROR_FAIL;
770
771 if (strncmp(desc_string, adapter_get_required_serial(),
772 sizeof(desc_string)))
773 return ERROR_FAIL;
774 }
775
776 retval = libusb_get_string_descriptor_ascii(usb_device_handle,
777 usb_desc->iProduct, (unsigned char *)desc_string,
778 sizeof(desc_string));
779 if (retval < 0)
780 return ERROR_FAIL;
781
782 if (!strstr(desc_string, "Versaloon"))
783 return ERROR_FAIL;
784
785 return ERROR_OK;
786 }
787
788 static int vsllink_usb_open(struct vsllink *vsllink)
789 {
790 ssize_t num_devices, i;
791 struct libusb_device **usb_devices;
792 struct libusb_device_descriptor usb_desc;
793 struct libusb_device_handle *usb_device_handle;
794 int retval;
795
796 num_devices = libusb_get_device_list(vsllink->libusb_ctx, &usb_devices);
797
798 if (num_devices <= 0)
799 return ERROR_FAIL;
800
801 for (i = 0; i < num_devices; i++) {
802 struct libusb_device *device = usb_devices[i];
803
804 retval = libusb_get_device_descriptor(device, &usb_desc);
805 if (retval != 0)
806 continue;
807
808 if (usb_desc.idVendor != versaloon_interface.usb_setting.vid ||
809 usb_desc.idProduct != versaloon_interface.usb_setting.pid)
810 continue;
811
812 retval = libusb_open(device, &usb_device_handle);
813 if (retval != 0)
814 continue;
815
816 retval = vsllink_check_usb_strings(usb_device_handle, &usb_desc);
817 if (retval == ERROR_OK)
818 break;
819
820 libusb_close(usb_device_handle);
821 }
822
823 libusb_free_device_list(usb_devices, 1);
824
825 if (i == num_devices)
826 return ERROR_FAIL;
827
828 retval = libusb_claim_interface(usb_device_handle,
829 versaloon_interface.usb_setting.interface);
830 if (retval != 0) {
831 LOG_ERROR("unable to claim interface");
832 libusb_close(usb_device_handle);
833 return ERROR_FAIL;
834 }
835
836 vsllink->usb_device_handle = usb_device_handle;
837 return ERROR_OK;
838 }
839
840 static void vsllink_usb_close(struct vsllink *vsllink)
841 {
842 libusb_release_interface(vsllink->usb_device_handle,
843 versaloon_interface.usb_setting.interface);
844 libusb_close(vsllink->usb_device_handle);
845 }
846
847 #define BYTES_PER_LINE 16
848
849 static void vsllink_debug_buffer(uint8_t *buffer, int length)
850 {
851 char line[81];
852 char s[4];
853 int i;
854 int j;
855
856 for (i = 0; i < length; i += BYTES_PER_LINE) {
857 snprintf(line, 5, "%04x", i & 0xffff);
858 for (j = i; j < i + BYTES_PER_LINE && j < length; j++) {
859 snprintf(s, 4, " %02x", buffer[j]);
860 strcat(line, s);
861 }
862 LOG_DEBUG_IO("%s", line);
863 }
864 }
865
866 static const struct command_registration vsllink_subcommand_handlers[] = {
867 {
868 .name = "usb_vid",
869 .handler = &vsllink_handle_usb_vid_command,
870 .mode = COMMAND_CONFIG,
871 .help = "Set USB VID",
872 .usage = "<vid>",
873 },
874 {
875 .name = "usb_pid",
876 .handler = &vsllink_handle_usb_pid_command,
877 .mode = COMMAND_CONFIG,
878 .help = "Set USB PID",
879 .usage = "<pid>",
880 },
881 {
882 .name = "usb_bulkin",
883 .handler = &vsllink_handle_usb_bulkin_command,
884 .mode = COMMAND_CONFIG,
885 .help = "Set USB input endpoint",
886 .usage = "<ep_in>",
887 },
888 {
889 .name = "usb_bulkout",
890 .handler = &vsllink_handle_usb_bulkout_command,
891 .mode = COMMAND_CONFIG,
892 .help = "Set USB output endpoint",
893 .usage = "<ep_out>",
894 },
895 {
896 .name = "usb_interface",
897 .handler = &vsllink_handle_usb_interface_command,
898 .mode = COMMAND_CONFIG,
899 .help = "Set USB output interface",
900 .usage = "<interface>",
901 },
902 COMMAND_REGISTRATION_DONE
903 };
904
905 static const struct command_registration vsllink_command_handlers[] = {
906 {
907 .name = "vsllink",
908 .mode = COMMAND_ANY,
909 .help = "perform vsllink management",
910 .chain = vsllink_subcommand_handlers,
911 .usage = "",
912 },
913 COMMAND_REGISTRATION_DONE
914 };
915
916 static const char * const vsllink_transports[] = {"jtag", "swd", NULL};
917
918 static const struct swd_driver vsllink_swd_driver = {
919 .init = vsllink_swd_init,
920 .switch_seq = vsllink_swd_switch_seq,
921 .read_reg = vsllink_swd_read_reg,
922 .write_reg = vsllink_swd_write_reg,
923 .run = vsllink_swd_run_queue,
924 };
925
926 static struct jtag_interface vsllink_interface = {
927 .supported = DEBUG_CAP_TMS_SEQ,
928 .execute_queue = vsllink_execute_queue,
929 };
930
931 struct adapter_driver vsllink_adapter_driver = {
932 .name = "vsllink",
933 .transports = vsllink_transports,
934 .commands = vsllink_command_handlers,
935
936 .init = vsllink_init,
937 .quit = vsllink_quit,
938 .reset = vsllink_reset,
939 .speed = vsllink_speed,
940 .khz = vsllink_khz,
941 .speed_div = vsllink_speed_div,
942
943 .jtag_ops = &vsllink_interface,
944 .swd_ops = &vsllink_swd_driver,
945 };

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)