SPI Bus
SPI device behaviour is emulated using the temu_SpiBus2 bus model.
The temu_SpiBus bus model has been deprecated as of TEMU 5.0.0, it should not
be used for new models and existing models should be migrated to the new bus model.
SpiBus2Interface
Transmissions are performed through the
temu_SpiBus2Iface interface provided by an instanced object of the bus model.
Connecting
To create a connection through an SPI bus an "SpiBus2" object needs to be instantiated. This manages the slave and master connections.
Connecting a master to the bus works as with any other model.
The master is connected to the bus object’s temu_SpiBus2Iface and stores it as a
temu_SpiBus2IfaceRef.
temu_connect(spiMaster, "spiBus", spiBus, "SpiBus2Iface")
connect a=spiMaster.spiBus b=spiBus:SpiBus2Iface
For slave devices a special procedure is required.
The temu_SpiBus2Iface provides connect and disconnect functions
which register a slave device with it’s corresponding chip number chipNum.
This number is used to relate the chipSelect raising and lowering to
a specific device. These should be used in favour or the typical connect functions.
When connecting or disconnecting a device the slave’s connected or disconnected
functions will be called respectively.
The slaves should use these to store the interface reference to the temu_SpiBus2.
Minimal implementations might look like this:
void
connected(temu_Object *Obj, uint8_t chipNum, temu_SpiBus2IfaceRef Device)
{
SPICTRL *spi = reinterpret_cast<SPICTRL *>(Obj);
spi->Super.ChipNum = chipNum;
spi->Bus = Device;
}
void
disconnected(temu_Object *Obj, uint8_t chipNum)
{
SPICTRL *spi = reinterpret_cast<SPICTRL *>(Obj);
spi->Bus.Iface = nullptr;
spi->Bus.Obj = nullptr;
}
connect-spi-slave slave=spidev0:SpiSlaveDevice2Iface chipNum=0 bus=spiBus:SpiBus2Iface
// Using the API directly
auto spiBusIf = reinterpret_cast<temu_SpiBus2Iface*>(
temu_getInterface(spiBus, "SpiBus2Iface", 0));
temu_SpiSlaveDevice2IfaceRef deviceRef = {(temu_Object *)spiDevice,
&spiSlaveDevIface};
uint8_t chipNum = 0;
spiBusIf->connect(spiBus, chipNum, deviceRef);
// or Calling the connect command
temu_execCommand("connect-spi-slave slave=spidev0:SpiSlaveDevice2Iface "
"chipNum=0 bus=spiBus:SpiBus2Iface");
Modelling
SPI-Slave models should expose their chip select number as a property to allow assigning
distinct numbers to all devices in accordance to the real wire layout being emulated.
To simplify this a model may use a struct of type temu_SpiSlaveDevice2 as its first
data member in place of the typical temu_Object.
During the registration of the model a call to temu_spiDevice2Register
will register the property.
| Most SPI slave device behaviour can be modelled nicely as a state machine starting when the chip select is raised, resetting when it is lowered and operating on each incoming character separately. |
Transmitting
A transmissions starts with raising the chip select signal of a slave
using the raiseChipSelect function of the interface.
This may be done by the SPI Controller used as the bus master or through any other means
such as an IO pin model which raises and lowers the chip select signal.
Using the transfer function of the bus allows the master to initiate
the transfer of data with the currently selected slave.
The contents of the temu_SpiTransaction being transferred allow for
the modeling of various SPI transmission setups.
When initiating the transfer the master should have filled out all
relevant values in the temu_SpiTransaction struct.
If the transmission was bi-directional the slave should immediately
reply by storing the requested ammount of data into the provided buffer.
Unresolved include directive in modules/buses/pages/spi.adoc - include::partial$auto-BusModels-meta-SPIBus2.adoc[]
Unresolved include directive in modules/buses/pages/spi.adoc - include::partial$auto-BusModels-SPIBus2.adoc[]