Xilinx Vitis Drivers API Documentation
spips Documentation

This file contains the implementation of the XSpiPs driver. It works for both the master and slave mode. User documentation for the driver functions is contained in this file in the form of comment blocks at the front of each function.

An SPI device connects to an SPI bus through a 4-wire serial interface. The SPI bus is a full-duplex, synchronous bus that facilitates communication between one master and one slave. The device is always full-duplex, which means that for every byte sent, one is received, and vice-versa. The master controls the clock, so it can regulate when it wants to send or receive data. The slave is under control of the master, it must respond quickly since it has no control of the clock and must send/receive data as fast or as slow as the master does.

Initialization & Configuration

The XSpiPs_Config structure is used by the driver to configure itself. This configuration structure is typically created by the tool-chain based on HW build properties.

To support multiple runtime loading and initialization strategies employed by various operating systems, the driver instance can be initialized in the following way:

  • XSpiPs_LookupConfig(DeviceId) - Use the divide identifier to find the static configuration structure defined in xspips_g.c. This is setup by the tools. For some operating systems the config structure will be initialized by the software and this call is not needed.
  • XSpiPs_CfgInitialize(InstancePtr, CfgPtr, EffectiveAddr) - Uses a configuration structure provided by the caller. If running in a system with address translation, the provided virtual memory base address replaces the physical address present in the configuration structure.

Multiple Masters

More than one master can exist, but arbitration is the responsibility of the higher layer software. The device driver does not perform any type of arbitration.

Multiple Slaves

Contention between multiple masters is detected by the hardware, in which case a mode fault occurs on the device. The device is disabled immediately by hardware, and the current word transfer is stopped. The Aborted word transfer due to the mode fault is resumed once the devie is enabled again.

Modes of Operation

There are four modes to perform a data transfer and the selection of a mode is based on Chip Select(CS) and Start. These two options individually, can be controlled either by software(Manual) or hardware(Auto).

  • Auto CS: Chip select is automatically asserted as soon as the first word is written into the TXFIFO and deasserted when the TXFIFO becomes empty
  • Manual CS: Software must assert and deassert CS.
  • Auto Start: Data transmission starts as soon as there is data in the TXFIFO and stalls when the TXFIFO is empty
  • Manual Start: Software must start data transmission at the beginning of the transaction or whenever the TXFIFO has become empty

The preferred combination is Manual CS and Auto Start. In this combination, the software asserts CS before loading any data into TXFIFO. In Auto Start mode, whenever data is in TXFIFO, controller sends it out until TXFIFO becomes empty. The software reads the RXFIFO whenever the data is available. If no further data, software disables CS.

Risks/challenges of other combinations:

  • Manual CS and Manual Start: Manual Start bit should be set after each TXFIFO write otherwise there could be a race condition where the TXFIFO becomes empty before the new word is written. In that case the transmission stops.
  • Auto CS with Manual or Auto Start: It is very difficult for software to keep the TXFIFO filled. Whenever the TXFIFO runs empty, CS is deasserted. This results in a single transaction to be split into multiple pieces each with its own chip select. This will result in garbage data to be sent.


The user must connect the interrupt handler of the driver, XSpiPs_InterruptHandler, to an interrupt system such that it will be called when an interrupt occurs. This function does not save and restore the processor context such that the user must provide this processing.

The driver handles the following interrupts:

  • Data Transmit Register/FIFO Underflow
  • Data Receive Register/FIFO Full
  • Data Receive Register/FIFO Not Empty
  • Data Transmit Register/FIFO Full
  • Data Transmit Register/FIFO Overwater
  • Mode Fault Error
  • Data Receive Register/FIFO Overrun

The Data Transmit Register/FIFO Overwater interrupt – indicates that the SPI device has transmitted the data available to transmit, and now its data register and FIFO is ready to accept more data. The driver uses this interrupt to indicate progress while sending data. The driver may have more data to send, in which case the data transmit register and FIFO is filled for subsequent transmission. When this interrupt arrives and all the data has been sent, the driver invokes the status callback with a value of XST_SPI_TRANSFER_DONE to inform the upper layer software that all data has been sent.

The Data Transmit Register/FIFO Underflow interrupt – indicates that, as slave, the SPI device was required to transmit but there was no data available to transmit in the transmit register (or FIFO). This may not be an error if the master is not expecting data. But in the case where the master is expecting data, this serves as a notification of such a condition. The driver reports this condition to the upper layer software through the status handler.

The Data Receive Register/FIFO Overrun interrupt – indicates that the SPI device received data and subsequently dropped the data because the data receive register and FIFO was full. The interrupt applies to both master and slave operation. The driver reports this condition to the upper layer software through the status handler. This likely indicates a problem with the higher layer protocol, or a problem with the slave performance.

