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