libfpgalink.h File Reference

Go to the source code of this file.

The FPGALink library makes it easier to talk to an FPGA over USB (via a suitable micro).

It performs three classes of function:


Overview

Types
enum  FLStatus {
  FL_SUCCESS = 0, FL_ALLOC_ERR, FL_USB_ERR, FL_PROTOCOL_ERR,
  FL_EARLY_TERM, FL_FX2_ERR, FL_FILE_ERR, FL_UNSUPPORTED_CMD_ERR,
  FL_UNSUPPORTED_DATA_ERR, FL_UNSUPPORTED_SIZE_ERR, FL_SVF_PARSE_ERR, FL_CONF_FORMAT,
  FL_PROG_PORT_MAP, FL_PROG_SEND, FL_PROG_RECV, FL_PROG_SHIFT,
  FL_PROG_JTAG_FSM, FL_PROG_JTAG_CLOCKS, FL_PROG_SVF_COMPARE, FL_PROG_SVF_UNKNOWN_CMD,
  FL_PROG_ERR, FL_PORT_IO, FL_BAD_STATE, FL_INTERNAL_ERR
}
enum  LogicalPort {
  LP_CHOOSE, LP_MISO, LP_MOSI, LP_SS,
  LP_SCK, LP_D8
}
enum  PinConfig { PIN_UNUSED, PIN_HIGH, PIN_LOW, PIN_INPUT }
enum  BitOrder { SPI_MSBFIRST, SPI_LSBFIRST }
Miscellaneous Functions
FLStatus flInitialise (int debugLevel, const char **error)
 Initialise the library with the given log level.
void flFreeError (const char *err)
 Free an error allocated when one of the other functions fails.
Connection Lifecycle
FLStatus flOpen (const char *vp, struct FLContext **handle, const char **error)
 Open a connection to the FPGALink device at the specified VID and PID.
void flClose (struct FLContext *handle)
 Close an existing connection to an FPGALink device.
Device Capabilities and Status
FLStatus flIsDeviceAvailable (const char *vp, uint8 *isAvailable, const char **error)
 Check if the given device is actually connected to the system.
uint8 flIsNeroCapable (struct FLContext *handle)
 Check to see if the device supports NeroProg.
uint8 flIsCommCapable (struct FLContext *handle, uint8 conduit)
 Check to see if the device supports CommFPGA.
uint16 flGetFirmwareID (struct FLContext *handle)
 Get the firmware ID.
uint32 flGetFirmwareVersion (struct FLContext *handle)
 Get the firmware version.
CommFPGA Operations
FLStatus flSelectConduit (struct FLContext *handle, uint8 conduit, const char **error)
 Select a different conduit.
FLStatus flIsFPGARunning (struct FLContext *handle, uint8 *isRunning, const char **error)
 Check to see if the FPGA is running.
FLStatus flReadChannel (struct FLContext *handle, uint8 channel, size_t numBytes, uint8 *buffer, const char **error)
 Synchronously read one or more bytes from the specified channel.
FLStatus flWriteChannel (struct FLContext *handle, uint8 channel, size_t numBytes, const uint8 *sendData, const char **error)
 Synchronously write one or more bytes to the specified channel.
FLStatus flSetAsyncWriteChunkSize (struct FLContext *handle, uint16 chunkSize, const char **error)
 Set the chunk size to be used for future async writes.
FLStatus flWriteChannelAsync (struct FLContext *handle, uint8 channel, size_t numBytes, const uint8 *sendData, const char **error)
 Asynchronously write one or more bytes to the specified channel.
FLStatus flFlushAsyncWrites (struct FLContext *handle, const char **error)
 Flush out any pending asynchronous writes.
FLStatus flAwaitAsyncWrites (struct FLContext *handle, const char **error)
 Wait for confirmation that pending asynchronous writes were received by the micro.
FLStatus flReadChannelAsyncSubmit (struct FLContext *handle, uint8 channel, uint32 numBytes, uint8 *buffer, const char **error)
 Submit an asynchronous read of one or more bytes from the specified channel.
FLStatus flReadChannelAsyncAwait (struct FLContext *handle, const uint8 **recvData, uint32 *requestLength, uint32 *actualLength, const char **error)
 Await the data from a previously-submitted asynchronous read.
FLStatus flResetToggle (struct FLContext *handle, const char **error)
NeroProg Operations
FLStatus flProgram (struct FLContext *handle, const char *progConfig, const char *progFile, const char **error)
 Program a device using the specified file.
FLStatus flProgramBlob (struct FLContext *handle, const char *progConfig, uint32 numBytes, const uint8 *progData, const char **error)
 Program a device using the specified programming blob.
FLStatus jtagScanChain (struct FLContext *handle, const char *portConfig, uint32 *numDevices, uint32 *deviceArray, uint32 arraySize, const char **error)
 Scan the JTAG chain and return an array of IDCODEs.
FLStatus progOpen (struct FLContext *handle, const char *portConfig, const char **error)
 Open an SPI/JTAG connection.
FLStatus progClose (struct FLContext *handle, const char **error)
 Close an SPI/JTAG connection.
FLStatus jtagShiftInOnly (struct FLContext *handle, uint32 numBits, const uint8 *tdiData, uint8 isLast, const char **error)
 Shift data into the JTAG state-machine.
FLStatus jtagShiftInOut (struct FLContext *handle, uint32 numBits, const uint8 *tdiData, uint8 *tdoData, uint8 isLast, const char **error)
 Shift data into and out of the JTAG state-machine.
FLStatus jtagClockFSM (struct FLContext *handle, uint32 bitPattern, uint8 transitionCount, const char **error)
 Clock transitionCount bits from bitPattern into TMS, starting with the LSB.
FLStatus jtagClocks (struct FLContext *handle, uint32 numClocks, const char **error)
 Toggle TCK numClocks times.
uint8 progGetPort (struct FLContext *handle, uint8 logicalPort)
 Get the physical port number of the specified logical port.
uint8 progGetBit (struct FLContext *handle, uint8 logicalPort)
 Get the physical bit number of the specified logical port.
FLStatus spiSend (struct FLContext *handle, uint32 numBytes, const uint8 *sendData, uint8 bitOrder, const char **error)
 Send a number of whole bytes over SPI, either LSB-first or MSB-first.
FLStatus spiRecv (struct FLContext *handle, uint32 numBytes, uint8 *buffer, uint8 bitOrder, const char **error)
 Receive a number of whole bytes over SPI, either LSB-first or MSB-first.
void spiBitSwap (uint32 numBytes, uint8 *data)
 Swap the bits in a byte array.
Firmware Operations
FLStatus flLoadStandardFirmware (const char *curVidPid, const char *newVidPid, const char **error)
 Load standard FPGALink firmware into the FX2's RAM.
FLStatus flFlashStandardFirmware (struct FLContext *handle, const char *newVidPid, const char **error)
 Flash standard FPGALink firmware into the FX2's EEPROM.
FLStatus flLoadCustomFirmware (const char *curVidPid, const char *fwFile, const char **error)
 Load custom firmware (.hex) into the FX2's RAM.
FLStatus flFlashCustomFirmware (struct FLContext *handle, const char *fwFile, const char **error)
 Flash a custom firmware from a file into the FX2's EEPROM.
FLStatus flSaveFirmware (struct FLContext *handle, uint32 eepromSize, const char *saveFile, const char **error)
 Save existing EEPROM data to a file.
