Xmega Application Note


spi_driver.h File Reference

XMEGA SPI driver header file. More...

#include "avr_compiler.h"
Include dependency graph for spi_driver.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  SPI_DataPacket
 SPI data packet struct. More...
struct  SPI_Master
 SPI master struct. Holds pointer to SPI module, buffers and necessary varibles. More...
struct  SPI_Slave
 SPI slave struct. Holds pointers to SPI module and used port. More...

Defines

#define SPI_BUSY   2
 The SPI module is busy with another transmission.
#define SPI_INTERRUPTED   1
 The transmission was interrupted by another master.
#define SPI_MasterInterruptTransmissionComplete(_spi)   ( (_spi)->dataPacket->complete )
 Checks if transmission is complete.
#define SPI_MasterSSHigh(_port, _pinBM)   ( (_port)->OUTSET = (_pinBM) )
 Releases SPI SS line(s).
#define SPI_MasterSSLow(_port, _pinBM)   ( (_port)->OUTCLR = (_pinBM) )
 Pulls SPI SS line(s) low in order to address the slave devices.
#define SPI_MISO_bm   0x40
 Bit mask for the MISO pin.
#define SPI_MOSI_bm   0x20
 Bit mask for the MOSI pin.
#define SPI_OK   0
 The transmission completed successfully.
#define SPI_SCK_bm   0x80
 Bit mask for the SCK pin.
#define SPI_SlaveDataAvailable(_spi)   ( (_spi)->module->STATUS & SPI_IF_bm )
 Check if new data is available.
#define SPI_SlaveReadByte(_spi)   ( (_spi)->module->DATA )
 Read received data byte.
#define SPI_SlaveWriteByte(_spi, _data)   ( (_spi)->module->DATA = (_data) )
 Write data byte to the SPI shift register.
#define SPI_SS_bm   0x10
 Bit mask for the SS pin.

Typedefs

typedef struct SPI_DataPacket SPI_DataPacket_t
 SPI data packet struct.
typedef struct SPI_Master SPI_Master_t
 SPI master struct. Holds pointer to SPI module, buffers and necessary varibles.
typedef struct SPI_Slave SPI_Slave_t
 SPI slave struct. Holds pointers to SPI module and used port.

Functions

void SPI_MasterCreateDataPacket (SPI_DataPacket_t *dataPacket, const uint8_t *transmitData, uint8_t *receiveData, uint8_t bytesToTransceive, PORT_t *ssPort, uint8_t ssPinMask)
 Create data packet.
void SPI_MasterInit (SPI_Master_t *spi, SPI_t *module, PORT_t *port, bool lsbFirst, SPI_MODE_t mode, SPI_INTLVL_t intLevel, bool clk2x, SPI_PRESCALER_t clockDivision)
 Initialize SPI module as master.
void SPI_MasterInterruptHandler (SPI_Master_t *spi)
 Common SPI master interrupt service routine.
uint8_t SPI_MasterInterruptTransceivePacket (SPI_Master_t *spi, SPI_DataPacket_t *dataPacket)
 Start transmission.
uint8_t SPI_MasterTransceiveByte (SPI_Master_t *spi, uint8_t TXdata)
 SPI mastertransceive byte.
bool SPI_MasterTransceivePacket (SPI_Master_t *spi, SPI_DataPacket_t *dataPacket)
 SPI transceive data packet.
void SPI_SlaveInit (SPI_Slave_t *spi, SPI_t *module, PORT_t *port, bool lsbFirst, SPI_MODE_t mode, SPI_INTLVL_t intLevel)
 Initialize SPI module as slave.

Detailed Description

XMEGA SPI driver header file.

This file contains the function prototypes and enumerator definitions for various configuration parameters for the XMEGA SPI driver.

The driver is not intended for size and/or speed critical code, since most functions are just a few lines of code, and the function call overhead would decrease code performance. The driver is intended for rapid prototyping and documentation purposes for getting started with the XMEGA SPI module.

For size and/or speed critical code, it is recommended to copy the function contents directly into your application instead of making a function call.

Application note:
AVR1309: Using the XMEGA SPI
Documentation
For comprehensive code documentation, supported compilers, compiler settings and supported devices see readme.html
Author:
Atmel Corporation: http://www.atmel.com
Support email: avr@atmel.com
Revision:
5407
Date:
2011-10-12 14:53:14 +0200 (on, 12 okt 2011)


