ZTEX

 
Products
Series 2 FPGA Boards
  USB-FPGA Module 2.18
  USB-FPGA Module 2.16
  USB-FPGA Module 2.14
  USB-FPGA Module 2.13
  USB-FPGA Module 2.12
  USB-FPGA Module 2.01
  FPGA Module 2.00
  Debug Board
  Series 1 Adapter
  Cluster Board
Discontinued:
  USB-FPGA Module 2.04
Obsolete products
  Series 1 FPGA Boards
To the ZTEX Shop ZTEX Shop
 SDK and Examples 
  Overview
  Default Firmware
  Documentation
  Downloads
  Example
  Licensing
  Release history
  ZTEX Wiki
 
 
Downloads
 
Contact
Imprint
Terms and Conditions
RoHS
 
    Home / Products         SDK    
    To the ZTEX Shop Shop   
    Wiki         Downloads    
    deutsch     englisch    

SDK for ZTEX FPGA Boards - Example

ZTEX provides a powerful Open Source SDK for the host software and the EZ-USB FX2 und FX3 USB controller. (For FPGA development Xilinx software is used.) This page gives an impression of the SDK usage.

Although note that development of own firmware becomes obsolete for many applications if default firmware is used.

Many other and more complex examples are part of the SDK.

Firmware

The firmware defines two endpoints. Data is read from host through endpoint 4, converted to uppercase and written back to endpoint 2. Because USB descriptors and ISR's are created automatically by the Firmware kit, the source code is quite compact:

Firmware for EZ-USB FX2: ucecho-fx2.c

#include[ztex-conf.h]   // Loads the configuration macros, see ztex-conf.h for available macros
#include[ztex-utils.h]  // include basic functions

// define endpoints 2 and 4, both belong to interface 0 (in/out are seen from the host
EP_CONFIG(2,0,BULK,IN,512,2);    
EP_CONFIG(4,0,BULK,OUT,512,2);   

// this product string is also used for identification by the host software
#define[PRODUCT_STRING]["ucecho for EZ-USB devices"]

// include the main part of the firmware kit, define the descriptors, ...
#include[ztex.h]

void main(void) 
{
    WORD i,size,j;
    BYTE b;

// init everything
    init_USB();

    REVCTL = 0x0;
    SYNCDELAY; 
    
    IFCONFIG = bmBIT7;  // Internal source, 48MHz
    SYNCDELAY; 

    EP2CS &= ~bmBIT0;   // stall = 0
    SYNCDELAY; 
    EP4CS &= ~bmBIT0;   // stall = 0
    SYNCDELAY; 

    EP2FIFOCFG = 0;
    SYNCDELAY;
    EP4FIFOCFG = 0;
    SYNCDELAY;

    FIFORESET = 0x80;   // reset FIFO ...
    SYNCDELAY;
    FIFORESET = 0x02;   // ... for EP 2
    SYNCDELAY;
    FIFORESET = 0x04;   // ... for EP 4
    SYNCDELAY;
    FIFORESET = 0x00;
    SYNCDELAY;  

    EP4BCL = 0x80;      // skip package, (re)arm EP4
    SYNCDELAY;
    EP4BCL = 0x80;      // skip package, (re)arm EP4
    SYNCDELAY;

    while (1) { 
        if ( !(EP4CS & bmBIT2) ) {                          // EP4 is not empty
            size = (EP4BCH << 8) | EP4BCL;
            if ( size>0 && size<=512 && !(EP2CS & bmBIT3)) {// EP2 is not full
                j = 0;
                for ( i=0; i<size; i++ ) {
                    b = EP4FIFOBUF[i];                      // data from EP4 ... 
                    if ( b>=(BYTE)'a' && b<=(BYTE)'z' ) {   // ... is converted to uppercase ...
                        b-=32;
                        j++;
                    }
                    EP2FIFOBUF[i] = b;                      // ... and written back to EP2 buffer
                } 

                EP2BCH = size >> 8;
                SYNCDELAY; 
                EP2BCL = size & 255;                       // arm EP2
            }
            SYNCDELAY; 
            EP4BCL = 0x80;                                 // skip package, (re)arm EP4
        }
    }
}

Firmware for EZ-USB FX3: ucecho-fx3.c

Also note that the Cypress SDK contains a very similar example (cyfxisolpmaninout) which is more than 1000 long. This demonstrates the efficiency of the ZTEX SDK.

#include "cyu3system.h"
#include "cyu3os.h"
#include "cyu3dma.h"

// loads default configuration macros
#include "ztex-conf.c"

CyU3PDmaChannel dma_out_handle, dma_in_handle;

/* Define endpoints 2 and 4. Both belong to interface 0 (in/out are seen from the host)
 * Burst size is 1 and DMA size is 2x1K. */
