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

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)