Copyright (c) 2009 Atmel Corporation. All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

3. The name of Atmel may not be used to endorse or promote products derived from this software without specific prior written permission.

4. This software may only be redistributed and used in connection with an Atmel AVR product.

THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Definition in file spi_driver.h.


Define Documentation

#define SPI_BUSY   2

The SPI module is busy with another transmission.

Definition at line 78 of file spi_driver.h.

Referenced by SPI_MasterInterruptTransceivePacket().

#define SPI_INTERRUPTED   1

The transmission was interrupted by another master.

Definition at line 77 of file spi_driver.h.

Referenced by SPI_MasterInterruptTransceivePacket().

#define SPI_MasterInterruptTransmissionComplete (   _spi)    ( (_spi)->dataPacket->complete )

Checks if transmission is complete.

Parameters:
_spiPointer to SPI_Master_t struct instance.
Returns:
The current status of the transmission.
Return values:
trueThe transmission is complete.
falseThe transmission is in progress.

Definition at line 123 of file spi_driver.h.

#define SPI_MasterSSHigh (   _port,
  _pinBM 
)    ( (_port)->OUTSET = (_pinBM) )

Releases SPI SS line(s).

Parameters:
_portPointer to the I/O port where the SS pins are located.
_pinBMA bitmask selecting the pins to release.
Return values:
NA

Definition at line 145 of file spi_driver.h.

Referenced by SPI_MasterInterruptHandler(), SPI_MasterTransceivePacket(), and main().

#define SPI_MasterSSLow (   _port,
  _pinBM 
)    ( (_port)->OUTCLR = (_pinBM) )

Pulls SPI SS line(s) low in order to address the slave devices.

Parameters:
_portPointer to the I/O port where the SS pins are located.
_pinBMA bitmask selecting the pins to pull low.
Return values:
NA

Definition at line 134 of file spi_driver.h.

Referenced by SPI_MasterInterruptTransceivePacket(), SPI_MasterTransceivePacket(), and main().

#define SPI_MISO_bm   0x40

Bit mask for the MISO pin.

Definition at line 71 of file spi_driver.h.

Referenced by SPI_SlaveInit().

#define SPI_MOSI_bm   0x20

Bit mask for the MOSI pin.

Definition at line 70 of file spi_driver.h.

Referenced by SPI_MasterInit().

#define SPI_OK   0

The transmission completed successfully.

Definition at line 76 of file spi_driver.h.

Referenced by SPI_MasterInterruptTransceivePacket(), and main().

#define SPI_SCK_bm   0x80

Bit mask for the SCK pin.

Definition at line 72 of file spi_driver.h.

Referenced by SPI_MasterInit().

#define SPI_SlaveDataAvailable (   _spi)    ( (_spi)->module->STATUS & SPI_IF_bm )

Check if new data is available.

Parameters:
_spiPointer to SPI_Slave_t struct instance.
Returns:
True if data available, false if not.

Definition at line 174 of file spi_driver.h.

Referenced by main().

#define SPI_SlaveReadByte (   _spi)    ( (_spi)->module->DATA )

Read received data byte.

Parameters:
_spiPointer to SPI_Slave_t struct instance.
Returns:
The received data.

Definition at line 164 of file spi_driver.h.

Referenced by ISR(), and main().

#define SPI_SlaveWriteByte (   _spi,
  _data 
)    ( (_spi)->module->DATA = (_data) )

Write data byte to the SPI shift register.

Parameters:
_spiPointer to SPI_Slave_t struct instance.
_dataThe data to write to the shift register.

Definition at line 154 of file spi_driver.h.

Referenced by ISR(), and main().

#define SPI_SS_bm   0x10

Bit mask for the SS pin.

Definition at line 69 of file spi_driver.h.

Referenced by SPI_MasterInterruptTransceivePacket().


Typedef Documentation

SPI data packet struct.

typedef struct SPI_Master SPI_Master_t

SPI master struct. Holds pointer to SPI module, buffers and necessary varibles.

typedef struct SPI_Slave SPI_Slave_t

SPI slave struct. Holds pointers to SPI module and used port.


Function Documentation