#undef EP_SETUP
#define EP_SETUP \
    INTERFACE(0, \
        EP_BULK(4, OUT, 1, /* direction as seen from the host */ \
            DMA(dma_in_handle, CY_U3P_DMA_TYPE_MANUAL_IN, 1, 2, CY_U3P_CPU_SOCKET_CONS, \
                CB(0,0) \
            ) \
        ) \
        EP_BULK(2, IN, 1, \
            DMA(dma_out_handle, CY_U3P_DMA_TYPE_MANUAL_OUT, 1, 2, CY_U3P_CPU_SOCKET_PROD, ) \
        ) \
    )

#undef ZTEX_PRODUCT_STRING 
#define ZTEX_PRODUCT_STRING "ucecho for EZ-USB FX3"

#include "ztex.c"       

void usb_start() {
    // start USB transfers as soon cable is connected
    ZTEX_REC(CyU3PDmaChannelSetXfer (&dma_in_handle, 0));
    ZTEX_REC(CyU3PDmaChannelSetXfer (&dma_out_handle, 0));
}

void usb_stop() {
    // nothing required here
}

void run () {
    CyU3PDmaBuffer_t inbuf, outbuf;
    CyU3PReturnStatus_t status;
    uint32_t i;

    ztex_log ( "ucecho for EZ-USB devices" );

    while (1) {
        if (ztex_usb_is_connected) {
            /* Wait for receiving a buffer from the producer socket (OUT endpoint). The call
             * will fail if there was an error or if the USB connection was reset / disconnected.
             * In case of error invoke the error handler and in case of reset / disconnection,
             * ztex_usb_is_connected will be 0; continue to beginning of the loop. */
            status = CyU3PDmaChannelGetBuffer (&dma_in_handle, &inbuf, CYU3P_WAIT_FOREVER);
            // ZTEX_LOG("EC=%d,  Read %d bytes", status, inbuf.count);
            if (!ztex_usb_is_connected || status==CY_U3P_ERROR_TIMEOUT) continue;
            ZTEX_REC_CONT(status);

            /* Wait for a free buffer to transmit the received data. 
             * The failure cases are same as above. */
            status = CyU3PDmaChannelGetBuffer (&dma_out_handle, &outbuf, CYU3P_WAIT_FOREVER);
            if (!ztex_usb_is_connected || status==CY_U3P_ERROR_TIMEOUT) continue;
            ZTEX_REC(status);

            /* Convert the data from the producer channel to the consumer channel. 
             * The inbuf.count holds the amount of valid data received. */
            CyU3PMemCopy (outbuf.buffer, inbuf.buffer, inbuf.count);
            for (i=0; i<inbuf.count; i++ )
                outbuf.buffer[i] = inbuf.buffer[i]>='a' && inbuf.buffer[i]<='z' ? 
                                   inbuf.buffer[i] - 32 : inbuf.buffer[i];

            /* Now discard the data from the producer channel so that the buffer is made
             * available to receive more data. */
            status = CyU3PDmaChannelDiscardBuffer (&dma_in_handle);
            if (!ztex_usb_is_connected) continue;
            ZTEX_REC(status);

            /* Commit the received data to the consumer pipe so that the data can be
             * transmitted back to the USB host. Since the same data is sent back, the
             * count shall be same as received and the status field of the call shall
             * be 0 for default use case. */
            status = CyU3PDmaChannelCommitBuffer (&dma_out_handle, inbuf.count, 0);
            // ZTEX_LOG("EC=%d,  Sent %d bytes", status, outbuf.status);
            if (!ztex_usb_is_connected) continue;
            ZTEX_REC(status);
        }
        else {
            /* No active data transfer. Sleep for a small amount of time. */
            CyU3PThreadSleep (100);
        }
    }
    
}

/*
 * Main function
 */
int main (void)
{
    // global configuration
    ztex_app_thread_run = run;
    ztex_usb_start = usb_start;
    ztex_usb_stop = usb_stop;
    
    ztex_main();        // starts the OS and never returns
    return 0;           // makes the compiler happy
}

Host Software: UCEcho.java

The Java host software writes strings entered by user to endpoint 4 and outputs the result read from endpoint 2. If no or incorrect firmware is installed, the EZ-USB variant is determined and the correct firmware image is uploaded automatically

import java.io.*;
import java.util.*;
import java.nio.*;

import org.usb4java.*;

import ztex.*;

// *****************************************************************************
// ******* ParameterException **************************************************
// *****************************************************************************
// Exception the prints a help message
class ParameterException extends Exception {
    public final static String helpMsg = new String (
                "Parameters:\n"+
                "    -d <number>       Device Number (default: 0)\n" +
                "    -f                Force uploads\n" +
                "    -p                Print bus info\n" +
                "    -h                This help" );
    
    public ParameterException (String msg) {
        super( msg + "\n" + helpMsg );
    }
}

