CYGPKG_DEVS_SPI_MCFxxxx_QSPI -- eCos Support for the Freescale Coldfire QSPI Bus
Several processors in the Freescale ColdFire family come with an
on-chip SPI device, also known as QSPI. This package provides an eCos
bus driver for that device. It implements the functionality defined by
the generic SPI package CYGPKG_IO_SPI. The driver
supports both polled and interrupt-driven transfers. Typical supported
transfer rates range from 128KHz to 33MHz, although the exact details
depend on the specific ColdFire processor being used and on the
processor's clock speed. The hardware does not support DMA so large
transfers at high transfer rates will consume much of the available
This bus driver package does not instantiate any
cyg_spi_bus structures. It is possible for a
processor to have more than one SPI bus, so it is better to leave it
to the processor HAL to define the bus or buses. Instead the bus
driver package just provides functions and utility macros for use by
the processor HAL. Similarly the bus driver package does not provide
any cyg_spi_device structures. Exactly which
devices are attached to the SPI bus is a characteristic of the
platform so usually it is the platform HAL which provides the device instances.
This SPI bus driver package should be loaded automatically when
selecting a target containing a ColdFire processor with QSPI hardware,
and it should never be necessary to load the package explicitly. If
the application does not use any of the SPI functionality then all the
SPI support code should be removed at link-time and the application
does not suffer any overheads.
The package contains a single configuration option
Usually this option should not be manipulated by application
developers, instead it is set by the processor HAL.
When the option is disabled the driver will optimize for the common
case of a single bus.
The only other configuration options provided by this package relate
to compiler flags.
The header file cyg/io/mcfxxxx_qspi.h provides a utility
macro CYG_MCFxxxx_QSPI_BUS to allow processor HALs
to instantiate a bus. Existing HALs such as the MCF521x's will show
how to use this macro.
For most boards the platform HAL will create
cyg_spi_device instances for all attached SPI
devices, and will initialize the system so that the SPI-related
processor pins are connected appropriately. Some development boards
may not have any SPI devices but instead export the relevant signals
to expansion connectors. In those cases it will be the responsibility
of application code to create the device instances and manipulate the
GPIO pins appropriately.
Device instances should take the form of a
cyg_mcfxxxx_qspi_device structure, which
contains a cyg_spi_device as its first field.
This defines a variable hal_spi_atod which can be
used by other packages or by application code as an argument to the
I/O functions provided by the generic SPI package
CYGPKG_IO_SPI. A gcc extension, designated
initializers, is used to fill in the
qspi_common.spi_bus structure field. The
structure contains a further seven fields which define exactly how to
interact with the SPI device. Most of these fields are simply hardware
register values, and the appropriate ColdFire User Manual should be
consulted for full details of these registers. The header file
cyg/hal/hal_io.h will provide
#define's for the various bits, for example
HAL_MCFxxxx_QSPIx_QMR_MSTR for the master mode bit
of the QMR register.
When performing a transfer to this SPI device the bus driver will use
the qspi_qmr field for the QSPI hardware's
QMR register. The main fields in this register are:
This bit specifies that the QSPI hardware should operate in master
mode. It must always be set.
The data items transferred can range from 8 to 16 bits. For example,
to specify 12-bit data items the qspi_qmr
field should include HAL_MCFxxxx_QSPIx_QMR_BITS_12.
Clock polarity. The default is inactive-low, active-high. If the
device requires the opposite polarity then
HAL_MCFxxxx_QSPIx_QMR_CPOL should be specified.
Clock phase. The default is to capture data on the leading clock edge.
If the device captures data on the trailing edge instead then
HAL_MCFxxxx_QSPIx_QMR_CPHA should be specified.
Baud rate divider. This should be a small number, usually between 1
and 255, which controls the clock rate. The value to be used depends
on the device's maximum clock rate, the specific processor used, and
the processor's clock speed.
This field is used to set the QSPI delay register QDLYR when
performing transfers to this device. It contains two delay fields,
QCD and DTL, which can be used in conjunction with
qspi_qcr for fine control over bus timing.
Most devices do not have any special requirements here so a value of 0
can be used. The register also contains an SPE bit to start a
transfer, but that bit is used by the bus driver and should not be set
in the device structure.
This field is used to set the QWR register. Only one bit, CSIV, in
this register may be defined. The other fields in the register are
manipulated by the bus driver. Usually if the device has an
active-low chip select then the CSIV bit should be set, otherwise the
structure field should be 0. If a custom chip select control function
is used then that may require different CSIV behaviour.
This is used to fill in the command RAM registers during a data
transfer. It contains five fields. The CONT bit is not normally
required but can provide additional control over the chip select. Note
that some versions of the various ColdFire User Manuals give an
incomplete description of this bit and the errata sheets should be
consulted as well. The BITSE bit should be set if transfers involve
data items which are not 8 bits. The DT and DSCK bits can be used to
enable one or both delays in the QDLYR register. The QSPI_CS field
consists of four bits for the four QSPI chip select pins. If all the
devices connected to the SPI bus are active-high and each is connected
directly to a chip select, then only of these bits should be set. If
all the devices are active-low then only one of the bits should be
With some hardware the QSPI_CS bits can be more complicated. For
example consider an SPI bus with an active-high device attached to
QSPI chip selects 0 and 1, and active-low devices attached to the
other two chip selects. The device definition for the CS0 device
should have the QWR CSIV bit clear. The QCR QSPI_CS bits should have
bits 0, 2 and 3 set. Between transfers all chip select pins will be
low. This will activate the devices on CS2 and CS3, but since there is
no clock signal this is harmless. When a transfer happens CS0, CS2 and
CS3 will all be high, and CS1 will remain low. This will activate the
device on CS0, but leave the other three devices inactive. Hence only
the specified device is active during a transfer.
If the hardware requires further control over the chip selects then
the device definition can include a custom
There is no support for using different QCR values for different parts
of a transfer, for example the first data item versus the rest of the
transfer. Such functionality is rarely useful and would require extra
complexity in the bus driver, including performance-critical parts.
This is used to fill in the command RAM registers during a tick
operation, when none of the devices should be active. Some devices
need to see a certain number of clock signals even when their chip
select is not active, or they will not operate correctly. The hardware
fields are the same as for qspi_qcr.
Usually the QSPI_CS bits will be all 0 or all 1, but some hardware may
require a more complicated value.
When performing a tick operation this field will be used as the data
to be transferred. Usually the value will not matter because, by the
definition of an SPI tick, none of the SPI devices will be selected.
Some hardware may have chip select requirements which cannot be
satisfied simply by setting the QWR CSIV and the QCR QSPI_CS bits. For
example if there are more than four SPI devices then the surplus may
have their chip selects connected to GPIO pins. Also some devices may
require that the chip select remain asserted for the duration of a
multi-transfer transaction, and that is not supported directly by the
QSPI hardware. To cope with such cases it is possible to define a
custom chip select
Consider a simple SPI device on a board with a 64MHz MCF5282
processor. The device uses 8-bit data, default clock polarity and
phase, can be driven at up to 10 MHz, does not require any special
delays, has an active-high chip select, and is connected to the
processor's QSPI CS0 pin. There are no other devices on the bus.
For a more complicated example, consider a board with an MCF5272
processor and an SPI device that involves 12-bit data items, uses
inverted clock polarity and phase, can only be driven at the slowest
clock rate, does not require any special delays or chip select logic,
has an active-low chip select, and is connected to the processor's
QSPI CS2 pin:
This definition assumes that there are no attached SPI devices with an
active-high chip select. If there are such devices then the
qspi_qcr_tick fields should be modified so
that these devices are not activated at the wrong time.
The header file cyg/io/mcfxxxx_qspi.h provides a utility
macro CYG_MCFxxxx_QSPI_DEVICE which can be used
to instantiate a device. Essentially the macro just expands to a
structure definition as above.
Advanced Chip Select Control
The ColdFire QSPI hardware provides support for controlling the chip
select signals of up to four SPI devices. In many situations this
support is adequate, but there are exceptions:
The QSPI chip select outputs may share processor pins with other
on-chip ColdFire devices. For example on the mcf5272 the QSPI CS2
signal uses the same pin as the uart1 CTS signal, so if the
application needs uart1 and hardware flow-control then that QSPI CS2
pin is no longer available.
If the hardware has more than four SPI devices then additional chip
selects are needed.
With most SPI devices the chip select signal only needs to be asserted
while I/O is taking place, but there are exceptions. For example
interactions with an MMC card involve a sequence of transfers, and the
chip select must remain asserted in between these transfers. Depending
on thread priorities and other factors there may be a considerable
delay between these transfers and the QSPI hardware does not provide
any way of keeping a chip select asserted indefinitely.
The issue of insufficient chip selects can usually be handled by
adding extra hardware, for example an external decoder chip possibly
complemented by inverters if there is a mixture of active-high and
active-low devices. This approach can be supported simply by
programming the right values for qspi_qcr
and qspi_qcr_tick, but the cost of the
extra hardware may be unacceptable. An alternative approach is to use
one or more of the processor's GPIO pins to control the extra devices.
The issue of persistent chip selects can be handled in one of two main
ways. A GPIO pin can be used to control the chip select, bypassing the
QSPI support. Alternatively the QWR CSIV bit can be used in an
inverted sense, to activate an SPI device rather than to define the
To support these variations an arbitrary chip select control function
can be specified for a device. Such a function takes two arguments.
The first is a pointer to the SPI device, possibly allowing the
function to be shared between multiple devices. The second is one of
During system initialization the QSPI bus driver will iterate over all
the attached SPI devices. If a device has a
qspi_cs_control function then this will be
invoked. A typical action would be to configure a GPIO pin. Note that
these calls happen quite early during system initialization so other
subsystems like standard I/O may not be set up yet.
This is used to assert the chip select, in other words to set the chip
select to low for an active-low device or high for an active-high
device. It will be called at the start of any transfer, unless the
previous transfer has left the chip select asserted.
This is used to deassert the chip select. It will be called at the end
of any transfer that specifies drop_cs. It will
also be called at the start of a tick operation.
To support persistent chip selects via the CSIV signal the bus driver
package provides two chip control functions
use these with say an active-low device:
The qspi_qwr field should be set to
HAL_MCFxxxx_QSPIx_QWR_CSIV, so the chip select is
high when there is no I/O taking place.
The qspi_cs_control field should be set to
This function will be invoked by the bus driver to assert or drop the
signal (initialization is a no-op).
The QSPI_CS bits in the qspi_qcr field
still have the usual meaning.
At the start of a transfer
clear the QWR CSIV bit. There is no I/O taking place yet so all chip
select outputs will switch to low, activating all active-low devices.
This is generally harmless since there is no clock signal.
When the I/O actually starts the qspi_qcr
field will be used, deactivating all devices except the current one.
At the end of each individual transfer the chip selects will revert to
their inactive state, which because of the CSIV setting means low.
Again this will activate all active-low devices, but there is no clock
signal so no I/O takes place.
For the last transfer of a transaction or for a tick operation
cyg_mcfxxxx_qspi_cs_control_active_low will be
invoked again with a DROP argument. It will reset the QWR CSIV bit to
1, deactivating all devices.
The overall effect is a persistent chip select with the desired
polarity, using just the QSPI hardware facilities rather than a GPIO