FLStatus flBootloader (struct FLContext *handle, const char **error)
 Put the AVR in DFU bootloader mode.
Utility Functions
void flSleep (uint32 ms)
 Sleep for the specified number of milliseconds.
uint8 * flLoadFile (const char *name, size_t *numBytes)
 Return a newly-allocated buffer with the specified file loaded into it.
void flFreeFile (uint8 *buffer)
 Free a buffer previously returned by flLoadFile().
FLStatus flSingleBitPortAccess (struct FLContext *handle, uint8 portNumber, uint8 bitNumber, uint8 pinConfig, uint8 *pinRead, const char **error)
 Configure a single port bit on the microcontroller.
FLStatus flMultiBitPortAccess (struct FLContext *handle, const char *portConfig, uint32 *readState, const char **error)
 Configure multiple port bits on the microcontroller.

Enumeration Type Documentation

enum FLStatus

Return codes from the functions.

Enumerator:
FL_SUCCESS 

The operation completed successfully.

FL_ALLOC_ERR 

There was a memory allocation error.

FL_USB_ERR 

There was some USB-related problem.

FL_PROTOCOL_ERR 

The device is probably not a valid FPGALink device.

FL_EARLY_TERM 

The device did an unexpected early read termination.

FL_FX2_ERR 

There was some problem talking to the FX2 chip.

FL_FILE_ERR 

There was a file-related problem.

FL_UNSUPPORTED_CMD_ERR 

The XSVF file contains an unsupported command.

FL_UNSUPPORTED_DATA_ERR 

The XSVF file contains an unsupported XENDIR or XENDDR.

FL_UNSUPPORTED_SIZE_ERR 

The XSVF file requires more buffer space than is available.

FL_SVF_PARSE_ERR 

The SVF file is not parseable.

FL_CONF_FORMAT 

The supplied programming config is malformed.

FL_PROG_PORT_MAP 

There was a problem remapping ports for programming.

FL_PROG_SEND 

There was a problem sending data during programming.

FL_PROG_RECV 

There was a problem receiving data during programming.

FL_PROG_SHIFT 

There was a problem with the requested shift operation.

FL_PROG_JTAG_FSM 

There was a problem navigating the JTAG state machine.

FL_PROG_JTAG_CLOCKS 

There was a problem issuing clocks during programming.

FL_PROG_SVF_COMPARE 

An SVF compare operation failed.

FL_PROG_SVF_UNKNOWN_CMD 

An unknown SVF command was encountered.

FL_PROG_ERR 

The device failed to start after programming.

FL_PORT_IO 

There was a problem doing port I/O.

FL_BAD_STATE 

You're trying to do something that is illegal in this state.

FL_INTERNAL_ERR 

An internal error occurred. Please report it!

Enum used by progGetPort() and progGetBit() to identify the programming pins.

Enumerator:
LP_CHOOSE 

These aren't the droids you're looking for. Move along.

LP_MISO 

The master-in, slave-out pin (TDO).

LP_MOSI 

The master-out, slave-in pin (TDI).

LP_SS 

The slave-select pin (TMS).

LP_SCK 

The serial clock pin (TCK).

LP_D8 

The parallel data port.

enum PinConfig

Enum used by flSingleBitPortAccess() to configure the pin direction and drive.

Enumerator:
PIN_UNUSED 

These are also not the droids you're looking for. Keep moving along.

PIN_HIGH 

Configure the pin as an output and drive it high.

PIN_LOW 

Configure the pin as an output and drive it low.

PIN_INPUT 

Configure the pin as an input.

enum BitOrder

Enum used by spiSend() and spiRecv() to set the order bits are clocked in.

Enumerator:
SPI_MSBFIRST 

Clock each byte most-significant bit first.

SPI_LSBFIRST 

Clock each byte least-significant bit first.


Function Documentation

FLStatus flInitialise ( int  debugLevel,
const char **  error 
)

Initialise the library with the given log level.

This may fail if LibUSB cannot talk to the USB host controllers through its kernel driver (e.g a Linux kernel with USB support disabled, or a machine lacking a USB host controller).

Parameters:
debugLevel0->none, 1, 2, 3->lots.
errorA pointer to a const char* which will be set on exit to an allocated error message if something goes wrong. Responsibility for this allocated memory passes to the caller and must be freed with flFreeError(). If error is NULL, no allocation is done and no message is returned, but the return code will still be valid.
Returns:
  • FL_SUCCESS if the operation completed successfully.
  • FL_USB_ERR if there were problems initialising LibUSB.
void flFreeError ( const char *  err)

Free an error allocated when one of the other functions fails.

Parameters:
errAn error message previously allocated by one of the other library functions.
FLStatus flOpen ( const char *  vp,
struct FLContext **  handle,
const char **  error 
)

Open a connection to the FPGALink device at the specified VID and PID.

Connects to the device and verifies it's an FPGALink device, then queries its capabilities.

Parameters:
vpThe Vendor/Product (i.e VVVV:PPPP) of the FPGALink device. You may also specify an optional device ID (e.g 1D50:602B:0004). If no device ID is supplied, it selects the first device with matching VID:PID.
handleA pointer to a struct FLContext* which will be set on exit to point at a newly-allocated context structure. Responsibility for this allocated memory (and its associated USB resources) passes to the caller and must be freed with flClose(). Will be set NULL if an error occurs.
errorA pointer to a const char* which will be set on exit to an allocated error message if something goes wrong. Responsibility for this allocated memory passes to the caller and must be freed with flFreeError(). If error is NULL, no allocation is done and no message is returned, but the return code will still be valid.
Returns:
  • FL_SUCCESS if all is well (*handle is valid).
  • FL_ALLOC_ERR if there was a memory allocation failure.
  • FL_USB_ERR if the VID:PID is invalid or the device cannot be found or opened.
  • FL_PROTOCOL_ERR if the device is not an FPGALink device.
void flClose ( struct FLContext *  handle)

Close an existing connection to an FPGALink device.

If the handle is NULL, this function does nothing.

Parameters:
handleThe handle returned by flOpen(), or NULL.
FLStatus flIsDeviceAvailable ( const char *  vp,
uint8 *  isAvailable,
const char **  error 
)

Check if the given device is actually connected to the system.

The LibUSB devices in the system are searched for a device with the given VID:PID.

There is a short period of time following a call to flLoadStandardFirmware() or flLoadCustomFirmware() during which this function will still return with *isAvailable == 1 for the "current" VID:PID, so when you load new firmware, it's important to either wait a while before calling this function, or alternatively just ensure that the "new" VID:PID is different from the "current" VID:PID to avoid such false positives.

Parameters:
vpThe Vendor/Product (i.e VVVV:PPPP) of the FPGALink device. You may also specify an optional device ID (e.g 1D50:602B:0004). If no device ID is supplied, it selects the first device with matching VID:PID.
isAvailableA pointer to an 8-bit integer which will be set on exit to 1 if available else 0.
errorA pointer to a const char* which will be set on exit to an allocated error message if something goes wrong. Responsibility for this allocated memory passes to the caller and must be freed with flFreeError(). If error is NULL, no allocation is done and no message is returned, but the return code will still be valid.
Returns:
  • FL_SUCCESS if all is well (*isAvailable is valid).
  • FL_USB_ERR if the VID:PID is invalid or if no USB buses were found (did you remember to call flInitialise()?).
