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

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)