Buses

In alambre terminology, a bus is a mechanism for connecting devices to the system. Interfaces are included for a few standard buses that are often found in embedded systems. Device drivers will often use one or more bus interfaces to interact with the corresponding device.

General Purpose IO (GPIO)

GPIO refers to the ability to turn on and off specific pins. Microcontrollers often have GPIO ports that are collections of pins that are controlled by the same byte (or word) in memory. At present there is no standard model for GPIO ports, since these vary from system to system and are not often used together as a unit, but individual pins are modelled by the IGpioPin interface which is often used by device drivers for devices that require control of a single signal.

Specific implementations of GPIO pins are most often found via system objects, which expose the built-in facilities of a given microcontroller or embedded system.

class IGpioPin

Represents a particular GPIO pin.

On many systems a GPIO pin is part of a GPIO port that consists of 8, 16 or 32 pins. This interface represents only one such pin, and is useful for configuring device driver classes that make use of GPIOs.

Public Type

PinValue enum

Possible values of a pin.

Values:

  • LOW = 0 -
  • HIGH = 1 -

PinDirection enum

Possible directions of a pin.

Values:

  • INPUT = 0 -
  • OUTPUT = 1 -
Public Functions

void set(void)

Set the pin’s value to HIGH.

This is only meaningful for pins configured for the OUTPUT direction and may have other hardware-dependent consequences on INPUT pins.

void clear(void)

Set the pin’s value to LOW.

This is only meaningful for pins configured for the OUTPUT direction and may have other hardware-dependent consequences on INPUT pins.

void write(PinValue value)

Write the given value to the pin.

This is only meaningful for pins configured for the OUTPUT direction and may have other hardware-dependent consequences on INPUT pins.

PinValue read(void)

Determine the current value of the pin.

For some hardware this may work only for pins configured for the INPUT direction.

void set_direction(PinDirection direction)

Configure the direction of the pin.

Not all pins are direction-configurable. An implementation of this method will not be provided on such hardware.

PinDirection get_direction(void)

Determine the current direction of the pin.

On hardware with configurable pin direction this will return the configured pin direction. On systems where pin direction is forced, this will return the forced direction.

Serial Peripheral Interface (SPI)

The Serial Peripheral Interface is a protocol for synchronous data communication between a master and one or more slaves. The master is the device in control of the transmission rate and in control of which device is selected to communicate on the bus at a given time.

Microcontrollers most often take the “master” role on the SPI bus, so most SPI implementations implement only this part. One key example where this is not true is when one microcontroller is communicating with another via SPI, which of course means that one of them must at as the slave.

For the purposes of this library we separate the concept of the SPI bus, the data and clock signals, from the concept of an SPI channel, with which we model the master’s interaction with a particular slave on the bus. When the system is acting as a master and communicating with one or more slave devices there will generally be one SPI bus and then one SPI channel for each slave device on the bus.

The SPI bus is represented by the interface ISpiBus. A channel is represented by an instance of the wrapper class SpiChannel, which is parameterized by the SPI bus it belongs to and the GPIO pin that will act as the slave select signal.

Finally, there is included a simple software implementation of SPI that works in terms of GPIO pins and only supports output in the master role. This is implemented in SoftwareSpiMasterOutputBus. Hardware-specific SPI implementations are made available via system objects.

class ISpiBus

Represents an SPI bus.

The SPI *bus* represents the shared data and clock signals of the bus. A particular device on the bus also has a slave select signal, which is represented by the SpiChannel wrapper class.

This is a generic interface that could be used for both master and slave SPI roles depending on the selected implementation.

This interface does not provide a mechanism to control the data rate or specific pulsing behavior of the SPI bus; an implementation may provide a way to customize these details, or they may be fixed.

Public Type

BitOrder enum

Values:

  • LSB_FIRST = 1 -
  • MSB_FIRST = 2 -
Public Functions

void shift_out(uint8_t value, BitOrder order)

Transmit an 8-bit value on the SPI bus in the bit order given.

uint8_t shift_in(BitOrder order)

Recieve an 8-bit value on the SPI bus in the bit order given.

In slave mode this will block until all eight bits have been recieved, with the rate of transmission under the control of the master.

template < class SPI_BUS_TYPE, class SELECT_PIN_TYPE >
class SpiChannel

Represents the combination of an SPI master bus and an SPI slave.

Extends the ISpiBus interface with additional methods for selecting and deselecting the corresponding device. This can be used to encapsulate the entire configuration for communicating with a given device, leaving a device driver to simply send and recieve bytes.

There are no checks to make sure that only one device on the bus is selected at a time. This is the caller’s responsibility. It is good manners for a device driver using an SPI channel to only select its device for the duration of a specific function call, and deselect it before returning control to the caller.

It doesn’t make any sense to use this class with an SPI bus acting as a slave, since only the master role can select and deselect devices.

Public Functions

SpiChannel(SPI_BUS_TYPE * spi_bus, SELECT_PIN_TYPE * select_pin)

Create a new channel with the given bus and select pin.

As a side-effect of the instantiation the pin will be configured as an output and set high to deselect the device.

void shift_out(uint8_t value, ISpiBus::BitOrder order)

Transmit an 8-bit value on the SPI bus in the bit order given.

uint8_t shift_in(ISpiBus::BitOrder order)

Recieve an 8-bit value on the SPI bus in the bit order given.

In slave mode this will block until all eight bits have been recieved, with the rate of transmission under the control of the master.

void select()

Activate the remote slave in preparation for sending or recieving data.

A device driver that calls this method as part of the implementation of one of its operations should always deselect the device before returning from that operation so the caller does not accidentally activate two devices on the bus simultaneously.

void deselect()

Deactvate the remote device.

For many devices this also serves to signal that a (possibly multi-byte) transmission is complete.

template < class OUTPUT_PIN_TYPE, class CLOCK_PIN_TYPE >
class SoftwareSpiMasterOutputBus

A simple implementation of an SPI master in terms of a pair of GPIO pins.

This implementation only supports transmission of data. The shift_in method is not implemented.

This class builds an SPI bus in terms of the GPIO bus. Some systems may provide alternative implementations of SPI implemented within the microcontroller itself, but this implementation can in theory work anywhere two GPIO pins are available.

This implementation is only able to operate in SPI master mode, and it will transmit as fast as the underlying system can execute the loop over the bits. On faster systems the transmission rate may be too fast for some devices.

Table Of Contents

Previous topic

Features

Next topic

Devices

This Page