uint8 flIsNeroCapable ( struct FLContext *  handle)

Check to see if the device supports NeroProg.

NeroProg is the collective name for all the various programming algorithms supported by FPGALink, including but not limited to JTAG. An affirmative response means you are free to call flProgram(), flProgramBlob(), jtagScanChain(), progOpen(), progClose(), jtagShiftInOnly(), jtagShiftInOut(), jtagClockFSM(), jtagClocks(), progGetPort(), progGetBit(), spiSend(), spiRecv() and spiBitSwap().

This function merely returns a flag determined by flOpen(), so it cannot fail.

Parameters:
handleThe handle returned by flOpen().
Returns:
An 8-bit integer: 1 if the device supports NeroProg, else 0.
uint8 flIsCommCapable ( struct FLContext *  handle,
uint8  conduit 
)

Check to see if the device supports CommFPGA.

CommFPGA is a set of channel read/write protocols. The micro may implement several different CommFPGA protocols, distinguished by the chosen conduit. A micro will typically implement its first CommFPGA protocol on conduit 1, and additional protocols on conduit 2, 3 etc. Conduit 0 is reserved for communication over JTAG using a virtual TAP state machine implemented in the FPGA, and is not implemented yet.

This function returns 1 if the micro supports CommFPGA on the chosen conduit, else 0.

Note that this function can only know the capabilities of the micro itself; it cannot determine whether the FPGA contains suitable logic to implement the protocol, or even whether there is an FPGA physically wired to the micro in the first place.

An affirmative response means you are free to call flIsFPGARunning(), flReadChannel(), flWriteChannel(), flSetAsyncWriteChunkSize(), flWriteChannelAsync(), flFlushAsyncWrites() flAwaitAsyncWrites(), flReadChannelAsyncSubmit(), and flReadChannelAsyncAwait().

This function merely returns information determined by flOpen(), so it cannot fail.

Parameters:
handleThe handle returned by flOpen().
conduitThe conduit you're interested in (this will typically be 1).
Returns:
An 8-bit integer: 1 if the device supports CommFPGA, else 0.
uint16 flGetFirmwareID ( struct FLContext *  handle)

Get the firmware ID.

Each firmware (or fork of an existing firmware) has its own 16-bit ID, which this function retrieves.

This function merely returns information determined by flOpen(), so it cannot fail.

Parameters:
handleThe handle returned by flOpen().
Returns:
A 16-bit unsigned integer giving the firmware ID.
uint32 flGetFirmwareVersion ( struct FLContext *  handle)

Get the firmware version.

Each firmware knows the GitHub tag from which is was built, or if it was built from a trunk, it knows the date on which it was built. This function returns a 32-bit integer giving that information. If printed as a hex number, it gives an eight-digit ISO date.

This function merely returns information determined by flOpen(), so it cannot fail.

Parameters:
handleThe handle returned by flOpen().
Returns:
A 32-bit unsigned integer giving the firmware version.
FLStatus flSelectConduit ( struct FLContext *  handle,
uint8  conduit,
const char **  error 
)

Select a different conduit.

Select a different conduit for CommFPGA communication. Typically a micro will implement its first CommFPGA protocol on conduit 1. It may or may not also implement others on conduit 2, 3, 4 etc. It may also implement comms-over-JTAG using a virtual TAP FSM on the FPGA. You can use flIsCommCapable() to determine whether the micro supports CommFPGA on a given conduit.

If mixing NeroProg operations with CommFPGA operations, it may be necessary to switch conduits. For example, if your PCB is wired to use some of the CommFPGA signals during programming, you will have to switch back and forth. But if the pins used for CommFPGA are independent of the pins used for NeroProg, you need only select the correct conduit on startup and then leave it alone.

Parameters:
handleThe handle returned by flOpen().
conduitThe conduit to select (current range 0-15).
errorA pointer to a const char* which will be set on exit to an allocated error message if something goes wrong. Responsibility for this allocated memory passes to the caller and must be freed with flFreeError(). If error is NULL, no allocation is done and no message is returned, but the return code will still be valid.
Returns:
  • FL_SUCCESS if the operation completed successfully.
  • FL_USB_ERR if the device doesn't respond, or the conduit is out of range.
FLStatus flIsFPGARunning ( struct FLContext *  handle,
uint8 *  isRunning,
const char **  error 
)

Check to see if the FPGA is running.

This may only be called if flIsCommCapable() returns true. It merely verifies that the FPGA is asserting that it's ready to read commands on the chosen conduit. Some conduits may not have the capability to determine this, and will therefore just optimistically report true. Before calling this function you should verify that the FPGALink device actually supports CommFPGA using flIsCommCapable(), and select the conduit you wish to use with flSelectConduit().

Parameters:
handleThe handle returned by flOpen().
isRunningA pointer to an 8-bit integer which will be set on exit to 1 if the FPGA is running, else 0.
errorA pointer to a const char* which will be set on exit to an allocated error message if something goes wrong. Responsibility for this allocated memory passes to the caller and must be freed with flFreeError(). If error is NULL, no allocation is done and no message is returned, but the return code will still be valid.
Returns:
  • FL_SUCCESS if all is well (*isRunning is valid).
  • FL_PROTOCOL_ERR if the device does not support CommFPGA.
FLStatus flReadChannel ( struct FLContext *  handle,
uint8  channel,
size_t  numBytes,
uint8 *  buffer,
const char **  error 
)

Synchronously read one or more bytes from the specified channel.

Read numBytes bytes from the FPGA channel channel into the buffer array. Before calling this function you should verify that the FPGALink device actually supports CommFPGA using flIsCommCapable().

Because this function is synchronous, it will block until the data has been returned. You must not use this function between an async read submit...await pair.

Parameters:
handleThe handle returned by flOpen().
channelThe FPGA channel to read (0-127).
numBytesThe number of bytes to read.
bufferThe address of a buffer to store the bytes read from the FPGA.
errorA pointer to a const char* which will be set on exit to an allocated error message if something goes wrong. Responsibility for this allocated memory passes to the caller and must be freed with flFreeError(). If error is NULL, no allocation is done and no message is returned, but the return code will still be valid.
Returns:
  • FL_SUCCESS if the operation completed successfully.
  • FL_USB_ERR if a USB read or write error occurred.
  • FL_PROTOCOL_ERR if the device does not support CommFPGA.
FLStatus flWriteChannel ( struct FLContext *  handle,
uint8  channel,
size_t  numBytes,
const uint8 *  sendData,
const char **  error 
)

Synchronously write one or more bytes to the specified channel.

Write numBytes bytes from the sendData array to FPGA channel channel. Before calling this function you should verify that the FPGALink device actually supports CommFPGA using flIsCommCapable().

Because this function is synchronous, it will block until the OS has confirmed that the data has been correctly sent over USB and received by the micro. It cannot confirm that the data has been received by the FPGA however: it may be waiting in the micro's output buffer.