void SPI_MasterCreateDataPacket ( SPI_DataPacket_t dataPacket,
const uint8_t *  transmitData,
uint8_t *  receiveData,
uint8_t  bytesToTransceive,
PORT_t *  ssPort,
uint8_t  ssPinMask 
)

Create data packet.

This function prepares a data packet for transmission. Note that memory for dataPacket, transmitData and receiveData must be allocated outside this function.

Note:
The size of the receiveData and transmitData must be equal and bytesToTransceive should be set accordingly.
Parameters:
dataPacketPointer to data packet used for this transmission.
transmitDataPointer to data to transmit.
receiveDataPointer to receive buffer.
bytesToTransceiveThe number of bytes to transmit/receive.
ssPortPointer to I/O port where the SS pin used for this transmission is located.
ssPinMaskPin mask selecting the SS pin in ssPort.

Definition at line 176 of file spi_driver.c.

References SPI_DataPacket::ssPort, SPI_DataPacket::ssPinMask, SPI_DataPacket::transmitData, SPI_DataPacket::receiveData, SPI_DataPacket::bytesToTransceive, SPI_DataPacket::bytesTransceived, and SPI_DataPacket::complete.

Referenced by main().

{
        dataPacket->ssPort            = ssPort;
        dataPacket->ssPinMask         = ssPinMask;
        dataPacket->transmitData      = transmitData;
        dataPacket->receiveData       = receiveData;
        dataPacket->bytesToTransceive  = bytesToTransceive;
        dataPacket->bytesTransceived   = 0;
        dataPacket->complete          = false;
}
void SPI_MasterInit ( SPI_Master_t spi,
SPI_t *  module,
PORT_t *  port,
bool  lsbFirst,
SPI_MODE_t  mode,
SPI_INTLVL_t  intLevel,
bool  clk2x,
SPI_PRESCALER_t  clockDivision 
)

Initialize SPI module as master.

This function initializes a SPI module as master. The CTRL and INTCTRL registers for the SPI module is set according to the inputs to the function. In addition, data direction for the MOSI and SCK pins is set to output.

Parameters:
spiThe SPI_Master_t struct instance.
moduleThe SPI module.
portThe I/O port where the SPI module is connected.
lsbFirstData order will be LSB first if this is set to a non-zero value.
modeSPI mode (Clock polarity and phase).
intLevelSPI interrupt level.
clk2xSPI double speed mode
clockDivisionSPI clock prescaler divison factor.

Definition at line 90 of file spi_driver.c.

References SPI_Master::module, SPI_Master::port, SPI_Master::interrupted, SPI_Master::dataPacket, SPI_MOSI_bm, and SPI_SCK_bm.

Referenced by main().

{
        spi->module         = module;
        spi->port           = port;
        spi->interrupted    = false;

        spi->module->CTRL   = clockDivision |                  /* SPI prescaler. */
                              (clk2x ? SPI_CLK2X_bm : 0) |     /* SPI Clock double. */
                              SPI_ENABLE_bm |                  /* Enable SPI module. */
                              (lsbFirst ? SPI_DORD_bm  : 0) |  /* Data order. */
                              SPI_MASTER_bm |                  /* SPI master. */
                              mode;                            /* SPI mode. */

        /* Interrupt level. */
        spi->module->INTCTRL = intLevel;

        /* No assigned data packet. */
        spi->dataPacket = NULL;

        /* MOSI and SCK as output. */
        spi->port->DIRSET  = SPI_MOSI_bm | SPI_SCK_bm;
}
void SPI_MasterInterruptHandler ( SPI_Master_t spi)

Common SPI master interrupt service routine.

This function is called by the SPI interrupt service handlers. For each SPI module that uses this driver, the ISR should call this function with a pointer to the related SPI_Master_t struct as argument.

Parameters:
spiPointer to the modules own SPI_Master_t struct.

Definition at line 202 of file spi_driver.c.

References SPI_Master::dataPacket, SPI_DataPacket::bytesTransceived, SPI_Master::module, SPI_Master::interrupted, SPI_DataPacket::receiveData, dataPacket, SPI_DataPacket::bytesToTransceive, SPI_DataPacket::transmitData, SPI_DataPacket::ssPinMask, SPI_MasterSSHigh, SPI_DataPacket::ssPort, and SPI_DataPacket::complete.

