OpenCores
URL https://opencores.org/ocsvn/xulalx25soc/xulalx25soc/trunk

Subversion Repositories xulalx25soc

[/] [xulalx25soc/] [trunk/] [sw/] [usbi.cpp] - Blame information for rev 5

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 5 dgisselq
////////////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    
4
//
5
// Project:     XuLA2 board
6
//
7
// Purpose:     Creates a USB port, similar to a serial port, out of the
8
//              XuLA2 JTAG interface S/W.
9
//
10
//
11
// Creator:     Dan Gisselquist, Ph.D.
12
//              Gisselquist Technology, LLC
13
//
14
////////////////////////////////////////////////////////////////////////////////
15
//
16
// Copyright (C) 2015, Gisselquist Technology, LLC
17
//
18
// This program is free software (firmware): you can redistribute it and/or
19
// modify it under the terms of  the GNU General Public License as published
20
// by the Free Software Foundation, either version 3 of the License, or (at
21
// your option) any later version.
22
//
23
// This program is distributed in the hope that it will be useful, but WITHOUT
24
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
25
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
26
// for more details.
27
//
28
// License:     GPL, v3, as defined and found on www.gnu.org,
29
//              http://www.gnu.org/licenses/gpl.html
30
//
31
//
32
////////////////////////////////////////////////////////////////////////////////
33
//
34
//
35
#include <stdio.h>
36
#include <stdlib.h>
37
#include <unistd.h>
38
#include <string.h>
39
#include <ctype.h>
40
// #include <usb.h>
41
 
42
#include <libusb.h>
43
 
44
#include "llcomms.h"
45
#include "usbi.h"
46
 
47
// Walk us through the JTAG Chain:
48
//      5-1's to go to test/reset
49
//      0        to go to Run-Test/Idle
50
//      1       to go to select-dr-scan
51
//      1       to go to select-ir-scan
52
//      0        to go to capture-ir
53
//      0        to go to shift-ir
54
//      (6-bit code 0x02 through TDI to IR, while sending 0-bits to TMS)
55
//      1       to leave shift IR and go to exit1-ir
56
//      1       to go to update-ir
57
//      1       to go to select-dr-scan
58
//      0        to go to capture-dr
59
//      0        to go to shift-dr
60
#define RESET_JTAG_LEN  12
61
static const char       RESET_TO_USER_DR[RESET_JTAG_LEN] = {
62
        JTAG_CMD,
63
        21, // clocks
64
        0,0,0,     // Also clocks, higher order bits
65
        PUT_TMS_MASK | PUT_TDI_MASK, // flags
66
        (char)(0x0df),  // TMS: Five ones, then one zero, and two ones -- low bits first
67
        0x00,   // TDI: irrelevant here
68
        (char)0x80,     // TMS: two zeros, then six zeros
69
        0x08,   // TDI: user command #1, bit reversed
70
        0x03,   // TMS: three ones, then two zeros
71
        0x00    // TDI byte -- irrelevant here
72
        //
73
        // 0xc0, // TDI byte -- user command #2
74
        // 0x40,        // TDI: user command #1
75
        // 0x0c, // TDI byte -- user command #2, bit reversed
76
};
77
 
78
//
79
//      TMS: 
80
#define TX_DR_LEN       12
81
static const    char    TX_DR_BITS[TX_DR_LEN] = {
82
        JTAG_CMD,
83
        48, // clocks
84
        0,0,0,     // Also clocks, higher order bits
85
        PUT_TDI_MASK, // flags
86
        (char)0x0ff, 0, 0, 0, 0, 0   // Six data bytes
87
        // module_id = 255
88
        // 32'h(payload.length)
89
        // payload
90
        // module_id + payload.len + num_result_bits, length=32 + payload ???
91
};
92
 
93
//
94
//      TMS: 
95
//      
96
#define REQ_RX_LEN      6
97
static const    char    REQ_RX_BITS[REQ_RX_LEN] = {
98
        JTAG_CMD,
99
        (const char)((USB_PKTLEN-REQ_RX_LEN)*8), // bits-requested
100
        0,0,0,     // Also clocks, higher order bits
101
        GET_TDO_MASK|TDI_VAL_MASK, // flags:TDI is kept low here, so no TDI flag
102
        // No data given, since there's no info to send or receive
103
        // Leave the result in shift-DR mode
104
};
105
 