Parameters:
handleThe handle returned by flOpen().
channelThe FPGA channel to write (0-127).
numBytesThe number of bytes to write.
sendDataThe address of the array of bytes to be written to the FPGA.
errorA pointer to a const char* which will be set on exit to an allocated error message if something goes wrong. Responsibility for this allocated memory passes to the caller and must be freed with flFreeError(). If error is NULL, no allocation is done and no message is returned, but the return code will still be valid.
Returns:
  • FL_SUCCESS if the operation completed successfully.
  • FL_ALLOC_ERR if there was a memory allocation failure.
  • FL_USB_ERR if a USB write error occurred.
  • FL_PROTOCOL_ERR if the device does not support CommFPGA.
  • FL_BAD_STATE if there are async reads in progress.
FLStatus flSetAsyncWriteChunkSize ( struct FLContext *  handle,
uint16  chunkSize,
const char **  error 
)

Set the chunk size to be used for future async writes.

By default, the flWriteChannelAsync() function buffers up to 64KiB of data before sending anything over USB. Chunking the data in this way is more efficient than sending lots of little messages. However, the choice of chunk size affects the steady-state throughput in interesting ways. If you need to, you can choose to make the chunks smaller than 64KiB.

You should not call this when there is some send data buffered. You should either call this before the first call to flWriteChannelAsync(), or call it immediately after a call to flFlushAsyncWrites().

Parameters:
handleThe handle returned by flOpen().
chunkSizeThe new chunksize in bytes. Passing zero sets the chunkSize to 64KiB.
errorA pointer to a const char* which will be set on exit to an allocated error message if something goes wrong. Responsibility for this allocated memory passes to the caller and must be freed with flFreeError(). If error is NULL, no allocation is done and no message is returned, but the return code will still be valid.
Returns:
  • FL_SUCCESS if the operation completed successfully.
  • FL_BAD_STATE if there is some outstanding send data.
FLStatus flWriteChannelAsync ( struct FLContext *  handle,
uint8  channel,
size_t  numBytes,
const uint8 *  sendData,
const char **  error 
)

Asynchronously write one or more bytes to the specified channel.

Write numBytes bytes from the sendData array to FPGA channel channel. Before calling this function you should verify that the FPGALink device actually supports CommFPGA using flIsCommCapable().

This function is asynchronous. That means it will return immediately, usually before anything has been actually sent over USB. If the operation fails, you will not be notified of the failure until a future call to flAwaitAsyncWrites() or flReadChannelAsyncAwait(). The data is copied internally, so there's no need to worry about preserving the data: it's safe to call flWriteChannelAsync() on a stack-allocated array, for example.

Parameters:
handleThe handle returned by flOpen().
channelThe FPGA channel to write (0-127).
numBytesThe number of bytes to write.
sendDataThe address of the array of bytes to be written to the FPGA.
errorA pointer to a const char* which will be set on exit to an allocated error message if something goes wrong. Responsibility for this allocated memory passes to the caller and must be freed with flFreeError(). If error is NULL, no allocation is done and no message is returned, but the return code will still be valid.
Returns:
  • FL_SUCCESS if the operation completed successfully.
  • FL_ALLOC_ERR if there was a memory allocation failure.
  • FL_USB_ERR if a USB write error occurred.
  • FL_PROTOCOL_ERR if the device does not support CommFPGA.
FLStatus flFlushAsyncWrites ( struct FLContext *  handle,
const char **  error 
)

Flush out any pending asynchronous writes.

Flush any writes that have been buffered up, or do nothing if no writes have been buffered. This only triggers the send over USB; it does not guarantee the micro successfully received the data. See flAwaitAsyncWrites().

Parameters:
handleThe handle returned by flOpen().
errorA pointer to a const char* which will be set on exit to an allocated error message if something goes wrong. Responsibility for this allocated memory passes to the caller and must be freed with flFreeError(). If error is NULL, no allocation is done and no message is returned, but the return code will still be valid.
Returns:
  • FL_SUCCESS if the operation completed successfully.
  • FL_USB_ERR if a USB write error occurred.
  • FL_PROTOCOL_ERR if the device does not support CommFPGA.
FLStatus flAwaitAsyncWrites ( struct FLContext *  handle,
const char **  error 
)

Wait for confirmation that pending asynchronous writes were received by the micro.

The first thing this does is to call flFlushAsyncWrites() to flush out any outstanding write commands. It will then block until the OS confirms that all the asynchronous write commands sent by flWriteChannelAsync() were correctly sent over USB and received by the micro. It cannot confirm that that the writes were received by the FPGA however: they may be waiting in the micro's output buffer.

Parameters:
handleThe handle returned by flOpen().
errorA pointer to a const char* which will be set on exit to an allocated error message if something goes wrong. Responsibility for this allocated memory passes to the caller and must be freed with flFreeError(). If error is NULL, no allocation is done and no message is returned, but the return code will still be valid.
Returns:
  • FL_SUCCESS if the operation completed successfully.
  • FL_USB_ERR if one of the outstanding async operations failed.
  • FL_PROTOCOL_ERR if the device does not support CommFPGA.
  • FL_BAD_STATE if there are async reads in progress.
FLStatus flReadChannelAsyncSubmit ( struct FLContext *  handle,
uint8  channel,
uint32  numBytes,
uint8 *  buffer,
const char **  error 
)

Submit an asynchronous read of one or more bytes from the specified channel.

Submit an asynchronous read of numBytes bytes from the FPGA channel channel. You can request at most 64KiB of data asynchronously. Before calling this function you should verify that the FPGALink device actually supports CommFPGA using flIsCommCapable().

This function is asynchronous. That means it will return immediately, usually before the read request has been sent over USB. You will not find out the result of the read until you later call flReadChannelAsyncAwait() - this will give you your data, or tell you what went wrong.

You should always ensure that for each call to flReadChannelAsyncSubmit(), there is a matching call to flReadChannelAsyncAwait(). You should not call any of flSetAsyncWriteChunkSize(), flAwaitAsyncWrites(), flWriteChannel() or flReadChannel() between a submit...await pair.

USB host controllers typically need just one level of nesting of submit...await pairs to keep them busy. That means sequences like submit, submit, await, submit, await, submit, ..., await, await.

Parameters:
handleThe handle returned by flOpen().
channelThe FPGA channel to read (0-127).
numBytesThe number of bytes to read, <= 64KiB (hence uint32 rather than size_t).
bufferA buffer to receive the data, or NULL if you want to borrow one.
errorA pointer to a const char* which will be set on exit to an allocated error message if something goes wrong. Responsibility for this allocated memory passes to the caller and must be freed with flFreeError(). If error is NULL, no allocation is done and no message is returned, but the return code will still be valid.
Returns:
  • FL_SUCCESS if the operation completed successfully.
  • FL_USB_ERR if a USB read or write error occurred.
  • FL_PROTOCOL_ERR if the device does not support CommFPGA.
FLStatus flReadChannelAsyncAwait ( struct FLContext *  handle,
const uint8 **  recvData,
uint32 *  requestLength,
uint32 *  actualLength,
const char **  error 
)

Await the data from a previously-submitted asynchronous read.

Block until the outcome of a previous call to flReadChannelAsyncSubmit() is known. If the read was successful, you are given the resulting data. If not, an error code/message.

On successful outcome, the three out parameters are populated with a pointer to the FPGA data, the requested length and the actual length. Unless the FPGA and micro support early termination of reads, the two lengths will be identical.

Unless you provided your own buffer when you called flReadChannelAsyncSubmit(), the data returned is stored in an internal buffer. It is guaranteed to remain valid until your next call to any of the CommFPGA functions.

