|
|
SDK für ZTEX-FPGA Boards - Beispiel
ZTEX stellt ein leistungsfähiges Open-Source SDK für die Entwicklung der Host-Software und der Firmware für den EZ-USB FX2 und FX3 USB-Controller
zur Verfügung. (Für die FPGA-Entwicklung wird Xilinx Software verwendet.)
Diese Seite gibt einen Eindruck über die SDK-Verwendung.
Bitte beachten Sie auch, dass die Entwicklung von eigener Firmware für viele Anwendungen überflüssig ist, falls die Standard-Firmware verwendet wird.
Viele weitere und komplexere Bespiele sind Teil des SDK.
Firmware
Die Firmware definiert zwei Endpoints. Daten werden vom Host über Endpoint 4 eingelesen, in Großbuchstaben konvertiert und via Endpoint 2 zurück geschrieben.
Da die USB-Deskriptoren und ISR vom Firmware-Kit automatisch erzeugt werden, ist der Quellcode relativ kompakt:
Firmware für den 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 für den EZ-USB FX3: ucecho-fx3.c
Beachten Sie, dass das Cypress SDK einen sehr ähnliches Beispiel beinhaltet (cyfxisolpmaninout) welches mehr als 1000 Zeilen lang ist.
Dieses verdeutlicht die Effizienz des 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
Die Java Host-Software schreibt durch den Benutzer eingegebene Zeichenketten zum Endpoint 4 und gibt das via Endpoint 2 eingelesene Resultat aus.
Falls keine oder falsche Firmware installiert ist, wird die EZ-USB Variante festgestellt und automatisch das korrekte Firmware-Abbild hochgeladen.
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() );
}
}
}
|
Beispiel Aufruf
Es folgt ein Beispiel-Aufruf mit Ausgabe einschließlich FX3 Log-Meldungen.
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'
|
|