95c59303b0d68fa936a1857a07f66369c0659408
[openocd.git] / src / jtag / 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, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #if IS_CYGWIN == 1
25 #include "windows.h"
26 #undef ERROR
27 #endif
28
29 #include "replacements.h"
30
31 /* project specific includes */
32 #include "log.h"
33 #include "types.h"
34 #include "jtag.h"
35 #include "configuration.h"
36 #include "time_support.h"
37 #include "bitq.h"
38
39 /* system includes */
40 #include <string.h>
41 #include <stdlib.h>
42 #include <unistd.h>
43
44 #include <sys/time.h>
45 #include <time.h>
46
47 #include "ftd2xx.h"
48
49
50 int presto_jtag_speed(int speed);
51 int presto_jtag_register_commands(struct command_context_s *cmd_ctx);
52 int presto_jtag_init(void);
53 int presto_jtag_quit(void);
54
55 jtag_interface_t presto_interface =
56 {
57 .name = "presto",
58 .execute_queue = bitq_execute_queue,
59 .support_pathmove = 1,
60 .speed = presto_jtag_speed,
61 .register_commands = presto_jtag_register_commands,
62 .init = presto_jtag_init,
63 .quit = presto_jtag_quit,
64 };
65
66
67 int presto_bitq_out(int tms, int tdi, int tdo_req);
68 int presto_bitq_flush(void);
69 int presto_bitq_sleep(unsigned long us);
70 int presto_bitq_reset(int rst, int en);
71 int presto_bitq_in_rdy(void);
72 int presto_bitq_in(void);
73
74 bitq_interface_t presto_bitq =
75 {
76 .out = presto_bitq_out,
77 .flush = presto_bitq_flush,
78 .sleep = presto_bitq_sleep,
79 .reset = presto_bitq_reset,
80 .in_rdy = presto_bitq_in_rdy,
81 .in = presto_bitq_in,
82 };
83
84
85 /* -------------------------------------------------------------------------- */
86
87
88 #define FT_DEVICE_NAME_LEN 64
89 #define FT_DEVICE_SERNUM_LEN 64
90
91 #define PRESTO_VID_PID 0x0403f1a0
92
93 #define PRST_OK 0
94 #define PRST_ERR 1
95 #define PRST_TIMEOUT 2
96
97 #define BUFFER_SIZE (64*62)
98
99
100 typedef struct presto_s
101 {
102 FT_HANDLE handle;
103 FT_STATUS status;
104
105 char serial[FT_DEVICE_SERNUM_LEN];
106
107 BYTE buff_out[BUFFER_SIZE];
108 int buff_out_pos;
109
110 BYTE buff_in[BUFFER_SIZE];
111 int buff_in_exp; /* expected in buffer length */
112 int buff_in_len; /* length of data received */
113 int buff_in_pos;
114
115 unsigned long total_out;
116 unsigned long total_in;
117
118 int jtag_tms; /* last tms state */
119 int jtag_tck; /* last tck state */
120
121 int jtag_tdi_data;
122 int jtag_tdi_count;
123
124 } presto_t;
125
126 presto_t presto_state;
127 presto_t *presto=&presto_state;
128
129 BYTE presto_init_seq[] =
130 {
131 0x80, 0xA0, 0xA8, 0xB0, 0xC0, 0xE0
132 };
133
134
135 int presto_open(char *req_serial)
136 {
137 int i;
138 DWORD numdevs;
139 DWORD vidpid;
140 char devname[FT_DEVICE_NAME_LEN];
141 FT_DEVICE device;
142
143 BYTE presto_data;
144 unsigned long ftbytes;
145
146 presto->handle = (FT_HANDLE)INVALID_HANDLE_VALUE;
147
148 presto->buff_out_pos=0;
149 presto->buff_in_pos=0;
150 presto->buff_in_len=0;
151 presto->buff_in_exp=0;
152
153 presto->total_out=0;
154 presto->total_in=0;
155
156 presto->jtag_tms=0;
157 presto->jtag_tck=0;
158 presto->jtag_tdi_data=0;
159 presto->jtag_tdi_count=0;
160
161 if (FT_ListDevices(&numdevs, NULL, FT_LIST_NUMBER_ONLY)!=FT_OK) return PRST_ERR;
162 for (i=0; i<numdevs; i++)
163 {
164 if (FT_Open(i, &(presto->handle))!=FT_OK) continue;
165 if (FT_GetDeviceInfo(presto->handle,&device,&vidpid,presto->serial,devname,NULL)==FT_OK)
166 {
167 if (vidpid==PRESTO_VID_PID && (req_serial==NULL || !strcmp(presto->serial,req_serial)))
168 break;
169 }
170 FT_Close(presto->handle);
171 presto->handle = (FT_HANDLE)INVALID_HANDLE_VALUE;
172 }
173
174 if (presto->handle == (FT_HANDLE)INVALID_HANDLE_VALUE) return PRST_ERR;
175
176 if ((presto->status=FT_SetLatencyTimer(presto->handle,1))!=FT_OK) return PRST_ERR;
177 if ((presto->status=FT_SetTimeouts(presto->handle,100,0))!=FT_OK) return PRST_ERR;
178 if ((presto->status=FT_Purge(presto->handle, FT_PURGE_TX|FT_PURGE_RX))!=FT_OK) return PRST_ERR;
179
180 presto_data=0xD0;
181 if ((presto->status=FT_Write(presto->handle,&presto_data,1,&ftbytes))!=FT_OK) return PRST_ERR;
182 if ((presto->status=FT_Read(presto->handle,&presto_data,1,&ftbytes))!=FT_OK) return PRST_ERR;
183
184 if (ftbytes!=1)
185 {
186 if ((presto->status=FT_SetBitMode(presto->handle,0x80,1))!=FT_OK) return PRST_ERR;
187 if ((presto->status=FT_Purge(presto->handle, FT_PURGE_TX|FT_PURGE_RX))!=FT_OK) return PRST_ERR ;
188 if ((presto->status=FT_SetBaudRate(presto->handle,9600))!=FT_OK) return PRST_ERR;
189
190 presto_data=0;
191 for (i=0; i<4*62; i++)
192 if ((presto->status=FT_Write(presto->handle,&presto_data,1,&ftbytes))!=FT_OK) return PRST_ERR;
193
194 usleep(100000);
195
196 if ((presto->status=FT_SetBitMode(presto->handle,0x00,0))!=FT_OK) return PRST_ERR;
197 if ((presto->status=FT_Purge(presto->handle, FT_PURGE_TX|FT_PURGE_RX))!=FT_OK) return PRST_ERR;
198
199 presto_data=0xD0;
200 if ((presto->status=FT_Write(presto->handle,&presto_data,1,&ftbytes))!=FT_OK) return PRST_ERR;
201 if ((presto->status=FT_Read(presto->handle,&presto_data,1,&ftbytes))!=FT_OK) return PRST_ERR;
202 if (ftbytes!=1) return PRST_ERR;
203 }
204
205 if ((presto->status=FT_SetTimeouts(presto->handle,0,0))!=FT_OK) return PRST_ERR;
206
207 presto->status=FT_Write(presto->handle,&presto_init_seq,sizeof(presto_init_seq),&ftbytes);
208 if (presto->status!=FT_OK) return PRST_ERR;
209 if (ftbytes!=sizeof(presto_init_seq)) return PRST_TIMEOUT;
210
211 return PRST_OK;
212 }
213
214
215 int presto_close(void)
216 {
217 unsigned long ftbytes;
218
219 int result=PRST_OK;
220
221 if (presto->handle == (FT_HANDLE)INVALID_HANDLE_VALUE) return result;
222
223 presto->status=FT_Write(presto->handle,&presto_init_seq,sizeof(presto_init_seq),&ftbytes);
224 if (presto->status!=FT_OK) result=PRST_ERR;
225 if (ftbytes!=sizeof(presto_init_seq)) result=PRST_TIMEOUT;
226
227 if ((presto->status=FT_SetLatencyTimer(presto->handle,16))!=FT_OK) result=PRST_ERR;
228
229 if ((presto->status=FT_Close(presto->handle))!=FT_OK) result=PRST_ERR;
230 else presto->handle = (FT_HANDLE)INVALID_HANDLE_VALUE;
231
232 return result;
233 }
234
235
236 int presto_flush(void)
237 {
238 unsigned long ftbytes;
239
240 if (presto->buff_out_pos==0) return PRST_OK;
241 if (presto->status!=FT_OK) return PRST_ERR;
242
243 if ((presto->status=FT_Write(presto->handle, presto->buff_out, presto->buff_out_pos, &ftbytes))!=FT_OK)
244 {
245 presto->buff_out_pos=0;
246 return PRST_ERR;
247 }
248
249 presto->total_out+=ftbytes;
250
251 if (presto->buff_out_pos!=ftbytes)
252 {
253 presto->buff_out_pos=0;
254 return PRST_TIMEOUT;
255 }
256
257 presto->buff_out_pos=0;
258
259 if (presto->buff_in_exp==0) return PRST_OK;
260
261 presto->buff_in_pos=0;
262 presto->buff_in_len=0;
263
264 if ((presto->status=FT_Read(presto->handle, presto->buff_in, presto->buff_in_exp, &ftbytes))!=FT_OK)
265 {
266 presto->buff_in_exp=0;
267 return PRST_ERR;
268 }
269
270 presto->total_in+=ftbytes;
271
272 if (ftbytes!=presto->buff_in_exp)
273 {
274 presto->buff_in_exp=0;
275 return PRST_TIMEOUT;
276 }
277
278 presto->buff_in_len=presto->buff_in_exp;
279 presto->buff_in_exp=0;
280
281 return PRST_OK;
282 }
283
284
285 int presto_sendbyte(int data)
286 {
287 if (data==EOF) return presto_flush();
288
289 if (presto->buff_out_pos < BUFFER_SIZE)
290 {
291 presto->buff_out[presto->buff_out_pos++]=(BYTE)data;
292 if (((data&0xC0)==0x40) || ((data&0xD0)==0xD0))
293 presto->buff_in_exp++;
294 }
295 else return PRST_ERR;
296
297 if (presto->buff_out_pos >= BUFFER_SIZE) return presto_flush();
298 return PRST_OK;
299 }
300
301
302 int presto_getbyte(void)
303 {
304 if (presto->buff_in_pos<presto->buff_in_len)
305 return presto->buff_in[presto->buff_in_pos++];
306
307 if (presto->buff_in_exp==0) return -1;
308 if (presto_flush()!=PRST_OK) 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
316
317 /* -------------------------------------------------------------------------- */
318
319
320 int presto_bitq_out(int tms, int tdi, int tdo_req)
321 {
322 unsigned char cmdparam;
323
324 if (presto->jtag_tck==0)
325 {
326 presto_sendbyte(0xA4);
327 presto->jtag_tck=1;
328 }
329
330 else if (!tdo_req && tms==presto->jtag_tms)
331 {
332 if (presto->jtag_tdi_count==0) presto->jtag_tdi_data=(tdi!=0);
333 else presto->jtag_tdi_data|=(tdi!=0)<<presto->jtag_tdi_count;
334 if (++presto->jtag_tdi_count==4)
335 {
336 presto->jtag_tdi_data|=(presto->jtag_tdi_count-1)<<4;
337 presto_sendbyte(presto->jtag_tdi_data);
338 presto->jtag_tdi_count=0;
339 }
340 return 0;
341 }
342
343 if (presto->jtag_tdi_count)
344 {
345 presto->jtag_tdi_data|=(presto->jtag_tdi_count-1)<<4;
346 presto_sendbyte(presto->jtag_tdi_data);
347 presto->jtag_tdi_count=0;
348 }
349
350 if (tdi) cmdparam=0x0B;
351 else cmdparam=0x0A;
352
353 presto_sendbyte(0xC0|cmdparam);
354
355 if (tms!=presto->jtag_tms)
356 {
357 if (tms) presto_sendbyte(0xEC);
358 else presto_sendbyte(0xE8);
359 presto->jtag_tms=tms;
360 }
361
362 if (tdo_req) presto_sendbyte(0xD4|cmdparam);
363 else presto_sendbyte(0xC4|cmdparam);
364
365 return 0;
366 }
367
368
369 int presto_bitq_flush(void)
370 {
371 if (presto->jtag_tdi_count)
372 {
373 presto->jtag_tdi_data|=(presto->jtag_tdi_count-1)<<4;
374 presto_sendbyte(presto->jtag_tdi_data);
375 presto->jtag_tdi_count=0;
376 }
377
378 presto_sendbyte(0xCA);
379 presto->jtag_tck=0;
380
381 presto_sendbyte(0xA0);
382
383 return presto_flush();
384 }
385
386
387 int presto_bitq_in_rdy(void)
388 {
389 if (presto->buff_in_pos>=presto->buff_in_len) return 0;
390 return presto->buff_in_len-presto->buff_in_pos;
391 }
392
393
394 int presto_bitq_in(void)
395 {
396 if (presto->buff_in_pos>=presto->buff_in_len) return -1;
397 if (presto->buff_in[presto->buff_in_pos++]&0x08) return 1;
398 return 0;
399 }
400
401
402 int presto_bitq_sleep(unsigned long us)
403 {
404 long waits;
405
406 if (us>100000)
407 {
408 presto_bitq_flush();
409 jtag_sleep(us);
410 return 0;
411 }
412
413 waits=us/170+2;
414 while (waits--) presto_sendbyte(0x80);
415
416 return 0;
417 }
418
419
420 int presto_bitq_reset(int trst, int srst)
421 {
422 unsigned char cmd;
423
424 cmd=0xE8;
425 if (presto->jtag_tms) cmd|=0x04;
426
427 if (trst || srst) cmd|=0x02;
428
429 presto_sendbyte(cmd);
430 return 0;
431 }
432
433
434 /* -------------------------------------------------------------------------- */
435
436
437 int presto_jtag_speed(int speed)
438 {
439 jtag_speed=speed;
440 return ERROR_OK;
441 }
442
443
444 char *presto_serial;
445
446 int presto_handle_serial_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
447 {
448 if (argc == 1)
449 {
450 if (presto_serial) free(presto_serial);
451 presto_serial = strdup(args[0]);
452 }
453 else
454 {
455 ERROR("expected exactly one argument to presto_serial <serial-number>");
456 }
457
458 return ERROR_OK;
459 }
460
461
462 int presto_jtag_register_commands(struct command_context_s *cmd_ctx)
463 {
464 register_command(cmd_ctx, NULL, "presto_serial", presto_handle_serial_command,
465 COMMAND_CONFIG, NULL);
466 return ERROR_OK;
467 }
468
469
470 int presto_jtag_init(void)
471 {
472 if (presto_open(presto_serial)!=0)
473 {
474 presto_close();
475 if (presto_serial!=NULL) ERROR("Cannot open PRESTO, serial number %s", presto_serial);
476 else ERROR("Cannot open PRESTO");
477 return ERROR_JTAG_INIT_FAILED;
478 }
479 INFO("PRESTO open, serial number %s", presto->serial);
480
481 bitq_interface=&presto_bitq;
482 return ERROR_OK;
483 }
484
485
486 int presto_jtag_quit(void)
487 {
488 bitq_cleanup();
489 presto_close();
490 INFO("PRESTO closed");
491
492 if (presto_serial)
493 {
494 free(presto_serial);
495 presto_serial=NULL;
496 }
497
498 return ERROR_OK;
499 }

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)