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 */
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 ((now
.tv_sec
> timeout
.tv_sec
) ||
121 ((now
.tv_sec
== timeout
.tv_sec
) && (now
.tv_usec
> timeout
.tv_usec
)))
125 if (ftbytes
!= size
) {
126 /* this is just a warning, there might have been timeout when detecting PRESTO,
127 *which is not fatal */
128 LOG_WARNING("couldn't read the requested number of bytes from PRESTO (%u < %u)",
129 (unsigned)ftbytes
, (unsigned)size
);
130 return ERROR_JTAG_DEVICE_ERROR
;
136 static int presto_open_libftdi(char *req_serial
)
140 LOG_DEBUG("searching for PRESTO using libftdi");
142 /* initialize FTDI context structure */
143 if (ftdi_init(&presto
->ftdic
) < 0) {
144 LOG_ERROR("unable to init libftdi: %s", presto
->ftdic
.error_str
);
145 return ERROR_JTAG_DEVICE_ERROR
;
148 /* context, vendor id, product id */
149 if (ftdi_usb_open_desc(&presto
->ftdic
, PRESTO_VID
, PRESTO_PID
, NULL
, req_serial
) < 0) {
150 LOG_ERROR("unable to open PRESTO: %s", presto
->ftdic
.error_str
);
151 return ERROR_JTAG_DEVICE_ERROR
;
154 if (ftdi_usb_reset(&presto
->ftdic
) < 0) {
155 LOG_ERROR("unable to reset PRESTO device");
156 return ERROR_JTAG_DEVICE_ERROR
;
159 if (ftdi_set_latency_timer(&presto
->ftdic
, 1) < 0) {
160 LOG_ERROR("unable to set latency timer");
161 return ERROR_JTAG_DEVICE_ERROR
;
164 if (ftdi_usb_purge_buffers(&presto
->ftdic
) < 0) {
165 LOG_ERROR("unable to purge PRESTO buffers");
166 return ERROR_JTAG_DEVICE_ERROR
;
170 if (presto_write(&presto_data
, 1) != ERROR_OK
) {
171 LOG_ERROR("error writing to PRESTO");
172 return ERROR_JTAG_DEVICE_ERROR
;
175 if (presto_read(&presto_data
, 1) != ERROR_OK
) {
176 LOG_DEBUG("no response from PRESTO, retrying");
178 if (ftdi_usb_purge_buffers(&presto
->ftdic
) < 0)
179 return ERROR_JTAG_DEVICE_ERROR
;
182 if (presto_write(&presto_data
, 1) != ERROR_OK
)
183 return ERROR_JTAG_DEVICE_ERROR
;
185 if (presto_read(&presto_data
, 1) != ERROR_OK
) {
186 LOG_ERROR("no response from PRESTO, giving up");
187 return ERROR_JTAG_DEVICE_ERROR
;
191 if (presto_write(presto_init_seq
, sizeof(presto_init_seq
)) != ERROR_OK
) {
192 LOG_ERROR("error writing PRESTO init sequence");
193 return ERROR_JTAG_DEVICE_ERROR
;
199 static int presto_open(char *req_serial
)
201 presto
->buff_out_pos
= 0;
202 presto
->buff_in_pos
= 0;
203 presto
->buff_in_len
= 0;
204 presto
->buff_in_exp
= 0;
206 presto
->total_out
= 0;
207 presto
->total_in
= 0;
209 presto
->jtag_tms
= 0;
210 presto
->jtag_tck
= 0;
211 presto
->jtag_rst
= 0;
212 presto
->jtag_tdi_data
= 0;
213 presto
->jtag_tdi_count
= 0;
215 presto
->jtag_speed
= 0;
217 return presto_open_libftdi(req_serial
);
220 static int presto_close(void)
223 int result
= ERROR_OK
;
225 presto
->retval
= ftdi_write_data(&presto
->ftdic
, presto_init_seq
, sizeof(presto_init_seq
));
226 if (presto
->retval
!= sizeof(presto_init_seq
))
227 result
= ERROR_JTAG_DEVICE_ERROR
;
229 presto
->retval
= ftdi_set_latency_timer(&presto
->ftdic
, 16);
230 if (presto
->retval
< 0)
231 result
= ERROR_JTAG_DEVICE_ERROR
;
233 presto
->retval
= ftdi_usb_close(&presto
->ftdic
);
234 if (presto
->retval
< 0)
235 result
= ERROR_JTAG_DEVICE_ERROR
;
237 ftdi_deinit(&presto
->ftdic
);
242 static int presto_flush(void)
244 if (presto
->buff_out_pos
== 0)
247 if (presto
->retval
< 0) {
248 LOG_DEBUG("error in previous communication, canceling I/O operation");
249 return ERROR_JTAG_DEVICE_ERROR
;
252 if (presto_write(presto
->buff_out
, presto
->buff_out_pos
) != ERROR_OK
) {
253 presto
->buff_out_pos
= 0;
254 return ERROR_JTAG_DEVICE_ERROR
;
257 presto
->total_out
+= presto
->buff_out_pos
;
258 presto
->buff_out_pos
= 0;
260 if (presto
->buff_in_exp
== 0)
263 presto
->buff_in_pos
= 0;
264 presto
->buff_in_len
= 0;
266 if (presto_read(presto
->buff_in
, presto
->buff_in_exp
) != ERROR_OK
) {
267 presto
->buff_in_exp
= 0;
268 return ERROR_JTAG_DEVICE_ERROR
;
271 presto
->total_in
+= presto
->buff_in_exp
;
272 presto
->buff_in_len
= presto
->buff_in_exp
;
273 presto
->buff_in_exp
= 0;
278 static int presto_sendbyte(int data
)
281 return presto_flush();
283 if (presto
->buff_out_pos
< BUFFER_SIZE
) {
284 presto
->buff_out
[presto
->buff_out_pos
++] = (uint8_t)data
;
285 if (((data
& 0xC0) == 0x40) || ((data
& 0xD0) == 0xD0))
286 presto
->buff_in_exp
++;
288 return ERROR_JTAG_DEVICE_ERROR
;
290 /* libftdi does not do background read, be sure that USB IN buffer does not overflow (128
292 if (presto
->buff_out_pos
>= BUFFER_SIZE
|| presto
->buff_in_exp
== 128)
293 return presto_flush();
299 static int presto_getbyte(void)
301 if (presto
->buff_in_pos
< presto
->buff_in_len
)
302 return presto
->buff_in
[presto
->buff_in_pos
++];
304 if (presto
->buff_in_exp
== 0)
307 if (presto_flush() != ERROR_OK
)
310 if (presto
->buff_in_pos
< presto
->buff_in_len
)
311 return presto
->buff_in
[presto
->buff_in_pos
++];
317 /* -------------------------------------------------------------------------- */
319 static int presto_tdi_flush(void)
321 if (presto
->jtag_tdi_count
== 0)
324 if (presto
->jtag_tck
== 0) {
325 LOG_ERROR("BUG: unexpected TAP condition, TCK low");
329 presto
->jtag_tdi_data
|= (presto
->jtag_tdi_count
- 1) << 4;
330 presto_sendbyte(presto
->jtag_tdi_data
);
331 presto
->jtag_tdi_count
= 0;
332 presto
->jtag_tdi_data
= 0;
337 static int presto_tck_idle(void)
339 if (presto
->jtag_tck
== 1) {
340 presto_sendbyte(0xCA);
341 presto
->jtag_tck
= 0;
347 /* -------------------------------------------------------------------------- */
349 static int presto_bitq_out(int tms
, int tdi
, int tdo_req
)
354 if (presto
->jtag_tck
== 0)
355 presto_sendbyte(0xA4); /* LED idicator - JTAG active */
356 else if (presto
->jtag_speed
== 0 && !tdo_req
&& tms
== presto
->jtag_tms
) {
357 presto
->jtag_tdi_data
|= (tdi
!= 0) << presto
->jtag_tdi_count
;
359 if (++presto
->jtag_tdi_count
== 4)
367 cmd
= tdi
? 0xCB : 0xCA;
368 presto_sendbyte(cmd
);
370 if (tms
!= presto
->jtag_tms
) {
371 presto_sendbyte((tms
? 0xEC : 0xE8) | (presto
->jtag_rst
? 0x02 : 0));
372 presto
->jtag_tms
= tms
;
375 /* delay with TCK low */
376 for (i
= presto
->jtag_speed
; i
> 1; i
--)
377 presto_sendbyte(cmd
);
380 presto_sendbyte(cmd
| (tdo_req
? 0x10 : 0));
382 /* delay with TCK high */
383 for (i
= presto
->jtag_speed
; i
> 1; i
--)
384 presto_sendbyte(cmd
);
386 presto
->jtag_tck
= 1;
391 static int presto_bitq_flush(void)
396 presto_sendbyte(0xA0); /* LED idicator - JTAG idle */
398 return presto_flush();
401 static int presto_bitq_in_rdy(void)
403 if (presto
->buff_in_pos
>= presto
->buff_in_len
)
405 return presto
->buff_in_len
-presto
->buff_in_pos
;
408 static int presto_bitq_in(void)
410 if (presto
->buff_in_pos
>= presto
->buff_in_len
)
412 if (presto
->buff_in
[presto
->buff_in_pos
++]&0x08)
417 static int presto_bitq_sleep(unsigned long us
)
430 waits
= us
/ 170 + 2;
432 presto_sendbyte(0x80);
437 static int presto_bitq_reset(int trst
, int srst
)
442 /* add a delay after possible TCK transition */
443 presto_sendbyte(0x80);
444 presto_sendbyte(0x80);
446 presto
->jtag_rst
= trst
|| srst
;
447 presto_sendbyte((presto
->jtag_rst
? 0xEA : 0xE8) | (presto
->jtag_tms
? 0x04 : 0));
452 static struct bitq_interface presto_bitq
= {
453 .out
= &presto_bitq_out
,
454 .flush
= &presto_bitq_flush
,
455 .sleep
= &presto_bitq_sleep
,
456 .reset
= &presto_bitq_reset
,
457 .in_rdy
= &presto_bitq_in_rdy
,
458 .in
= &presto_bitq_in
,
461 /* -------------------------------------------------------------------------- */
463 static int presto_adapter_khz(int khz
, int *jtag_speed
)
467 return ERROR_COMMAND_SYNTAX_ERROR
;
473 *jtag_speed
= (1000 + khz
-1)/khz
;
478 static int presto_jtag_speed_div(int speed
, int *khz
)
480 if ((speed
< 0) || (speed
> 1000)) {
482 return ERROR_COMMAND_SYNTAX_ERROR
;
493 static int presto_jtag_speed(int speed
)
497 if (presto_jtag_speed_div(speed
, &khz
))
498 return ERROR_COMMAND_SYNTAX_ERROR
;
500 presto
->jtag_speed
= speed
;
503 LOG_INFO("setting speed to %d, max. TCK freq. is %d MHz", speed
, khz
/1000);
505 LOG_INFO("setting speed to %d, max. TCK freq. is %d kHz", speed
, khz
);
510 static char *presto_serial
;
512 COMMAND_HANDLER(presto_handle_serial_command
)
517 presto_serial
= strdup(CMD_ARGV
[0]);
519 return ERROR_COMMAND_SYNTAX_ERROR
;
524 static const struct command_registration presto_command_handlers
[] = {
526 .name
= "presto_serial",
527 .handler
= presto_handle_serial_command
,
528 .mode
= COMMAND_CONFIG
,
529 .help
= "Configure USB serial number of Presto device.",
530 .usage
= "serial_string",
532 COMMAND_REGISTRATION_DONE
535 static int presto_jtag_init(void)
537 if (presto_open(presto_serial
) != ERROR_OK
) {
539 if (presto_serial
!= NULL
)
540 LOG_ERROR("Cannot open PRESTO, serial number '%s'", presto_serial
);
542 LOG_ERROR("Cannot open PRESTO");
543 return ERROR_JTAG_INIT_FAILED
;
545 LOG_INFO("PRESTO open, serial number '%s'", presto
->serial
);
547 bitq_interface
= &presto_bitq
;
551 static int presto_jtag_quit(void)
555 LOG_INFO("PRESTO closed");
559 presto_serial
= NULL
;
565 struct jtag_interface presto_interface
= {
567 .commands
= presto_command_handlers
,
569 .execute_queue
= bitq_execute_queue
,
570 .speed
= presto_jtag_speed
,
571 .khz
= presto_adapter_khz
,
572 .speed_div
= presto_jtag_speed_div
,
573 .init
= presto_jtag_init
,
574 .quit
= presto_jtag_quit
,
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)