0a18dc9c4c0c1ab676138c5bbf68aa2a5b743d2a
[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 #if BUILD_PRESTO_FTD2XX == 1
38 #include <ftd2xx.h>
39 #include "ftd2xx_common.h"
40 #elif BUILD_PRESTO_LIBFTDI == 1
41 #include <ftdi.h>
42 #else
43 #error "BUG: either FTD2XX and LIBFTDI has to be used"
44 #endif
45
46 /* -------------------------------------------------------------------------- */
47
48 #define FT_DEVICE_NAME_LEN 64
49 #define FT_DEVICE_SERNUM_LEN 64
50
51 #define PRESTO_VID_PID 0x0403f1a0
52 #define PRESTO_VID (0x0403)
53 #define PRESTO_PID (0xf1a0)
54
55 #define BUFFER_SIZE (64*62)
56
57 struct presto {
58 #if BUILD_PRESTO_FTD2XX == 1
59 FT_HANDLE handle;
60 FT_STATUS status;
61 #elif BUILD_PRESTO_LIBFTDI == 1
62 struct ftdi_context ftdic;
63 int retval;
64 #endif
65
66 char serial[FT_DEVICE_SERNUM_LEN];
67
68 uint8_t buff_out[BUFFER_SIZE];
69 int buff_out_pos;
70
71 uint8_t buff_in[BUFFER_SIZE];
72 int buff_in_exp;/* expected in buffer length */
73 int buff_in_len;/* length of data received */
74 int buff_in_pos;
75
76 unsigned long total_out;
77 unsigned long total_in;
78
79 int jtag_tms; /* last tms state */
80 int jtag_tck; /* last tck state */
81 int jtag_rst; /* last trst state */
82
83 int jtag_tdi_data;
84 int jtag_tdi_count;
85
86 int jtag_speed;
87 };
88
89 static struct presto presto_state;
90 static struct presto *presto = &presto_state;
91
92 static uint8_t presto_init_seq[] = {
93 0x80, 0xA0, 0xA8, 0xB0, 0xC0, 0xE0
94 };
95
96 static int presto_write(uint8_t *buf, uint32_t size)
97 {
98 #if BUILD_PRESTO_FTD2XX == 1
99 DWORD ftbytes;
100 presto->status = FT_Write(presto->handle, buf, size, &ftbytes);
101 if (presto->status != FT_OK) {
102 LOG_ERROR("FT_Write returned: %s", ftd2xx_status_string(presto->status));
103 return ERROR_JTAG_DEVICE_ERROR;
104 }
105
106 #elif BUILD_PRESTO_LIBFTDI == 1
107 uint32_t ftbytes;
108 presto->retval = ftdi_write_data(&presto->ftdic, buf, size);
109 if (presto->retval < 0) {
110 LOG_ERROR("ftdi_write_data: %s", ftdi_get_error_string(&presto->ftdic));
111 return ERROR_JTAG_DEVICE_ERROR;
112 }
113 ftbytes = presto->retval;
114 #endif
115
116 if (ftbytes != size) {
117 LOG_ERROR("couldn't write the requested number of bytes to PRESTO (%u < %u)",
118 (unsigned)ftbytes, (unsigned)size);
119 return ERROR_JTAG_DEVICE_ERROR;
120 }
121
122 return ERROR_OK;
123 }
124
125 static int presto_read(uint8_t *buf, uint32_t size)
126 {
127 #if BUILD_PRESTO_FTD2XX == 1
128 DWORD ftbytes;
129 presto->status = FT_Read(presto->handle, buf, size, &ftbytes);
130 if (presto->status != FT_OK) {
131 LOG_ERROR("FT_Read returned: %s", ftd2xx_status_string(presto->status));
132 return ERROR_JTAG_DEVICE_ERROR;
133 }
134
135 #elif BUILD_PRESTO_LIBFTDI == 1
136 uint32_t ftbytes = 0;
137
138 struct timeval timeout, now;
139 gettimeofday(&timeout, NULL);
140 timeval_add_time(&timeout, 1, 0); /* one second timeout */
141
142 while (ftbytes < size) {
143 presto->retval = ftdi_read_data(&presto->ftdic, buf + ftbytes, size - ftbytes);
144 if (presto->retval < 0) {
145 LOG_ERROR("ftdi_read_data: %s", ftdi_get_error_string(&presto->ftdic));
146 return ERROR_JTAG_DEVICE_ERROR;
147 }
148 ftbytes += presto->retval;
149
150 gettimeofday(&now, NULL);
151 if ((now.tv_sec > timeout.tv_sec) ||
152 ((now.tv_sec == timeout.tv_sec) && (now.tv_usec > timeout.tv_usec)))
153 break;
154 }
155 #endif
156
157 if (ftbytes != size) {
158 /* this is just a warning, there might have been timeout when detecting PRESTO,
159 *which is not fatal */
160 LOG_WARNING("couldn't read the requested number of bytes from PRESTO (%u < %u)",
161 (unsigned)ftbytes, (unsigned)size);
162 return ERROR_JTAG_DEVICE_ERROR;
163 }
164
165 return ERROR_OK;
166 }
167
168 #if BUILD_PRESTO_FTD2XX == 1
169 static int presto_open_ftd2xx(char *req_serial)
170 {
171 uint32_t i;
172 DWORD numdevs;
173 DWORD vidpid;
174 char devname[FT_DEVICE_NAME_LEN];
175 FT_DEVICE device;
176
177 BYTE presto_data;
178 DWORD ftbytes;
179
180 presto->handle = (FT_HANDLE)INVALID_HANDLE_VALUE;
181
182 #if IS_WIN32 == 0
183 /* Add non-standard Vid/Pid to the linux driver */
184 presto->status = FT_SetVIDPID(PRESTO_VID, PRESTO_PID);
185 if (presto->status != FT_OK) {
186 LOG_ERROR("couldn't add PRESTO VID/PID");
187 exit(-1);
188 }
189 #endif
190
191 presto->status = FT_ListDevices(&numdevs, NULL, FT_LIST_NUMBER_ONLY);
192 if (presto->status != FT_OK) {
193 LOG_ERROR("FT_ListDevices failed: %s", ftd2xx_status_string(presto->status));
194 return ERROR_JTAG_DEVICE_ERROR;
195 }
196
197 LOG_DEBUG("FTDI devices available: %" PRIu32, (uint32_t)numdevs);
198 for (i = 0; i < numdevs; i++) {
199 presto->status = FT_Open(i, &(presto->handle));
200 if (presto->status != FT_OK) {
201 /* this is not fatal, the device may be legitimately open by other process,
202 *hence debug message only */
203 LOG_DEBUG("FT_Open failed: %s", ftd2xx_status_string(presto->status));
204 continue;
205 }
206 LOG_DEBUG("FTDI device %i open", (int)i);
207
208 presto->status = FT_GetDeviceInfo(presto->handle, &device,
209 &vidpid, presto->serial, devname, NULL);
210 if (presto->status == FT_OK) {
211 if (vidpid == PRESTO_VID_PID && (req_serial == NULL ||
212 !strcmp(presto->serial, req_serial)))
213 break;
214 } else
215 LOG_DEBUG("FT_GetDeviceInfo failed: %s", ftd2xx_status_string(
216 presto->status));
217
218 LOG_DEBUG("FTDI device %i does not match, closing", (int)i);
219 FT_Close(presto->handle);
220 presto->handle = (FT_HANDLE)INVALID_HANDLE_VALUE;
221 }
222
223 if (presto->handle == (FT_HANDLE)INVALID_HANDLE_VALUE)
224 return ERROR_JTAG_DEVICE_ERROR; /* presto not open, return */
225
226 presto->status = FT_SetLatencyTimer(presto->handle, 1);
227 if (presto->status != FT_OK)
228 return ERROR_JTAG_DEVICE_ERROR;
229
230 presto->status = FT_SetTimeouts(presto->handle, 100, 0);
231 if (presto->status != FT_OK)
232 return ERROR_JTAG_DEVICE_ERROR;
233
234 presto->status = FT_Purge(presto->handle, FT_PURGE_TX | FT_PURGE_RX);
235 if (presto->status != FT_OK)
236 return ERROR_JTAG_DEVICE_ERROR;
237
238 presto_data = 0xD0;
239 presto->status = FT_Write(presto->handle, &presto_data, 1, &ftbytes);
240 if (presto->status != FT_OK)
241 return ERROR_JTAG_DEVICE_ERROR;
242
243 /* delay between first write/read turnaround (after purge?) necessary
244 * under Linux for unknown reason,
245 * probably a bug in library threading */
246 usleep(100000);
247 presto->status = FT_Read(presto->handle, &presto_data, 1, &ftbytes);
248 if (presto->status != FT_OK)
249 return ERROR_JTAG_DEVICE_ERROR;
250
251 if (ftbytes != 1) {
252 LOG_DEBUG("PRESTO reset");
253
254 presto->status = FT_Purge(presto->handle, FT_PURGE_TX | FT_PURGE_RX);
255 if (presto->status != FT_OK)
256 return ERROR_JTAG_DEVICE_ERROR;
257 presto->status = FT_SetBitMode(presto->handle, 0x80, 1);
258 if (presto->status != FT_OK)
259 return ERROR_JTAG_DEVICE_ERROR;
260 presto->status = FT_SetBaudRate(presto->handle, 9600);
261 if (presto->status != FT_OK)
262 return ERROR_JTAG_DEVICE_ERROR;
263
264 presto_data = 0;
265 for (i = 0; i < 4 * 62; i++) {
266 presto->status = FT_Write(presto->handle, &presto_data, 1, &ftbytes);
267 if (presto->status != FT_OK)
268 return ERROR_JTAG_DEVICE_ERROR;
269 }
270 usleep(100000);
271
272 presto->status = FT_SetBitMode(presto->handle, 0x00, 0);
273 if (presto->status != FT_OK)
274 return ERROR_JTAG_DEVICE_ERROR;
275
276 presto->status = FT_Purge(presto->handle, FT_PURGE_TX | FT_PURGE_RX);
277 if (presto->status != FT_OK)
278 return ERROR_JTAG_DEVICE_ERROR;
279
280 presto_data = 0xD0;
281 presto->status = FT_Write(presto->handle, &presto_data, 1, &ftbytes);
282 if (presto->status != FT_OK)
283 return ERROR_JTAG_DEVICE_ERROR;
284
285 /* delay between first write/read turnaround (after purge?) necessary under Linux for unknown reason,
286 probably a bug in library threading */
287 usleep(100000);
288 presto->status = FT_Read(presto->handle, &presto_data, 1, &ftbytes);
289 if (presto->status != FT_OK)
290 return ERROR_JTAG_DEVICE_ERROR;
291
292 if (ftbytes != 1) {
293 LOG_DEBUG("PRESTO not responding");
294 return ERROR_JTAG_DEVICE_ERROR;
295 }
296 }
297
298 presto->status = FT_SetTimeouts(presto->handle, 0, 0);
299 if (presto->status != FT_OK)
300 return ERROR_JTAG_DEVICE_ERROR;
301
302 presto->status = FT_Write(presto->handle, &presto_init_seq,
303 sizeof(presto_init_seq), &ftbytes);
304
305 if (presto->status != FT_OK || ftbytes != sizeof(presto_init_seq))
306 return ERROR_JTAG_DEVICE_ERROR;
307
308 return ERROR_OK;
309 }
310
311 #elif BUILD_PRESTO_LIBFTDI == 1
312 static int presto_open_libftdi(char *req_serial)
313 {
314 uint8_t presto_data;
315
316 LOG_DEBUG("searching for PRESTO using libftdi");
317
318 /* initialize FTDI context structure */
319 if (ftdi_init(&presto->ftdic) < 0) {
320 LOG_ERROR("unable to init libftdi: %s", presto->ftdic.error_str);
321 return ERROR_JTAG_DEVICE_ERROR;
322 }
323
324 /* context, vendor id, product id */
325 if (ftdi_usb_open_desc(&presto->ftdic, PRESTO_VID, PRESTO_PID, NULL, req_serial) < 0) {
326 LOG_ERROR("unable to open PRESTO: %s", presto->ftdic.error_str);
327 return ERROR_JTAG_DEVICE_ERROR;
328 }
329
330 if (ftdi_usb_reset(&presto->ftdic) < 0) {
331 LOG_ERROR("unable to reset PRESTO device");
332 return ERROR_JTAG_DEVICE_ERROR;
333 }
334
335 if (ftdi_set_latency_timer(&presto->ftdic, 1) < 0) {
336 LOG_ERROR("unable to set latency timer");
337 return ERROR_JTAG_DEVICE_ERROR;
338 }
339
340 if (ftdi_usb_purge_buffers(&presto->ftdic) < 0) {
341 LOG_ERROR("unable to purge PRESTO buffers");
342 return ERROR_JTAG_DEVICE_ERROR;
343 }
344
345 presto_data = 0xD0;
346 if (presto_write(&presto_data, 1) != ERROR_OK) {
347 LOG_ERROR("error writing to PRESTO");
348 return ERROR_JTAG_DEVICE_ERROR;
349 }
350
351 if (presto_read(&presto_data, 1) != ERROR_OK) {
352 LOG_DEBUG("no response from PRESTO, retrying");
353
354 if (ftdi_usb_purge_buffers(&presto->ftdic) < 0)
355 return ERROR_JTAG_DEVICE_ERROR;
356
357 presto_data = 0xD0;
358 if (presto_write(&presto_data, 1) != ERROR_OK)
359 return ERROR_JTAG_DEVICE_ERROR;
360
361 if (presto_read(&presto_data, 1) != ERROR_OK) {
362 LOG_ERROR("no response from PRESTO, giving up");
363 return ERROR_JTAG_DEVICE_ERROR;
364 }
365 }
366
367 if (presto_write(presto_init_seq, sizeof(presto_init_seq)) != ERROR_OK) {
368 LOG_ERROR("error writing PRESTO init sequence");
369 return ERROR_JTAG_DEVICE_ERROR;
370 }
371
372 return ERROR_OK;
373 }
374 #endif /* BUILD_PRESTO_LIBFTDI == 1 */
375
376 static int presto_open(char *req_serial)
377 {
378 presto->buff_out_pos = 0;
379 presto->buff_in_pos = 0;
380 presto->buff_in_len = 0;
381 presto->buff_in_exp = 0;
382
383 presto->total_out = 0;
384 presto->total_in = 0;
385
386 presto->jtag_tms = 0;
387 presto->jtag_tck = 0;
388 presto->jtag_rst = 0;
389 presto->jtag_tdi_data = 0;
390 presto->jtag_tdi_count = 0;
391
392 presto->jtag_speed = 0;
393
394 #if BUILD_PRESTO_FTD2XX == 1
395 return presto_open_ftd2xx(req_serial);
396 #elif BUILD_PRESTO_LIBFTDI == 1
397 return presto_open_libftdi(req_serial);
398 #endif
399 }
400
401 static int presto_close(void)
402 {
403
404 int result = ERROR_OK;
405
406 #if BUILD_PRESTO_FTD2XX == 1
407 DWORD ftbytes;
408
409 if (presto->handle == (FT_HANDLE)INVALID_HANDLE_VALUE)
410 return result;
411
412 presto->status = FT_Purge(presto->handle, FT_PURGE_TX | FT_PURGE_RX);
413 if (presto->status != FT_OK)
414 result = ERROR_JTAG_DEVICE_ERROR;
415
416 presto->status = FT_Write(presto->handle,
417 &presto_init_seq,
418 sizeof(presto_init_seq),
419 &ftbytes);
420 if (presto->status != FT_OK || ftbytes != sizeof(presto_init_seq))
421 result = ERROR_JTAG_DEVICE_ERROR;
422
423 presto->status = FT_SetLatencyTimer(presto->handle, 16);
424 if (presto->status != FT_OK)
425 result = ERROR_JTAG_DEVICE_ERROR;
426
427 presto->status = FT_Close(presto->handle);
428 if (presto->status != FT_OK)
429 result = ERROR_JTAG_DEVICE_ERROR;
430 else
431 presto->handle = (FT_HANDLE)INVALID_HANDLE_VALUE;
432
433 #elif BUILD_PRESTO_LIBFTDI == 1
434
435 presto->retval = ftdi_write_data(&presto->ftdic, presto_init_seq, sizeof(presto_init_seq));
436 if (presto->retval != sizeof(presto_init_seq))
437 result = ERROR_JTAG_DEVICE_ERROR;
438
439 presto->retval = ftdi_set_latency_timer(&presto->ftdic, 16);
440 if (presto->retval < 0)
441 result = ERROR_JTAG_DEVICE_ERROR;
442
443 presto->retval = ftdi_usb_close(&presto->ftdic);
444 if (presto->retval < 0)
445 result = ERROR_JTAG_DEVICE_ERROR;
446 else
447 ftdi_deinit(&presto->ftdic);
448 #endif
449
450 return result;
451 }
452
453 static int presto_flush(void)
454 {
455 if (presto->buff_out_pos == 0)
456 return ERROR_OK;
457
458 #if BUILD_PRESTO_FTD2XX == 1
459 if (presto->status != FT_OK) {
460 #elif BUILD_PRESTO_LIBFTDI == 1
461 if (presto->retval < 0) {
462 #endif
463 LOG_DEBUG("error in previous communication, canceling I/O operation");
464 return ERROR_JTAG_DEVICE_ERROR;
465 }
466
467 if (presto_write(presto->buff_out, presto->buff_out_pos) != ERROR_OK) {
468 presto->buff_out_pos = 0;
469 return ERROR_JTAG_DEVICE_ERROR;
470 }
471
472 presto->total_out += presto->buff_out_pos;
473 presto->buff_out_pos = 0;
474
475 if (presto->buff_in_exp == 0)
476 return ERROR_OK;
477
478 presto->buff_in_pos = 0;
479 presto->buff_in_len = 0;
480
481 if (presto_read(presto->buff_in, presto->buff_in_exp) != ERROR_OK) {
482 presto->buff_in_exp = 0;
483 return ERROR_JTAG_DEVICE_ERROR;
484 }
485
486 presto->total_in += presto->buff_in_exp;
487 presto->buff_in_len = presto->buff_in_exp;
488 presto->buff_in_exp = 0;
489
490 return ERROR_OK;
491 }
492
493 static int presto_sendbyte(int data)
494 {
495 if (data == EOF)
496 return presto_flush();
497
498 if (presto->buff_out_pos < BUFFER_SIZE) {
499 presto->buff_out[presto->buff_out_pos++] = (uint8_t)data;
500 if (((data & 0xC0) == 0x40) || ((data & 0xD0) == 0xD0))
501 presto->buff_in_exp++;
502 } else
503 return ERROR_JTAG_DEVICE_ERROR;
504
505 #if BUILD_PRESTO_FTD2XX == 1
506 if (presto->buff_out_pos >= BUFFER_SIZE)
507 #elif BUILD_PRESTO_LIBFTDI == 1
508 /* libftdi does not do background read, be sure that USB IN buffer does not overflow (128
509 *bytes only!) */
510 if (presto->buff_out_pos >= BUFFER_SIZE || presto->buff_in_exp == 128)
511 #endif
512 return presto_flush();
513
514 return ERROR_OK;
515 }
516
517 #if 0
518 static int presto_getbyte(void)
519 {
520 if (presto->buff_in_pos < presto->buff_in_len)
521 return presto->buff_in[presto->buff_in_pos++];
522
523 if (presto->buff_in_exp == 0)
524 return -1;
525
526 if (presto_flush() != ERROR_OK)
527 return -1;
528
529 if (presto->buff_in_pos < presto->buff_in_len)
530 return presto->buff_in[presto->buff_in_pos++];
531
532 return -1;
533 }
534 #endif
535
536 /* -------------------------------------------------------------------------- */
537
538 static int presto_tdi_flush(void)
539 {
540 if (presto->jtag_tdi_count == 0)
541 return 0;
542
543 if (presto->jtag_tck == 0) {
544 LOG_ERROR("BUG: unexpected TAP condition, TCK low");
545 return -1;
546 }
547
548 presto->jtag_tdi_data |= (presto->jtag_tdi_count - 1) << 4;
549 presto_sendbyte(presto->jtag_tdi_data);
550 presto->jtag_tdi_count = 0;
551 presto->jtag_tdi_data = 0;
552
553 return 0;
554 }
555
556 static int presto_tck_idle(void)
557 {
558 if (presto->jtag_tck == 1) {
559 presto_sendbyte(0xCA);
560 presto->jtag_tck = 0;
561 }
562
563 return 0;
564 }
565
566 /* -------------------------------------------------------------------------- */
567
568 static int presto_bitq_out(int tms, int tdi, int tdo_req)
569 {
570 int i;
571 unsigned char cmd;
572
573 if (presto->jtag_tck == 0)
574 presto_sendbyte(0xA4); /* LED idicator - JTAG active */
575 else if (presto->jtag_speed == 0 && !tdo_req && tms == presto->jtag_tms) {
576 presto->jtag_tdi_data |= (tdi != 0) << presto->jtag_tdi_count;
577
578 if (++presto->jtag_tdi_count == 4)
579 presto_tdi_flush();
580
581 return 0;
582 }
583
584 presto_tdi_flush();
585
586 cmd = tdi ? 0xCB : 0xCA;
587 presto_sendbyte(cmd);
588
589 if (tms != presto->jtag_tms) {
590 presto_sendbyte((tms ? 0xEC : 0xE8) | (presto->jtag_rst ? 0x02 : 0));
591 presto->jtag_tms = tms;
592 }
593
594 /* delay with TCK low */
595 for (i = presto->jtag_speed; i > 1; i--)
596 presto_sendbyte(cmd);
597
598 cmd |= 0x04;
599 presto_sendbyte(cmd | (tdo_req ? 0x10 : 0));
600
601 /* delay with TCK high */
602 for (i = presto->jtag_speed; i > 1; i--)
603 presto_sendbyte(cmd);
604
605 presto->jtag_tck = 1;
606
607 return 0;
608 }
609
610 static int presto_bitq_flush(void)
611 {
612 presto_tdi_flush();
613 presto_tck_idle();
614
615 presto_sendbyte(0xA0); /* LED idicator - JTAG idle */
616
617 return presto_flush();
618 }
619
620 static int presto_bitq_in_rdy(void)
621 {
622 if (presto->buff_in_pos >= presto->buff_in_len)
623 return 0;
624 return presto->buff_in_len-presto->buff_in_pos;
625 }
626
627 static int presto_bitq_in(void)
628 {
629 if (presto->buff_in_pos >= presto->buff_in_len)
630 return -1;
631 if (presto->buff_in[presto->buff_in_pos++]&0x08)
632 return 1;
633 return 0;
634 }
635
636 static int presto_bitq_sleep(unsigned long us)
637 {
638 long waits;
639
640 presto_tdi_flush();
641 presto_tck_idle();
642
643 if (us > 100000) {
644 presto_bitq_flush();
645 jtag_sleep(us);
646 return 0;
647 }
648
649 waits = us / 170 + 2;
650 while (waits--)
651 presto_sendbyte(0x80);
652
653 return 0;
654 }
655
656 static int presto_bitq_reset(int trst, int srst)
657 {
658 presto_tdi_flush();
659 presto_tck_idle();
660
661 /* add a delay after possible TCK transition */
662 presto_sendbyte(0x80);
663 presto_sendbyte(0x80);
664
665 presto->jtag_rst = trst || srst;
666 presto_sendbyte((presto->jtag_rst ? 0xEA : 0xE8) | (presto->jtag_tms ? 0x04 : 0));
667
668 return 0;
669 }
670
671 static struct bitq_interface presto_bitq = {
672 .out = &presto_bitq_out,
673 .flush = &presto_bitq_flush,
674 .sleep = &presto_bitq_sleep,
675 .reset = &presto_bitq_reset,
676 .in_rdy = &presto_bitq_in_rdy,
677 .in = &presto_bitq_in,
678 };
679
680 /* -------------------------------------------------------------------------- */
681
682 static int presto_adapter_khz(int khz, int *jtag_speed)
683 {
684 if (khz < 0) {
685 *jtag_speed = 0;
686 return ERROR_COMMAND_SYNTAX_ERROR;
687 }
688
689 if (khz >= 3000)
690 *jtag_speed = 0;
691 else
692 *jtag_speed = (1000 + khz-1)/khz;
693
694 return 0;
695 }
696
697 static int presto_jtag_speed_div(int speed, int *khz)
698 {
699 if ((speed < 0) || (speed > 1000)) {
700 *khz = 0;
701 return ERROR_COMMAND_SYNTAX_ERROR;
702 }
703
704 if (speed == 0)
705 *khz = 3000;
706 else
707 *khz = 1000/speed;
708
709 return 0;
710 }
711
712 static int presto_jtag_speed(int speed)
713 {
714 int khz;
715
716 if (presto_jtag_speed_div(speed, &khz))
717 return ERROR_COMMAND_SYNTAX_ERROR;
718
719 presto->jtag_speed = speed;
720
721 if (khz%1000 == 0)
722 LOG_INFO("setting speed to %d, max. TCK freq. is %d MHz", speed, khz/1000);
723 else
724 LOG_INFO("setting speed to %d, max. TCK freq. is %d kHz", speed, khz);
725
726 return 0;
727 }
728
729 static char *presto_serial;
730
731 COMMAND_HANDLER(presto_handle_serial_command)
732 {
733 if (CMD_ARGC == 1) {
734 if (presto_serial)
735 free(presto_serial);
736 presto_serial = strdup(CMD_ARGV[0]);
737 } else
738 return ERROR_COMMAND_SYNTAX_ERROR;
739
740 return ERROR_OK;
741 }
742
743 static const struct command_registration presto_command_handlers[] = {
744 {
745 .name = "presto_serial",
746 .handler = presto_handle_serial_command,
747 .mode = COMMAND_CONFIG,
748 .help = "Configure USB serial number of Presto device.",
749 .usage = "serial_string",
750 },
751 COMMAND_REGISTRATION_DONE
752 };
753
754 static int presto_jtag_init(void)
755 {
756 if (presto_open(presto_serial) != ERROR_OK) {
757 presto_close();
758 if (presto_serial != NULL)
759 LOG_ERROR("Cannot open PRESTO, serial number '%s'", presto_serial);
760 else
761 LOG_ERROR("Cannot open PRESTO");
762 return ERROR_JTAG_INIT_FAILED;
763 }
764 LOG_INFO("PRESTO open, serial number '%s'", presto->serial);
765
766 bitq_interface = &presto_bitq;
767 return ERROR_OK;
768 }
769
770 static int presto_jtag_quit(void)
771 {
772 bitq_cleanup();
773 presto_close();
774 LOG_INFO("PRESTO closed");
775
776 if (presto_serial) {
777 free(presto_serial);
778 presto_serial = NULL;
779 }
780
781 return ERROR_OK;
782 }
783
784 struct jtag_interface presto_interface = {
785 .name = "presto",
786 .commands = presto_command_handlers,
787
788 .execute_queue = bitq_execute_queue,
789 .speed = presto_jtag_speed,
790 .khz = presto_adapter_khz,
791 .speed_div = presto_jtag_speed_div,
792 .init = presto_jtag_init,
793 .quit = presto_jtag_quit,
794 };

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)