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

Subversion Repositories usb_fpga_2_14

[/] [usb_fpga_2_14/] [trunk/] [capi/] [c/] [memfifo.c] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 ZTEX
/*%
2
   ZTEX Core API for C with examples
3
   Copyright (C) 2009-2017 ZTEX GmbH.
4
   http://www.ztex.de
5
 
6
   This Source Code Form is subject to the terms of the Mozilla Public
7
   License, v. 2.0. If a copy of the MPL was not distributed with this file,
8
   You can obtain one at http://mozilla.org/MPL/2.0/.
9
 
10
   Alternatively, the contents of this file may be used under the terms
11
   of the GNU General Public License Version 3, as described below:
12
 
13
   This program is free software; you can redistribute it and/or modify
14
   it under the terms of the GNU General Public License version 3 as
15
   published by the Free Software Foundation.
16
 
17
   This program is distributed in the hope that it will be useful, but
18
   WITHOUT ANY WARRANTY; without even the implied warranty of
19
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20
   General Public License for more details.
21
 
22
   You should have received a copy of the GNU General Public License
23
   along with this program; if not, see http://www.gnu.org/licenses/.
24
%*/
25
 
26
/** @file
27
memfifo example for C.
28
This example demonstrates the usage of the C API and the high speed interface of the default firmware.
29
 
30
It performs certain tests (device and data integrity, read-write tests, performance) using the memory FIFO as described on
31
<a href="http://wiki.ztex.de/doku.php?id=en:ztex_boards:ztex_fpga_boards:memfifo:memfifo">memfifo example</a>.
32
 
33
The correct bitstream is detected and found automatically if the binary is executed from
34
the directory tree of the SDK. Otherwise it can be specified with parameter '-s'.
35
 
36
Full list of options can be obtained with '-h'
37
@include memfifo.c
38
@cond memfifo
39
*/
40
 
41
#include <stdio.h>
42
#include <stdarg.h>
43
#include <stdlib.h>
44
#include <string.h>
45
#include <fcntl.h>
46
#include <sys/types.h>
47
#include <sys/time.h>
48
#include <libusb-1.0/libusb.h>
49
 
50
#include "ztex.h"
51
 
52
#define BULK_BUF_SIZE 4*1024*1024
53
#define RW_SIZE 65000                   // must be smaller then FIFO size, 64K on USB-FPGA Module 2.01
54
 
55
static char* prog_name = NULL;          // name of the program
56
 
57
static int paramerr(const char* format,...)
58
{
59
    fprintf(stderr, "Usage: %s options\n",prog_name);
60
    fprintf(stderr, "  -h                           Display this usage information\n"
61
                    "  -fu <vendor ID>:<product ID> Select device by USB IDs, default: 0x221A:0x100, <0:ignore ID\n"
62
                    "  -fd <bus>:<device>           Select device by bus number and device address\n"
63
                    "  -fs <string>                 Select device by serial number string\n"
64
                    "  -fp <string>                 Select device by product string\n"
65
                    "  -s <path>                    Additional search path for bitstream, default '.."DIRSEP".."DIRSEP"examples"DIRSEP"memfifo'\n"
66
                    "  -r                           Reset device (default: reset configuration only)\n"
67
                    "  -i                           Print device info\n"
68
                    "  -p                           Print matching USB devices\n"
69
                    "  -pa                          Print all USB devices\n"
70
            );
71
    if ( format ) {
72
        va_list args;
73
        va_start(args,format);
74
        vfprintf(stderr, format, args);
75
        va_end(args);
76
        return 1;
77
    }
78
    return 0;
79
}
80
 