// *****************************************************************************
// ******* UCEcho *************************************************************
// *****************************************************************************
class UCEcho extends Ztex1v1 {

// ******* Debug ***************************************************************
// constructor
    public UCEcho ( ZtexDevice1 pDev ) throws UsbException {
        super ( pDev );
    }

// ******* echo ****************************************************************
// writes a string to Endpoint 4, reads it back from Endpoint 2 and outputs the result
    public void echo ( String input ) throws UsbException {
        int i = bulkWrite(0x04, allocateByteBuffer(input.getBytes()) , 1000);
        if ( i<0 ) throw new UsbException("Error sending data: " + LibUsb.strError(i));
        System.out.println("Send "+i+" bytes: `"+input+"'" );

        try { Thread.sleep( 10 ); } catch ( InterruptedException e ) { }

        ByteBuffer buffer = BufferUtils.allocateByteBuffer(1024);
        i = bulkRead(0x82, buffer, 1000);
        if ( i<0 ) throw new UsbException("Error receiving data: " + LibUsb.strError(i));
        else if (i==0) System.out.println("Read "+0+" bytes" );  
        else {
            byte[] buf = new byte[i];
            buffer.get(buf);
            System.out.println("Read "+i+" bytes: `"+new String(buf,0,i)+"'" );  
        } 
    }


// ******* main ****************************************************************
    public static void main (String args[]) {
    
        int devNum = 0;
        boolean force = false;
        
        try {

// Scan the USB. This also creates and initializes a new USB context.
            ZtexScanBus1 bus = new ZtexScanBus1( ZtexDevice1.ztexVendorId, 
                                                 ZtexDevice1.ztexProductId, true, false, 1);
            if ( bus.numberOfDevices() <= 0) {
                System.err.println("No devices found");
                System.exit(0);
            }
            
// scan the command line arguments
            for (int i=0; i<args.length; i++ ) {
                if ( args[i].equals("-d") ) {
                    i++;
                    try {
                        if (i>=args.length) throw new Exception();
                        devNum = Integer.parseInt( args[i] );
                    } 
                    catch (Exception e) {
                        throw new ParameterException("Device number expected after -d");
                    }
                }
                else if ( args[i].equals("-f") ) {
                    force = true;
                }
                else if ( args[i].equals("-p") ) {
                    bus.printBus(System.out);
                    System.exit(0);
                }
                else if ( args[i].equals("-h") ) {
                        System.err.println(ParameterException.helpMsg);
                        System.exit(0);
                }
                else throw new ParameterException("Invalid Parameter: "+args[i]);
            }
            

// create the main class            
            UCEcho ztex = new UCEcho ( bus.device(devNum) );
            bus.unref();
            
// upload the firmware if necessary
            if ( force || ! ztex.valid() || 
                 ! ztex.dev().productString().equals("ucecho for EZ-USB devices") ) {
                String imgfn = "ucecho-fx2.ihx";
                if ( ztex.dev().fx3() ) {
                    System.out.println( "Trying to overwrite firmware in RAM. This only " + 
                                        "works if a board specific firmware with reset\n" + 
                                        "support is running. If uploading firmware fails "+
                                        " please restart board with disabled firmware." );
                    imgfn = "ucecho-fx3.img";
                }
                System.out.println( "Firmware upload time: " + 
                                    ztex.uploadFirmware( imgfn, force ) + " ms");
            }
            
// claim interface 0
            ztex.trySetConfiguration ( 1 );
            ztex.claimInterface ( 0 );
            
// print board log
            ztex.debug2PrintNextLogMessages(System.out);

// read string from stdin and write it to USB device
            try {
                String str = "";
                BufferedReader reader = new BufferedReader( new InputStreamReader( System.in ) );
                while ( ! str.equals("quit") ) {
                    System.out.print("Enter a string or `quit' to exit the program: ");
                    str = reader.readLine();
                    if ( ! str.equals("") ) ztex.echo(str);
                    System.out.println("");
                    ztex.debug2PrintNextLogMessages(System.out);
                }
            }
            catch ( Exception e ) {
                System.out.println("ucecho test failed: " + e.getLocalizedMessage() );
            }

            ztex.debug2PrintNextLogMessages(System.out); 

            ztex.dispose();  // this also releases claimed interfaces

        }
        catch (Exception e) {
            System.out.println("Error: "+e.getLocalizedMessage() );
        } 
   } 
   
}

Example call

An example call with output including FX3 log messages can be found below.

stefan@ws2:/drv_s2/usb-fpga/ucecho$ java -cp UCEcho.jar UCEcho
Trying to overwrite firmware in RAM. This only works if a board specific firmware with reset
support is running. If uploading firmware fails please restart board with disabled firmware.
Firmware upload time: 144 ms
Info: Found 128 MBit SPI Flash
ucecho for EZ-USB devices
Info: USB setup finished: super speed
Info: USB disconnected.
Info: USB setup finished: super speed
Enter a string or `quit' to exit the program: hello world!
Send 12 bytes: `hello world!'
Read 12 bytes: `HELLO WORLD!'

Enter a string or `quit' to exit the program: quit
Send 4 bytes: `quit'
Read 4 bytes: `QUIT'


[Home]  [Impressum]   
© ZTEX GmbH