SPI protocol
Description of the SPI protocol and its implementation in the Typhoon HIL toolchain.
Protocol introduction
The Serial Peripheral interface (SPI) is a synchronous serial communication interface specification used for short-distance communication, primarily in embedded systems.
SPI devices communicate in full duplex mode using a master-slave architecture usually with a single master. The master (controller) device originates the frame for reading and writing. Multiple slave-devices may be supported through selection with individual chip select (CS), sometimes called slave select (SS) lines.
Interface
The SPI bus specifies four logic signals
- SCLK: Serial Clock (output from master)
- MOSI: Master Out Slave In (data output from master)
- MISO: Master In Slave Out (data output from slave)
- CS /SS : Chip/Slave Select (output from master to indicate that data is being sent)
MOSI on master connects to MOSI on slave. MISO on master connects to MISO on slave.
Clock polarity and phase
SPI has 4 operating modes that correspond to the four possible clocking configurations. These configurations are defined with the clock polarity (CPOL) and clock phase (CPHA).
- Mode 0: Data is sampled on the rising edge of the clock pulse with a non-inverted clock polarity (CPOL = 0, CPHA = 0)
- Mode 1: Data is sampled on the falling edge of the clock pulse with a non-inverted clock polarity (CPOL = 0, CPHA = 1)
- Mode 2: Data is sampled on the falling edge of the clock pulse with an inverted clock polarity (CPOL = 1, CPHA = 0)
- Mode 3: Data is sampled on the rising edge of the clock pulse with an inverted clock polarity (CPOL = 1, CPHA = 1)
Independent slave configuration
In the independent slave configuration, there is an independent chip select line for each slave. The master asserts only one chip select at a time. Since the MISO pins of all slaves are connected together, they are required to be tri-state pins (high, low or high-impedance), where the high-impedance output must be applied when the slave is not selected.
Daisy chain configuration
Some products that implement SPI may be connected in a daisy chain configuration, the first slave output being connected to the second slave input, etc. The SPI port of each slave is designed to send out during the second group of clock pulses an exact copy of the data it received during the first group of clock pulses. The whole chain acts as a communication shift register; daisy chaining is often done with shift registers to provide a bank of inputs or outputs through SPI. Each slave copies input to output in the next clock cycle until active low SS line goes high. Such a feature only requires a single SS line from the master, rather than a separate SS line for each slave.
SPI protocol in Typhoon HIL toolchain
Currently, only SPI Slave functionality is implemented in the Typhoon HIL toolchain. It is supported by the following Typhoon HIL devices: HIL101, HIL404, HIL506, and HIL606.
SPI is implemented using the GPIO connector on a HIL device. This limits the use of the protocol to the devices that have this type of connector. This limits the use of the protocol to the devices that have a GPIO connector. Information regarding the available ports for each HIL device model is documented in each device's General Specifications section in the Hardware Manual.. The pinout for the GPIO connector per HIL device is also detailed there in the Mechanical section.
The pinout for the SPI protocol can be customized through the SPI Slave component in Schematic Editor, as shown in Table 1.
SPI Slave
The SPI Slave component implements the Slave part of the SPI protocol. Using this component you can configure the SPI Slave operating mode described in Protocol introduction, define the Register map and define the message frames.
The SPI component icon and dialog window are shown in Table 1.
Icon | Dialog window | Properties |
---|---|---|
SPI Slave |
|
The SPI Slave component properties are described in Table 2.
Tab | Property name | Description |
---|---|---|
General | Execution rate | Signal Processing execution rate |
SPI mode | Defines the SPI operation mode | |
MOSI pin | Defines which GPIO pin is used for the MOSI signal | |
MISO pin | Defines which GPIO pin is used for the MISO signal | |
SCLK pin | Defines which GPIO pin is used for the SPI clock signal | |
CS/SS pin | Defines which GPIO pin is used for the chip select signal | |
Message | Default return | Defines a 1 byte value which will be sent by the SPI Slave in parts of the message not reserved for register data. |
Write frame | Defines the structure of the write frame. This property is defined as a list of Python dictionaries. | |
Read frame | Defines the structure of the read frame. This property is defined as a list of Python dictionaries. | |
Message output | Defines the structure of the data that is returned as a response to the read frame. This property is defined as a list of Python dictionaries. | |
Receive output | Choose whether the message output is sent in the same message as the read frame (this appends the output frame to the read frame), or as part of the next message (output is sent at the start of the next message). | |
Generate message structure | Pressing the button will present an additional dialog window that allows the user to specify the message frames in more intuitive manner. | |
Registers | Register | Definition of the SPI Slave register map. The property is defined as a Python dictionary. A detailed description of the register map specification is in Register map |
Generate registers | Pressing the button will present an additional dialog window that allows the user to specify the register map in more intuitive manner. |
Message frames
- Write frame - represents the write command coming from the SPI Master. Using this message, the Master can change the value of the Slave register on the specified address
- Read frame - represents the read command coming from the SPI Master. Using this message, the Master requests data from the Slave on the specified address
- Output frame - represents the Slaves answer to the read message form the Master
These message frames have customizable structures which can be defined based on user requirements. For the structure to be functional, it has to follow these requirements:
- Write and read frames must contain Command and Address parts
- Write and output frames must contain a Register data field
- Command and Address parts of the write and read frame must start from the same bit and have the same length
- If the output frame is sent in the next message, read and write frames must have a size greater or equal to the size of the output frame
- The start bit of the first part in the Output frame should be equal to the total size of the Read frame
Field | Description |
---|---|
Message part | Defines whether the part is a Command, Address, Register data or Input data (Input data is used as a filler and its contents is ignored) |
Start bit | Position of first bit of that message part in the message frame |
Length | Size of that message part, defined in bits |
Logic | Defines the logic for the command (not available other frame parts) |
Value | Defines the value for the command (not available for other frame parts) |
Register map
The Register map defines the list of registers on the Slave device, their addresses, types, lengths and Endianness. These registers define inputs and outputs of the SPI Slave component.
Field | Description |
---|---|
Signal name | Defines the name of the register |
Register address | Defines the register address which is used to access register data |
IO type | Defines the register as an input or output (constant type registers can only be defined as outputs) |
Signal type | Defines the register as a variable or constant (input registers can only be defined as variables) |
Data type | Defines the type of data that the register holds (only registers defined as constant can have the String data type) |
Length | Defines the register size in bytes (depends on the register data type) |
Endian | Defines the Endianness of the register data |
Signal value | Defines the initial register value (values can only be set for output registers) |
Accessing registers
Register data can be accessed using the user-defined register address or the addresses generated for each byte of a register. These addresses are automatically generated based on the user-defined register address using 1 byte increments. An example of this is shown in Figure 1.
Interractions between registers
User-defined registers are stored in memory as a C array, with their order being the same as the order of definition (register address does not affect order). This makes it possible to access data from multiple registers with a single write or read command.
For example, if the registers are defined as shown in Figure 1 a read Frame can be sent with the Address 0x10 requesting 2 bytes of data. The response would contain data from Registers 2 and 3.
SPI reset
The SPI Slave application can be disabled by providing a non-zero value to the the reset input while the simulation is running. This will cause the application to reset and stay in a disabled state until a 0 is detected at the reset input. Resetting the SPI Slave application will clear all active SPI status codes.
SPI status
The SPI status output is used to monitor the SPI status which can help troubleshoot potential errors. Table 5 contains possible error codes and their descriptions. Each error has dedicated bit value(s) that respresent the error code status.
Value | Error |
---|---|
64 (0x40) | Transfer buffer underflow |
32 (0x20) | Receive buffer full |
16 (0x10) | Transfer buffer full |
2 (0x02) | Modfail |
1 (0x01) | Receive buffer overflow |
SPI Slave example
This example uses a SCADA Input to set the value of the input register, as well as Probes to read the values of the output registers. The SPI Slave component is configured as shown in the following figures.
The message structure definition is shown in Figure 2.
The registers definition is shown in Figure 3.
Timing diagrams of message frames
The timing diagrams for the specified message structures are as follows:
- Write frame
- Read frame with output frame in the same message
- Output frame in a new message