SPI Drivers

The Embedded SDK includes drivers for SPI communications for the microcontrollers that contain an SPI peripheral. The SPI drivers are provided with a common public API so that they can be used across any of the supported platforms. The SPI drivers do not preallocate any memory or other resources; therefore unused ports will not use any resources unless explicitly opened by the application.

Opening A Port

The code snippet below demonstrates how to initialize the driver and open an SPI port.

#include "mcu_spi.h"
#include <assert.h>

static SPI spi;                         /* Allocate an instance of the driver */

void APP_Function(void)
{
    STATUS status;


    status = SPI_Open(&spi,             /* Open an SPI port */		 
                      0,                /* Port number (0 in this case) */
                      1000000,          /* Clock frequency, in hertz */
                      SPI_DEFAULT);     /* Clock phase options */

    assert(status == SUCCESS);
}

Selecting a Target

The provided drivers include the ability to select and deselect a target chip. When a chip is selected, the driver also acquires exclusive access to the port by acquiring an underlying mutex that exists within the driver. The calling thread will have exclusive access until the port is released by deselecting the target. The code snippet below shows a typical pattern that is used to activate a target chip-select on a pin (P2.21) and then later deactivates the same chip-select.
#include "mcu_spi.h"
#include <assert.h>

void APP_Function(void)
{
    STATUS status;


    status = SPI_Select(&spi,       /* Select the target chip */
                        P2_21,      /* The pin to drive the chip-select (P2.21) */
                        INFINITE);  /* Max time to wait to acquire exclusive access to the bus */

    assert(status == SUCCESS);


    /* Perform I/O operations here...
    This thread also has exclusive 
    access to the bus */


    status = SPI_Deselect(&spi,     /* Deselect the target chip (release exclusive access) */
                          P2_21);   /* The pin to be deselected (P2.21) */	

    assert(status == SUCCESS);
}

Transferring Data

The provided drivers either use interrupts or DMA to actually perform the transfer. When a calling thread requests a transfer, the transfer is staged and the calling thread is blocked while the hardware completes the transfer. Once the transfer has completed, an interrupt will signal the calling thread and execution will resume. A timeout interval can be specified to avoid a dead-lock condition if the hardware were to fail and never generate an interrupt, but care must be taken so that timeout conditions do not occur during normal operation. Ensure the specified timeout value is large enough to accommodate the transfer rate and the amount of data being transferred. The code snippet below shows how to send and receive several data bytes using an open port.
#include "mcu_spi.h"
#include <assert.h>

void APP_Function(void)
{
    STATUS status;
    BYTE data[3];
    BYTE buf[3];



    data[0] = 0;                    /* Initialize some arbitrary data */
    data[1] = 1;
    data[2] = 2;	

    status = SPI_Write(&spi,        /* Write the data out the port */
                       data,        /* Pointer to the data to be written */
                       3,           /* Number of bytes to transmitted */
                       1000);       /* Max time, in kernel ticks, to wait for completion */

    assert(status == SUCCESS);


    status = SPI_Read(&spi,         /* Read data over the port */
                      buf,          /* Pointer to a buffer for the data */
                      3,            /* Number of bytes to be received */
                      1000);        /* Max time, in kernel ticks, to wait for completion */

    assert(status == SUCCESS);
}

SPI API

