Nav:  [home][elec][periph][usb-fx2][software] > [io_examples]
 
Go:  [local] [io] [advanced] [fx2pipe]
← [What are these? Why?]

Electronics -- USB-FX2: Software Examples with IO

A collection of example software for the USB-FX2 board which make use of some IO lines on the board.

Download All Examples in an Archive

In order to try the examples on this page, you should download this tarball since the code on this page does not contain the necessary include files which are (of course) part of the archive.

Source: usb-fx2-io-examples-0.4.tar.gz   [11kb gzipped source tarball]
Version:0.4   (2008-06-05)
Author:Wolfgang Wieser   (report bugs here)
License:GNU GPL (Version 2)
Requires:libusb, cycfx2prog

For building and running, please refer to the local examples since it works just the same here. However, make sure to do the required external signal wiring for each example as lined out in the example explanation below.

Note: All these examples have been tested with my USB-FX2 board.

If you experience trouble, please fix them and drop me a note. Also check out the troubleshooting hints.

Bulk Read Benchmark

First, let's start with the simplest program making use of the IO lines on the USB-FX2 board: A bulk read benchmark firmware which spends all its time just trying to send data like mad over the USB link - as much as the host can sustain.

Here's the code: Basically, we run the FX2LP in synchronious slave FIFO mode with AUTOIN enabled. However, we use internal interface clocking at maximum speed (48 MHz) and simply tie the write stobe line low to have data committed into the FIFOs as fast as possible. Since we're using the complete 16bit wide bus at 48 MHz, the theoretical FIFO transfer rate is 96MBytes/sec which is way above maximum theoretical USB-2.0 bandwidth of 60MBytes/s (well, even less due to protocol overhead).

Hence, this firmware can be used to test host controller and host software performance.

static void Initialize(void)
{
    CPUCS = 0x12;  // 48MHz, output to CLKOUT signal enabled.
    
    // Internally clocked (48MHz) sync slave fifo mode.
    // Output to IFCLK not enabled (set bit5 to enable).
    IFCONFIG = 0xc3;  SYNCDELAY;
    REVCTL = 0x03;    SYNCDELAY;  // See TRM...
    
    // Configure EP6 (IN) for bulk input, quad-buffered (4*512 bytes).
    EP6CFG = 0xe0;  SYNCDELAY;
    
    FIFORESET = 0x80;  SYNCDELAY;  // NAK all requests from host.
    FIFORESET = 0x82;  SYNCDELAY;  // Reset individual EP (2,4,6,8)
    FIFORESET = 0x84;  SYNCDELAY;
    FIFORESET = 0x86;  SYNCDELAY;
    FIFORESET = 0x88;  SYNCDELAY;
    FIFORESET = 0x00;  SYNCDELAY;  // Resume normal operation.
    
    // Configure EP6 for AUTOIN, 16bit wide bus.
    EP6FIFOCFG = 0x0d;  SYNCDELAY;
    
    // PORTACFG: FLAGD SLCS(*) 0 0 0 0 INT1 INT0
    PORTACFG = 0x00;  SYNCDELAY; // (delay maybe not needed)
    
    // All default polarities: SLWR active low,...
    FIFOPINPOLAR=0x00;  SYNCDELAY;
    
    // This determines how much data is accumulated in the FIFOs before a
    // USB packet is committed. Use 512 bytes to be sure.
    EP6AUTOINLENH = 0x02; SYNCDELAY;  // MSB
    EP6AUTOINLENL = 0x00; SYNCDELAY;  // LSB
}

void main()
{
    Initialize();
    
    for(;;) {}
}

USB-FX2 wiring points [9kb]
[click to enlarge: 40kb JPEG]

Before running this firmware, you need to manually do the following wiring:

  • Connect to HIGH (3.3V): PA2/SLOE, PA5/FIFOADR1, RDY0/SLRD
  • Connect to LOW (GND): PA4/FIFOADR0, RDY1/SLWR

The FIFOADR pins select the right FIFO buffer address for the endpoint 6 since that's what we're using. The RDY pins are set for writing to the FIFOs and SLOE to HIGH to indicate input direction on the bus.

The necessary signal connection points are shown on the image on the left: connect blue signals to GND and red ones to +3.3V. (These levels are available on the three-terminal connector near the left top.)

When running the example (make run), you should see something like this:

cycfx2prog prg:bench_in.ihx run bench_bulk:6,16777216
Using ID 04b4:8613 on 006.004.
Putting 8051 into reset.
Programming 8051 using "bench_in.ihx".
Putting 8051 out of reset.
Read 16777216 bytes in 828 msec (chunk size 65536): 19.332 Mb/sec (256 calls, 65536 bytes/call)