Parameters:
handleThe handle returned by flOpen().
recvDataA pointer to a const uint8 * which will be set on exit to point to a buffer containing the bytes read from the FPGA.
requestLengthA pointer to a uint32 which will be set on exit to the number of bytes requested in the corresponding call to flReadChannelAsyncSubmit().
actualLengthA pointer to a uint32 which will be set on exit to the number of bytes actually read from the FPGA.
errorA pointer to a const char* which will be set on exit to an allocated error message if something goes wrong. Responsibility for this allocated memory passes to the caller and must be freed with flFreeError(). If error is NULL, no allocation is done and no message is returned, but the return code will still be valid.
Returns:
  • FL_SUCCESS if the operation completed successfully.
  • FL_USB_ERR if one of the outstanding async operations failed.
FLStatus flResetToggle ( struct FLContext *  handle,
const char **  error 
)

Under some circumstances (e.g a Linux VM running on a Windows VirtualBox host talking to an FX2-based FPGALink device), it's necessary to manually reset the USB endpoints before doing any reads or writes. I admit this is hacky, and probably represents a bug somewhere.

Parameters:
handleThe handle returned by flOpen().
errorA pointer to a const char* which will be set on exit to an allocated error message if something goes wrong. Responsibility for this allocated memory passes to the caller and must be freed with flFreeError(). If error is NULL, no allocation is done and no message is returned, but the return code will still be valid.
Returns:
  • FL_SUCCESS if the operation completed successfully.
  • FL_USB_ERR if a USB error occurred.
FLStatus flProgram ( struct FLContext *  handle,
const char *  progConfig,
const char *  progFile,
const char **  error 
)

Program a device using the specified file.

This will program an FPGA or CPLD using the specified microcontroller ports and the specified programming file. Several programming algorithms are supported (JTAG, Xilinx Slave-Serial, Xilinx SelectMap and Altera Passive-Serial). In each case, it's necessary to tell the micro which ports to use. Here are some examples:

A Digilent board using JTAG: progConfig="J:D0D2D3D4":

  • TDO: PD0
  • TDI: PD2
  • TMS: PD3
  • TCK: PD4

MakeStuff LX9 using JTAG: progConfig="J:A7A0A3A1":

  • TDO: PA7
  • TDI: PA0
  • TMS: PA3
  • TCK: PA1

EP2C5 Mini Board using Altera Passive-Serial: progConfig="AS:B5B6B1B2" (note that the board normally connects MSEL[1:0] to ground, hard-coding it in Active-Serial mode. For Passive-Serial to work you need to lift pin 85 and pull it up to VCC):

  • nCONFIG: PD5
  • CONF_DONE: PD6
  • DCLK: PD1
  • DATA0: PD2

Aessent aes220 using Xilinx Slave-Serial: progConfig="XS:D0D5D1D6A7[D3?,B1+,B5+,B3+]":

  • PROG_B: PD0
  • INIT_B: PD5
  • DONE: PD1
  • CCLK: PD6
  • DIN: PA7
  • Tristate DOUT (PD3)
  • Drive M[2:0]="111" (PB1, PB5, PB3) for Slave-Serial

Aessent aes220 using Xilinx SelectMAP: progConfig="XP:D0D5D1D6A01234567[B4-,D2-,D3?,B1+,B5+,B3-]":

  • PROG_B: PD0
  • INIT_B: PD5
  • DONE: PD1
  • CCLK: PD6
  • D[7:0]: PA[7:0]
  • Drive RDWR_B="0" (PB4)
  • Drive CSI_B="0" (PD2)
  • Tristate DOUT (PD3)
  • Drive M[2:0]="110" (PB1, PB5, PB3) for SelectMAP

Note that this approach of specifying and implementing many disparate programming algorithms on the host side in terms of a much smaller set of building-block operations on the microcontroller is optimized for microcontrollers which support efficient remapping of I/O pins. For example the FX2 has a Von Neumann architecture where both code and data are stored in a single RAM-based address space, so port remapping can easily be achieved with self-modifying code. Conversely, the AVRs have Harvard architecture, where code and data are in separate address spaces, with code in flash so it cannot be self-modified. And actually, the AVR firmware is more likely to be tuned to a specific board layout than the more generic FX2 firmware.

So, the bottom line is, even if you're using a microcontroller whose port pins are hard-coded, you still have to supply the port pins to use when you call functions expecting progConfig.

You can either append the programming filename to the end of progConfig (e.g "J:A7A0A3A1:fpga.xsvf") or you can supply the programming filename separately in progFile.

Parameters:
handleThe handle returned by flOpen().
progConfigThe port configuration described above.
progFileThe name of the programming file, or NULL if it's already given in progConfig.
errorA pointer to a const char* which will be set on exit to an allocated error message if something goes wrong. Responsibility for this allocated memory passes to the caller and must be freed with flFreeError(). If error is NULL, no allocation is done and no message is returned, but the return code will still be valid.
Returns:
  • FL_SUCCESS if the operation completed successfully.
  • FL_ALLOC_ERR if we ran out of memory during programming.
  • FL_USB_ERR if a USB error occurred.
  • FL_FILE_ERR if the programming file is unreadable or an unexpected format.
  • FL_UNSUPPORTED_CMD_ERR if an XSVF file contains an unsupported command.
  • FL_UNSUPPORTED_DATA_ERR if an XSVF file contains an unsupported XENDDR/XENDIR.
  • FL_UNSUPPORTED_SIZE_ERR if an XSVF command is too long.
  • FL_SVF_PARSE_ERR if an SVF file is unparseable.
  • FL_CONF_FORMAT if progConfig is malformed.
  • FL_PROG_PORT_MAP if the micro was unable to map its ports to those given.
  • FL_PROG_SEND if the micro refused to accept programming data.
  • FL_PROG_RECV if the micro refused to provide programming data.
  • FL_PROG_SHIFT if the micro refused to begin a JTAG shift operation.
  • FL_PROG_JTAG_FSM if the micro refused to navigate the TAP state-machine.
  • FL_PROG_JTAG_CLOCKS if the micro refused to send JTAG clocks.
  • FL_PROG_SVF_COMPARE if an SVF/XSVF compare operation failed.
  • FL_PROG_SVF_UNKNOWN_CMD if an SVF/XSVF unknown command was encountered.
  • FL_PROG_ERR if the FPGA failed to start after programming.
  • FL_PORT_IO if the micro refused to configure one of its ports.
FLStatus flProgramBlob ( struct FLContext *  handle,
const char *  progConfig,
uint32  numBytes,
const uint8 *  progData,
const char **  error 
)

Program a device using the specified programming blob.

This is similar to flProgram(), except that instead of reading the programming information from a file, it runs the programming operation from a binary blob already stored in memory. For JTAG programming this is assumed to be a CSVF file; for Xilinx programming it is assumed to be a raw bitstream (.bin) file.