106
/*
107
#define RETURN_TO_RESET_LEN     7
108
static const char       RETURN_TO_RESET[RETURN_TO_RESET_LEN] = {
109
        JTAG_CMD,
110
        5, // clocks
111
        0,0,0,  // Also clocks, higher order bits
112
        PUT_TMS_MASK, // flags
113
        (char)0x0ff, // Five ones
114
};
115
*/
116
 
117
USBI::USBI(void) {
118
        int     config;
119
 
120
        m_total_nread = 0;
121
 
122
        if (0 != libusb_init(&m_usb_context)) {
123
                fprintf(stderr, "Error initializing the USB library\n");
124
                perror("O/S Err:");
125
                exit(-1);
126
        }
127
 
128
        m_xula_usb_device = libusb_open_device_with_vid_pid(m_usb_context,
129
                VENDOR_ID, PRODUCT_ID);
130
        if (!m_xula_usb_device) {
131
                fprintf(stderr, "Could not open XuLA device\n");
132
                perror("O/S Err:");
133
 
134
                libusb_exit(m_usb_context);
135
                exit(-1);
136
        }
137
 
138
        if (0 != libusb_get_configuration(m_xula_usb_device, &config)) {
139
                fprintf(stderr, "Could not get configuration\n");
140
                perror("O/S Err:");
141
 
142
                libusb_close(m_xula_usb_device);
143
                libusb_exit(m_usb_context);
144
                exit(-1);
145
        }
146
 
147
        if (0 != libusb_claim_interface(m_xula_usb_device, XESS_INTERFACE)) {
148
                fprintf(stderr, "Could not claim interface\n");
149
                perror("O/S Err:");
150
 
151
                libusb_close(m_xula_usb_device);
152
                libusb_exit(m_usb_context);
153
                exit(-1);
154
        }
155
 
156
        unsigned char   abuf[RESET_JTAG_LEN];
157
        int     actual_length = RESET_JTAG_LEN, r;
158
 
159
        memcpy(abuf, RESET_TO_USER_DR, RESET_JTAG_LEN);
160
        r = libusb_bulk_transfer(m_xula_usb_device, XESS_ENDPOINT_OUT,
161
                abuf, RESET_JTAG_LEN, &actual_length, 4);
162
        if ((r!=0)||(actual_length != RESET_JTAG_LEN)) {
163
                // Try clearing the queue twice, then doing this
164
                do {
165
                        r = libusb_bulk_transfer(m_xula_usb_device, XESS_ENDPOINT_IN,
166
                                (unsigned char *)m_rxbuf, USB_PKTLEN, &actual_length, 20);
167
                } while((r==0)&&(actual_length > 0));
168
 
169
                r = libusb_bulk_transfer(m_xula_usb_device, XESS_ENDPOINT_OUT,
170
                        abuf, RESET_JTAG_LEN, &actual_length, 4);
171
                if ((r != 0)||(actual_length != RESET_JTAG_LEN)) {
172
                        printf("Some error took place requesting RESET_TO_USER_DR\n");
173
                        printf("r = %d, actual_length = %d (vs %d requested)\n",
174
                                r, actual_length, RESET_JTAG_LEN);
175
                        perror("O/S Err");
176
                        exit(-2);
177
                }
178
        }
179
 
180
        // Initialize our read FIFO
181
        m_rbeg = m_rend = 0;
182
 
183
        flush_read();
184
}
185
 
186
void    USBI::close(void) {
187
        // Release our interface
188
        if (0 != libusb_release_interface(m_xula_usb_device, XESS_INTERFACE)) {
189
                fprintf(stderr, "Could not release interface\n");
190
                perror("O/S Err:");
191
 
192
                libusb_close(m_xula_usb_device);
193
                libusb_exit(m_usb_context);
194
                exit(-1);
195
        }
196
 
197
        // And then close our device with
198
        libusb_close(m_xula_usb_device);
199
 
200
        // And just before exiting, we free our USB context
201
        libusb_exit(m_usb_context);
202
}
203
 
