fe54b1312fd95c7ac317a221f222946b9459e2ca
[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 int result;
139 DWORD numdevs;
140 DWORD vidpid;
141 char devname[FT_DEVICE_NAME_LEN];
142 FT_DEVICE device;
143
144 BYTE presto_data;
145 unsigned long ftbytes;
146
147 presto->handle=INVALID_HANDLE_VALUE;
148
149 presto->buff_out_pos=0;
150 presto->buff_in_pos=0;
151 presto->buff_in_len=0;
152 presto->buff_in_exp=0;
153
154 presto->total_out=0;
155 presto->total_in=0;
156
157 presto->jtag_tms=0;
158 presto->jtag_tck=0;
159 presto->jtag_tdi_data=0;
160 presto->jtag_tdi_count=0;
161
162 if (FT_ListDevices(&numdevs, NULL, FT_LIST_NUMBER_ONLY)!=FT_OK) return PRST_ERR;
163 for (i=0; i<numdevs; i++)
164 {
165 if (FT_Open(i, &(presto->handle))!=FT_OK) continue;
166 if (FT_GetDeviceInfo(presto->handle,&device,&vidpid,presto->serial,devname,NULL)==FT_OK)
167 {
168 if (vidpid==PRESTO_VID_PID && (req_serial==NULL || !strcmp(presto->serial,req_serial)))
169 break;
170 }
171 FT_Close(presto->handle);
172 presto->handle=INVALID_HANDLE_VALUE;
173 }
174
175 if (presto->handle==INVALID_HANDLE_VALUE) return PRST_ERR;
176
177 if ((presto->status=FT_SetLatencyTimer(presto->handle,1))!=FT_OK) return PRST_ERR;
178 if ((presto->status=FT_SetTimeouts(presto->handle,100,0))!=FT_OK) return PRST_ERR;
179 if ((presto->status=FT_Purge(presto->handle, FT_PURGE_TX|FT_PURGE_RX))!=FT_OK) return PRST_ERR;
180
181 presto_data=0xD0;
182 if ((presto->status=FT_Write(presto->handle,&presto_data,1,&ftbytes))!=FT_OK) return PRST_ERR;
183 if ((presto->status=FT_Read(presto->handle,&presto_data,1,&ftbytes))!=FT_OK) return PRST_ERR;
184
185 if (ftbytes!=1)
186 {
187 if ((presto->status=FT_SetBitMode(presto->handle,0x80,1))!=FT_OK) return PRST_ERR;
188 if ((presto->status=FT_Purge(presto->handle, FT_PURGE_TX|FT_PURGE_RX))!=FT_OK) return PRST_ERR ;
189 if ((presto->status=FT_SetBaudRate(presto->handle,9600))!=FT_OK) return PRST_ERR;
190
191 presto_data=0;
192 for (i=0; i<4*62; i++)
193 if ((presto->status=FT_Write(presto->handle,&presto_data,1,&ftbytes))!=FT_OK) return PRST_ERR;
194
195 usleep(100000);
196
197 if ((presto->status=FT_SetBitMode(presto->handle,0x00,0))!=FT_OK) return PRST_ERR;
198 if ((presto->status=FT_Purge(presto->handle, FT_PURGE_TX|FT_PURGE_RX))!=FT_OK) return PRST_ERR;
199
200 presto_data=0xD0;
201 if ((presto->status=FT_Write(presto->handle,&presto_data,1,&ftbytes))!=FT_OK) return PRST_ERR;
202 if ((presto->status=FT_Read(presto->handle,&presto_data,1,&ftbytes))!=FT_OK) return PRST_ERR;
203 if (ftbytes!=1) return PRST_ERR;
204 }
205
206 if ((presto->status=FT_SetTimeouts(presto->handle,0,0))!=FT_OK) return PRST_ERR;
207
208 presto->status=FT_Write(presto->handle,&presto_init_seq,sizeof(presto_init_seq),&ftbytes);
209 if (presto->status!=FT_OK) return PRST_ERR;
210 if (ftbytes!=sizeof(presto_init_seq)) return PRST_TIMEOUT;
211
212 return PRST_OK;
213 }
214
215
216 int presto_close(void)
217 {
218 unsigned long ftbytes;
219
220 int result=PRST_OK;
221
222 if (presto->handle==INVALID_HANDLE_VALUE) return result;
223
224 presto->status=FT_Write(presto->handle,&presto_init_seq,sizeof(presto_init_seq),&ftbytes);
225 if (presto->status!=FT_OK) result=PRST_ERR;
226 if (ftbytes!=sizeof(presto_init_seq)) result=PRST_TIMEOUT;
227
228 if ((presto->status=FT_SetLatencyTimer(presto->handle,16))!=FT_OK) result=PRST_ERR;
229
230 if ((presto->status=FT_Close(presto->handle))!=FT_OK) result=PRST_ERR;
231 else presto->handle=INVALID_HANDLE_VALUE;
232
233 return result;
234 }
235
236
237 int presto_flush(void)
238 {
239 unsigned long ftbytes;
240
241 if (presto->buff_out_pos==0) return PRST_OK;
242 if (presto->status!=FT_OK) return PRST_ERR;
243
244 if ((presto->status=FT_Write(presto->handle, presto->buff_out, presto->buff_out_pos, &ftbytes))!=FT_OK)
245 {
246 presto->buff_out_pos=0;
247 return PRST_ERR;
248 }
249
250 presto->total_out+=ftbytes;
251
252 if (presto->buff_out_pos!=ftbytes)
253 {
254 presto->buff_out_pos=0;
255 return PRST_TIMEOUT;
256 }
257
258 presto->buff_out_pos=0;
259
260 if (presto->buff_in_exp==0) return PRST_OK;
261
262 presto->buff_in_pos=0;
263 presto->buff_in_len=0;
264
265 if ((presto->status=FT_Read(presto->handle, presto->buff_in, presto->buff_in_exp, &ftbytes))!=FT_OK)
266 {
267 presto->buff_in_exp=0;
268 return PRST_ERR;
269 }
270
271 presto->total_in+=ftbytes;
272
273 if (ftbytes!=presto->buff_in_exp)
274 {
275 presto->buff_in_exp=0;
276 return PRST_TIMEOUT;
277 }
278
279 presto->buff_in_len=presto->buff_in_exp;
280 presto->buff_in_exp=0;
281
282 return PRST_OK;
283 }
284
285
286 int presto_sendbyte(int data)
287 {
288 if (data==EOF) return presto_flush();
289
290 if (presto->buff_out_pos < BUFFER_SIZE)
291 {
292 presto->buff_out[presto->buff_out_pos++]=(BYTE)data;
293 if (((data&0xC0)==0x40) || ((data&0xD0)==0xD0))
294 presto->buff_in_exp++;
295 }
296 else return PRST_ERR;
297
298 if (presto->buff_out_pos >= BUFFER_SIZE) return presto_flush();
299 return PRST_OK;
300 }
301
302
303 int presto_getbyte(void)
304 {
305 if (presto->buff_in_pos<presto->buff_in_len)
306 return presto->buff_in[presto->buff_in_pos++];
307
308 if (presto->buff_in_exp==0) return -1;
309 if (presto_flush()!=PRST_OK) return -1;
310
311 if (presto->buff_in_pos<presto->buff_in_len)
312 return presto->buff_in[presto->buff_in_pos++];
313
314 return -1;
315 }
316
317
318 /* -------------------------------------------------------------------------- */
319
320
321 int presto_bitq_out(int tms, int tdi, int tdo_req)
322 {
323 unsigned char cmdparam;
324
325 if (presto->jtag_tck==0)
326 {
327 presto_sendbyte(0xA4);
328 presto->jtag_tck=1;
329 }
330
331 else if (!tdo_req && tms==presto->jtag_tms)
332 {
333 if (presto->jtag_tdi_count==0) presto->jtag_tdi_data=(tdi!=0);
334 else presto->jtag_tdi_data|=(tdi!=0)<<presto->jtag_tdi_count;
335 if (++presto->jtag_tdi_count==4)
336 {
337 presto->jtag_tdi_data|=(presto->jtag_tdi_count-1)<<4;
338 presto_sendbyte(presto->jtag_tdi_data);
339 presto->jtag_tdi_count=0;
340 }
341 return 0;
342 }
343
344 if (presto->jtag_tdi_count)
345 {
346 presto->jtag_tdi_data|=(presto->jtag_tdi_count-1)<<4;
347 presto_sendbyte(presto->jtag_tdi_data);
348 presto->jtag_tdi_count=0;
349 }
350
351 if (tdi) cmdparam=0x0B;
352 else cmdparam=0x0A;
353
354 presto_sendbyte(0xC0|cmdparam);
355
356 if (tms!=presto->jtag_tms)
357 {
358 if (tms) presto_sendbyte(0xEC);
359 else presto_sendbyte(0xE8);
360 presto->jtag_tms=tms;
361 }
362
363 if (tdo_req) presto_sendbyte(0xD4|cmdparam);
364 else presto_sendbyte(0xC4|cmdparam);
365
366 return 0;
367 }
368
369
370 int presto_bitq_flush(void)
371 {
372 if (presto->jtag_tdi_count)
373 {
374 presto->jtag_tdi_data|=(presto->jtag_tdi_count-1)<<4;
375 presto_sendbyte(presto->jtag_tdi_data);
376 presto->jtag_tdi_count=0;
377 }
378
379 presto_sendbyte(0xCA);
380 presto->jtag_tck=0;
381
382 presto_sendbyte(0xA0);
383
384 return presto_flush();
385 }
386
387
388 int presto_bitq_in_rdy(void)
389 {
390 if (presto->buff_in_pos>=presto->buff_in_len) return 0;
391 return presto->buff_in_len-presto->buff_in_pos;
392 }
393
394
395 int presto_bitq_in(void)
396 {
397 if (presto->buff_in_pos>=presto->buff_in_len) return -1;
398 if (presto->buff_in[presto->buff_in_pos++]&0x08) return 1;
399 return 0;
400 }
401
402
403 int presto_bitq_sleep(unsigned long us)
404 {
405 long waits;
406
407 if (us>100000)
408 {
409 presto_bitq_flush();
410 jtag_sleep(us);
411 return 0;
412 }
413
414 waits=us/170+2;
415 while (waits--) presto_sendbyte(0x80);
416
417 return 0;
418 }
419
420
421 int presto_bitq_reset(int trst, int srst)
422 {
423 unsigned char cmd;
424
425 cmd=0xE8;
426 if (presto->jtag_tms) cmd|=0x04;
427
428 if (trst || srst) cmd|=0x02;
429
430 presto_sendbyte(cmd);
431 return 0;
432 }
433
434
435 /* -------------------------------------------------------------------------- */
436
437
438 int presto_jtag_speed(int speed)
439 {
440 jtag_speed=speed;
441 return ERROR_OK;
442 }
443
444
445 char *presto_serial;
446
447 int presto_handle_serial_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
448 {
449 if (argc == 1)
450 {
451 if (presto_serial) free(presto_serial);
452 presto_serial = strdup(args[0]);
453 }
454 else
455 {
456 ERROR("expected exactly one argument to presto_serial <serial-number>");
457 }
458
459 return ERROR_OK;
460 }
461
462
463 int presto_jtag_register_commands(struct command_context_s *cmd_ctx)
464 {
465 register_command(cmd_ctx, NULL, "presto_serial", presto_handle_serial_command,
466 COMMAND_CONFIG, NULL);
467 return ERROR_OK;
468 }
469
470
471 int presto_jtag_init(void)
472 {
473 if (presto_open(presto_serial)!=0)
474 {
475 presto_close();
476 if (presto_serial!=NULL) ERROR("Cannot open PRESTO, serial number %s", presto_serial);
477 else ERROR("Cannot open PRESTO");
478 return ERROR_JTAG_INIT_FAILED;
479 }
480 INFO("PRESTO open, serial number %s", presto->serial);
481
482 bitq_interface=&presto_bitq;
483 return ERROR_OK;
484 }
485
486
487 int presto_jtag_quit(void)
488 {
489 bitq_cleanup();
490 presto_close();
491 INFO("PRESTO closed");
492
493 if (presto_serial)
494 {
495 free(presto_serial);
496 presto_serial=NULL;
497 }
498
499 return ERROR_OK;
500 }

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)