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/adapter.h>
33 #include <jtag/interface.h>
34 #include <helper/time_support.h>
37 /* PRESTO access library includes */
38 #include "libftdi_helper.h"
40 /* -------------------------------------------------------------------------- */
42 #define FT_DEVICE_NAME_LEN 64
43 #define FT_DEVICE_SERNUM_LEN 64
45 #define PRESTO_VID_PID 0x0403f1a0
46 #define PRESTO_VID (0x0403)
47 #define PRESTO_PID (0xf1a0)
49 #define BUFFER_SIZE (64*62)
52 struct ftdi_context ftdic
;
55 char serial
[FT_DEVICE_SERNUM_LEN
];
57 uint8_t buff_out
[BUFFER_SIZE
];
60 uint8_t buff_in
[BUFFER_SIZE
];
61 int buff_in_exp
;/* expected in buffer length */
62 int buff_in_len
;/* length of data received */
65 unsigned long total_out
;
66 unsigned long total_in
;
68 int jtag_tms
; /* last tms state */
69 int jtag_tck
; /* last tck state */
70 int jtag_rst
; /* last trst state */
78 static struct presto presto_state
;
79 static struct presto
*presto
= &presto_state
;
81 static uint8_t presto_init_seq
[] = {
82 0x80, 0xA0, 0xA8, 0xB0, 0xC0, 0xE0
85 static int presto_write(uint8_t *buf
, uint32_t size
)
88 presto
->retval
= ftdi_write_data(&presto
->ftdic
, buf
, size
);
89 if (presto
->retval
< 0) {
90 LOG_ERROR("ftdi_write_data: %s", ftdi_get_error_string(&presto
->ftdic
));
91 return ERROR_JTAG_DEVICE_ERROR
;
93 ftbytes
= presto
->retval
;
95 if (ftbytes
!= size
) {
96 LOG_ERROR("couldn't write the requested number of bytes to PRESTO (%u < %u)",
97 (unsigned)ftbytes
, (unsigned)size
);
98 return ERROR_JTAG_DEVICE_ERROR
;
104 static int presto_read(uint8_t *buf
, uint32_t size
)
106 uint32_t ftbytes
= 0;
108 struct timeval timeout
, now
;
109 gettimeofday(&timeout
, NULL
);
110 timeval_add_time(&timeout
, 1, 0); /* one second timeout */
112 while (ftbytes
< size
) {
113 presto
->retval
= ftdi_read_data(&presto
->ftdic
, buf
+ ftbytes
, size
- ftbytes
);
114 if (presto
->retval
< 0) {
115 LOG_ERROR("ftdi_read_data: %s", ftdi_get_error_string(&presto
->ftdic
));
116 return ERROR_JTAG_DEVICE_ERROR
;
118 ftbytes
+= presto
->retval
;
120 gettimeofday(&now
, NULL
);
121 if (timeval_compare(&now
, &timeout
) > 0)
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(const 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_tcioflush(&presto
->ftdic
) < 0) {
165 LOG_ERROR("unable to flush 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_tcioflush(&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(const 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 indicator - 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 indicator - 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 int presto_jtag_init(void)
512 const char *presto_serial
= adapter_get_required_serial();
514 if (presto_open(presto_serial
) != ERROR_OK
) {
517 LOG_ERROR("Cannot open PRESTO, serial number '%s'", presto_serial
);
519 LOG_ERROR("Cannot open PRESTO");
520 return ERROR_JTAG_INIT_FAILED
;
522 LOG_INFO("PRESTO open, serial number '%s'", presto
->serial
);
524 bitq_interface
= &presto_bitq
;
528 static int presto_jtag_quit(void)
532 LOG_INFO("PRESTO closed");
536 static struct jtag_interface presto_interface
= {
537 .execute_queue
= bitq_execute_queue
,
540 struct adapter_driver presto_adapter_driver
= {
542 .transports
= jtag_only
,
544 .init
= presto_jtag_init
,
545 .quit
= presto_jtag_quit
,
546 .speed
= presto_jtag_speed
,
547 .khz
= presto_adapter_khz
,
548 .speed_div
= presto_jtag_speed_div
,
550 .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)