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

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)