Parameters:
handleThe handle returned by flOpen().
progConfigThe port configuration described in flProgram().
numBytesThe number of bytes of programming data.
progDataA pointer to the start of the programming data.
errorA pointer to a const char* which will be set on exit to an allocated error message if something goes wrong. Responsibility for this allocated memory passes to the caller and must be freed with flFreeError(). If error is NULL, no allocation is done and no message is returned, but the return code will still be valid.
Returns:
  • FL_SUCCESS if the operation completed successfully.
  • FL_USB_ERR if a USB error occurred.
  • FL_CONF_FORMAT if progConfig is malformed.
  • FL_PROG_PORT_MAP if the micro was unable to map its ports to those given.
  • FL_PROG_SEND if the micro refused to accept programming data.
  • FL_PROG_RECV if the micro refused to provide programming data.
  • FL_PROG_SHIFT if the micro refused to begin a JTAG shift operation.
  • FL_PROG_JTAG_FSM if the micro refused to navigate the TAP state-machine.
  • FL_PROG_JTAG_CLOCKS if the micro refused to send JTAG clocks.
  • FL_PROG_SVF_COMPARE if an SVF/XSVF compare operation failed.
  • FL_PROG_SVF_UNKNOWN_CMD if an SVF/XSVF unknown command was encountered.
  • FL_PROG_ERR if the FPGA failed to start after programming.
  • FL_PORT_IO if the micro refused to configure one of its ports.
FLStatus jtagScanChain ( struct FLContext *  handle,
const char *  portConfig,
uint32 *  numDevices,
uint32 *  deviceArray,
uint32  arraySize,
const char **  error 
)

Scan the JTAG chain and return an array of IDCODEs.

Count the number of devices on the JTAG chain, and set *numDevices accordingly. Then, if deviceArray is not NULL, populate it with at most arraySize IDCODEs, in chain order.

Parameters:
handleThe handle returned by flOpen().
portConfigThe port bits to use for TDO, TDI, TMS & TCK, e.g "D0D2D3D4".
numDevicesA pointer to a uint32 which will be set on exit to the number of devices in the JTAG chain.
deviceArrayA pointer to an array of uint32, which will be populated on exit with a list of IDCODEs in chain order. May be NULL, in which case the function returns after setting *numDevices.
arraySizeThe number of 32-bit IDCODE slots available in deviceArray.
errorA pointer to a const char* which will be set on exit to an allocated error message if something goes wrong. Responsibility for this allocated memory passes to the caller and must be freed with flFreeError(). If error is NULL, no allocation is done and no message is returned, but the return code will still be valid.
Returns:
  • FL_SUCCESS if the operation completed successfully.
  • FL_CONF_FORMAT if portConfig is malformed.
  • FL_PROG_PORT_MAP if the micro was unable to map its ports to those given.
  • FL_PROG_SEND if the micro refused to accept programming data.
  • FL_PROG_RECV if the micro refused to provide programming data.
  • FL_PROG_SHIFT if the micro refused to begin a JTAG shift operation.
  • FL_PROG_JTAG_FSM if the micro refused to navigate the TAP state-machine.
  • FL_PORT_IO if the micro refused to configure one of its ports.
FLStatus progOpen ( struct FLContext *  handle,
const char *  portConfig,
const char **  error 
)

Open an SPI/JTAG connection.

Open a SPI/JTAG connection using the supplied portConfig. You must open a connection before calling jtagShiftInOut(), jtagShiftInOnly(), jtagClockFSM(), jtagClocks(), spiSend() or spiRecv(). And you must close the connection when you're finished, with progClose().

Parameters:
handleThe handle returned by flOpen().
portConfigThe port bits to use for MISO(TDO), MOSI(TDI), SS(TMS) and SCK(TCK), e.g "D0D2D3D4".
errorA pointer to a const char* which will be set on exit to an allocated error message if something goes wrong. Responsibility for this allocated memory passes to the caller and must be freed with flFreeError(). If error is NULL, no allocation is done and no message is returned, but the return code will still be valid.
Returns:
  • FL_SUCCESS if the operation completed successfully.
  • FL_CONF_FORMAT if portConfig is malformed.
  • FL_PROG_PORTMAP if the micro refused to map its ports to those given.
  • FL_PORT_IO if the micro refused to configure one of its ports.
FLStatus progClose ( struct FLContext *  handle,
const char **  error 
)

Close an SPI/JTAG connection.

Close an SPI/JTAG connection previously opened by progOpen(), and tri-state the four programming pins.

Parameters:
handleThe handle returned by flOpen().
errorA pointer to a const char* which will be set on exit to an allocated error message if something goes wrong. Responsibility for this allocated memory passes to the caller and must be freed with flFreeError(). If error is NULL, no allocation is done and no message is returned, but the return code will still be valid.
Returns:
  • FL_SUCCESS if the operation completed successfully.
  • FL_PORT_IO if the micro refused to configure one of its ports.
FLStatus jtagShiftInOnly ( struct FLContext *  handle,
uint32  numBits,
const uint8 *  tdiData,
uint8  isLast,
const char **  error 
)

Shift data into the JTAG state-machine.

Shift numBits bits LSB-first from tdiData into TDI. If isLast is zero, leave the TAP state-machine in Shift-xR, otherwise exit to Exit1-xR on the final bit. If you want tdiData to be all zeros you can use SHIFT_ZEROS, or if you want it to be all ones you can use SHIFT_ONES. This is more efficient than explicitly sending an array containing all zeros or all 0xFFs.

Parameters:
handleThe handle returned by flOpen().
numBitsThe number of bits to clock into the JTAG state-machine.
tdiDataA pointer to the source data, or SHIFT_ZEROS or SHIFT_ONES.
isLastEither 0 to remain in Shift-xR, or 1 to exit to Exit1-xR.
errorA pointer to a const char* which will be set on exit to an allocated error message if something goes wrong. Responsibility for this allocated memory passes to the caller and must be freed with flFreeError(). If error is NULL, no allocation is done and no message is returned, but the return code will still be valid.
Returns:
  • FL_SUCCESS if the operation completed successfully.
  • FL_PROG_SEND if the micro refused to accept programming data.
  • FL_PROG_SHIFT if the micro refused to begin a JTAG shift operation.
FLStatus jtagShiftInOut ( struct FLContext *  handle,
uint32  numBits,
const uint8 *  tdiData,
uint8 *  tdoData,
uint8  isLast,
const char **  error 
)

Shift data into and out of the JTAG state-machine.

Shift numBits bits LSB-first from tdiData into TDI; at the same time shift the same number of bits LSB-first from TDO into tdoData. If isLast is zero, leave the TAP state-machine in Shift-xR, otherwise exit to Exit1-xR on the final bit. If you want tdiData to be all zeros you can use SHIFT_ZEROS, or if you want it to be all ones you can use SHIFT_ONES. This is more efficient than explicitly sending an array containing all zeros or all 0xFFs.

Parameters:
handleThe handle returned by flOpen().
numBitsThe number of bits to clock into and out of the JTAG state-machine.
tdiDataA pointer to the source data, or SHIFT_ZEROS or SHIFT_ONES.
tdoDataA pointer to a buffer to receive output data, or NULL if you don't care.
isLastEither 0 to remain in Shift-xR, or 1 to exit to Exit1-xR.
errorA pointer to a const char* which will be set on exit to an allocated error message if something goes wrong. Responsibility for this allocated memory passes to the caller and must be freed with flFreeError(). If error is NULL, no allocation is done and no message is returned, but the return code will still be valid.
Returns:
  • FL_SUCCESS if the operation completed successfully.
  • FL_PROG_SEND if the micro refused to accept programming data.
  • FL_PROG_RECV if the micro refused to provide programming data.
  • FL_PROG_SHIFT if the micro refused to begin a JTAG shift operation.