81
int main(int argc, char **argv)
82
{
83
    int id_vendor = 0x221A;     // ZTEX vendor ID
84
    int id_product = 0x100;     // default product ID for ZTEX firmware
85
    int status = 0;
86
    libusb_device **devs = NULL;
87
    int print_all=0, print=0, print_info=0, reset_dev=0;
88
    int busnum = -1, devnum = -1;
89
    char *sn_string = NULL, *product_string = NULL;
90
    libusb_device_handle *handle = NULL;
91
    ztex_device_info info;
92
    char *bitstream_fn = NULL, *bitstream_path = NULL;
93
    char sbuf[8192];
94
    unsigned char *mbuf = NULL;
95
    int transferred, size;
96
    struct timeval tv1,tv2;
97
 
98
    // process parameters
99
    prog_name = argv[0];
100
    for (int i=1; i<argc; i++) {
101
        if ( !strcmp(argv[i],"-h") ) return paramerr(NULL);
102
        else if ( !strcmp(argv[i],"-p") ) print=1;
103
        else if ( !strcmp(argv[i],"-pa") ) print_all=1;
104
        else if ( !strcmp(argv[i],"-i") ) print_info=1;
105
        else if ( !strcmp(argv[i],"-r") ) reset_dev=1;
106
        else if ( !strcmp(argv[i],"-fu") ) {
107
            i++;
108
            if (i>=argc || sscanf(argv[i],"%i:%i", &id_vendor, &id_product)!=2 ) return paramerr("Error: <vendor ID>:<product ID> expected after -fu\n");
109
        }
110
        else if ( !strcmp(argv[i],"-fd") ) {
111
            i++;
112
            if (i>=argc || sscanf(argv[i],"%i:%i", &busnum, &devnum)!=2 ) return paramerr("Error: <bus>:<device> expected after -fd\n");
113
        }
114
        else if ( !strcmp(argv[i],"-fs") ) {
115
            i++;
116
            if (i>=argc ) return paramerr("Error: <string> expected after -fs\n");
117
            sn_string = argv[i];
118
        }
119
        else if ( !strcmp(argv[i],"-fp") ) {
120
            i++;
121
            if (i>=argc ) return paramerr("Error: <string> expected after -fp\n");
122
            product_string = argv[i];
123
        }
124
        else if ( !strcmp(argv[i],"-s") ) {
125
            i++;
126
            if (i>=argc ) return paramerr("Error: <path> expected after -s\n");
127
            bitstream_path = argv[i];
128
        }
129
        else return paramerr("Error: Invalid parameter %s\n", argv[i]);
130
    }
131
 
132
 
133
    // INIT libusb
134
    status = libusb_init(NULL);
135
    if (status < 0) {
136
        fprintf(stderr,"Error: Unable to init libusb: %s\n", libusb_error_name(status));
137
        return 1;
138
    }
139
 
140
    // find all USB devices
141
    status = libusb_get_device_list(NULL, &devs);
142
    if (status < 0) {
143
        fprintf(stderr,"Error: Unable to get device list: %s\n", libusb_error_name(status));
144
        goto err;
145
    }
146
 
147
    // print bus info or find device
148
    int dev_idx = ztex_scan_bus(sbuf, sizeof(sbuf), devs, print_all ? -1 : print ? 1 : 0, id_vendor, id_product, busnum, devnum, sn_string, product_string);
149
    printf(sbuf);
150
    fflush(stdout);
151
    if ( print || print_all ) {
152
        status = 0;
153
        goto noerr;
154
    } else if ( dev_idx<0 ) {
155
        if (dev_idx==-1) fprintf(stderr,"Error: No device found\n");
156
        goto err;
157
    }
158
 
159
    // open device
160
    status = libusb_open(devs[dev_idx], &handle);
161
    if (status < 0) {
162
        fprintf(stderr,"Error: Unable to open device: %s\n", libusb_error_name(status));
163
        goto err;
164
    }
165
    libusb_free_device_list(devs, 1);
166
    devs=NULL;
167
 
168
    // reset configuration or device
169
   if ( ! reset_dev ) {
170
        status = libusb_set_configuration(handle,-1);
171
        if (status < 0) {
172
            fprintf(stderr,"Warning: Unable to unconfigure device: %s, trying to reset it\n", libusb_error_name(status));
173
#if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64)
174
            fprintf(stderr,"Due to limitations of Windows neither this nor device reset works. This may cause further errors ...\n");
175
#endif    
176
            reset_dev = 1;
177
        }
178
    }
179
    if ( reset_dev ) {
180
        status = libusb_reset_device(handle);
181
        if (status < 0) {
182
            fprintf(stderr,"Error: Unable to reset device: %s\n", libusb_error_name(status));
183
            goto err;
184
        }
185
    }
186
    status = libusb_set_configuration(handle,1);
187
    if (status < 0) fprintf(stderr,"Warning: Unable to set configuration 1: %s\n", libusb_error_name(status));
188
    fflush(stderr);
189
 
190
    // get and print device info
191
    status = ztex_get_device_info(handle, &info);
192
    if ( status < 0 ) {
193
        fprintf(stderr,"Error: Unable to get device info: %s\n", libusb_error_name(status));
194
        goto err;
195
    }
196
    if ( print_info ) {
197
        ztex_print_device_info( sbuf, sizeof(sbuf), &info );
198
        printf(sbuf);
199
        status = ztex_get_fpga_config(handle);
200
        if ( status < 0 ) {
201
            fprintf(stderr,"Error: Unable to get FPGA configuration state: %s\n", libusb_error_name(status));
202
            goto err;
203
        }
204
        printf("FPGA: %s\n", status==0 ? "unconfigured" : "configured");
205
        status = 0;
206
        goto noerr;
207
    }
208
 
209
    // find bitstream
210
    bitstream_fn = ztex_find_bitstream( &info, bitstream_path ? bitstream_path : ".."DIRSEP".."DIRSEP"examples"DIRSEP"memfifo" , "memfifo");
211
    if ( bitstream_fn )  {
212
        printf("Using bitstream '%s'\n", bitstream_fn);
213
        fflush(stdout);
214
    }
215
    else {
216
        fprintf(stderr,"Warning: Bitstream not found\n");
217
        goto nobitstream;
218
    }
219
 
220
    // read and upload bitstream
221
    FILE *fd = fopen(bitstream_fn, "rb");
222
    if ( fd == NULL ) {
223
        fprintf(stderr,"Warning: Error opening file '%s'\n", bitstream_fn);
224
        goto nobitstream;
225
    }
226
    status = ztex_upload_bitstream(sbuf,sizeof(sbuf),handle,&info,fd,-1);
227
    fclose(fd);
228
    fprintf(stderr,sbuf);
229
 
230
nobitstream:
231
    fflush(stderr);
232
    // check config
233
    status = ztex_get_fpga_config(handle);
234
    if ( status < 0 ) {
235
        fprintf(stderr,"Error: Unable to get FPGA configuration state: %s\n", libusb_error_name(status));
236
        goto err;
237
    } else if ( status == 0 ) {
238
        fprintf(stderr,"Error: FPGA not configured\n");
239
        goto err;
240
    }
241
 
242
    // claim interface
243
    status = libusb_claim_interface(handle, 0);
244
    if ( status < 0 ) {
245
        fprintf(stderr,"Error claiming interface 0: %s\n", libusb_error_name(status));
246
        goto err;
247
    }
248
 
249
    mbuf = malloc(BULK_BUF_SIZE);
250
    if ( !mbuf ) {
251
        fprintf(stderr,"Error allocating %d bytes\n", BULK_BUF_SIZE);
252
        goto err;
253
    }
254
 
255
// verify mode and prepare device if necessary
256
    if ( ztex_default_gpio_ctl(handle,0,0) ) {
257
        fprintf(stderr,"Warning: wrong initial mode, switching to mode 0\n");
258
        ztex_default_gpio_ctl(handle,7,0);
259
        ztex_default_reset(handle,0);
260
        libusb_bulk_transfer(handle, info.default_in_ep, mbuf, BULK_BUF_SIZE, &transferred, 250);
261
    } else {
262
        status = libusb_bulk_transfer(handle, info.default_in_ep, mbuf, BULK_BUF_SIZE, &transferred, 250);
263
        if ( (status>=0) && (transferred>0) ) fprintf(stderr,"Warning: found %d bytes in EZ-USB FIFO\n", transferred);
264
    }
265
    fflush(stderr);
266
 
267
// test 1: read-write test (mode 0)
268
    for (int i=0; i<RW_SIZE; i+=2) {
269
        mbuf[i] = (i>>1) & 127;
270
        mbuf[i+1] = 128 | ((i >> 8 ) & 127);
271
    }
272
    TWO_TRIES(status, libusb_bulk_transfer(handle, info.default_out_ep, mbuf, RW_SIZE, &transferred, 2000));
273
    if ( status < 0 ) {
274
        fprintf(stderr,"Bulk write error: %s\n", libusb_error_name(status));
275
        goto err;
276
    }
277
    printf("Read-write test, short packet test: wrote %d Bytes\n", transferred);
278
    fflush(stdout);
279
 
280
    TWO_TRIES(status, libusb_bulk_transfer(handle, info.default_in_ep, mbuf, BULK_BUF_SIZE, &transferred, 4000));
281
    if ( status < 0 ) {
282
        fprintf(stderr,"Bulk read error: %s\n", libusb_error_name(status));
283
        goto err;
284
    }
285
    {
286
        int i=mbuf[0]>>7;
287
        int j=mbuf[i] | ((mbuf[i+1] & 127)<<7);
288
        printf("Read-write test: read (%d=%d*512+%d) Bytes.  %d leading Bytes lost", transferred, transferred/512, transferred&511, j*2  );
289
        if ( j ) printf("(This may be platform specific)" );
290
        size = 0;
291
        for (i=i+2; i+1<transferred; i+=2) {
292
            int k = mbuf[i] | ((mbuf[i+1] & 127)<<7);
293
            if ( k != ((j+1) & 0x3fff) ) size +=1;
294
            j=k;
295
        }
296
        printf(". %d data errors.  %d Bytes remaining in FIFO due to memory transfer granularity\n", size, RW_SIZE-transferred);
297
        fflush(stdout);
298
    }
299
 
300
// test 2: read rate test using test data generator (mode 1)
301
    // reset application and set mode 1
302
    ztex_default_reset(handle,0);
303
    status = ztex_default_gpio_ctl(handle,7,1);
304
    if ( status < 0 ) {
305
        fprintf(stderr,"Error setting GPIO's: %s\n", libusb_error_name(status));
306
        goto err;
307
    }
308
 
309
    // read data and measure time, first packets are ignored because EZ-USB buffer may be filled
310
    printf("Measuring read rate using libusb_bulk_transfer ... \n");
311
    fflush(stdout);
312
    size=0;
313
    for (int i=0; i<55; i++) {
314
        if ( i==5 ) gettimeofday(&tv1, NULL);
315
        TWO_TRIES( status, libusb_bulk_transfer(handle, info.default_in_ep, mbuf, BULK_BUF_SIZE, &transferred, 2000));
316
        if ( status < 0 ) {
317
            fprintf(stderr,"Bulk read error: %s\n", libusb_error_name(status));
318
            goto err;
319
        }
320
        if ( (i==0) && ( (mbuf[0]!=0) && (mbuf[1]!=239) ) ) {
321
            fprintf(stderr,"Warning: Invalid start of data: %d %d, leading data may went lost\n",mbuf[0], mbuf[1]);
322
        }
323
        if ( i>=5 ) size+=transferred;
324
    }
325
    gettimeofday(&tv2, NULL);
326
    printf("Read %.1f MB at %.1f MB/s\n", size/(1024.0*1024.0), size/( (tv2.tv_sec-tv1.tv_sec)*1e6 + (tv2.tv_usec-tv1.tv_usec) ));
327
    fflush(stdout);
328
 
329
    // release resources
330
    status = 0;
331
    goto noerr;
332
err:
333
    status = 1;
334
noerr:
335
    if ( mbuf ) free(mbuf);
336
    if ( bitstream_fn ) free(bitstream_fn);
337
    if ( handle ) {
338
        libusb_release_interface(handle,0);
339
        libusb_close(handle);
340
    }
341
    if ( devs ) libusb_free_device_list(devs, 1);
342
    libusb_exit(NULL);
343
#if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64)
344
    printf("Press <return> to quit\n");
345
    fflush(NULL);
346
    fgetc(stdin);
347
#endif    
348
    return status;
349
}
350
///@endcond

powered by: WebSVN 2.1.0

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