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

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)