204
void    USBI::write(char *buf, int len) {
205
        int     r, actual_length;
206
 
207
        if (len >= USB_PKTLEN) {
208
                const int       nv = USB_PKTLEN/2-1;
209
                for(int pos=0; pos<len; pos+=nv)
210
                        write(&buf[pos], (len-pos>nv)?(nv):len-pos);
211
        } else {
212
                memset(m_txbuf, 0, len+6);
213
                m_txbuf[0] = JTAG_CMD;
214
                m_txbuf[1] = len * 8;
215
                m_txbuf[2] = 0;
216
                m_txbuf[3] = 0;
217
                m_txbuf[4] = 0;
218
                m_txbuf[5] = PUT_TDI_MASK | GET_TDO_MASK;
219
 
220
                for(int i=0; i<len; i++)
221
                        m_txbuf[6+i] = buf[i];
222
                r = libusb_bulk_transfer(m_xula_usb_device, XESS_ENDPOINT_OUT,
223
                        (unsigned char*)m_txbuf, len+6, &actual_length, 0);
224
                if ((r!=0)||(actual_length != len+6)) {
225
                        printf("WRITE::(buf, %d) -- ERR\n", len+6);
226
                        printf("r = %d, actual_length = %d (!= %d requested)\n", r,
227
                                actual_length, len+6);
228
 
229
                        if (r == -7) {
230
                                r = libusb_bulk_transfer(m_xula_usb_device,
231
                                        XESS_ENDPOINT_OUT,
232
                                        (unsigned char*)m_txbuf, len+6,
233
                                        &actual_length, 2);
234
                                if ((r!=0)||(actual_length != len+6)) {
235
                                        printf("WRITE::(buf, %d) -- ERR\n", len+6);
236
                                        printf("r = %d, actual_length = %d (!= %d requested)\n", r,
237
                                                actual_length, len+6);
238
                                        perror("O/S Err");
239
 
240
                                        exit(-2);
241
                                }
242
                        } else {
243
                                perror("O/S Err");
244
                                exit(-2);
245
                        }
246
                }
247
 
248
                // Try to read back however many bytes we can
249
                r = libusb_bulk_transfer(m_xula_usb_device, XESS_ENDPOINT_IN,
250
                        (unsigned char*)m_rxbuf, USB_PKTLEN, &actual_length, 20);
251
                if ((r==0)&&(actual_length > 0)) {
252
                        push_fifo(m_rxbuf, actual_length);
253
                } else {
254
                        printf("Some error took place in receiving\n");
255
                        perror("O/S Err");
256
                }
257
        }
258
}
259
 
260
int     USBI::read(char *buf, int len) {
261
        return read(buf, len, 4);
262
}
263
 
264
int     USBI::read(char *buf, int len, int timeout_ms) {
265
        int     left = len, nr=0;
266
 
267
        // printf("USBI::read(%d) (FIFO is %d-%d)\n", len, m_rend, m_rbeg);
268
        nr = pop_fifo(buf, left);
269
        left -= nr;
270
 
271
        while(left > 0) {
272
                raw_read(left, timeout_ms);
273
                nr = pop_fifo(buf, left);
274
                left -= nr;
275
 
276
                // printf("\tWHILE (nr = %d, LEFT = %d, len=%d)\n", nr, left, len);
277
                if (nr == 0)
278
                        break;
279
        }
280
 
281
        // printf("READ %d characters (%d req, %d left)\n", len-left, len, left);
282
        return len-left;
283
}
284
 
285
void    USBI::raw_read(const int clen, int timeout_ms) {
286
        int     avail = (m_rbeg - m_rend)&(RCV_BUFMASK), actual_length;
287
        int     len = clen;
288
        if (len > RCV_BUFMASK-avail)
289
                len = RCV_BUFMASK-avail;
290
        if (len > 26)
291
                len = 26;
292
 
293
        // printf("USBI::RAW-READ(%d, was %d)\n", len, clen);
294
        memcpy(m_txbuf, REQ_RX_BITS, REQ_RX_LEN);
295
 
296
        int r = libusb_bulk_transfer(m_xula_usb_device, XESS_ENDPOINT_OUT,
297
                (unsigned char *)m_txbuf, REQ_RX_LEN, &actual_length,
298
                timeout_ms);
299
        if ((r==0)&&(actual_length == REQ_RX_LEN)) {
300
        } else if (r == -7) {
301
                // Nothing to read in the timeout provided
302
                // We'll have to request this data again ... later
303
                return;
304
        } else {
305
                printf("READ(WRITE,READ-REQ) -- ERR\n");
306
                printf("r = %d, actual_length = %d (!= %d requested)\n", r,
307
                        actual_length, len+6);
308
                perror("O/S Err");
309
                exit(-2);
310
        }
311
 
312
        // Try to read back however many bytes we can
313
        r = libusb_bulk_transfer(m_xula_usb_device, XESS_ENDPOINT_IN,
314
                (unsigned char *)m_rxbuf, USB_PKTLEN, &actual_length, 0);
315
        if ((r==0)&&(actual_length > 0)) {
316
                /*
317
                printf("RAW-READ() -> %d Read\n", actual_length);
318
                for(int i=0; i<actual_length; i++)
319
                        printf("%02x ", m_rxbuf[i] & 0x0ff);
320
                printf("\n");
321
                */
322
                push_fifo(m_rxbuf, actual_length);
323
        } else if (r == -7) {
324
                // Nothing to read in the timeout provided
325
                // Return, adding nothing to our FIFO
326
        } else {
327
                printf("Some error took place in receiving\n");
328
                perror("O/S Err");
329
        }
330
 
331
        // fprintf(stderr, "\tUSBI::RAW-READ() -- COMPLETE (%d avail)\n",
332
                // (m_rbeg-m_rend)&(RCV_BUFMASK));
333
}
334
 
