Xmega Application Note | |||||
#include "spi_driver.h"
Go to the source code of this file.
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. |
This file contains the function implementations 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.
Several functions use the following construct: "some_register = ... | (some_parameter ? SOME_BIT_bm : 0) | ..." Although the use of the ternary operator ( if ? then : else ) is discouraged, in some occasions the operator makes it possible to write pretty clean and neat code. In this driver, the construct is used to set or not set a configuration bit based on a boolean input parameter, such as the "some_parameter" in the example above.
Copyright (c) 2008, 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.
THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 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.c.
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.
dataPacket | Pointer to data packet used for this transmission. | |
transmitData | Pointer to data to transmit. | |
receiveData | Pointer to receive buffer. | |
bytesToTransceive | The number of bytes to transmit/receive. | |
ssPort | Pointer to I/O port where the SS pin used for this transmission is located. | |
ssPinMask | Pin mask selecting the SS pin in ssPort. |
Definition at line 173 of file spi_driver.c.
References SPI_DataPacket::bytesToTransceive, SPI_DataPacket::bytesTransceived, SPI_DataPacket::complete, SPI_DataPacket::receiveData, SPI_DataPacket::ssPinMask, SPI_DataPacket::ssPort, and SPI_DataPacket::transmitData.
Referenced by main().
00179 { 00180 dataPacket->ssPort = ssPort; 00181 dataPacket->ssPinMask = ssPinMask; 00182 dataPacket->transmitData = transmitData; 00183 dataPacket->receiveData = receiveData; 00184 dataPacket->bytesToTransceive = bytesToTransceive; 00185 dataPacket->bytesTransceived = 0; 00186 dataPacket->complete = false; 00187 }
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.
spi | The SPI_Master_t struct instance. | |
module | The SPI module. | |
port | The I/O port where the SPI module is connected. | |
lsbFirst | Data order will be LSB first if this is set to a non-zero value. | |
mode | SPI mode (Clock polarity and phase). | |
intLevel | SPI interrupt level. | |
clk2x | SPI double speed mode | |
clockDivision | SPI clock prescaler divison factor. |
Definition at line 87 of file spi_driver.c.
References SPI_Master::dataPacket, SPI_Master::interrupted, SPI_Master::module, SPI_Master::port, SPI_MOSI_bm, and SPI_SCK_bm.
Referenced by main().
00095 { 00096 spi->module = module; 00097 spi->port = port; 00098 spi->interrupted = false; 00099 00100 spi->module->CTRL = clockDivision | /* SPI prescaler. */ 00101 (clk2x ? SPI_CLK2X_bm : 0) | /* SPI Clock double. */ 00102 SPI_ENABLE_bm | /* Enable SPI module. */ 00103 (lsbFirst ? SPI_DORD_bm : 0) | /* Data order. */ 00104 SPI_MASTER_bm | /* SPI master. */ 00105 mode; /* SPI mode. */ 00106 00107 /* Interrupt level. */ 00108 spi->module->INTCTRL = intLevel; 00109 00110 /* No assigned data packet. */ 00111 spi->dataPacket = NULL; 00112 00113 /* MOSI and SCK as output. */ 00114 spi->port->DIRSET = SPI_MOSI_bm | SPI_SCK_bm; 00115 }
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.
spi | Pointer to the modules own SPI_Master_t struct. |
Definition at line 199 of file spi_driver.c.
References SPI_DataPacket::bytesToTransceive, SPI_DataPacket::bytesTransceived, SPI_DataPacket::complete, dataPacket, SPI_Master::dataPacket, SPI_Master::interrupted, SPI_Master::module, SPI_DataPacket::receiveData, SPI_MasterSSHigh, SPI_DataPacket::ssPinMask, SPI_DataPacket::ssPort, and SPI_DataPacket::transmitData.
Referenced by ISR().
00200 { 00201 uint8_t data; 00202 uint8_t bytesTransceived = spi->dataPacket->bytesTransceived; 00203 00204 /* If SS pin interrupt (SS used and pulled low). 00205 * No data received at this point. */ 00206 if ( !(spi->module->CTRL & SPI_MASTER_bm) ) { 00207 spi->interrupted = true; 00208 } 00209 00210 else { /* Data interrupt. */ 00211 00212 /* Store received data. */ 00213 data = spi->module->DATA; 00214 spi->dataPacket->receiveData[bytesTransceived] = data; 00215 00216 /* Next byte. */ 00217 bytesTransceived++; 00218 00219 /* If more data. */ 00220 if (bytesTransceived < spi->dataPacket->bytesToTransceive) { 00221 /* Put data byte in transmit data register. */ 00222 data = spi->dataPacket->transmitData[bytesTransceived]; 00223 spi->module->DATA = data; 00224 } 00225 00226 /* Transmission complete. */ 00227 else { 00228 00229 /* Release SS to slave(s). */ 00230 uint8_t ssPinMask = spi->dataPacket->ssPinMask; 00231 SPI_MasterSSHigh(spi->dataPacket->ssPort, ssPinMask); 00232 00233 spi->dataPacket->complete = true; 00234 } 00235 } 00236 /* Write back bytesTransceived to data packet. */ 00237 spi->dataPacket->bytesTransceived = bytesTransceived; 00238 }
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.
spi | The SPI_Master_t struct instance. | |
dataPacket | The SPI_dataPacket_t struct instance. |
SPI_OK | The transmission was completed successfully. | |
SPI_BUSY | The SPI module is busy. | |
SPI_INTERRUPTED | The transmission was interrupted by another master. |
Definition at line 255 of file spi_driver.c.
References SPI_DataPacket::bytesTransceived, SPI_DataPacket::complete, SPI_Master::dataPacket, SPI_Master::interrupted, SPI_Master::module, SPI_Master::port, SPI_BUSY, SPI_INTERRUPTED, SPI_MasterSSLow, SPI_OK, SPI_SS_bm, SPI_DataPacket::ssPinMask, SPI_DataPacket::ssPort, and SPI_DataPacket::transmitData.
Referenced by main().
00257 { 00258 uint8_t data; 00259 bool interrupted = spi->interrupted; 00260 00261 /* If no packets sent so far. */ 00262 if (spi->dataPacket == NULL) { 00263 spi->dataPacket = dataPacket; 00264 } 00265 00266 /* If ongoing transmission. */ 00267 else if (spi->dataPacket->complete == false) { 00268 return (SPI_BUSY); 00269 } 00270 00271 /* If interrupted by other master. */ 00272 else if (interrupted) { 00273 /* If SS released. */ 00274 if (spi->port->OUT & SPI_SS_bm) { 00275 /* No longer interrupted. */ 00276 interrupted = false; 00277 } 00278 else { 00279 return (SPI_INTERRUPTED); 00280 } 00281 } 00282 00283 /* NOT interrupted by other master. 00284 * Start transmission. */ 00285 spi->dataPacket = dataPacket; 00286 spi->dataPacket->complete = false; 00287 spi->interrupted = false; 00288 00289 /* SS to slave(s) low.*/ 00290 uint8_t ssPinMask = spi->dataPacket->ssPinMask; 00291 SPI_MasterSSLow(spi->dataPacket->ssPort, ssPinMask); 00292 00293 spi->dataPacket->bytesTransceived = 0; 00294 00295 /* Start sending data. */ 00296 data = spi->dataPacket->transmitData[0]; 00297 spi->module->DATA = data; 00298 00299 /* Successs */ 00300 return (SPI_OK); 00301 }
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.
spi | The SPI_Master_t struct instance. | |
TXdata | Data to transmit to slave. |
Definition at line 324 of file spi_driver.c.
References SPI_Master::module.
Referenced by main().
00325 { 00326 /* Send pattern. */ 00327 spi->module->DATA = TXdata; 00328 00329 /* Wait for transmission complete. */ 00330 while(!(spi->module->STATUS & SPI_IF_bm)) { 00331 00332 } 00333 /* Read received data. */ 00334 uint8_t result = spi->module->DATA; 00335 00336 return(result); 00337 }
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.
spi | The SPI_Master_t struct instance. | |
dataPacket | The SPI_dataPacket_t struct instance. |
true | Success | |
false | Failure |
Definition at line 354 of file spi_driver.c.
References SPI_DataPacket::bytesToTransceive, SPI_DataPacket::bytesTransceived, SPI_DataPacket::complete, SPI_Master::dataPacket, SPI_Master::module, SPI_DataPacket::receiveData, SPI_MasterSSHigh, SPI_MasterSSLow, SPI_DataPacket::ssPinMask, SPI_DataPacket::ssPort, and SPI_DataPacket::transmitData.
Referenced by main().
00356 { 00357 /* Check if data packet has been created. */ 00358 if(dataPacket == NULL) { 00359 return false; 00360 } 00361 00362 /* Assign datapacket to SPI module. */ 00363 spi->dataPacket = dataPacket; 00364 00365 uint8_t ssPinMask = spi->dataPacket->ssPinMask; 00366 00367 /* If SS signal to slave(s). */ 00368 if (spi->dataPacket->ssPort != NULL) { 00369 /* SS to slave(s) low. */ 00370 SPI_MasterSSLow(spi->dataPacket->ssPort, ssPinMask); 00371 } 00372 00373 /* Transceive bytes. */ 00374 uint8_t bytesTransceived = 0; 00375 uint8_t bytesToTransceive = dataPacket->bytesToTransceive; 00376 while (bytesTransceived < bytesToTransceive) { 00377 00378 /* Send pattern. */ 00379 uint8_t data = spi->dataPacket->transmitData[bytesTransceived]; 00380 spi->module->DATA = data; 00381 00382 /* Wait for transmission complete. */ 00383 while(!(spi->module->STATUS & SPI_IF_bm)) { 00384 00385 } 00386 /* Read received data. */ 00387 data = spi->module->DATA; 00388 spi->dataPacket->receiveData[bytesTransceived] = data; 00389 00390 bytesTransceived++; 00391 } 00392 00393 /* If SS signal to slave(s). */ 00394 if (spi->dataPacket->ssPort != NULL) { 00395 /* Release SS to slave(s). */ 00396 SPI_MasterSSHigh(spi->dataPacket->ssPort, ssPinMask); 00397 } 00398 00399 /* Set variables to indicate that transmission is complete. */ 00400 spi->dataPacket->bytesTransceived = bytesTransceived; 00401 spi->dataPacket->complete = true; 00402 00403 /* Report success. */ 00404 return true; 00405 }
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.
spi | The SPI_Slave_t instance. | |
module | Pointer to the SPI module. | |
port | The I/O port where the SPI module is connected. | |
lsbFirst | Data order will be LSB first if this is set to true. | |
mode | SPI mode (Clock polarity and phase). | |
intLevel | SPI interrupt level. |
Definition at line 132 of file spi_driver.c.
References SPI_Slave::module, SPI_Slave::port, and SPI_MISO_bm.
Referenced by main().
00138 { 00139 /* SPI module. */ 00140 spi->module = module; 00141 spi->port = port; 00142 00143 spi->module->CTRL = SPI_ENABLE_bm | /* Enable SPI module. */ 00144 (lsbFirst ? SPI_DORD_bm : 0) | /* Data order. */ 00145 mode; /* SPI mode. */ 00146 00147 /* Interrupt level. */ 00148 spi->module->INTCTRL = intLevel; 00149 00150 /* MISO as output. */ 00151 spi->port->DIRSET = SPI_MISO_bm; 00152 }
Generated on Mon Nov 2 13:52:26 2009 for AVR1309 Using the XMEGA SPI by ![]() |