FLStatus jtagClockFSM ( struct FLContext *  handle,
uint32  bitPattern,
uint8  transitionCount,
const char **  error 
)

Clock transitionCount bits from bitPattern into TMS, starting with the LSB.

Navigate the TAP state-machine by clocking an arbitrary sequence of bits into TMS.

Parameters:
handleThe handle returned by flOpen().
bitPatternThe pattern of bits to clock into TMS, LSB first.
transitionCountThe number of bits to clock.
errorA pointer to a const char* which will be set on exit to an allocated error message if something goes wrong. Responsibility for this allocated memory passes to the caller and must be freed with flFreeError(). If error is NULL, no allocation is done and no message is returned, but the return code will still be valid.
Returns:
  • FL_SUCCESS if the operation completed successfully.
  • FL_PROG_JTAG_FSM if the micro refused to navigate the TAP state-machine.
FLStatus jtagClocks ( struct FLContext *  handle,
uint32  numClocks,
const char **  error 
)

Toggle TCK numClocks times.

Parameters:
handleThe handle returned by flOpen().
numClocksThe number of clocks to put out on TCK.
errorA pointer to a const char* which will be set on exit to an allocated error message if something goes wrong. Responsibility for this allocated memory passes to the caller and must be freed with flFreeError(). If error is NULL, no allocation is done and no message is returned, but the return code will still be valid.
Returns:
  • FL_SUCCESS if the operation completed successfully.
  • FL_PROG_JTAG_CLOCKS if the micro refused to send JTAG clocks.
uint8 progGetPort ( struct FLContext *  handle,
uint8  logicalPort 
)

Get the physical port number of the specified logical port.

Get the physical port number assigned to the specified logical port by the preceding call to progOpen(). This is just a convenience function to avoid re-parsing the port config, which is typically supplied by the user as a string. For example, to send data to a SPI peripheral, you'll probably want to assert SS. So you'll want to call progGetPort(handle, LP_SS) to find out which physical port SS was assigned to.

Parameters:
handleThe handle returned by flOpen().
logicalPortThe LogicalPort to query for.
Returns:
The physical port mapped to the given LogicalPort.
uint8 progGetBit ( struct FLContext *  handle,
uint8  logicalPort 
)

Get the physical bit number of the specified logical port.

Get the physical bit number assigned to the specified logical port by the preceding call to progOpen(). This is just a convenience function to avoid re-parsing the port config, which is typically supplied by the user as a string. For example, to send data to a SPI peripheral, you'll probably want to assert SS. So you'll want to call progGetBit(handle, LP_SS) to find out which physical port bit SS was assigned to.

Parameters:
handleThe handle returned by flOpen().
logicalPortThe LogicalPort to query for.
Returns:
The physical bit mapped to the given LogicalPort.
FLStatus spiSend ( struct FLContext *  handle,
uint32  numBytes,
const uint8 *  sendData,
uint8  bitOrder,
const char **  error 
)

Send a number of whole bytes over SPI, either LSB-first or MSB-first.

Shift numBytes bytes from sendData into the microcontroller's SPI bus (if any), either MSB-first or LSB-first. You must have previously called progOpen().

Parameters:
handleThe handle returned by flOpen().
numBytesThe number of bytes to send.
sendDataA pointer to the source data.
bitOrderEither SPI_MSBFIRST or SPI_LSBFIRST (see BitOrder).
errorA pointer to a const char* which will be set on exit to an allocated error message if something goes wrong. Responsibility for this allocated memory passes to the caller and must be freed with flFreeError(). If error is NULL, no allocation is done and no message is returned, but the return code will still be valid.
Returns:
  • FL_SUCCESS if the operation completed successfully.
  • FL_ALLOC_ERR if there was a memory allocation failure.
  • FL_USB_ERR if USB communications failed whilst sending the data.
  • FL_PROTOCOL_ERR if the device does not support SPI.
FLStatus spiRecv ( struct FLContext *  handle,
uint32  numBytes,
uint8 *  buffer,
uint8  bitOrder,
const char **  error 
)

Receive a number of whole bytes over SPI, either LSB-first or MSB-first.

Shift numBytes bytes from the microcontroller's SPI bus (if any) into buffer, either MSB-first or LSB-first. You must have previously called progOpen().

Parameters:
handleThe handle returned by flOpen().
bufferA pointer to a buffer to receive the data.
numBytesThe number of bytes to receive.
bitOrderEither SPI_MSBFIRST or SPI_LSBFIRST (see BitOrder).
errorA pointer to a const char* which will be set on exit to an allocated error message if something goes wrong. Responsibility for this allocated memory passes to the caller and must be freed with flFreeError(). If error is NULL, no allocation is done and no message is returned, but the return code will still be valid.
Returns:
  • FL_SUCCESS if the operation completed successfully.
  • FL_USB_ERR if USB communications failed whilst receiving the data.
  • FL_PROTOCOL_ERR if the device does not support SPI.
void spiBitSwap ( uint32  numBytes,
uint8 *  data 
)

Swap the bits in a byte array.

Swap the bits in a byte, so that 0x01 -> 0x80, 0x02 -> 0x40 etc.

Parameters:
numBytesThe number of bytes to be bit-swapped.
dataA pointer to an array of uint8 to be bit-swapped.
FLStatus flLoadStandardFirmware ( const char *  curVidPid,
const char *  newVidPid,
const char **  error 
)

Load standard FPGALink firmware into the FX2's RAM.

Load the FX2 chip at the "current" VID:PID with a precompiled firmware such that it will renumerate as the "new" VID:PID. The firmware is loaded into RAM, so the change is not permanent. Typically after calling flLoadStandardFirmware() applications should wait for the renumeration to complete by calling flIsDeviceAvailable() repeatedly until the "new" VID:PID becomes active.

Parameters:
curVidPidThe current Vendor/Product (i.e VVVV:PPPP) of the FX2 device.
newVidPidThe Vendor/Product/Device (i.e VVVV:PPPP:DDDD) that you want the FX2 device to renumerate as.
errorA pointer to a const char* which will be set on exit to an allocated error message if something goes wrong. Responsibility for this allocated memory passes to the caller and must be freed with flFreeError(). If error is NULL, no allocation is done and no message is returned, but the return code will still be valid.
Returns:
  • FL_SUCCESS if the firmware loaded successfully.
  • FL_ALLOC_ERR if there was a memory allocation failure.
  • FL_USB_ERR if one of the VID:PIDs was invalid or the current VID:PID was not found.
  • FL_FX2_ERR if there was a problem talking to the FX2.
FLStatus flFlashStandardFirmware ( struct FLContext *  handle,
const char *  newVidPid,
const char **  error 
)

Flash standard FPGALink firmware into the FX2's EEPROM.

Warning:
This function will make permanent changes to your hardware. Remember to make a backup copy of the existing EEPROM firmware with flSaveFirmware() before calling it.

Overwrite the FX2's EEPROM with a precompiled FPGALink firmware such that the board will enumerate on power-on as the "new" VID:PID.

Parameters:
handleThe handle returned by flOpen().
newVidPidThe Vendor/Product (i.e VVVV:PPPP) you want the FX2 to be on power-on.
errorA pointer to a const char* which will be set on exit to an allocated error message if something goes wrong. Responsibility for this allocated memory passes to the caller and must be freed with flFreeError(). If error is NULL, no allocation is done and no message is returned, but the return code will still be valid.
Returns:
  • FL_SUCCESS if the firmware flashed successfully.
  • FL_ALLOC_ERR if there was a memory allocation failure.
  • FL_USB_ERR if the VID:PID was invalid.
  • FL_FX2_ERR if there was a problem talking to the FX2.
