![]() |
FlxCard
|
This note defines an application program interface (API) for the use of the FLX PCIe I/O card in the ATLAS read-out system. The intention of the API is to satisfy the needs of simple test programs as well as the requirements of the FelixApplication.
This is the header file for the FlxCard object
This note defines an application program interface (API) for use with FLX PCIe cards.
The API can also be used for the Wupper release. Wupper is the OpenCore version of the PCIe DMA engine of the FLX firmware. See:
https://opencores.org/project/virtex7_pcie_dma
The main requirements that drove the design of this API as well as the underlying software were:
The following issues are related to the implementation of the API:
Links to documentation on how to install additional software and build FlxCard can be found in:
https://gitlab.cern.ch/atlas-tdaq-felix/flxcard/blob/master/README.md
The source code of the library (FlxCard.cpp) uses the DEBUG_TEXT macro
Example:
DEBUG_TEXT(DFDB_FELIX, 15, "card number = " << cardno);
If the code gets compiled without –DDEBUG_LEVEL=1 the macros will disappear (i.e. will not impact performance) If the macros are enabled the generation of the debug text can be controlled via two variables:
#include "DFDebug/DFDebug.h" DF::GlobalDebugSettings::setup(dblevel, dbpackage);
dbpackage defines the package for which text is output. In order to activate line in the example above one has to set dbpackage=DFDB_FELIX dblevel defines the level of verbosity. Only messages that have a level equal or smaller than dblevel will be printed.
All errors will be reported through exceptions. For that purpose an exception class, FlxException.cpp, has been added. The FlxException object inherits from std::runtime_error and provides some additional data members such as an error code.
At the level of the FlxCard source code a macro is used for throwing exceptions:
#define THROW_FLX_EXCEPTION(errorCode, message) throw FlxException(FlxException::errorCode, message);
Section 'Application Program Interface' contains the definition of the API. For each function the section gives a detailed description of all input and output parameters, a description of the functionality and the return codes. The section contains sub-section for the type definitions used by the API as well as functions concerning the return codes.
The methods of the API are grouped by function into several categories.
For the implementation of the API it will be necessary to develop service functions for internal use. They are not described in this API document.
The remarks below apply to all functions defined in the API:
In order to optimize user code for performance and to spot potential race conditions between processes and threads it is important to know details about the interface between this library and the device driver underneath. The methods listed in the table below make a call to the driver (typically via an ioctl()
function or to mmap()
).
Method | Type of driver access |
---|---|
card_open() | open() and ioctl(SETCARD) |
card_close() | close() |
dma_max_tlp_bytes() | ioctl(GET_TLP) |
irq_enable() | ioctl(UNMASK_IRQ) |
irq_disable() | ioctl(MASK_IRQ) |
irq_wait() | ioctl(WAIT_IRQ) |
irq_cancel() | ioctl(CANCEL_IRQ_WAIT) |
irq_clear() | ioctl(CLEAR_IRQ) |
irq_reset_conters() | ioctl(RESET_IRQ_COUNTERS) |
map_memory_bar() | mmap() |
number_of_cards() | ioctl(GETCARDS) |
This section provides some information about how I2C transfers work in the FELIX system. At the level of the software tools several of the applications in the flxcard package perform I2C transfers. The program flx-i2c allows for the execution of single transfers. Program flx-init
provides functions that execute lists of I2C transactions in order to e.g. set the clock frequency of the TTC interface.
Description of flx-i2c:
Command “flx-i2c list” produces a list of I2C devices. Below is the output for an FLX-712. FLX-709, FLX-710, FLX-711 and FLX-128 cards are of course also supported.
The function of the FELIX can be implemented on several types of PCI cards. They are known as FLX-709, FLX-710, FLX-711, FLX-712 and FLX-128. Each type of PCI card has its own I2C tree. This tree connects to the FPGA. Therefore all I2C commands originate in the firmware and the used programs I2C transactions by reading from and writing to registers of the firmware (via PCIe).
The switch I2C addresses are the address of the single I2C switches on the FELIX cards. All I2C devices (see below) connect to these switches. Hence every I2C access from the firmware is first routed to a switch and from there reaches the endpoint.
On a FLX with more than one switch, the first one is connected to the firmware (primary switch) and the second connects to one of the ports of the first; therefore, it is a secondary switch that cannot be reached directly from the firmware.
The output of “flx-i2c list” is what we call the “I2C model”. At the level of the software it is defined as an array of structures of type “i2c_device_t” in FlxCard.cpp.
Below is a description of the columns of the table above:
Column | Description |
---|---|
Device | This is the name of a discrete chip with a I2C interface |
Model | This is the actual part number of the device |
Switch port | An I2C switch has 8 ports. Each port has its own range of 128 device addresses. Therefore up to 128 I2C devices could be connected to each port in principle. The first number is the switch port (0..7). The number after the “:” characters is the secondary and tertiary switch number in case of cascaded switches (present on certain hardware platforms), or '-' if that number does not apply. Therefore e.g. “7:-:-” refers to a port that connects directly to I2C endpoint devices while “4:3:-” means that two switches are cascaded. The first number (“4”) is the port of the first switch and the second number (“3”) refers to the port of the second switch. |
Address | This is a 7-bit address value that selects the I2C endpoint device. The addresses of the endpoints are hardwired in the hardware design. |
The applications internally use functions of the flxcard API: i2c_devices_read(), i2c_devices_write(), i2c_read_byte() and i2c_write_byte(). See the appropriate section in another chapter for the details of these methods.