]> git.sur5r.net Git - openocd/blob - src/jtag/presto.c
95c59303b0d68fa936a1857a07f66369c0659408
[openocd] / 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 }