Co-Simulation/Примеры кода
Материал из Wiki
- Техническое задание
- Описание FT2232H
- Описание FT232H
- (TUMPA) TIAO USB Multi Protocol Adapter
- (TUMPA) Litle
- Описание макета
- Примеры кода
Литература
Пример win
FT_HANDLE ftHandle; // Handle of the FTDI device FT_STATUS ftStatus; // Result of each D2XX call DWORD dwNumDevs; // The number of devices unsigned int uiDevIndex = 0xF; // The device in the list that we'll use BYTE byOutputBuffer[1024]; // Buffer to hold MPSSE commands and data to be sent to the FT2232H BYTE byInputBuffer[1024]; // Buffer to hold data read from the FT2232H DWORD dwCount = 0; // General loop index DWORD dwNumBytesToSend = 0; // Index to the output buffer DWORD dwNumBytesSent = 0; // Count of actual bytes sent - used with FT_Write DWORD dwNumBytesToRead = 0; // Number of bytes available to read in the driver's input buffer DWORD dwNumBytesRead = 0; // Count of actual bytes read - used with FT_Read DWORD dwClockDivisor = 0x0001; // Value of clock divisor, SCL Frequency = 60/((1+0x05DB)*2) (MHz) = 20khz DWORD RxBytes = 0; DWORD TxBytes = 0; DWORD EventDWord = 0; printf("Checking for FTDI devices...\n"); ftStatus = FT_CreateDeviceInfoList(&dwNumDevs); // Get the number of FTDI devices if (ftStatus != FT_OK) // Did the command execute OK? { printf("Error in getting the number of devices\n"); return 1; // Exit with error } if (dwNumDevs < 1) // Exit if we don't see any { printf("There are no FTDI devices installed\n"); return 1; // Exist with error } // Open the port - For this application note, we'll assume the first device is a FT2232H or FT4232H // Further checks can be made against the device descriptions, locations, serial numbers, etc. // before opening the port. printf("\nAssume first device has the FIFO and open it...\n"); ftStatus = FT_Open(0, &ftHandle); if (ftStatus != FT_OK) { printf("Open Failed with error %d\n", ftStatus); return 1; // Exit with error }
Листинг файла baud_test.c
/* baud_test.c * * test setting the baudrate and compare it with the expected runtime * * options: * -p <devicestring> defaults to "i:0x0403:0x6001" (this is the first FT232R with default id) * d:<devicenode> path of bus and device-node (e.g. "003/001") within usb device tree (usually at /proc/bus/usb/) * i:<vendor>:<product> first device with given vendor and product id, * ids can be decimal, octal (preceded by "0") or hex (preceded by "0x") * i:<vendor>:<product>:<index> as above with index being the number of the device (starting with 0) * if there are more than one * s:<vendor>:<product>:<serial> first device with given vendor id, product id and serial string * -d <datasize to send in bytes> * -b <baudrate> (divides by 16 if bitbang as taken from the ftdi datasheets) * -m <mode to use> r: serial a: async bitbang s:sync bitbang h:sync FIFO * -c <chunksize> * * (C) 2009 by Gerd v. Egidy <gerd.von.egidy@intra2net.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * */ #include <sys/time.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <ftdi.h> double get_prec_time() { struct timeval tv; double res; gettimeofday(&tv,NULL); res=tv.tv_sec; res+=((double)tv.tv_usec/1000000); return res; } int main(int argc, char **argv) { struct ftdi_context *ftdi; int i, t; unsigned char *txbuf; unsigned char *rxbuf; double start, duration, plan; int retval= 0; // default values int baud=9600; int set_baud; int datasize=100000; char default_devicedesc[] = "i:0x0403:0x6014"; char *devicedesc=default_devicedesc; int txchunksize=256; enum ftdi_mpsse_mode test_mode=BITMODE_BITBANG; while ((t = getopt (argc, argv, "b:d:p:m:c:")) != -1) { switch (t) { case 'd': datasize = atoi (optarg); break; case 'm': switch (*optarg) { case 'r': // serial test_mode=BITMODE_RESET; break; case 'a': // async test_mode=BITMODE_BITBANG; break; case 's': // sync test_mode=BITMODE_SYNCBB; break; case 'h': // sync test_mode=BITMODE_SYNCFF; break; } break; case 'b': baud = atoi (optarg); break; case 'p': devicedesc=optarg; break; case 'c': txchunksize = atoi (optarg); break; } } txbuf=malloc(txchunksize); rxbuf=malloc(txchunksize); if (txbuf == NULL || rxbuf == NULL) { fprintf(stderr, "can't malloc\n"); return EXIT_FAILURE; } if ((ftdi = ftdi_new()) == 0) { fprintf(stderr, "ftdi_new failed\n"); retval = EXIT_FAILURE; goto done; } if (ftdi_usb_open_string(ftdi, devicedesc) < 0) { fprintf(stderr,"Can't open ftdi device: %s\n",ftdi_get_error_string(ftdi)); retval = EXIT_FAILURE; goto do_deinit; } set_baud=baud; if (test_mode!=BITMODE_RESET) { // we do bitbang, so real baudrate / 16 set_baud=baud/16; } ftdi_set_baudrate(ftdi,set_baud); printf("real baudrate used: %d\n",(test_mode==BITMODE_RESET) ? ftdi->baudrate : ftdi->baudrate*16); if (ftdi_set_bitmode(ftdi, 0xFF,test_mode) < 0) { fprintf(stderr,"Can't set mode: %s\n",ftdi_get_error_string(ftdi)); retval = EXIT_FAILURE; goto do_close; } if (test_mode==BITMODE_RESET) { // serial 8N1: 8 data bits, 1 startbit, 1 stopbit plan=((double)(datasize*10))/baud; } else { // bitbang means 8 bits at once plan=((double)datasize)/baud; } printf("this test should take %.2f seconds\n",plan); // prepare data to send: 0 and 1 bits alternating (except for serial start/stopbit): // maybe someone wants to look at this with a scope or logic analyzer for (i=0; i<txchunksize; i++) { if (test_mode==BITMODE_RESET) txbuf[i]=0xAA; else txbuf[i]=(i%2) ? 0xff : 0; } if (ftdi_write_data_set_chunksize(ftdi, txchunksize) < 0 || ftdi_read_data_set_chunksize(ftdi, txchunksize) < 0) { fprintf(stderr,"Can't set chunksize: %s\n",ftdi_get_error_string(ftdi)); retval = EXIT_FAILURE; goto do_close; } if (test_mode==BITMODE_SYNCBB) { // completely clear the receive buffer before beginning while (ftdi_read_data(ftdi, rxbuf, txchunksize)>0); } if (test_mode==BITMODE_SYNCFF) { // completely clear the receive buffer before beginning while (ftdi_read_data(ftdi, rxbuf, txchunksize)>0); } start=get_prec_time(); // don't wait for more data to arrive, take what we get and keep on sending // yes, we really would like to have libusb 1.0+ with async read/write... ftdi->usb_read_timeout=1; i=0; while (i < datasize) { int sendsize=txchunksize; if (i+sendsize > datasize) sendsize=datasize-i; if ((sendsize=ftdi_write_data(ftdi, txbuf, sendsize)) < 0) { fprintf(stderr,"write failed at %d: %s\n", i, ftdi_get_error_string(ftdi)); retval = EXIT_FAILURE; goto do_close; } i+=sendsize; if (test_mode==BITMODE_SYNCBB) { // read the same amount of data as sent ftdi_read_data(ftdi, rxbuf, sendsize); } if (test_mode==BITMODE_SYNCFF) { // read the same amount of data as sent ftdi_read_data(ftdi, rxbuf, sendsize); } } duration=get_prec_time()-start; printf("and took %.4f seconds, this is %.0f baud or factor %.3f\n",duration,(plan*baud)/duration,plan/duration); do_close: ftdi_usb_close(ftdi); do_deinit: ftdi_free(ftdi); done: if(rxbuf) free(rxbuf); if(txbuf) free(txbuf); exit (retval); }
Листинг файла stream_test.c
/* stream_test.c * * Test reading from FT2232H in synchronous FIFO mode. * * The FT2232H must supply data due to an appropriate circuit * * To check for skipped block with appended code, * a structure as follows is assumed * 1* uint32_t num (incremented in 0x4000 steps) * 3* uint32_t dont_care * * After start, data will be read in streaming until the program is aborted * Progess information wil be printed out * If a filename is given on the command line, the data read will be * written to that file * */ #include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <string.h> #include <unistd.h> #include <getopt.h> #include <signal.h> #include <errno.h> #include <ftdi.h> void check_outfile(char *); static FILE *outputFile; static int check = 1; static int exitRequested = 0; /* * sigintHandler -- * * SIGINT handler, so we can gracefully exit when the user hits ctrl-C. */ static void sigintHandler(int signum) { exitRequested = 1; } static void usage(const char *argv0) { fprintf(stderr, "Usage: %s [options...] \n" "Test streaming read from FT2232H\n" "[-P string] only look for product with given string\n" "[-n] don't check for special block structure\n" "\n" "If some filename is given, write data read to that file\n" "Progess information is printed each second\n" "Abort with ^C\n" "\n" "Options:\n" "\n" "Copyright (C) 2009 Micah Dowty <micah@navi.cx>\n" "Adapted for use with libftdi (C) 2010 Uwe Bonnes <bon@elektron.ikp.physik.tu-darmstadt.de>\n", argv0); exit(1); } static uint32_t start = 0; static uint32_t offset = 0; static uint64_t blocks = 0; static uint32_t skips = 0; static uint32_t n_err = 0; static int readCallback(uint8_t *buffer, int length, FTDIProgressInfo *progress, void *userdata) { if (length) { if (check) { int i,rem; uint32_t num; for (i= offset; i<length-16; i+=16) { num = *(uint32_t*) (buffer+i); if (start && (num != start +0x4000)) { uint32_t delta = ((num-start)/0x4000)-1; fprintf(stderr, "Skip %7d blocks from 0x%08x to 0x%08x at blocks %10llu\n", delta, start -0x4000, num, (unsigned long long)blocks); n_err++; skips += delta; } blocks ++; start = num; } rem = length -i; if (rem >3) { num = *(uint32_t*) (buffer+i); if (start && (num != start +0x4000)) { uint32_t delta = ((num-start)/0x4000)-1; fprintf(stderr, "Skip %7d blocks from 0x%08x to 0x%08x at blocks %10llu\n", delta, start -0x4000, num, (unsigned long long) blocks); n_err++; skips += delta; } start = num; } else if (rem) start += 0x4000; if (rem != 0) { blocks ++; offset = 16-rem; } } if (outputFile) { if (fwrite(buffer, length, 1, outputFile) != 1) { perror("Write error"); return 1; } } } if (progress) { fprintf(stderr, "%10.02fs total time %9.3f MiB captured %7.1f kB/s curr rate %7.1f kB/s totalrate %d dropouts\n", progress->totalTime, progress->current.totalBytes / (1024.0 * 1024.0), progress->currentRate / 1024.0, progress->totalRate / 1024.0, n_err); } return exitRequested ? 1 : 0; } int main(int argc, char **argv) { struct ftdi_context *ftdi; int err, c; FILE *of = NULL; char const *outfile = 0; outputFile =0; exitRequested = 0; char *descstring = NULL; int option_index; static struct option long_options[] = {{NULL},}; while ((c = getopt_long(argc, argv, "P:n", long_options, &option_index)) !=- 1) switch (c) { case -1: break; case 'P': descstring = optarg; break; case 'n': check = 0; break; default: usage(argv[0]); } if (optind == argc - 1) { // Exactly one extra argument- a dump file outfile = argv[optind]; } else if (optind < argc) { // Too many extra args usage(argv[0]); } if ((ftdi = ftdi_new()) == 0) { fprintf(stderr, "ftdi_new failed\n"); return EXIT_FAILURE; } if (ftdi_set_interface(ftdi, INTERFACE_A) < 0) { fprintf(stderr, "ftdi_set_interface failed\n"); ftdi_free(ftdi); return EXIT_FAILURE; } if (ftdi_usb_open_desc(ftdi, 0x0403, 0x6014, descstring, NULL) < 0) { fprintf(stderr,"Can't open ftdi device: %s\n",ftdi_get_error_string(ftdi)); ftdi_free(ftdi); return EXIT_FAILURE; } /* A timeout value of 1 results in may skipped blocks */ if(ftdi_set_latency_timer(ftdi, 2)) { fprintf(stderr,"Can't set latency, Error %s\n",ftdi_get_error_string(ftdi)); ftdi_usb_close(ftdi); ftdi_free(ftdi); return EXIT_FAILURE; } /* if(ftdi_usb_purge_rx_buffer(ftdi) < 0) { fprintf(stderr,"Can't rx purge\n",ftdi_get_error_string(ftdi)); return EXIT_FAILURE; }*/ if (outfile) if ((of = fopen(outfile,"w+")) == 0) fprintf(stderr,"Can't open logfile %s, Error %s\n", outfile, strerror(errno)); if (of) if (setvbuf(of, NULL, _IOFBF , 1<<16) == 0) outputFile = of; signal(SIGINT, sigintHandler); err = ftdi_readstream(ftdi, readCallback, NULL, 8, 256); if (err < 0 && !exitRequested) exit(1); if (outputFile) { fclose(outputFile); outputFile = NULL; } fprintf(stderr, "Capture ended.\n"); // if (ftdi_set_bitmode(ftdi, 0xff, BITMODE_RESET) < 0) if (ftdi_set_bitmode(ftdi, 0xff, BITMODE_SYNCFF) < 0) { fprintf(stderr,"Can't set synchronous fifo mode, Error %s\n",ftdi_get_error_string(ftdi)); ftdi_usb_close(ftdi); ftdi_free(ftdi); return EXIT_FAILURE; } ftdi_usb_close(ftdi); ftdi_free(ftdi); signal(SIGINT, SIG_DFL); if (check && outfile) { if ((outputFile = fopen(outfile,"r")) == 0) { fprintf(stderr,"Can't open logfile %s, Error %s\n", outfile, strerror(errno)); ftdi_usb_close(ftdi); ftdi_free(ftdi); return EXIT_FAILURE; } check_outfile(descstring); fclose(outputFile); } else if (check) fprintf(stderr,"%d errors of %llu blocks (%Le), %d (%Le) blocks skipped\n", n_err, (unsigned long long) blocks, (long double)n_err/(long double) blocks, skips, (long double)skips/(long double) blocks); exit (0); } void check_outfile(char *descstring) { if(strcmp(descstring,"FT2232HTEST") == 0) { char buf0[1024]; char buf1[1024]; char bufr[1024]; char *pa, *pb, *pc; unsigned int num_lines = 0, line_num = 1; int err_count = 0; unsigned int num_start, num_end; pa = buf0; pb = buf1; pc = buf0; if(fgets(pa, 1023, outputFile) == NULL) { fprintf(stderr,"Empty output file\n"); return; } while(fgets(pb, 1023, outputFile) != NULL) { num_lines++; unsigned int num_save = num_start; if( sscanf(pa,"%6u%94s%6u",&num_start, bufr,&num_end) !=3) { fprintf(stdout,"Format doesn't match at line %8d \"%s", num_lines, pa); err_count++; line_num = num_save +2; } else { if ((num_start+1)%100000 != num_end) { if (err_count < 20) fprintf(stdout,"Malformed line %d \"%s\"\n", num_lines, pa); err_count++; } else if(num_start != line_num) { if (err_count < 20) fprintf(stdout,"Skipping from %d to %d\n", line_num, num_start); err_count++; } line_num = num_end; } pa = pb; pb = pc; pc = pa; } if(err_count) fprintf(stdout,"\n%d errors of %d data sets %f\n", err_count, num_lines, (double) err_count/(double)num_lines); else fprintf(stdout,"No errors for %d lines\n",num_lines); } else if(strcmp(descstring,"LLBBC10") == 0) { uint32_t block0[4]; uint32_t block1[4]; uint32_t *pa = block0; uint32_t *pb = block1; uint32_t *pc = block0; uint32_t start= 0; uint32_t nread = 0; int n_shown = 0; int n_errors = 0; if (fread(pa, sizeof(uint32_t), 4,outputFile) < 4) { fprintf(stderr,"Empty result file\n"); return; } while(fread(pb, sizeof(uint32_t), 4,outputFile) != 0) { blocks++; nread = pa[0]; if(start>0 && (nread != start)) { if(n_shown < 30) { fprintf(stderr, "Skip %7d blocks from 0x%08x to 0x%08x at blocks %10llu \n", (nread-start)/0x4000, start -0x4000, nread, (unsigned long long) blocks); n_shown ++; } n_errors++; } else if (n_shown >0) n_shown--; start = nread + 0x4000; pa = pb; pb = pc; pc = pa; } if(n_errors) fprintf(stderr, "%d blocks wrong from %llu blocks read\n", n_errors, (unsigned long long) blocks); else fprintf(stderr, "%llu blocks all fine\n", (unsigned long long) blocks); } }