FLStatus flLoadCustomFirmware ( const char *  curVidPid,
const char *  fwFile,
const char **  error 
)

Load custom firmware (.hex) into the FX2's RAM.

Load the FX2 chip at the given VID:PID with a .hex firmware file. The firmware is loaded into RAM, so the change is not permanent.

Parameters:
curVidPidThe current Vendor/Product (i.e VVVV:PPPP) of the FX2 device.
fwFileA .hex file containing new FX2 firmware to be loaded into the FX2's RAM.
errorA pointer to a const char* which will be set on exit to an allocated error message if something goes wrong. Responsibility for this allocated memory passes to the caller and must be freed with flFreeError(). If error is NULL, no allocation is done and no message is returned, but the return code will still be valid.
Returns:
  • FL_SUCCESS if the firmware loaded successfully.
  • FL_ALLOC_ERR if there was a memory allocation failure.
  • FL_USB_ERR if the VID:PID was invalid.
  • FL_FX2_ERR if there was a problem talking to the FX2.
  • FL_FILE_ERR if fwFile has a bad extension or could not be loaded.
FLStatus flFlashCustomFirmware ( struct FLContext *  handle,
const char *  fwFile,
const char **  error 
)

Flash a custom firmware from a file into the FX2's EEPROM.

Warning:
This function will make permanent changes to your hardware. Remember to make a backup copy of the existing EEPROM firmware with flSaveFirmware() before calling it.

Overwrite the FX2's EEPROM with a custom firmware from a .hex or .iic file.

Parameters:
handleThe handle returned by flOpen().
fwFileA .hex or .iic file containing new FX2 firmware to be loaded into the FX2's EEPROM.
errorA pointer to a const char* which will be set on exit to an allocated error message if something goes wrong. Responsibility for this allocated memory passes to the caller and must be freed with flFreeError(). If error is NULL, no allocation is done and no message is returned, but the return code will still be valid.
Returns:
  • FL_SUCCESS if the firmware loaded successfully.
  • FL_ALLOC_ERR if there was a memory allocation failure.
  • FL_FX2_ERR if there was a problem talking to the FX2.
  • FL_FILE_ERR if the firmware file could not be loaded.
FLStatus flSaveFirmware ( struct FLContext *  handle,
uint32  eepromSize,
const char *  saveFile,
const char **  error 
)

Save existing EEPROM data to a file.

The existing EEPROM firmware is saved to an .iic file, for backup purposes.

Parameters:
handleThe handle returned by flOpen().
eepromSizeThe size in kilobits of the EEPROM (e.g Nexys2's EEPROM is 128kbit).
saveFileAn .iic file to save the EEPROM to.
errorA pointer to a const char* which will be set on exit to an allocated error message if something goes wrong. Responsibility for this allocated memory passes to the caller and must be freed with flFreeError(). If error is NULL, no allocation is done and no message is returned, but the return code will still be valid.
Returns:
  • FL_SUCCESS if the firmware loaded successfully.
  • FL_ALLOC_ERR if there was a memory allocation failure.
  • FL_FX2_ERR if there was a problem talking to the FX2.
  • FL_FILE_ERR if saveFile file could not be written.
FLStatus flBootloader ( struct FLContext *  handle,
const char **  error 
)

Put the AVR in DFU bootloader mode.

This is an AVR-specific utility function to make firmware upgrades easier on boards on which the /HWB and /RESET pins are not easily accesible. The "gordon" utility has an option to invoke this.

Parameters:
handleThe handle returned by flOpen().
errorA pointer to a const char* which will be set on exit to an allocated error message if something goes wrong. Responsibility for this allocated memory passes to the caller and must be freed with flFreeError(). If error is NULL, no allocation is done and no message is returned, but the return code will still be valid.
Returns:
  • FL_SUCCESS if the port access command completed successfully.
  • FL_USB_ERR if the device is not running suitable FPGALink/AVR firmware.
void flSleep ( uint32  ms)

Sleep for the specified number of milliseconds.

Parameters:
msThe number of milliseconds to sleep.
uint8* flLoadFile ( const char *  name,
size_t *  numBytes 
)

Return a newly-allocated buffer with the specified file loaded into it.

The specified file is queried for its length, that length is written to the numBytes parameter. Then a buffer of that length is allocated, and the file is loaded into it and a pointer to the buffer returned. The responsibility for the buffer passes to the caller; it must be freed later by a call to flFreeFile().

Parameters:
nameThe name of the file to load.
numBytesA pointer to a size_t which will be populated with the file's length.
Returns:
A pointer to the allocated buffer, or NULL if the file could not be loaded.
void flFreeFile ( uint8 *  buffer)

Free a buffer previously returned by flLoadFile().

Parameters:
bufferA buffer previously returned by flLoadFile().
FLStatus flSingleBitPortAccess ( struct FLContext *  handle,
uint8  portNumber,
uint8  bitNumber,
uint8  pinConfig,
uint8 *  pinRead,
const char **  error 
)

Configure a single port bit on the microcontroller.

With this function you can set a single microcontroller port bit to one of the enums in PinConfig, and read back the current state of the bit.

Parameters:
handleThe handle returned by flOpen().
portNumberWhich port to configure (i.e 0=PortA, 1=PortB, 2=PortC, etc).
bitNumberThe bit within the chosen port to use.
pinConfigEither PIN_INPUT, PIN_HIGH or PIN_LOW.
pinReadPointer to a uint8 to be set on exit to 0 or 1 depending on the current state of the pin. May be NULL if you're not interested.
errorA pointer to a const char* which will be set on exit to an allocated error message if something goes wrong. Responsibility for this allocated memory passes to the caller and must be freed with flFreeError(). If error is NULL, no allocation is done and no message is returned, but the return code will still be valid.
Returns:
  • FL_SUCCESS if the port access command completed successfully.
  • FL_PORT_IO if the micro failed to respond to the port access command.
FLStatus flMultiBitPortAccess ( struct FLContext *  handle,
const char *  portConfig,
uint32 *  readState,
const char **  error 
)

Configure multiple port bits on the microcontroller.

With this function you can set multiple microcontroller port bits to either PIN_INPUT, PIN_HIGH or PIN_LOW, and read back the current state of each bit. This is achieved by sending a comma-separated list of port configurations, e.g "A12-,B2+,C7?". A "+" or a "-" suffix sets the port as an output, driven high or low respectively, and a "?" suffix sets the port as an input. The current state of up to 32 bits are returned in readState, LSB first.

Parameters:
handleThe handle returned by flOpen().
portConfigA comma-separated sequence of port configurations.
readStatePointer to a uint32 to be set on exit to the port readback.
errorA pointer to a const char* which will be set on exit to an allocated error message if something goes wrong. Responsibility for this allocated memory passes to the caller and must be freed with flFreeError(). If error is NULL, no allocation is done and no message is returned, but the return code will still be valid.
Returns:
  • FL_SUCCESS if the port access command completed successfully.
  • FL_CONF_FORMAT if portConfig is malformed.
  • FL_PORT_IO if the micro failed to respond to the port access command.