Remove support for the GPL incompatible FTDI D2XX library
[openocd.git] / src / jtag / drivers / presto.c
1 /***************************************************************************
2 * Copyright (C) 2007 by Pavel Chromy *
3 * chromy@asix.cz *
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 /**
20 * @file
21 * Holds driver for PRESTO programmer from ASIX.
22 * http://tools.asix.net/prg_presto.htm
23 */
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 #if IS_CYGWIN == 1
29 #include "windows.h"
30 #endif
31
32 #include <jtag/interface.h>
33 #include <helper/time_support.h>
34 #include "bitq.h"
35
36 /* PRESTO access library includes */
37 #include <ftdi.h>
38
39 /* -------------------------------------------------------------------------- */
40
41 #define FT_DEVICE_NAME_LEN 64
42 #define FT_DEVICE_SERNUM_LEN 64
43
44 #define PRESTO_VID_PID 0x0403f1a0
45 #define PRESTO_VID (0x0403)
46 #define PRESTO_PID (0xf1a0)
47
48 #define BUFFER_SIZE (64*62)
49
50 struct presto {
51 struct ftdi_context ftdic;
52 int retval;
53
54 char serial[FT_DEVICE_SERNUM_LEN];
55
56 uint8_t buff_out[BUFFER_SIZE];
57 int buff_out_pos;
58
59 uint8_t buff_in[BUFFER_SIZE];
60 int buff_in_exp;/* expected in buffer length */
61 int buff_in_len;/* length of data received */
62 int buff_in_pos;
63
64 unsigned long total_out;
65 unsigned long total_in;
66
67 int jtag_tms; /* last tms state */
68 int jtag_tck; /* last tck state */
69 int jtag_rst; /* last trst state */
70
71 int jtag_tdi_data;
72 int jtag_tdi_count;
73
74 int jtag_speed;
75 };
76
77 static struct presto presto_state;
78 static struct presto *presto = &presto_state;
79
80 static uint8_t presto_init_seq[] = {
81 0x80, 0xA0, 0xA8, 0xB0, 0xC0, 0xE0
82 };
83
84 static int presto_write(uint8_t *buf, uint32_t size)
85 {
86 uint32_t ftbytes;
87 presto->retval = ftdi_write_data(&presto->ftdic, buf, size);
88 if (presto->retval < 0) {
89 LOG_ERROR("ftdi_write_data: %s", ftdi_get_error_string(&presto->ftdic));
90 return ERROR_JTAG_DEVICE_ERROR;
91 }
92 ftbytes = presto->retval;
93
94 if (ftbytes != size) {
95 LOG_ERROR("couldn't write the requested number of bytes to PRESTO (%u < %u)",
96 (unsigned)ftbytes, (unsigned)size);
97 return ERROR_JTAG_DEVICE_ERROR;
98 }
99
100 return ERROR_OK;
101 }
102
103 static int presto_read(uint8_t *buf, uint32_t size)
104 {
105 uint32_t ftbytes = 0;
106
107 struct timeval timeout, now;
108 gettimeofday(&timeout, NULL);
109 timeval_add_time(&timeout, 1, 0); /* one second timeout */
110
111 while (ftbytes < size) {
112 presto->retval = ftdi_read_data(&presto->ftdic, buf + ftbytes, size - ftbytes);
113 if (presto->retval < 0) {
114 LOG_ERROR("ftdi_read_data: %s", ftdi_get_error_string(&presto->ftdic));
115 return ERROR_JTAG_DEVICE_ERROR;
116 }
117 ftbytes += presto->retval;
118
119 gettimeofday(&now, NULL);
120 if ((now.tv_sec > timeout.tv_sec) ||
121 ((now.tv_sec == timeout.tv_sec) && (now.tv_usec > timeout.tv_usec)))
122 break;
123 }
124
125 if (ftbytes != size) {
126 /* this is just a warning, there might have been timeout when detecting PRESTO,
127 *which is not fatal */
128 LOG_WARNING("couldn't read the requested number of bytes from PRESTO (%u < %u)",
129 (unsigned)ftbytes, (unsigned)size);
130 return ERROR_JTAG_DEVICE_ERROR;
131 }
132
133 return ERROR_OK;
134 }
135
136 static int presto_open_libftdi(char *req_serial)
137 {
138 uint8_t presto_data;
139
140 LOG_DEBUG("searching for PRESTO using libftdi");
141
142 /* initialize FTDI context structure */
143 if (ftdi_init(&presto->ftdic) < 0) {
144 LOG_ERROR("unable to init libftdi: %s", presto->ftdic.error_str);
145 return ERROR_JTAG_DEVICE_ERROR;
146 }
147
148 /* context, vendor id, product id */
149 if (ftdi_usb_open_desc(&presto->ftdic, PRESTO_VID, PRESTO_PID, NULL, req_serial) < 0) {
150 LOG_ERROR("unable to open PRESTO: %s", presto->ftdic.error_str);
151 return ERROR_JTAG_DEVICE_ERROR;
152 }
153
154 if (ftdi_usb_reset(&presto->ftdic) < 0) {
155 LOG_ERROR("unable to reset PRESTO device");
156 return ERROR_JTAG_DEVICE_ERROR;
157 }
158
159 if (ftdi_set_latency_timer(&presto->ftdic, 1) < 0) {
160 LOG_ERROR("unable to set latency timer");
161 return ERROR_JTAG_DEVICE_ERROR;
162 }
163
164 if (ftdi_usb_purge_buffers(&presto->ftdic) < 0) {
165 LOG_ERROR("unable to purge PRESTO buffers");
166 return ERROR_JTAG_DEVICE_ERROR;
167 }
168
169 presto_data = 0xD0;
170 if (presto_write(&presto_data, 1) != ERROR_OK) {
171 LOG_ERROR("error writing to PRESTO");
172 return ERROR_JTAG_DEVICE_ERROR;
173 }
174
175 if (presto_read(&presto_data, 1) != ERROR_OK) {
176 LOG_DEBUG("no response from PRESTO, retrying");
177
178 if (ftdi_usb_purge_buffers(&presto->ftdic) < 0)
179 return ERROR_JTAG_DEVICE_ERROR;
180
181 presto_data = 0xD0;
182 if (presto_write(&presto_data, 1) != ERROR_OK)
183 return ERROR_JTAG_DEVICE_ERROR;
184
185 if (presto_read(&presto_data, 1) != ERROR_OK) {
186 LOG_ERROR("no response from PRESTO, giving up");
187 return ERROR_JTAG_DEVICE_ERROR;
188 }
189 }
190
191 if (presto_write(presto_init_seq, sizeof(presto_init_seq)) != ERROR_OK) {
192 LOG_ERROR("error writing PRESTO init sequence");
193 return ERROR_JTAG_DEVICE_ERROR;
194 }
195
196 return ERROR_OK;
197 }
198
199 static int presto_open(char *req_serial)
200 {
201 presto->buff_out_pos = 0;
202 presto->buff_in_pos = 0;
203 presto->buff_in_len = 0;
204 presto->buff_in_exp = 0;
205
206 presto->total_out = 0;
207 presto->total_in = 0;
208
209 presto->jtag_tms = 0;
210 presto->jtag_tck = 0;
211 presto->jtag_rst = 0;
212 presto->jtag_tdi_data = 0;
213 presto->jtag_tdi_count = 0;
214
215 presto->jtag_speed = 0;
216
217 return presto_open_libftdi(req_serial);
218 }
219
220 static int presto_close(void)
221 {
222
223 int result = ERROR_OK;
224
225 presto->retval = ftdi_write_data(&presto->ftdic, presto_init_seq, sizeof(presto_init_seq));
226 if (presto->retval != sizeof(presto_init_seq))
227 result = ERROR_JTAG_DEVICE_ERROR;
228
229 presto->retval = ftdi_set_latency_timer(&presto->ftdic, 16);
230 if (presto->retval < 0)
231 result = ERROR_JTAG_DEVICE_ERROR;
232
233 presto->retval = ftdi_usb_close(&presto->ftdic);
234 if (presto->retval < 0)
235 result = ERROR_JTAG_DEVICE_ERROR;
236 else
237 ftdi_deinit(&presto->ftdic);
238
239 return result;
240 }
241
242 static int presto_flush(void)
243 {
244 if (presto->buff_out_pos == 0)
245 return ERROR_OK;
246
247 if (presto->retval < 0) {
248 LOG_DEBUG("error in previous communication, canceling I/O operation");
249 return ERROR_JTAG_DEVICE_ERROR;
250 }
251
252 if (presto_write(presto->buff_out, presto->buff_out_pos) != ERROR_OK) {
253 presto->buff_out_pos = 0;
254 return ERROR_JTAG_DEVICE_ERROR;
255 }
256
257 presto->total_out += presto->buff_out_pos;
258 presto->buff_out_pos = 0;
259
260 if (presto->buff_in_exp == 0)
261 return ERROR_OK;
262
263 presto->buff_in_pos = 0;
264 presto->buff_in_len = 0;
265
266 if (presto_read(presto->buff_in, presto->buff_in_exp) != ERROR_OK) {
267 presto->buff_in_exp = 0;
268 return ERROR_JTAG_DEVICE_ERROR;
269 }
270
271 presto->total_in += presto->buff_in_exp;
272 presto->buff_in_len = presto->buff_in_exp;
273 presto->buff_in_exp = 0;
274
275 return ERROR_OK;
276 }
277
278 static int presto_sendbyte(int data)
279 {
280 if (data == EOF)
281 return presto_flush();
282
283 if (presto->buff_out_pos < BUFFER_SIZE) {
284 presto->buff_out[presto->buff_out_pos++] = (uint8_t)data;
285 if (((data & 0xC0) == 0x40) || ((data & 0xD0) == 0xD0))
286 presto->buff_in_exp++;
287 } else
288 return ERROR_JTAG_DEVICE_ERROR;
289
290 /* libftdi does not do background read, be sure that USB IN buffer does not overflow (128
291 *bytes only!) */
292 if (presto->buff_out_pos >= BUFFER_SIZE || presto->buff_in_exp == 128)
293 return presto_flush();
294
295 return ERROR_OK;
296 }
297
298 #if 0
299 static int presto_getbyte(void)
300 {
301 if (presto->buff_in_pos < presto->buff_in_len)
302 return presto->buff_in[presto->buff_in_pos++];
303
304 if (presto->buff_in_exp == 0)
305 return -1;
306
307 if (presto_flush() != ERROR_OK)
308 return -1;
309
310 if (presto->buff_in_pos < presto->buff_in_len)
311 return presto->buff_in[presto->buff_in_pos++];
312
313 return -1;
314 }
315 #endif
316
317 /* -------------------------------------------------------------------------- */
318
319 static int presto_tdi_flush(void)
320 {
321 if (presto->jtag_tdi_count == 0)
322 return 0;
323
324 if (presto->jtag_tck == 0) {
325 LOG_ERROR("BUG: unexpected TAP condition, TCK low");
326 return -1;
327 }
328
329 presto->jtag_tdi_data |= (presto->jtag_tdi_count - 1) << 4;
330 presto_sendbyte(presto->jtag_tdi_data);
331 presto->jtag_tdi_count = 0;
332 presto->jtag_tdi_data = 0;
333
334 return 0;
335 }
336
337 static int presto_tck_idle(void)
338 {
339 if (presto->jtag_tck == 1) {
340 presto_sendbyte(0xCA);
341 presto->jtag_tck = 0;
342 }
343
344 return 0;
345 }
346
347 /* -------------------------------------------------------------------------- */
348
349 static int presto_bitq_out(int tms, int tdi, int tdo_req)
350 {
351 int i;
352 unsigned char cmd;
353
354 if (presto->jtag_tck == 0)
355 presto_sendbyte(0xA4); /* LED idicator - JTAG active */
356 else if (presto->jtag_speed == 0 && !tdo_req && tms == presto->jtag_tms) {
357 presto->jtag_tdi_data |= (tdi != 0) << presto->jtag_tdi_count;
358
359 if (++presto->jtag_tdi_count == 4)
360 presto_tdi_flush();
361
362 return 0;
363 }
364
365 presto_tdi_flush();
366
367 cmd = tdi ? 0xCB : 0xCA;
368 presto_sendbyte(cmd);
369
370 if (tms != presto->jtag_tms) {
371 presto_sendbyte((tms ? 0xEC : 0xE8) | (presto->jtag_rst ? 0x02 : 0));
372 presto->jtag_tms = tms;
373 }
374
375 /* delay with TCK low */
376 for (i = presto->jtag_speed; i > 1; i--)
377 presto_sendbyte(cmd);
378
379 cmd |= 0x04;
380 presto_sendbyte(cmd | (tdo_req ? 0x10 : 0));
381
382 /* delay with TCK high */
383 for (i = presto->jtag_speed; i > 1; i--)
384 presto_sendbyte(cmd);
385
386 presto->jtag_tck = 1;
387
388 return 0;
389 }
390
391 static int presto_bitq_flush(void)
392 {
393 presto_tdi_flush();
394 presto_tck_idle();
395
396 presto_sendbyte(0xA0); /* LED idicator - JTAG idle */
397
398 return presto_flush();
399 }
400
401 static int presto_bitq_in_rdy(void)
402 {
403 if (presto->buff_in_pos >= presto->buff_in_len)
404 return 0;
405 return presto->buff_in_len-presto->buff_in_pos;
406 }
407
408 static int presto_bitq_in(void)
409 {
410 if (presto->buff_in_pos >= presto->buff_in_len)
411 return -1;
412 if (presto->buff_in[presto->buff_in_pos++]&0x08)
413 return 1;
414 return 0;
415 }
416
417 static int presto_bitq_sleep(unsigned long us)
418 {
419 long waits;
420
421 presto_tdi_flush();
422 presto_tck_idle();
423
424 if (us > 100000) {
425 presto_bitq_flush();
426 jtag_sleep(us);
427 return 0;
428 }
429
430 waits = us / 170 + 2;
431 while (waits--)
432 presto_sendbyte(0x80);
433
434 return 0;
435 }
436
437 static int presto_bitq_reset(int trst, int srst)
438 {
439 presto_tdi_flush();
440 presto_tck_idle();
441
442 /* add a delay after possible TCK transition */
443 presto_sendbyte(0x80);
444 presto_sendbyte(0x80);
445
446 presto->jtag_rst = trst || srst;
447 presto_sendbyte((presto->jtag_rst ? 0xEA : 0xE8) | (presto->jtag_tms ? 0x04 : 0));
448
449 return 0;
450 }
451
452 static struct bitq_interface presto_bitq = {
453 .out = &presto_bitq_out,
454 .flush = &presto_bitq_flush,
455 .sleep = &presto_bitq_sleep,
456 .reset = &presto_bitq_reset,
457 .in_rdy = &presto_bitq_in_rdy,
458 .in = &presto_bitq_in,
459 };
460
461 /* -------------------------------------------------------------------------- */
462
463 static int presto_adapter_khz(int khz, int *jtag_speed)
464 {
465 if (khz < 0) {
466 *jtag_speed = 0;
467 return ERROR_COMMAND_SYNTAX_ERROR;
468 }
469
470 if (khz >= 3000)
471 *jtag_speed = 0;
472 else
473 *jtag_speed = (1000 + khz-1)/khz;
474
475 return 0;
476 }
477
478 static int presto_jtag_speed_div(int speed, int *khz)
479 {
480 if ((speed < 0) || (speed > 1000)) {
481 *khz = 0;
482 return ERROR_COMMAND_SYNTAX_ERROR;
483 }
484
485 if (speed == 0)
486 *khz = 3000;
487 else
488 *khz = 1000/speed;
489
490 return 0;
491 }
492
493 static int presto_jtag_speed(int speed)
494 {
495 int khz;
496
497 if (presto_jtag_speed_div(speed, &khz))
498 return ERROR_COMMAND_SYNTAX_ERROR;
499
500 presto->jtag_speed = speed;
501
502 if (khz%1000 == 0)
503 LOG_INFO("setting speed to %d, max. TCK freq. is %d MHz", speed, khz/1000);
504 else
505 LOG_INFO("setting speed to %d, max. TCK freq. is %d kHz", speed, khz);
506
507 return 0;
508 }
509
510 static char *presto_serial;
511
512 COMMAND_HANDLER(presto_handle_serial_command)
513 {
514 if (CMD_ARGC == 1) {
515 if (presto_serial)
516 free(presto_serial);
517 presto_serial = strdup(CMD_ARGV[0]);
518 } else
519 return ERROR_COMMAND_SYNTAX_ERROR;
520
521 return ERROR_OK;
522 }
523
524 static const struct command_registration presto_command_handlers[] = {
525 {
526 .name = "presto_serial",
527 .handler = presto_handle_serial_command,
528 .mode = COMMAND_CONFIG,
529 .help = "Configure USB serial number of Presto device.",
530 .usage = "serial_string",
531 },
532 COMMAND_REGISTRATION_DONE
533 };
534
535 static int presto_jtag_init(void)
536 {
537 if (presto_open(presto_serial) != ERROR_OK) {
538 presto_close();
539 if (presto_serial != NULL)
540 LOG_ERROR("Cannot open PRESTO, serial number '%s'", presto_serial);
541 else
542 LOG_ERROR("Cannot open PRESTO");
543 return ERROR_JTAG_INIT_FAILED;
544 }
545 LOG_INFO("PRESTO open, serial number '%s'", presto->serial);
546
547 bitq_interface = &presto_bitq;
548 return ERROR_OK;
549 }
550
551 static int presto_jtag_quit(void)
552 {
553 bitq_cleanup();
554 presto_close();
555 LOG_INFO("PRESTO closed");
556
557 if (presto_serial) {
558 free(presto_serial);
559 presto_serial = NULL;
560 }
561
562 return ERROR_OK;
563 }
564
565 struct jtag_interface presto_interface = {
566 .name = "presto",
567 .commands = presto_command_handlers,
568
569 .execute_queue = bitq_execute_queue,
570 .speed = presto_jtag_speed,
571 .khz = presto_adapter_khz,
572 .speed_div = presto_jtag_speed_div,
573 .init = presto_jtag_init,
574 .quit = presto_jtag_quit,
575 };

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)