Referenced by ISR().

{
        uint8_t data;
        uint8_t bytesTransceived = spi->dataPacket->bytesTransceived;

        /* If SS pin interrupt (SS used and pulled low).
        *  No data received at this point. */
        if ( !(spi->module->CTRL & SPI_MASTER_bm) ) {
                spi->interrupted = true;
        }

        else {  /* Data interrupt. */

                /* Store received data. */
                data = spi->module->DATA;
                spi->dataPacket->receiveData[bytesTransceived] = data;

                /* Next byte. */
                bytesTransceived++;

                /* If more data. */
                if (bytesTransceived < spi->dataPacket->bytesToTransceive) {
                        /* Put data byte in transmit data register. */
                        data = spi->dataPacket->transmitData[bytesTransceived];
                        spi->module->DATA = data;
                }

                /* Transmission complete. */
                else {

                        /* Release SS to slave(s). */
                        uint8_t ssPinMask = spi->dataPacket->ssPinMask;
                        SPI_MasterSSHigh(spi->dataPacket->ssPort, ssPinMask);

                        spi->dataPacket->complete = true;
                }
        }
        /* Write back bytesTransceived to data packet. */
        spi->dataPacket->bytesTransceived = bytesTransceived;
}
uint8_t SPI_MasterInterruptTransceivePacket ( SPI_Master_t spi,
SPI_DataPacket_t dataPacket 
)

Start transmission.

This function starts a SPI transmission. A data packet must be prepared for transmission first.

Parameters:
spiThe SPI_Master_t struct instance.
dataPacketThe SPI_dataPacket_t struct instance.
Returns:
Status code
Return values:
SPI_OKThe transmission was completed successfully.
SPI_BUSYThe SPI module is busy.
SPI_INTERRUPTEDThe transmission was interrupted by another master.

Definition at line 258 of file spi_driver.c.

References SPI_Master::interrupted, SPI_Master::dataPacket, dataPacket, SPI_DataPacket::complete, SPI_BUSY, SPI_Master::port, SPI_SS_bm, SPI_INTERRUPTED, SPI_DataPacket::ssPinMask, SPI_MasterSSLow, SPI_DataPacket::ssPort, SPI_DataPacket::bytesTransceived, SPI_DataPacket::transmitData, SPI_Master::module, and SPI_OK.

Referenced by main().

{
        uint8_t data;
        bool interrupted = spi->interrupted;

        /* If no packets sent so far. */
        if (spi->dataPacket == NULL) {
                spi->dataPacket = dataPacket;
        }

        /* If ongoing transmission. */
        else if (spi->dataPacket->complete == false) {
                return (SPI_BUSY);
        }

        /* If interrupted by other master. */
        else if (interrupted) {
                /* If SS released. */
                if (spi->port->OUT & SPI_SS_bm) {
                        /* No longer interrupted. */
                        interrupted = false;
                }
                else {
                        return (SPI_INTERRUPTED);
                }
        }

        /* NOT interrupted by other master.
        * Start transmission. */
        spi->dataPacket = dataPacket;
        spi->dataPacket->complete = false;
        spi->interrupted = false;

        /* SS to slave(s) low.*/
        uint8_t ssPinMask = spi->dataPacket->ssPinMask;
        SPI_MasterSSLow(spi->dataPacket->ssPort, ssPinMask);

        spi->dataPacket->bytesTransceived = 0;

        /* Start sending data. */
        data = spi->dataPacket->transmitData[0];
        spi->module->DATA = data;

        /* Successs */
        return (SPI_OK);
}
uint8_t SPI_MasterTransceiveByte ( SPI_Master_t spi,
uint8_t  TXdata 
)

SPI mastertransceive byte.

This function clocks data in the DATA register to the slave, while data from the slave is clocked into the DATA register. The function does not check for ongoing access from other masters before initiating a transfer. For multimaster systems, checkers should be added to avoid bus contention.

SS line(s) must be pulled low before calling this function and released when finished.

Note:
This function is blocking and will not finish unless a successful transfer has been completed. It is recommended to use the interrupt-driven driver for applications where blocking functionality is not wanted.
Parameters:
spiThe SPI_Master_t struct instance.
TXdataData to transmit to slave.
Returns:
Data received from slave.

