1 /***************************************************************************
2 * Copyright (C) 2007 by Pavel Chromy *
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. *
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. *
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 ***************************************************************************/
21 * Holds driver for PRESTO programmer from ASIX.
22 * http://tools.asix.net/prg_presto.htm
32 #include <jtag/interface.h>
33 #include <helper/time_support.h>
36 /* PRESTO access library includes */
37 #include "libftdi_helper.h"
39 /* -------------------------------------------------------------------------- */
41 #define FT_DEVICE_NAME_LEN 64
42 #define FT_DEVICE_SERNUM_LEN 64
44 #define PRESTO_VID_PID 0x0403f1a0
45 #define PRESTO_VID (0x0403)
46 #define PRESTO_PID (0xf1a0)
48 #define BUFFER_SIZE (64*62)
51 struct ftdi_context ftdic
;
54 char serial
[FT_DEVICE_SERNUM_LEN
];
56 uint8_t buff_out
[BUFFER_SIZE
];
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 */
64 unsigned long total_out
;
65 unsigned long total_in
;
67 int jtag_tms
; /* last tms state */
68 int jtag_tck
; /* last tck state */
69 int jtag_rst
; /* last trst state */
77 static struct presto presto_state
;
78 static struct presto
*presto
= &presto_state
;
80 static uint8_t presto_init_seq
[] = {
81 0x80, 0xA0, 0xA8, 0xB0, 0xC0, 0xE0
84 static int presto_write(uint8_t *buf
, uint32_t size
)
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
;
92 ftbytes
= presto
->retval
;
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
;
103 static int presto_read(uint8_t *buf
, uint32_t size
)
105 uint32_t ftbytes
= 0;
107 struct timeval timeout
, now
;
108 gettimeofday(&timeout
, NULL
);
109 timeval_add_time(&timeout
, 1, 0); /* one second timeout */
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
;
117 ftbytes
+= presto
->retval
;
119 gettimeofday(&now
, NULL
);
120 if (timeval_compare(&now
, &timeout
) > 0)
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
;
135 static int presto_open_libftdi(char *req_serial
)
139 LOG_DEBUG("searching for PRESTO using libftdi");
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
;
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
;
153 if (ftdi_usb_reset(&presto
->ftdic
) < 0) {
154 LOG_ERROR("unable to reset PRESTO device");
155 return ERROR_JTAG_DEVICE_ERROR
;
158 if (ftdi_set_latency_timer(&presto
->ftdic
, 1) < 0) {
159 LOG_ERROR("unable to set latency timer");
160 return ERROR_JTAG_DEVICE_ERROR
;
163 if (ftdi_tcioflush(&presto
->ftdic
) < 0) {
164 LOG_ERROR("unable to flush PRESTO buffers");
165 return ERROR_JTAG_DEVICE_ERROR
;
169 if (presto_write(&presto_data
, 1) != ERROR_OK
) {
170 LOG_ERROR("error writing to PRESTO");
171 return ERROR_JTAG_DEVICE_ERROR
;
174 if (presto_read(&presto_data
, 1) != ERROR_OK
) {
175 LOG_DEBUG("no response from PRESTO, retrying");
177 if (ftdi_tcioflush(&presto
->ftdic
) < 0)
178 return ERROR_JTAG_DEVICE_ERROR
;
181 if (presto_write(&presto_data
, 1) != ERROR_OK
)
182 return ERROR_JTAG_DEVICE_ERROR
;
184 if (presto_read(&presto_data
, 1) != ERROR_OK
) {
185 LOG_ERROR("no response from PRESTO, giving up");
186 return ERROR_JTAG_DEVICE_ERROR
;
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
;
198 static int presto_open(char *req_serial
)
200 presto
->buff_out_pos
= 0;
201 presto
->buff_in_pos
= 0;
202 presto
->buff_in_len
= 0;
203 presto
->buff_in_exp
= 0;
205 presto
->total_out
= 0;
206 presto
->total_in
= 0;
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;
214 presto
->jtag_speed
= 0;
216 return presto_open_libftdi(req_serial
);
219 static int presto_close(void)
222 int result
= ERROR_OK
;
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
;
228 presto
->retval
= ftdi_set_latency_timer(&presto
->ftdic
, 16);
229 if (presto
->retval
< 0)
230 result
= ERROR_JTAG_DEVICE_ERROR
;
232 presto
->retval
= ftdi_usb_close(&presto
->ftdic
);
233 if (presto
->retval
< 0)
234 result
= ERROR_JTAG_DEVICE_ERROR
;
236 ftdi_deinit(&presto
->ftdic
);
241 static int presto_flush(void)
243 if (presto
->buff_out_pos
== 0)
246 if (presto
->retval
< 0) {
247 LOG_DEBUG("error in previous communication, canceling I/O operation");
248 return ERROR_JTAG_DEVICE_ERROR
;
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
;
256 presto
->total_out
+= presto
->buff_out_pos
;
257 presto
->buff_out_pos
= 0;
259 if (presto
->buff_in_exp
== 0)
262 presto
->buff_in_pos
= 0;
263 presto
->buff_in_len
= 0;
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
;
270 presto
->total_in
+= presto
->buff_in_exp
;
271 presto
->buff_in_len
= presto
->buff_in_exp
;
272 presto
->buff_in_exp
= 0;
277 static int presto_sendbyte(int data
)
280 return presto_flush();
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
++;
287 return ERROR_JTAG_DEVICE_ERROR
;
289 /* libftdi does not do background read, be sure that USB IN buffer does not overflow (128
291 if (presto
->buff_out_pos
>= BUFFER_SIZE
|| presto
->buff_in_exp
== 128)
292 return presto_flush();
298 static int presto_getbyte(void)
300 if (presto
->buff_in_pos
< presto
->buff_in_len
)
301 return presto
->buff_in
[presto
->buff_in_pos
++];
303 if (presto
->buff_in_exp
== 0)
306 if (presto_flush() != ERROR_OK
)
309 if (presto
->buff_in_pos
< presto
->buff_in_len
)
310 return presto
->buff_in
[presto
->buff_in_pos
++];
316 /* -------------------------------------------------------------------------- */
318 static int presto_tdi_flush(void)
320 if (presto
->jtag_tdi_count
== 0)
323 if (presto
->jtag_tck
== 0) {
324 LOG_ERROR("BUG: unexpected TAP condition, TCK low");
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;
336 static int presto_tck_idle(void)
338 if (presto
->jtag_tck
== 1) {
339 presto_sendbyte(0xCA);
340 presto
->jtag_tck
= 0;
346 /* -------------------------------------------------------------------------- */
348 static int presto_bitq_out(int tms
, int tdi
, int tdo_req
)
353 if (presto
->jtag_tck
== 0)
354 presto_sendbyte(0xA4); /* LED indicator - 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
;
358 if (++presto
->jtag_tdi_count
== 4)
366 cmd
= tdi
? 0xCB : 0xCA;
367 presto_sendbyte(cmd
);
369 if (tms
!= presto
->jtag_tms
) {
370 presto_sendbyte((tms
? 0xEC : 0xE8) | (presto
->jtag_rst
? 0x02 : 0));
371 presto
->jtag_tms
= tms
;
374 /* delay with TCK low */
375 for (i
= presto
->jtag_speed
; i
> 1; i
--)
376 presto_sendbyte(cmd
);
379 presto_sendbyte(cmd
| (tdo_req
? 0x10 : 0));
381 /* delay with TCK high */
382 for (i
= presto
->jtag_speed
; i
> 1; i
--)
383 presto_sendbyte(cmd
);
385 presto
->jtag_tck
= 1;
390 static int presto_bitq_flush(void)
395 presto_sendbyte(0xA0); /* LED indicator - JTAG idle */
397 return presto_flush();
400 static int presto_bitq_in_rdy(void)
402 if (presto
->buff_in_pos
>= presto
->buff_in_len
)
404 return presto
->buff_in_len
-presto
->buff_in_pos
;
407 static int presto_bitq_in(void)
409 if (presto
->buff_in_pos
>= presto
->buff_in_len
)
411 if (presto
->buff_in
[presto
->buff_in_pos
++]&0x08)
416 static int presto_bitq_sleep(unsigned long us
)
429 waits
= us
/ 170 + 2;
431 presto_sendbyte(0x80);
436 static int presto_bitq_reset(int trst
, int srst
)
441 /* add a delay after possible TCK transition */
442 presto_sendbyte(0x80);
443 presto_sendbyte(0x80);
445 presto
->jtag_rst
= trst
|| srst
;
446 presto_sendbyte((presto
->jtag_rst
? 0xEA : 0xE8) | (presto
->jtag_tms
? 0x04 : 0));
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
,
460 /* -------------------------------------------------------------------------- */
462 static int presto_adapter_khz(int khz
, int *jtag_speed
)
466 return ERROR_COMMAND_SYNTAX_ERROR
;
472 *jtag_speed
= (1000 + khz
-1)/khz
;
477 static int presto_jtag_speed_div(int speed
, int *khz
)
479 if ((speed
< 0) || (speed
> 1000)) {
481 return ERROR_COMMAND_SYNTAX_ERROR
;
492 static int presto_jtag_speed(int speed
)
496 if (presto_jtag_speed_div(speed
, &khz
))
497 return ERROR_COMMAND_SYNTAX_ERROR
;
499 presto
->jtag_speed
= speed
;
502 LOG_INFO("setting speed to %d, max. TCK freq. is %d MHz", speed
, khz
/1000);
504 LOG_INFO("setting speed to %d, max. TCK freq. is %d kHz", speed
, khz
);
509 static char *presto_serial
;
511 COMMAND_HANDLER(presto_handle_serial_command
)
515 presto_serial
= strdup(CMD_ARGV
[0]);
517 return ERROR_COMMAND_SYNTAX_ERROR
;
522 static const struct command_registration presto_subcommand_handlers
[] = {
525 .handler
= presto_handle_serial_command
,
526 .mode
= COMMAND_CONFIG
,
527 .help
= "Configure USB serial number of Presto device.",
528 .usage
= "serial_string",
530 COMMAND_REGISTRATION_DONE
533 static const struct command_registration presto_command_handlers
[] = {
537 .help
= "perform presto management",
538 .chain
= presto_subcommand_handlers
,
541 COMMAND_REGISTRATION_DONE
544 static int presto_jtag_init(void)
546 if (presto_open(presto_serial
) != ERROR_OK
) {
549 LOG_ERROR("Cannot open PRESTO, serial number '%s'", presto_serial
);
551 LOG_ERROR("Cannot open PRESTO");
552 return ERROR_JTAG_INIT_FAILED
;
554 LOG_INFO("PRESTO open, serial number '%s'", presto
->serial
);
556 bitq_interface
= &presto_bitq
;
560 static int presto_jtag_quit(void)
564 LOG_INFO("PRESTO closed");
567 presto_serial
= NULL
;
572 static struct jtag_interface presto_interface
= {
573 .execute_queue
= bitq_execute_queue
,
576 struct adapter_driver presto_adapter_driver
= {
578 .transports
= jtag_only
,
579 .commands
= presto_command_handlers
,
581 .init
= presto_jtag_init
,
582 .quit
= presto_jtag_quit
,
583 .speed
= presto_jtag_speed
,
584 .khz
= presto_adapter_khz
,
585 .speed_div
= presto_jtag_speed_div
,
587 .jtag_ops
= &presto_interface
,
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)