drivers/ft232r: Group adapter commands
[openocd.git] / src / jtag / drivers / ft232r.c
1 /***************************************************************************
2 * Copyright (C) 2010 Serge Vakulenko *
3 * serge@vak.ru *
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
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22
23 #if IS_CYGWIN == 1
24 #include "windows.h"
25 #undef LOG_ERROR
26 #endif
27
28 /* project specific includes */
29 #include <jtag/interface.h>
30 #include <jtag/commands.h>
31 #include <helper/time_support.h>
32 #include "libusb_helper.h"
33
34 /* system includes */
35 #include <string.h>
36 #include <stdlib.h>
37 #include <unistd.h>
38 #include <sys/time.h>
39 #include <time.h>
40
41 /*
42 * Sync bit bang mode is implemented as described in FTDI Application
43 * Note AN232R-01: "Bit Bang Modes for the FT232R and FT245R".
44 */
45
46 /*
47 * USB endpoints.
48 */
49 #define IN_EP 0x02
50 #define OUT_EP 0x81
51
52 /* Requests */
53 #define SIO_RESET 0 /* Reset the port */
54 #define SIO_MODEM_CTRL 1 /* Set the modem control register */
55 #define SIO_SET_FLOW_CTRL 2 /* Set flow control register */
56 #define SIO_SET_BAUD_RATE 3 /* Set baud rate */
57 #define SIO_SET_DATA 4 /* Set the data characteristics of the port */
58 #define SIO_POLL_MODEM_STATUS 5
59 #define SIO_SET_EVENT_CHAR 6
60 #define SIO_SET_ERROR_CHAR 7
61 #define SIO_SET_LATENCY_TIMER 9
62 #define SIO_GET_LATENCY_TIMER 10
63 #define SIO_SET_BITMODE 11
64 #define SIO_READ_PINS 12
65 #define SIO_READ_EEPROM 0x90
66 #define SIO_WRITE_EEPROM 0x91
67 #define SIO_ERASE_EEPROM 0x92
68
69 #define FT232R_BUF_SIZE_EXTRA 4096
70
71 static char *ft232r_serial_desc;
72 static uint16_t ft232r_vid = 0x0403; /* FTDI */
73 static uint16_t ft232r_pid = 0x6001; /* FT232R */
74 static struct libusb_device_handle *adapter;
75
76 static uint8_t *ft232r_output;
77 static size_t ft232r_output_len;
78
79 /**
80 * FT232R GPIO bit number to RS232 name
81 */
82 #define FT232R_BIT_COUNT 8
83 static char *ft232r_bit_name_array[FT232R_BIT_COUNT] = {
84 "TXD", /* 0: pin 1 TCK output */
85 "RXD", /* 1: pin 5 TDI output */
86 "RTS", /* 2: pin 3 TDO input */
87 "CTS", /* 3: pin 11 TMS output */
88 "DTR", /* 4: pin 2 /TRST output */
89 "DSR", /* 5: pin 9 unused */
90 "DCD", /* 6: pin 10 /SYSRST output */
91 "RI" /* 7: pin 6 unused */
92 };
93
94 static int tck_gpio; /* initialized to 0 by default */
95 static int tdi_gpio = 1;
96 static int tdo_gpio = 2;
97 static int tms_gpio = 3;
98 static int ntrst_gpio = 4;
99 static int nsysrst_gpio = 6;
100 static size_t ft232r_buf_size = FT232R_BUF_SIZE_EXTRA;
101 /** 0xFFFF disables restore by default, after exit serial port will not work.
102 * 0x15 sets TXD RTS DTR as outputs, after exit serial port will continue to work.
103 */
104 static uint16_t ft232r_restore_bitmode = 0xFFFF;
105
106 /**
107 * Perform sync bitbang output/input transaction.
108 * Before call, an array ft232r_output[] should be filled with data to send.
109 * Counter ft232r_output_len contains the number of bytes to send.
110 * On return, received data is put back to array ft232r_output[].
111 */
112 static int ft232r_send_recv(void)
113 {
114 /* FIFO TX buffer has 128 bytes.
115 * FIFO RX buffer has 256 bytes.
116 * First two bytes of received packet contain contain modem
117 * and line status and are ignored.
118 * Unfortunately, transfer sizes bigger than 64 bytes
119 * frequently cause hang ups. */
120 assert(ft232r_output_len > 0);
121
122 size_t total_written = 0;
123 size_t total_read = 0;
124 int rxfifo_free = 128;
125
126 while (total_read < ft232r_output_len) {
127 /* Write */
128 int bytes_to_write = ft232r_output_len - total_written;
129 if (bytes_to_write > 64)
130 bytes_to_write = 64;
131 if (bytes_to_write > rxfifo_free)
132 bytes_to_write = rxfifo_free;
133
134 if (bytes_to_write) {
135 int n;
136
137 if (jtag_libusb_bulk_write(adapter, IN_EP,
138 (char *) ft232r_output + total_written,
139 bytes_to_write, 1000, &n) != ERROR_OK) {
140 LOG_ERROR("usb bulk write failed");
141 return ERROR_JTAG_DEVICE_ERROR;
142 }
143
144 total_written += n;
145 rxfifo_free -= n;
146 }
147
148 /* Read */
149 uint8_t reply[64];
150 int n;
151
152 if (jtag_libusb_bulk_read(adapter, OUT_EP, (char *) reply,
153 sizeof(reply), 1000, &n) != ERROR_OK) {
154 LOG_ERROR("usb bulk read failed");
155 return ERROR_JTAG_DEVICE_ERROR;
156 }
157 if (n > 2) {
158 /* Copy data, ignoring first 2 bytes. */
159 memcpy(ft232r_output + total_read, reply + 2, n - 2);
160 int bytes_read = n - 2;
161 total_read += bytes_read;
162 rxfifo_free += bytes_read;
163 if (total_read > total_written) {
164 LOG_ERROR("read more bytes than wrote");
165 return ERROR_JTAG_DEVICE_ERROR;
166 }
167 }
168 }
169 ft232r_output_len = 0;
170 return ERROR_OK;
171 }
172
173 static void ft232r_increase_buf_size(size_t new_buf_size)
174 {
175 uint8_t *new_buf_ptr;
176 if (new_buf_size >= ft232r_buf_size) {
177 new_buf_size += FT232R_BUF_SIZE_EXTRA;
178 new_buf_ptr = realloc(ft232r_output, new_buf_size);
179 if (new_buf_ptr) {
180 ft232r_output = new_buf_ptr;
181 ft232r_buf_size = new_buf_size;
182 }
183 }
184 }
185
186 /**
187 * Add one TCK/TMS/TDI sample to send buffer.
188 */
189 static void ft232r_write(int tck, int tms, int tdi)
190 {
191 unsigned out_value = (1<<ntrst_gpio) | (1<<nsysrst_gpio);
192 if (tck)
193 out_value |= (1<<tck_gpio);
194 if (tms)
195 out_value |= (1<<tms_gpio);
196 if (tdi)
197 out_value |= (1<<tdi_gpio);
198
199 ft232r_increase_buf_size(ft232r_output_len);
200
201 if (ft232r_output_len >= ft232r_buf_size) {
202 /* FIXME: should we just execute queue here? */
203 LOG_ERROR("ft232r_write: buffer overflow");
204 return;
205 }
206 ft232r_output[ft232r_output_len++] = out_value;
207 }
208
209 /**
210 * Control /TRST and /SYSRST pins.
211 * Perform immediate bitbang transaction.
212 */
213 static void ft232r_reset(int trst, int srst)
214 {
215 unsigned out_value = (1<<ntrst_gpio) | (1<<nsysrst_gpio);
216 LOG_DEBUG("ft232r_reset(%d,%d)", trst, srst);
217
218 if (trst == 1)
219 out_value &= ~(1<<ntrst_gpio); /* switch /TRST low */
220 else if (trst == 0)
221 out_value |= (1<<ntrst_gpio); /* switch /TRST high */
222
223 if (srst == 1)
224 out_value &= ~(1<<nsysrst_gpio); /* switch /SYSRST low */
225 else if (srst == 0)
226 out_value |= (1<<nsysrst_gpio); /* switch /SYSRST high */
227
228 ft232r_increase_buf_size(ft232r_output_len);
229
230 if (ft232r_output_len >= ft232r_buf_size) {
231 /* FIXME: should we just execute queue here? */
232 LOG_ERROR("ft232r_write: buffer overflow");
233 return;
234 }
235
236 ft232r_output[ft232r_output_len++] = out_value;
237 ft232r_send_recv();
238 }
239
240 static int ft232r_speed(int divisor)
241 {
242 int baud = (divisor == 0) ? 3000000 :
243 (divisor == 1) ? 2000000 :
244 3000000 / divisor;
245 LOG_DEBUG("ft232r_speed(%d) rate %d bits/sec", divisor, baud);
246
247 if (jtag_libusb_control_transfer(adapter,
248 LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT,
249 SIO_SET_BAUD_RATE, divisor, 0, 0, 0, 1000) != 0) {
250 LOG_ERROR("cannot set baud rate");
251 return ERROR_JTAG_DEVICE_ERROR;
252 }
253 return ERROR_OK;
254 }
255
256 static int ft232r_init(void)
257 {
258 uint16_t avids[] = {ft232r_vid, 0};
259 uint16_t apids[] = {ft232r_pid, 0};
260 if (jtag_libusb_open(avids, apids, ft232r_serial_desc, &adapter, NULL)) {
261 LOG_ERROR("ft232r not found: vid=%04x, pid=%04x, serial=%s\n",
262 ft232r_vid, ft232r_pid, (!ft232r_serial_desc) ? "[any]" : ft232r_serial_desc);
263 return ERROR_JTAG_INIT_FAILED;
264 }
265
266 if (ft232r_restore_bitmode == 0xFFFF) /* serial port will not be restored after jtag: */
267 libusb_detach_kernel_driver(adapter, 0);
268 else /* serial port will be restored after jtag: */
269 libusb_set_auto_detach_kernel_driver(adapter, 1); /* 1: DONT_DETACH_SIO_MODULE */
270
271 if (libusb_claim_interface(adapter, 0)) {
272 LOG_ERROR("unable to claim interface");
273 return ERROR_JTAG_INIT_FAILED;
274 }
275
276 /* Reset the device. */
277 if (jtag_libusb_control_transfer(adapter,
278 LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT,
279 SIO_RESET, 0, 0, 0, 0, 1000) != 0) {
280 LOG_ERROR("unable to reset device");
281 return ERROR_JTAG_INIT_FAILED;
282 }
283
284 /* Sync bit bang mode. */
285 if (jtag_libusb_control_transfer(adapter,
286 LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT,
287 SIO_SET_BITMODE, (1<<tck_gpio) | (1<<tdi_gpio) | (1<<tms_gpio) | (1<<ntrst_gpio) | (1<<nsysrst_gpio) | 0x400,
288 0, 0, 0, 1000) != 0) {
289 LOG_ERROR("cannot set sync bitbang mode");
290 return ERROR_JTAG_INIT_FAILED;
291 }
292
293 /* Exactly 500 nsec between updates. */
294 unsigned divisor = 1;
295 unsigned char latency_timer = 1;
296
297 /* Frequency divisor is 14-bit non-zero value. */
298 if (jtag_libusb_control_transfer(adapter,
299 LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT,
300 SIO_SET_BAUD_RATE, divisor,
301 0, 0, 0, 1000) != 0) {
302 LOG_ERROR("cannot set baud rate");
303 return ERROR_JTAG_INIT_FAILED;
304 }
305 if (jtag_libusb_control_transfer(adapter,
306 LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT,
307 SIO_SET_LATENCY_TIMER, latency_timer, 0, 0, 0, 1000) != 0) {
308 LOG_ERROR("unable to set latency timer");
309 return ERROR_JTAG_INIT_FAILED;
310 }
311
312 ft232r_output = malloc(ft232r_buf_size);
313 if (!ft232r_output) {
314 LOG_ERROR("Unable to allocate memory for the buffer");
315 return ERROR_JTAG_INIT_FAILED;
316 }
317
318 return ERROR_OK;
319 }
320
321 static int ft232r_quit(void)
322 {
323 /* to restore serial port: set TXD RTS DTR as outputs, others as inputs, disable sync bit bang mode. */
324 if (ft232r_restore_bitmode != 0xFFFF) {
325 if (jtag_libusb_control_transfer(adapter,
326 LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT,
327 SIO_SET_BITMODE, ft232r_restore_bitmode,
328 0, 0, 0, 1000) != 0) {
329 LOG_ERROR("cannot set bitmode to restore serial port");
330 }
331 }
332
333 if (libusb_release_interface(adapter, 0) != 0)
334 LOG_ERROR("usb release interface failed");
335
336 jtag_libusb_close(adapter);
337
338 free(ft232r_output); /* free used memory */
339 ft232r_output = NULL; /* reset pointer to memory */
340 ft232r_buf_size = FT232R_BUF_SIZE_EXTRA; /* reset next initial buffer size */
341
342 return ERROR_OK;
343 }
344
345 static int ft232r_speed_div(int divisor, int *khz)
346 {
347 /* Maximum 3 Mbaud for bit bang mode. */
348 if (divisor == 0)
349 *khz = 3000;
350 else if (divisor == 1)
351 *khz = 2000;
352 else
353 *khz = 3000 / divisor;
354 return ERROR_OK;
355 }
356
357 static int ft232r_khz(int khz, int *divisor)
358 {
359 if (khz == 0) {
360 LOG_DEBUG("RCLK not supported");
361 return ERROR_FAIL;
362 }
363
364 /* Calculate frequency divisor. */
365 if (khz > 2500)
366 *divisor = 0; /* Special case: 3 MHz */
367 else if (khz > 1700)
368 *divisor = 1; /* Special case: 2 MHz */
369 else {
370 *divisor = (2*3000 / khz + 1) / 2;
371 if (*divisor > 0x3FFF)
372 *divisor = 0x3FFF;
373 }
374 return ERROR_OK;
375 }
376
377 static char *ft232r_bit_number_to_name(int bit)
378 {
379 if (bit >= 0 && bit < FT232R_BIT_COUNT)
380 return ft232r_bit_name_array[bit];
381 return "?";
382 }
383
384 static int ft232r_bit_name_to_number(const char *name)
385 {
386 int i;
387 if (name[0] >= '0' && name[0] <= '9' && name[1] == '\0') {
388 i = atoi(name);
389 if (i >= 0 && i < FT232R_BIT_COUNT)
390 return i;
391 }
392 for (i = 0; i < FT232R_BIT_COUNT; i++)
393 if (strcasecmp(name, ft232r_bit_name_array[i]) == 0)
394 return i;
395 return -1;
396 }
397
398 COMMAND_HANDLER(ft232r_handle_serial_desc_command)
399 {
400 if (CMD_ARGC == 1)
401 ft232r_serial_desc = strdup(CMD_ARGV[0]);
402 else
403 LOG_ERROR("require exactly one argument to "
404 "ft232r_serial_desc <serial>");
405 return ERROR_OK;
406 }
407
408 COMMAND_HANDLER(ft232r_handle_vid_pid_command)
409 {
410 if (CMD_ARGC > 2) {
411 LOG_WARNING("ignoring extra IDs in ft232r_vid_pid "
412 "(maximum is 1 pair)");
413 CMD_ARGC = 2;
414 }
415 if (CMD_ARGC == 2) {
416 COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], ft232r_vid);
417 COMMAND_PARSE_NUMBER(u16, CMD_ARGV[1], ft232r_pid);
418 } else
419 LOG_WARNING("incomplete ft232r_vid_pid configuration");
420
421 return ERROR_OK;
422 }
423
424 COMMAND_HANDLER(ft232r_handle_jtag_nums_command)
425 {
426 if (CMD_ARGC == 4) {
427 tck_gpio = ft232r_bit_name_to_number(CMD_ARGV[0]);
428 tms_gpio = ft232r_bit_name_to_number(CMD_ARGV[1]);
429 tdi_gpio = ft232r_bit_name_to_number(CMD_ARGV[2]);
430 tdo_gpio = ft232r_bit_name_to_number(CMD_ARGV[3]);
431 } else if (CMD_ARGC != 0)
432 return ERROR_COMMAND_SYNTAX_ERROR;
433
434 if (tck_gpio < 0)
435 return ERROR_COMMAND_SYNTAX_ERROR;
436 if (tms_gpio < 0)
437 return ERROR_COMMAND_SYNTAX_ERROR;
438 if (tdi_gpio < 0)
439 return ERROR_COMMAND_SYNTAX_ERROR;
440 if (tdo_gpio < 0)
441 return ERROR_COMMAND_SYNTAX_ERROR;
442
443 command_print(CMD,
444 "FT232R nums: TCK = %d %s, TMS = %d %s, TDI = %d %s, TDO = %d %s",
445 tck_gpio, ft232r_bit_number_to_name(tck_gpio),
446 tms_gpio, ft232r_bit_number_to_name(tms_gpio),
447 tdi_gpio, ft232r_bit_number_to_name(tdi_gpio),
448 tdo_gpio, ft232r_bit_number_to_name(tdo_gpio));
449
450 return ERROR_OK;
451 }
452
453 COMMAND_HANDLER(ft232r_handle_tck_num_command)
454 {
455 if (CMD_ARGC == 1)
456 tck_gpio = ft232r_bit_name_to_number(CMD_ARGV[0]);
457 else if (CMD_ARGC != 0)
458 return ERROR_COMMAND_SYNTAX_ERROR;
459
460 if (tck_gpio < 0)
461 return ERROR_COMMAND_SYNTAX_ERROR;
462
463 command_print(CMD,
464 "FT232R num: TCK = %d %s", tck_gpio, ft232r_bit_number_to_name(tck_gpio));
465
466 return ERROR_OK;
467 }
468
469 COMMAND_HANDLER(ft232r_handle_tms_num_command)
470 {
471 if (CMD_ARGC == 1)
472 tms_gpio = ft232r_bit_name_to_number(CMD_ARGV[0]);
473 else if (CMD_ARGC != 0)
474 return ERROR_COMMAND_SYNTAX_ERROR;
475
476 if (tms_gpio < 0)
477 return ERROR_COMMAND_SYNTAX_ERROR;
478
479 command_print(CMD,
480 "FT232R num: TMS = %d %s", tms_gpio, ft232r_bit_number_to_name(tms_gpio));
481
482 return ERROR_OK;
483 }
484
485 COMMAND_HANDLER(ft232r_handle_tdo_num_command)
486 {
487 if (CMD_ARGC == 1)
488 tdo_gpio = ft232r_bit_name_to_number(CMD_ARGV[0]);
489 else if (CMD_ARGC != 0)
490 return ERROR_COMMAND_SYNTAX_ERROR;
491
492 if (tdo_gpio < 0)
493 return ERROR_COMMAND_SYNTAX_ERROR;
494
495 command_print(CMD,
496 "FT232R num: TDO = %d %s", tdo_gpio, ft232r_bit_number_to_name(tdo_gpio));
497
498 return ERROR_OK;
499 }
500
501 COMMAND_HANDLER(ft232r_handle_tdi_num_command)
502 {
503 if (CMD_ARGC == 1)
504 tdi_gpio = ft232r_bit_name_to_number(CMD_ARGV[0]);
505 else if (CMD_ARGC != 0)
506 return ERROR_COMMAND_SYNTAX_ERROR;
507
508 if (tdi_gpio < 0)
509 return ERROR_COMMAND_SYNTAX_ERROR;
510
511 command_print(CMD,
512 "FT232R num: TDI = %d %s", tdi_gpio, ft232r_bit_number_to_name(tdi_gpio));
513
514 return ERROR_OK;
515 }
516
517 COMMAND_HANDLER(ft232r_handle_trst_num_command)
518 {
519 if (CMD_ARGC == 1)
520 ntrst_gpio = ft232r_bit_name_to_number(CMD_ARGV[0]);
521 else if (CMD_ARGC != 0)
522 return ERROR_COMMAND_SYNTAX_ERROR;
523
524 if (ntrst_gpio < 0)
525 return ERROR_COMMAND_SYNTAX_ERROR;
526
527 command_print(CMD,
528 "FT232R num: TRST = %d %s", ntrst_gpio, ft232r_bit_number_to_name(ntrst_gpio));
529
530 return ERROR_OK;
531 }
532
533 COMMAND_HANDLER(ft232r_handle_srst_num_command)
534 {
535 if (CMD_ARGC == 1)
536 nsysrst_gpio = ft232r_bit_name_to_number(CMD_ARGV[0]);
537 else if (CMD_ARGC != 0)
538 return ERROR_COMMAND_SYNTAX_ERROR;
539
540 if (nsysrst_gpio < 0)
541 return ERROR_COMMAND_SYNTAX_ERROR;
542
543 command_print(CMD,
544 "FT232R num: SRST = %d %s", nsysrst_gpio, ft232r_bit_number_to_name(nsysrst_gpio));
545
546 return ERROR_OK;
547 }
548
549 COMMAND_HANDLER(ft232r_handle_restore_serial_command)
550 {
551 if (CMD_ARGC == 1)
552 COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], ft232r_restore_bitmode);
553 else if (CMD_ARGC != 0)
554 return ERROR_COMMAND_SYNTAX_ERROR;
555
556 command_print(CMD,
557 "FT232R restore serial: 0x%04X (%s)",
558 ft232r_restore_bitmode, ft232r_restore_bitmode == 0xFFFF ? "disabled" : "enabled");
559
560 return ERROR_OK;
561 }
562
563 static const struct command_registration ft232r_subcommand_handlers[] = {
564 {
565 .name = "serial_desc",
566 .handler = ft232r_handle_serial_desc_command,
567 .mode = COMMAND_CONFIG,
568 .help = "USB serial descriptor of the adapter",
569 .usage = "serial string",
570 },
571 {
572 .name = "vid_pid",
573 .handler = ft232r_handle_vid_pid_command,
574 .mode = COMMAND_CONFIG,
575 .help = "USB VID and PID of the adapter",
576 .usage = "vid pid",
577 },
578 {
579 .name = "jtag_nums",
580 .handler = ft232r_handle_jtag_nums_command,
581 .mode = COMMAND_CONFIG,
582 .help = "gpio numbers for tck, tms, tdi, tdo. (in that order)",
583 .usage = "<0-7|TXD-RI> <0-7|TXD-RI> <0-7|TXD-RI> <0-7|TXD-RI>",
584 },
585 {
586 .name = "tck_num",
587 .handler = ft232r_handle_tck_num_command,
588 .mode = COMMAND_CONFIG,
589 .help = "gpio number for tck.",
590 .usage = "<0-7|TXD|RXD|RTS|CTS|DTR|DSR|DCD|RI>",
591 },
592 {
593 .name = "tms_num",
594 .handler = ft232r_handle_tms_num_command,
595 .mode = COMMAND_CONFIG,
596 .help = "gpio number for tms.",
597 .usage = "<0-7|TXD|RXD|RTS|CTS|DTR|DSR|DCD|RI>",
598 },
599 {
600 .name = "tdo_num",
601 .handler = ft232r_handle_tdo_num_command,
602 .mode = COMMAND_CONFIG,
603 .help = "gpio number for tdo.",
604 .usage = "<0-7|TXD|RXD|RTS|CTS|DTR|DSR|DCD|RI>",
605 },
606 {
607 .name = "tdi_num",
608 .handler = ft232r_handle_tdi_num_command,
609 .mode = COMMAND_CONFIG,
610 .help = "gpio number for tdi.",
611 .usage = "<0-7|TXD|RXD|RTS|CTS|DTR|DSR|DCD|RI>",
612 },
613 {
614 .name = "srst_num",
615 .handler = ft232r_handle_srst_num_command,
616 .mode = COMMAND_CONFIG,
617 .help = "gpio number for srst.",
618 .usage = "<0-7|TXD|RXD|RTS|CTS|DTR|DSR|DCD|RI>",
619 },
620 {
621 .name = "trst_num",
622 .handler = ft232r_handle_trst_num_command,
623 .mode = COMMAND_CONFIG,
624 .help = "gpio number for trst.",
625 .usage = "<0-7|TXD|RXD|RTS|CTS|DTR|DSR|DCD|RI>",
626 },
627 {
628 .name = "restore_serial",
629 .handler = ft232r_handle_restore_serial_command,
630 .mode = COMMAND_CONFIG,
631 .help = "bitmode control word that restores serial port.",
632 .usage = "bitmode_control_word",
633 },
634 COMMAND_REGISTRATION_DONE
635 };
636
637 static const struct command_registration ft232r_command_handlers[] = {
638 {
639 .name = "ft232r",
640 .mode = COMMAND_ANY,
641 .help = "perform ft232r management",
642 .chain = ft232r_subcommand_handlers,
643 .usage = "",
644 },
645 COMMAND_REGISTRATION_DONE
646 };
647
648 /*
649 * Synchronous bitbang protocol implementation.
650 */
651
652 static void syncbb_end_state(tap_state_t state)
653 {
654 if (tap_is_state_stable(state))
655 tap_set_end_state(state);
656 else {
657 LOG_ERROR("BUG: %i is not a valid end state", state);
658 exit(-1);
659 }
660 }
661
662 static void syncbb_state_move(int skip)
663 {
664 int i = 0, tms = 0;
665 uint8_t tms_scan = tap_get_tms_path(tap_get_state(), tap_get_end_state());
666 int tms_count = tap_get_tms_path_len(tap_get_state(), tap_get_end_state());
667
668 for (i = skip; i < tms_count; i++) {
669 tms = (tms_scan >> i) & 1;
670 ft232r_write(0, tms, 0);
671 ft232r_write(1, tms, 0);
672 }
673 ft232r_write(0, tms, 0);
674
675 tap_set_state(tap_get_end_state());
676 }
677
678 /**
679 * Clock a bunch of TMS (or SWDIO) transitions, to change the JTAG
680 * (or SWD) state machine.
681 */
682 static int syncbb_execute_tms(struct jtag_command *cmd)
683 {
684 unsigned num_bits = cmd->cmd.tms->num_bits;
685 const uint8_t *bits = cmd->cmd.tms->bits;
686
687 LOG_DEBUG_IO("TMS: %d bits", num_bits);
688
689 int tms = 0;
690 for (unsigned i = 0; i < num_bits; i++) {
691 tms = ((bits[i/8] >> (i % 8)) & 1);
692 ft232r_write(0, tms, 0);
693 ft232r_write(1, tms, 0);
694 }
695 ft232r_write(0, tms, 0);
696
697 return ERROR_OK;
698 }
699
700 static void syncbb_path_move(struct pathmove_command *cmd)
701 {
702 int num_states = cmd->num_states;
703 int state_count;
704 int tms = 0;
705
706 state_count = 0;
707 while (num_states) {
708 if (tap_state_transition(tap_get_state(), false) == cmd->path[state_count]) {
709 tms = 0;
710 } else if (tap_state_transition(tap_get_state(), true) == cmd->path[state_count]) {
711 tms = 1;
712 } else {
713 LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition",
714 tap_state_name(tap_get_state()),
715 tap_state_name(cmd->path[state_count]));
716 exit(-1);
717 }
718
719 ft232r_write(0, tms, 0);
720 ft232r_write(1, tms, 0);
721
722 tap_set_state(cmd->path[state_count]);
723 state_count++;
724 num_states--;
725 }
726
727 ft232r_write(0, tms, 0);
728
729 tap_set_end_state(tap_get_state());
730 }
731
732 static void syncbb_runtest(int num_cycles)
733 {
734 int i;
735
736 tap_state_t saved_end_state = tap_get_end_state();
737
738 /* only do a state_move when we're not already in IDLE */
739 if (tap_get_state() != TAP_IDLE) {
740 syncbb_end_state(TAP_IDLE);
741 syncbb_state_move(0);
742 }
743
744 /* execute num_cycles */
745 for (i = 0; i < num_cycles; i++) {
746 ft232r_write(0, 0, 0);
747 ft232r_write(1, 0, 0);
748 }
749 ft232r_write(0, 0, 0);
750
751 /* finish in end_state */
752 syncbb_end_state(saved_end_state);
753 if (tap_get_state() != tap_get_end_state())
754 syncbb_state_move(0);
755 }
756
757 /**
758 * Function syncbb_stableclocks
759 * issues a number of clock cycles while staying in a stable state.
760 * Because the TMS value required to stay in the RESET state is a 1, whereas
761 * the TMS value required to stay in any of the other stable states is a 0,
762 * this function checks the current stable state to decide on the value of TMS
763 * to use.
764 */
765 static void syncbb_stableclocks(int num_cycles)
766 {
767 int tms = (tap_get_state() == TAP_RESET ? 1 : 0);
768 int i;
769
770 /* send num_cycles clocks onto the cable */
771 for (i = 0; i < num_cycles; i++) {
772 ft232r_write(1, tms, 0);
773 ft232r_write(0, tms, 0);
774 }
775 }
776
777 static void syncbb_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size)
778 {
779 tap_state_t saved_end_state = tap_get_end_state();
780 int bit_cnt, bit0_index;
781
782 if (!((!ir_scan && (tap_get_state() == TAP_DRSHIFT)) || (ir_scan && (tap_get_state() == TAP_IRSHIFT)))) {
783 if (ir_scan)
784 syncbb_end_state(TAP_IRSHIFT);
785 else
786 syncbb_end_state(TAP_DRSHIFT);
787
788 syncbb_state_move(0);
789 syncbb_end_state(saved_end_state);
790 }
791
792 bit0_index = ft232r_output_len;
793 for (bit_cnt = 0; bit_cnt < scan_size; bit_cnt++) {
794 int tms = (bit_cnt == scan_size-1) ? 1 : 0;
795 int tdi;
796 int bytec = bit_cnt/8;
797 int bcval = 1 << (bit_cnt % 8);
798
799 /* if we're just reading the scan, but don't care about the output
800 * default to outputting 'low', this also makes valgrind traces more readable,
801 * as it removes the dependency on an uninitialised value
802 */
803 tdi = 0;
804 if ((type != SCAN_IN) && (buffer[bytec] & bcval))
805 tdi = 1;
806
807 ft232r_write(0, tms, tdi);
808 ft232r_write(1, tms, tdi);
809 }
810
811 if (tap_get_state() != tap_get_end_state()) {
812 /* we *KNOW* the above loop transitioned out of
813 * the shift state, so we skip the first state
814 * and move directly to the end state.
815 */
816 syncbb_state_move(1);
817 }
818 ft232r_send_recv();
819
820 if (type != SCAN_OUT)
821 for (bit_cnt = 0; bit_cnt < scan_size; bit_cnt++) {
822 int bytec = bit_cnt/8;
823 int bcval = 1 << (bit_cnt % 8);
824 int val = ft232r_output[bit0_index + bit_cnt*2 + 1];
825
826 if (val & (1<<tdo_gpio))
827 buffer[bytec] |= bcval;
828 else
829 buffer[bytec] &= ~bcval;
830 }
831 }
832
833 static int syncbb_execute_queue(void)
834 {
835 struct jtag_command *cmd = jtag_command_queue; /* currently processed command */
836 int scan_size;
837 enum scan_type type;
838 uint8_t *buffer;
839 int retval;
840
841 /* return ERROR_OK, unless a jtag_read_buffer returns a failed check
842 * that wasn't handled by a caller-provided error handler
843 */
844 retval = ERROR_OK;
845
846 /* ft232r_blink(1);*/
847
848 while (cmd) {
849 switch (cmd->type) {
850 case JTAG_RESET:
851 LOG_DEBUG_IO("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);
852
853 if ((cmd->cmd.reset->trst == 1) ||
854 (cmd->cmd.reset->srst &&
855 (jtag_get_reset_config() & RESET_SRST_PULLS_TRST))) {
856 tap_set_state(TAP_RESET);
857 }
858 ft232r_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
859 break;
860
861 case JTAG_RUNTEST:
862 LOG_DEBUG_IO("runtest %i cycles, end in %s", cmd->cmd.runtest->num_cycles,
863 tap_state_name(cmd->cmd.runtest->end_state));
864
865 syncbb_end_state(cmd->cmd.runtest->end_state);
866 syncbb_runtest(cmd->cmd.runtest->num_cycles);
867 break;
868
869 case JTAG_STABLECLOCKS:
870 /* this is only allowed while in a stable state. A check for a stable
871 * state was done in jtag_add_clocks()
872 */
873 syncbb_stableclocks(cmd->cmd.stableclocks->num_cycles);
874 break;
875
876 case JTAG_TLR_RESET: /* renamed from JTAG_STATEMOVE */
877 LOG_DEBUG_IO("statemove end in %s", tap_state_name(cmd->cmd.statemove->end_state));
878
879 syncbb_end_state(cmd->cmd.statemove->end_state);
880 syncbb_state_move(0);
881 break;
882
883 case JTAG_PATHMOVE:
884 LOG_DEBUG_IO("pathmove: %i states, end in %s", cmd->cmd.pathmove->num_states,
885 tap_state_name(cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]));
886
887 syncbb_path_move(cmd->cmd.pathmove);
888 break;
889
890 case JTAG_SCAN:
891 LOG_DEBUG_IO("%s scan end in %s", (cmd->cmd.scan->ir_scan) ? "IR" : "DR",
892 tap_state_name(cmd->cmd.scan->end_state));
893
894 syncbb_end_state(cmd->cmd.scan->end_state);
895 scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
896 type = jtag_scan_type(cmd->cmd.scan);
897 syncbb_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size);
898 if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK)
899 retval = ERROR_JTAG_QUEUE_FAILED;
900 free(buffer);
901 break;
902
903 case JTAG_SLEEP:
904 LOG_DEBUG_IO("sleep %" PRIu32, cmd->cmd.sleep->us);
905
906 jtag_sleep(cmd->cmd.sleep->us);
907 break;
908
909 case JTAG_TMS:
910 retval = syncbb_execute_tms(cmd);
911 break;
912 default:
913 LOG_ERROR("BUG: unknown JTAG command type encountered");
914 exit(-1);
915 }
916 if (ft232r_output_len > 0)
917 ft232r_send_recv();
918 cmd = cmd->next;
919 }
920 /* ft232r_blink(0);*/
921
922 return retval;
923 }
924
925 static struct jtag_interface ft232r_interface = {
926 .supported = DEBUG_CAP_TMS_SEQ,
927 .execute_queue = syncbb_execute_queue,
928 };
929
930 struct adapter_driver ft232r_adapter_driver = {
931 .name = "ft232r",
932 .transports = jtag_only,
933 .commands = ft232r_command_handlers,
934
935 .init = ft232r_init,
936 .quit = ft232r_quit,
937 .speed = ft232r_speed,
938 .khz = ft232r_khz,
939 .speed_div = ft232r_speed_div,
940
941 .jtag_ops = &ft232r_interface,
942 };

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)