Definition at line 327 of file spi_driver.c.

References SPI_Master::module.

Referenced by main().

{
        /* Send pattern. */
        spi->module->DATA = TXdata;

        /* Wait for transmission complete. */
        while(!(spi->module->STATUS & SPI_IF_bm)) {

        }
        /* Read received data. */
        uint8_t result = spi->module->DATA;

        return(result);
}
bool SPI_MasterTransceivePacket ( SPI_Master_t spi,
SPI_DataPacket_t dataPacket 
)

SPI transceive data packet.

This function transceives a number of bytes contained in a data packet struct. The SS line is kept low until all bytes are transceived. The received bytes are stored in the data packet struct.

Parameters:
spiThe SPI_Master_t struct instance.
dataPacketThe SPI_dataPacket_t struct instance.
Returns:
Wether the function was successfully completed
Return values:
trueSuccess
falseFailure

Definition at line 357 of file spi_driver.c.

References SPI_Master::dataPacket, dataPacket, SPI_DataPacket::ssPinMask, SPI_DataPacket::ssPort, SPI_MasterSSLow, SPI_DataPacket::bytesToTransceive, SPI_DataPacket::transmitData, SPI_Master::module, SPI_DataPacket::receiveData, SPI_MasterSSHigh, SPI_DataPacket::bytesTransceived, and SPI_DataPacket::complete.

Referenced by main().

{
        /* Check if data packet has been created. */
        if(dataPacket == NULL) {
                return false;
        }

        /* Assign datapacket to SPI module. */
        spi->dataPacket = dataPacket;

        uint8_t ssPinMask = spi->dataPacket->ssPinMask;

        /* If SS signal to slave(s). */
        if (spi->dataPacket->ssPort != NULL) {
                /* SS to slave(s) low. */
                SPI_MasterSSLow(spi->dataPacket->ssPort, ssPinMask);
        }

        /* Transceive bytes. */
        uint8_t bytesTransceived = 0;
        uint8_t bytesToTransceive = dataPacket->bytesToTransceive;
        while (bytesTransceived < bytesToTransceive) {

                /* Send pattern. */
                uint8_t data = spi->dataPacket->transmitData[bytesTransceived];
                spi->module->DATA = data;

                /* Wait for transmission complete. */
                while(!(spi->module->STATUS & SPI_IF_bm)) {

                }
                /* Read received data. */
                data = spi->module->DATA;
                spi->dataPacket->receiveData[bytesTransceived] = data;

                bytesTransceived++;
        }

        /* If SS signal to slave(s). */
        if (spi->dataPacket->ssPort != NULL) {
                /* Release SS to slave(s). */
                SPI_MasterSSHigh(spi->dataPacket->ssPort, ssPinMask);
        }

        /* Set variables to indicate that transmission is complete. */
        spi->dataPacket->bytesTransceived = bytesTransceived;
        spi->dataPacket->complete = true;

        /* Report success. */
        return true;
}
void SPI_SlaveInit ( SPI_Slave_t spi,
SPI_t *  module,
PORT_t *  port,
bool  lsbFirst,
SPI_MODE_t  mode,
SPI_INTLVL_t  intLevel 
)

Initialize SPI module as slave.

This function initializes a SPI module as slave. The CTRL and INTCTRL registers for the SPI module is set according to the inputs to the function. In addition, data direction for the MISO pin is set to output.

Parameters:
spiThe SPI_Slave_t instance.
modulePointer to the SPI module.
portThe I/O port where the SPI module is connected.
lsbFirstData order will be LSB first if this is set to true.
modeSPI mode (Clock polarity and phase).
intLevelSPI interrupt level.

Definition at line 135 of file spi_driver.c.

References SPI_Slave::module, SPI_Slave::port, and SPI_MISO_bm.

Referenced by main().

{
        /* SPI module. */
        spi->module       = module;
        spi->port         = port;

        spi->module->CTRL = SPI_ENABLE_bm |                /* Enable SPI module. */
                            (lsbFirst ? SPI_DORD_bm : 0) | /* Data order. */
                            mode;                          /* SPI mode. */

        /* Interrupt level. */
        spi->module->INTCTRL = intLevel;

        /* MISO as output. */
        spi->port->DIRSET = SPI_MISO_bm;
}