STATUS SPI_Open(SPI* port, BYTE number, UINT32 clkHz, UINT32 mode)
Opens an SPI port for communications.
PARAMETERS
port A pointer to a caller allocated SPI port to be opened.
number The port number for the port to be opened.
clkHz The clock frequency, in hertz, for the port.
mode The mode of control clock phase and polarity. Bitwise OR to specify multiple options.
SPI_DEFAULT Use default options (CPHA = 0 and CPOL = 1).
SPI_CPHA0 Use to sample data on the leading (first) clock edge (CPHA = 0).
SPI_CPHA1 Use to sample data on the trailing (second) clock edge (CPHA = 1).
SPI_CPOL0 Use for active high clock (CPOL = 0).
SPI_CPOL1 Use for active low clock (CPOL = 1).
RETURNS
SUCCESS The port has been configured and is open for communications.
ERR_NULLREFERENCE The argument 'port' was found to be NULL.
ERR_INVALIDCONTEXT The operation is not supported from the context of an interrupt service routine (ISR).
ERR_NOTSUPPORTED An unsupported port number was specified.
STATUS SPI_Close(SPI* port)
Closes an SPI port.
PARAMETERS
port A pointer to the port to be closed.
RETURNS
SUCCESS The port has been closed.
ERR_NULLREFERENCE The argument 'port' was found to be NULL.
ERR_INVALIDCONTEXT The operation is not supported from the context of an interrupt service routine (ISR).
ERR_NOTINITIALIZED The specified port has not been opened.
BOOLEAN SPI_IsOpen(SPI* port)
Returns an indication of whether an SPI port is currently open for communications.
PARAMETERS
port A pointer to the target SPI port.
RETURNS
TRUE if the SPI port is currently open; otherwise FALSE.
STATUS SPI_Select(SPI* port, PIN cs, UINT32 timeout)
Selects an SPI port by acquiring exclusive access to the port and activating the chip-select signal.
PARAMETERS
port A pointer to the target port.
cs The pin to be used as the chip-select signal.
timeout The maximum amount of time, in kernel ticks, to block and wait to acquire exclusive access to the port. Use '0' to return immediately without blocking and use 'INFINITE' to block and wait indefinitely.
RETURNS
SUCCESS The port has been selected.
ERR_NULLREFERENCE The argument 'port' was found to be NULL.
ERR_INVALIDCONTEXT The operation is not supported from the context of an interrupt service routine (ISR).
ERR_NOTINITIALIZED The specified port has not been opened.
ERR_TIMEOUT The specified amount of time has elapsed before exclusive access was acquired upon the port.
STATUS SPI_Deselect(SPI* port, PIN cs)
Deselects a port by deactivating the chip-select signal and releasing exclusive access to an SPI port.
PARAMETERS
port A pointer to the target port.
cs The pin to be used as the chip-select signal.
RETURNS
SUCCESS The port has been deselected.
ERR_NULLREFERENCE The argument 'port' was found to be NULL.
ERR_INVALIDCONTEXT The operation is not supported from the context of an interrupt service routine (ISR).
ERR_NOTINITIALIZED The specified port has not been opened.
STATUS SPI_Read(SPI* port, BYTE address, void* buf, UINT32 nbytes, UINT32 timeout)
Reads and returns data received from an SPI port.
PARAMETERS
port A pointer to the port to receive the data.
address The target device address to be read.
buf A pointer to a caller allocated buffer used to receive the data.
nbytes The total number of bytes to be received.
timeout The maximum amount of time, in kernel ticks, to block and wait for the transfer to complete. Must not be zero and must be large enough to allow the transfer to complete; based upon clock rate and amount of data being transferred. Use INFINITE to wait indefinitely.
RETURNS
SUCCESS The data was been received.
ERR_NULLREFERENCE The argument 'port' or 'buf' was found to be NULL.
ERR_INVALIDCONTEXT The operation is not supported from the context of an interrupt service routine (ISR).
ERR_NOTINITIALIZED The specified port has not been opened.
ERR_INCOMPLETE An error occurred while transferring the data and the transfer did not complete.
ERR_TIMEOUT The specified timeout interval has elapsed prior to the transfer being completed.
STATUS SPI_Write(SPI* port, BYTE address, const void* data, UINT32 nbytes, UINT32 timeout)
Writes data to an SPI port.
PARAMETERS
port A pointer to the port to be written.
address The target device address to be written.
data A pointer to the data to be written.
nbytes The total number of bytes to be written.
timeout The maximum amount of time, in kernel ticks, to block and wait for the transfer to complete. Must not be zero and must be large enough to allow the transfer to complete; based upon clock rate and amount of data being transferred. Use INFINITE to wait indefinitely.
RETURNS
SUCCESS The data has been written.
ERR_NULLREFERENCE The argument 'port' or 'data' was found to be NULL.
ERR_INVALIDCONTEXT The operation is not supported from the context of an interrupt service routine (ISR).
ERR_NOTINITIALIZED The specified port has not been opened.
ERR_INCOMPLETE An error occurred while transferring the data and the transfer did not complete.
ERR_TIMEOUT The specified timeout interval has elapsed prior to the transfer being completed.