Adding SPI support to an eCos port can take two forms. If there is
already an SPI bus driver for the target hardware then both that
driver and this generic SPI package CYGPKG_IO_SPI
should be included in the ecos.db target entry.
Typically the platform HAL will need to supply some platform-specific
information needed by the bus driver. In addition the platform HAL
should provide cyg_spi_device
structures for
every device attached to the bus. The exact details of this depend on
the bus driver so its documentation should be consulted for further
details. If there is no suitable SPI bus driver yet then a new driver
package will have to be written.
The generic SPI package CYGPKG_IO_SPI
defines a
data structure cyg_spi_device
. This contains
the information needed by the generic package, but not the additional
information needed by a bus driver to interact with the device. Each
bus driver will define a larger data structure, for example
cyg_mcf52xx_qspi_device
, which contains a
cyg_spi_device
as its first field. This is
analogous to C++ base and derived classes, but without any use of
virtual functions. The bus driver package should be consulted for the
details.
During initialization an SPI bus driver may need to know about all the devices attached to that bus. For example it may need to know which cpu pins should be configured as chip selects rather than GPIO pins. To achieve this all device definitions should specify the particular bus to which they are attached, for example:
struct cyg_mcf52xx_qspi_device hal_spi_atod CYG_SPI_DEVICE_ON_BUS(0) = { .spi_common.spi_bus = &cyg_mcf52xx_qspi_bus, … }; |
The CYG_SPI_DEVICE_ON_BUS
macro adds information
to the structure which causes the linker to group all such structures
in a single table. The bus driver's initialization code can then
iterate over this table.
An SPI bus driver usually involves a new hardware package. This needs to perform the following:
Define a device structure which contains a
cyg_spi_device
as its first element. This
should contain all the information needed by the bus driver to
interact with a device on that bus.
Provide functions for the following operations:
spi_transaction_begin |
spi_transaction_transfer |
spi_transaction_tick |
spi_transaction_end |
spi_get_config |
spi_set_config |
These correspond to the main API functions, but can assume that the bus is already locked so no other thread will be manipulating the bus or any of the attached devices. Some of these operations may be no-ops.
Define a bus structure which contains a
cyg_spi_bus
as its first element. This should
contain any additional information needed by the bus driver.
Optionally, instantiate the bus structure. The instance should have a well-known name since it needs to be referenced by the device structure initializers. For some drivers it may be best to create the bus inside the driver package. For other drivers it may be better to leave this to the platform HAL or the application. It depends on how much platform-specific knowledge is needed to fill in the bus structure.
Create a HAL table for the devices attached to this bus.
Arrange for the bus to be initialized early on during system
initialization. Typically this will happen via a prioritized static
constructor with priority CYG_INIT_BUS_SPI.
As part of this initialization the bus driver should
invoke the CYG_SPI_BUS_COMMON_INIT
macro on its
cyg_spi_bus
field.
Provide the appropriate documentation, including details of how the SPI device structures should be initialized.
There are no standard SPI testcases. It is not possible to write SPI code without knowing about the devices attached to the bus, and those are inherently hardware-specific.