So, that's a transfer rate of 19MBytes/sec. Not bad already but please note: This benchmark uses libusb and libusb clearly sucks performance-wise. Don't worry if you see ridiculously small numbers like 3Mb/s (!) on your computer (which may even go up with increasing interrupt load like playing music). The USB-FX2 is perfect like that but we can do better on the host side. Although the actual maximum transfer rate always also depends on the host controller in the computer (Intel ones seem to work fastest), clever software keeping several URBs in the request queue (like e.g. used in the FX2Pipe program or also by the SSRP project and by my USB Oscilloscope, too) are able to boost us up up to beyond 40Mb/s on Intel HCs (and over 35Mb/s on my Via-based PCI expansion card).

By the way, using the dbulk command to cycfx2prog, you can see the data acutually read from the FIFO lines and watch how they change when you tie individual port A or port D lines LOW or HIGH. However, note that since the FX2 has 2kb of internal buffer (it is programmed for quad-buffered operation with a buffer size of 512 bytes) you need to read more than 2kb before you see the changes on the input pins on the screen.

Slave FIFO Configurations

Since we're after speed, we either want to run the FX2LP in synchronious slave FIFO mode or in GPIF master mode. (SLWR signal timing constraints on behalf of the FX2 limit asynchronious transfers to somewhere below 16Mb/s; synchronious FIFO throughput is 96Mb/s and hence above USB-2.0 bandwidth.) Slave FIFO mode is gererally simpler than GPIF master especially when dealing with simple attached logic (like an AD or DA converter as opposed to an IDE drive).

In (synchronious) slave FIFO mode, the most interesting pins are the following ones (for a complete list please refer to the TRM):

  • PA2/SLOE: Active-low (by default) output enable pin for the 16 data lines made formed by ports A and D. Use HIGH to send data into the FX2 and LOW to read data from the FX2.
  • PA5,4/FIFOADR1,0: Select the endpoint (buffer) to communicate with. Values 00, 01, 10 and 11 are for endpoints 2, 4, 6 and 8, respectively. When using only one EP (e.g. 6), these can be set statically (e.g. 10 in the bench_in example above).
  • IFCLK: Sync FIFO interface clock; all the FIFO side runs with this clock; the speed must be 5MHz to 48MHz and can either be internally clocked or externally. Depending on the clock ratio of '8051 CPU and IFCLK, a varying synchronisation (delay SYNCDELAY in the sources) is required, check the TRM for details (p.15-115).
  • RDY0/SLRD: Active-low (by default) read strobe pin. By default, a low-to-high transition of IFCLK while SLRD is held low makes up a read operation (transfer data from FX2 to attached logic).
  • RDY0/SLWR: Active-low (by default) write strobe pin. By default, a low-to-high transition of IFCLK while SLWR is held low makes up a write operation (transfer data from attached logic to FX2).

And the most important config registers are:

  • IFCONFIG: Default: 1000 0000
    • bit7: 1 = internal clocking of IFCLK; 0 = external
    • bit6: 0 = 30MHz; 1 = 48MHz
    • bit5: 1 = enable output to IFCLK
    • bit4: 1 = invert IFCLK
    • bit3: 0 = sync mode; 1 = async mode
    • bit1,0: 11 = Slave FIFO; 00 = ports; 01 = reserved; 10 = GPIF

    Example: 0x43 for externally clocked and sync FIFO mode

    It is obvious that some combinations should be avoided (like setting bit7=0 and bit5=1).

  • EPxCFG: Default: 1110 0010
    • bit7: VALID: 1=enable
    • bit6: DIR: 1=in (USB-FX2 to host); 0=out (host to USB-FX2)
    • bit5,4: TYPE1,0: 00=ivalid; 01=isochronous; 10=bulk; 11=interrupt
    • bit3: SIZE: 0=512 bytes; 1=1024 bytes
    • bit2: always 0
    • bit1,0: BUF1,0: 00=quad; 01=invalid; 10=double; 11=triple

    Note that not all buffering schemes, types and directions are available for all endpoints. EP2 and EP6 have the most features as OUT and IN endpoints, respectively.

    Example: 0xe0 Quad-buffered (4*512 bytes) bulk input.

  • EPxFIFOCFG: Please refer to the TRM.

Simple bulk IO firmware can easily be implemented taking the above bench_in example as a pattern and simply substituting the correct values for IFCONFIG, EPxCFG and EPxFIFOCFG (and maybe some other related registers found in the TRM). As a further example, see e.g. the my USB Oscilloscope firmware.


[home] [site map]
Valid HTML 4.01!
Copyright © 2006-2009 by Wolfgang Wieser
Last modified: 2009-12-05 15:49:42