335
void    USBI::flush_read(void) {
336
        while(poll(4)) {
337
                m_rbeg = m_rend = 0;
338
        }
339
}
340
 
341
void    USBI::push_fifo(char *buf, int len) {
342
        char    last = 0;
343
        char    *sptr = buf;
344
 
345
        // printf("Pushing %d items onto FIFO (%d - %d)\n", len, m_rend, m_rbeg);
346
        if (m_rbeg != m_rend)
347
                last = m_rbuf[m_rend];
348
        for(int i=0; i<len; i++) {
349
                char v = *sptr++;
350
                if (((v & 0x80)||((unsigned char)v < 0x10))&&(v == last)) {
351
                        // printf("\tSkipping: %02x\n", v & 0x0ff);
352
                } else if ((unsigned char)v == 0x0ff) {
353
                } else {
354
                        m_rbuf[m_rbeg] = v;
355
                        m_rbeg = (m_rbeg+1)&(RCV_BUFMASK);
356
                        // printf("\tPushing: %02x\n", v & 0x0ff);
357
                } last = v;
358
        }
359
}
360
 
361
int     USBI::pop_fifo(char *buf, int len) {
362
        int     avail = (m_rbeg - m_rend)&(RCV_BUFMASK);
363
        int     left = len;
364
        int     nr = 0;
365
 
366
        // printf("Attempting to pop %d items from FIFO (%d - %d)\n",
367
                        // len, m_rend, m_rbeg);
368
        while((avail > 0)&&(left > 0)) {
369
                int ln = RCV_BUFLEN-m_rend;
370
                if (ln > left)
371
                        ln = left;
372
                if (ln > avail)
373
                        ln = avail;
374
                memcpy(&buf[len-left], &m_rbuf[m_rend], ln);
375
                left   -= ln;
376
                avail  -= ln;
377
                m_rend  = (m_rend + ln)&(RCV_BUFMASK);
378
                nr     += ln;
379
        }
380
 
381
        /*
382
        if (nr > 0)
383
                printf("\tPopped %d items, buf[0] = %02x (%d - %d)\n",
384
                        nr, buf[0], m_rend, m_rbeg);
385
        else
386
                printf("\tPopped nothing, %d - %d\n", m_rend, m_rbeg);
387
        */
388
        return nr;
389
}
390
 
391
bool    USBI::poll(unsigned ms) {
392
        int     avail = (m_rbeg-m_rend)&(RCV_BUFMASK);
393
        bool    r = true;
394
 
395
        // printf("POLL request\n");
396
 
397
        if ((avail < 2)&&((avail<1)||(m_rbuf[m_rend]&0x80)||(m_rbuf[m_rend]<0x10))) {
398
                raw_read(4,ms);
399
                avail = (m_rbeg-m_rend)&(RCV_BUFMASK);
400
                // printf("%d availabe\n", avail);
401
 
402
                char    v = (m_rbuf[(m_rbeg-1)&(RCV_BUFMASK)]);
403
                while(((v&0x80)==0)&&((unsigned)v>=0x10)&&(avail < RCV_BUFMASK-32)) {
404
                        raw_read(26,ms);
405
                        avail = (m_rbeg-m_rend)&(RCV_BUFMASK);
406
                }
407
                if (avail < 1)
408
                        r = false;
409
                else if ((avail==1)&&((m_rbuf[m_rend]&0x80)||(m_rbuf[m_rend]<0x10)))
410
                        r = false;
411
        }
412
 
413
        // printf("USBI::poll() -> %s (%d avail)\n", (r)?"true":"false", avail);
414
        return r;
415
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.