The Mode Fault Error interrupt – indicates that while configured as a master, the device was selected as a slave by another master. This can be used by the application for arbitration in a multimaster environment or to indicate a problem with arbitration. When this interrupt occurs, the driver invokes the status callback with a status value of XST_SPI_MODE_FAULT. It is up to the application to resolve the conflict. When configured as a slave, Mode Fault Error interrupt indicates that a slave device was selected as a slave by a master, but the slave device was disabled. When configured as a master, Mode Fault Error interrupt indicates that another SPI device is acting as a master on the bus.

Polled Operation

Transfer in polled mode is supported through a separate interface function XSpiPs_PolledTransfer(). Unlike the transfer function in the interrupt mode, this function blocks until all data has been sent/received.

Device Busy

Some operations are disallowed when the device is busy. The driver tracks whether a device is busy. The device is considered busy when a data transfer request is outstanding, and is considered not busy only when that transfer completes (or is aborted with a mode fault error). This applies to both master and slave devices.

Device Configuration

The device can be configured in various ways during the FPGA implementation process. Configuration parameters are stored in the xspips_g.c file or passed in via XSpiPs_CfgInitialize(). A table is defined where each entry contains configuration information for an SPI device, including the base address for the device.

RTOS Independence

This driver is intended to be RTOS and processor independent. It works with physical addresses only. Any needs for dynamic memory management, threads or thread mutual exclusion, virtual memory, or cache control must be satisfied by the layer above this driver.

Ver   Who    Date     Changes

1.00 drg/jz 01/25/10 First release 1.00 sdm 10/25/11 Removed the Divide by 2 in the SPI Clock Prescaler options as this is not supported in the device. 1.01 sg 03/07/12 Updated the code to always clear the relevant bits before writing to config register. Always clear the slave select bits before write and clear the bits to no slave at the end of transfer Modified the Polled transfer transmit/receive logic. Tx should wait on TXOW Interrupt and Rx on RXNEMTY. 1.02 sg 05/31/12 Updated XSPIPS_FIFO_DEPTH to 128 from 32 to match HW for CR 658289 1.03 sg 09/21/12 Added memory barrier dmb in polled transfer and interrupt handler to overcome the clock domain crossing issue in the controller. For CR #679252. 1.04a sg 01/30/13 Created XSPIPS_MANUAL_START_OPTION. Created macros XSpiPs_IsMaster, XSpiPs_IsManualStart and XSpiPs_IsManualChipSelect. Changed SPI Enable/Disable macro argument from BaseAddress to Instance Pointer. Added DelayNss argument to SetDelays and GetDelays API's. Added macros to set/get the RX Watermark value.Created macros XSpiPs_IsMaster, XSpiPs_IsManualStart and XSpiPs_IsManualChipSelect. Changed SPI transfer logic for polled and interrupt modes to be based on filled tx fifo count and receive based on it. RXNEMPTY interrupt is not used. SetSlaveSelect API logic is modified to drive the bit position low based on the slave select value requested. GetSlaveSelect API will return the value based on bit position that is low. Created XSPIPS_CR_MODF_GEN_EN_MASK macro and added it to XSPIPS_CR_RESET_STATE. Created XSPIPS_IXR_WR_TO_CLR_MASK for interrupts which need write-to-clear. Added shift and mask macros for d_nss parameter. Added Rx Watermark mask. 1.05a hk 26/04/13 Added disable and enable in XSpiPs_SetOptions when CPOL/CPHA bits are set/reset. Fix for CR#707669. 1.06a hk 08/22/13 Changed GetSlaveSelect function. CR# 727866. Added masking ConfigReg before writing in SetSlaveSel Added extended slave select support - CR#722569. Added prototypes of reset API and related constant definitions. Added check for MODF in polled transfer function. 3.0 vm 12/09/14 Modified driver source code for MISRA-C:2012 compliance. Support for Zynq Ultrascale Mp added. ms 03/17/17 Added readme.txt file in examples folder for doxygen generation. ms 04/05/17 Modified Comment lines in functions of spips examples to recognize it as documentation block for doxygen generation and also modified filename tag in eeprom interrupt, eeprom polled and flash polled files to include them in doxygen examples. 3.1 tjs 04/12/18 InputClockHz parameter copied in instance for use in application. CR#998910 3.2 aru 01/20/19 Fixes violations according to MISRAC-2012 in safety mode and done changes such as Declared the pointer param as Pointer to const. 3.2 nsk 03/26/19 Add support for versal - CR #1025583. 3.3 mus 04/05/19 Replaced XPLAT_versal macro with XPLAT_VERSAL, to be in sync with standalone BSP 3.3 akm 08/06/19 Initialized DeviceID in XSpiPs_CfgInitialize function. 3.5 akm 09/02/20 Updated the Makefile to support parallel make execution. 3.6 sg 02/05/21 Added polled mode example for TPM device. 3.7 asa 04/01/22 Updated version to 3.7. Fixed issue in selftest example.