spi.c File Reference


Detailed Description

SPI driver for AVR32 UC3.

This file defines a useful set of functions for the SPI interface on AVR32 devices.

Author:
Atmel Corporation: http://www.atmel.com
Support and FAQ: http://support.atmel.no/

Definition in file spi.c.

#include "spi.h"

Go to the source code of this file.

Data Structures

union  u_avr32_spi_cr_t
union  u_avr32_spi_csr_t
union  u_avr32_spi_idr_t
union  u_avr32_spi_ier_t
union  u_avr32_spi_mr_t
union  u_avr32_spi_tdr_t

Functions

static int getBaudDiv (const spi_options_t *options, unsigned int pba_hz)
 Calculates the baudrate divider.
void spi_disable (volatile avr32_spi_t *spi)
 Disables the SPI.
void spi_enable (volatile avr32_spi_t *spi)
 Enables the SPI.
unsigned char spi_getStatus (volatile avr32_spi_t *spi)
 Gets status information from the SPI.
spi_status_t spi_initMaster (volatile avr32_spi_t *spi, const spi_options_t *options)
 Initializes the SPI in master mode.
spi_status_t spi_initSlave (volatile avr32_spi_t *spi, unsigned char bits, unsigned char spi_mode)
 Initializes the SPI in slave mode.
spi_status_t spi_initTest (volatile avr32_spi_t *spi)
 Sets up the SPI in a test mode where the transmitter is connected to the receiver (local loopback).
int spi_is_enabled (volatile avr32_spi_t *spi)
 Tests if the SPI is enabled.
spi_status_t spi_read (volatile avr32_spi_t *spi, unsigned short *data)
 Reads one data word in master mode or in slave mode.
unsigned char spi_readRegisterFullCheck (volatile avr32_spi_t *spi)
 Checks if there is data in the receive register.
void spi_reset (volatile avr32_spi_t *spi)
 Resets the SPI controller.
spi_status_t spi_selectChip (volatile avr32_spi_t *spi, unsigned char chip)
 Selects slave chip.
spi_status_t spi_selectionMode (volatile avr32_spi_t *spi, unsigned char variable_ps, unsigned char pcs_decode, unsigned char delay)
 Sets up how and when the slave chips are selected (master mode only).
spi_status_t spi_setupChipReg (volatile avr32_spi_t *spi, const spi_options_t *options, unsigned int pba_hz)
 Sets options for a specific slave chip.
spi_status_t spi_unselectChip (volatile avr32_spi_t *spi, unsigned char chip)
 Unselects slave chip.
spi_status_t spi_variableSlaveWrite (volatile avr32_spi_t *spi, unsigned short data, unsigned char pcs, unsigned char lastxfer)
 Selects a slave in master variable peripheral select mode and writes one data word to it.
spi_status_t spi_write (volatile avr32_spi_t *spi, unsigned short data)
 Writes one data word in master fixed peripheral select mode or in slave mode.
unsigned char spi_writeEndCheck (volatile avr32_spi_t *spi)
 Checks if all transmissions are complete.
unsigned char spi_writeRegisterEmptyCheck (volatile avr32_spi_t *spi)
 Checks if there is no data in the transmit register.


Function Documentation

static int getBaudDiv ( const spi_options_t options,
unsigned int  pba_hz 
) [static]

Calculates the baudrate divider.

Parameters:
options Pointer to a structure containing initialization options for an SPI channel.
pba_hz SPI module input clock frequency (PBA clock, Hz).
Returns:
Divider or error code.
Return values:
>=0 Success.
<0 Error.

Definition at line 120 of file spi.c.

References spi_options_t::baudrate.

Referenced by spi_setupChipReg().

00121 {
00122   int baudDiv = (pba_hz + options->baudrate / 2) / options->baudrate;
00123 
00124   if (baudDiv <= 0 || baudDiv > 255) {
00125     return -1;
00126   }
00127 
00128   return baudDiv;
00129 }

void spi_disable ( volatile avr32_spi_t *  spi  ) 

Disables the SPI.

Ensures that nothing is transferred while setting up buffers.

Parameters:
spi Base address of the SPI instance.
Warning:
This may cause data loss if used on a slave SPI.

Definition at line 334 of file spi.c.

00335 {
00336   spi->cr = AVR32_SPI_CR_SPIDIS_MASK;
00337 }

void spi_enable ( volatile avr32_spi_t *  spi  ) 

Enables the SPI.

Parameters:
spi Base address of the SPI instance.

Definition at line 328 of file spi.c.

Referenced by at45dbx_resources_init(), init_spiMaster(), and init_spiSlave().

00329 {
00330   spi->cr = AVR32_SPI_CR_SPIEN_MASK;
00331 }

unsigned char spi_getStatus ( volatile avr32_spi_t *  spi  ) 

Gets status information from the SPI.

Parameters:
spi Base address of the SPI instance.
Returns:
Status.
Return values:
SPI_OK Success.
SPI_ERROR_OVERRUN Overrun error.
SPI_ERROR_MODE_FAULT Mode fault (SPI addressed as slave while in master mode).
SPI_ERROR_OVERRUN_AND_MODE_FAULT Overrun error and mode fault.

Definition at line 420 of file spi.c.

References SPI_ERROR_MODE_FAULT, SPI_ERROR_OVERRUN, SPI_ERROR_OVERRUN_AND_MODE_FAULT, and SPI_OK.

00421 {
00422   spi_status_t ret = SPI_OK;
00423   unsigned long sr = spi->sr;
00424 
00425   if (sr & AVR32_SPI_SR_OVRES_MASK) {
00426     ret = SPI_ERROR_OVERRUN;
00427   }
00428 
00429   if (sr & AVR32_SPI_SR_MODF_MASK) {
00430     ret += SPI_ERROR_MODE_FAULT;
00431   }
00432 
00433   if (ret == (SPI_ERROR_OVERRUN + SPI_ERROR_MODE_FAULT)) {
00434     return SPI_ERROR_OVERRUN_AND_MODE_FAULT;
00435   }
00436   else if (ret > 0) {
00437     return ret;
00438   } else {
00439     return SPI_OK;
00440   }
00441 }

spi_status_t spi_initMaster ( volatile avr32_spi_t *  spi,
const spi_options_t options 
)

Initializes the SPI in master mode.

Parameters:
spi Base address of the SPI instance.
options Pointer to a structure containing initialization options.
Returns:
Status.
Return values:
SPI_OK Success.
SPI_ERROR_ARGUMENT Invalid argument(s) passed.

Definition at line 170 of file spi.c.

References spi_options_t::modfdis, u_avr32_spi_mr_t::MR, u_avr32_spi_mr_t::mr, SPI_ERROR_ARGUMENT, and SPI_OK.

Referenced by at45dbx_resources_init(), and init_spiMaster().

00171 {
00172   u_avr32_spi_mr_t u_avr32_spi_mr;
00173 
00174   if (options->modfdis > 1) {
00175     return SPI_ERROR_ARGUMENT;
00176   }
00177 
00178   // Reset.
00179   spi->cr = AVR32_SPI_CR_SWRST_MASK;
00180 
00181   // Master Mode.
00182   u_avr32_spi_mr.mr = spi->mr;
00183   u_avr32_spi_mr.MR.mstr = 1;
00184   u_avr32_spi_mr.MR.modfdis = options->modfdis;
00185   u_avr32_spi_mr.MR.llb = 0;
00186   u_avr32_spi_mr.MR.pcs = (1 << AVR32_SPI_MR_PCS_SIZE) - 1;
00187   spi->mr = u_avr32_spi_mr.mr;
00188 
00189   return SPI_OK;
00190 }

spi_status_t spi_initSlave ( volatile avr32_spi_t *  spi,
unsigned char  bits,
unsigned char  spi_mode 
)

Initializes the SPI in slave mode.

Parameters:
spi Base address of the SPI instance.
bits Number of bits in each transmitted character (8 to 16).
spi_mode Clock polarity and phase.
Returns:
Status.
Return values:
SPI_OK Success.
SPI_ERROR_ARGUMENT Invalid argument(s) passed.

Definition at line 138 of file spi.c.

References SPI_ERROR_ARGUMENT, and SPI_OK.

Referenced by init_spiSlave().

00141 {
00142   if (spi_mode > 3 ||
00143       bits < 8 || bits > 16) {
00144     return SPI_ERROR_ARGUMENT;
00145   }
00146 
00147   // Reset.
00148   spi->cr = AVR32_SPI_CR_SWRST_MASK;
00149 
00150   // Will use CSR0 offsets; these are the same for CSR0 to CSR3.
00151   spi->csr0 = ((spi_mode >> 1) << AVR32_SPI_CSR0_CPOL_OFFSET) |
00152               (((spi_mode & 0x1) ^ 0x1) << AVR32_SPI_CSR0_NCPHA_OFFSET) |
00153               ((bits - 8) << AVR32_SPI_CSR0_BITS_OFFSET);
00154 
00155   return SPI_OK;
00156 }

spi_status_t spi_initTest ( volatile avr32_spi_t *  spi  ) 

Sets up the SPI in a test mode where the transmitter is connected to the receiver (local loopback).

Parameters:
spi Base address of the SPI instance.
Returns:
Status.
Return values:
SPI_OK Success.

Definition at line 159 of file spi.c.

References SPI_OK.

00160 {
00161   // Reset.
00162   spi->cr = AVR32_SPI_CR_SWRST_MASK;
00163   spi->mr |= AVR32_SPI_MR_MSTR_MASK | // Master Mode.
00164              AVR32_SPI_MR_LLB_MASK;   // Local Loopback.
00165 
00166   return SPI_OK;
00167 }

int spi_is_enabled ( volatile avr32_spi_t *  spi  ) 

Tests if the SPI is enabled.

Parameters:
spi Base address of the SPI instance.
Returns:
1 if the SPI is enabled, otherwise 0.

Definition at line 340 of file spi.c.

00341 {
00342   return (spi->sr & AVR32_SPI_SR_SPIENS_MASK) != 0;
00343 }

spi_status_t spi_read ( volatile avr32_spi_t *  spi,
unsigned short *  data 
)

Reads one data word in master mode or in slave mode.

Parameters:
spi Base address of the SPI instance.
data Pointer to the location where to store the received data word.
Returns:
Status.
Return values:
SPI_OK Success.
SPI_ERROR_TIMEOUT Time-out.
Note:
Will block program execution until time-out occurs if no data is received or last transmission is not complete. Invoke spi_writeEndCheck or spi_readRegisterFullCheck beforehand if needed.

Definition at line 403 of file spi.c.

References SPI_ERROR_TIMEOUT, SPI_OK, and SPI_TIMEOUT.

Referenced by at45dbx_mem_check(), at45dbx_read_byte(), at45dbx_read_sector_2_ram(), at45dbx_wait_ready(), and spi_slaveReceiveAndCompare().

00404 {
00405   unsigned int timeout = SPI_TIMEOUT;
00406 
00407   while ((spi->sr & (AVR32_SPI_SR_RDRF_MASK | AVR32_SPI_SR_TXEMPTY_MASK)) !=
00408          (AVR32_SPI_SR_RDRF_MASK | AVR32_SPI_SR_TXEMPTY_MASK)) {
00409     if (!timeout--) {
00410       return SPI_ERROR_TIMEOUT;
00411     }
00412   }
00413 
00414   *data = spi->rdr >> AVR32_SPI_RDR_RD_OFFSET;
00415 
00416   return SPI_OK;
00417 }

unsigned char spi_readRegisterFullCheck ( volatile avr32_spi_t *  spi  ) 

Checks if there is data in the receive register.

Parameters:
spi Base address of the SPI instance.
Returns:
Status.
Return values:
1 Some data in RDR.
0 No data in RDR.

Definition at line 397 of file spi.c.

Referenced by main().

00398 {
00399   return ((spi->sr & AVR32_SPI_SR_RDRF_MASK) != 0);
00400 }

void spi_reset ( volatile avr32_spi_t *  spi  ) 

Resets the SPI controller.

Parameters:
spi Base address of the SPI instance.

Definition at line 132 of file spi.c.

00133 {
00134   spi->cr = AVR32_SPI_CR_SWRST_MASK;
00135 }

spi_status_t spi_selectChip ( volatile avr32_spi_t *  spi,
unsigned char  chip 
)

Selects slave chip.

Parameters:
spi Base address of the SPI instance.
chip Slave chip number (normal: 0 to 3, extarnally decoded signal: 0 to 14).
Returns:
Status.
Return values:
SPI_OK Success.
SPI_ERROR_ARGUMENT Invalid argument(s) passed.

Definition at line 215 of file spi.c.

References SPI_ERROR_ARGUMENT, and SPI_OK.

Referenced by at45dbx_chipselect_df(), and init_spiMaster().

00216 {
00217 #ifdef FREERTOS_USED
00218   while (pdFALSE == xSemaphoreTake(xSPIMutex, 20));
00219 #endif
00220 
00221   // Assert all lines; no peripheral is selected.
00222   spi->mr |= AVR32_SPI_MR_PCS_MASK;
00223 
00224   if (spi->mr & AVR32_SPI_MR_PCSDEC_MASK) {
00225     // The signal is decoded; allow up to 15 chips.
00226     if (chip > 14) {
00227       return SPI_ERROR_ARGUMENT;
00228     }
00229 
00230     spi->mr &= ~AVR32_SPI_MR_PCS_MASK | (chip << AVR32_SPI_MR_PCS_OFFSET);
00231   } else {
00232     if (chip > 3) {
00233       return SPI_ERROR_ARGUMENT;
00234     }
00235 
00236     spi->mr &= ~(1 << (AVR32_SPI_MR_PCS_OFFSET + chip));
00237   }
00238 
00239   return SPI_OK;
00240 }

spi_status_t spi_selectionMode ( volatile avr32_spi_t *  spi,
unsigned char  variable_ps,
unsigned char  pcs_decode,
unsigned char  delay 
)

Sets up how and when the slave chips are selected (master mode only).

Parameters:
spi Base address of the SPI instance.
variable_ps Target slave is selected in transfer register for every character to transmit.
pcs_decode The four chip select lines are decoded externally. Values 0 to 14 can be given to spi_selectChip.
delay Delay in PBA periods between chip selects.
Returns:
Status.
Return values:
SPI_OK Success.
SPI_ERROR_ARGUMENT Invalid argument(s) passed.

Definition at line 193 of file spi.c.

References u_avr32_spi_mr_t::MR, u_avr32_spi_mr_t::mr, SPI_ERROR_ARGUMENT, and SPI_OK.

Referenced by at45dbx_resources_init(), and init_spiMaster().

00197 {
00198   u_avr32_spi_mr_t u_avr32_spi_mr;
00199 
00200   if (variable_ps > 1 ||
00201       pcs_decode > 1) {
00202     return SPI_ERROR_ARGUMENT;
00203   }
00204 
00205   u_avr32_spi_mr.mr = spi->mr;
00206   u_avr32_spi_mr.MR.ps = variable_ps;
00207   u_avr32_spi_mr.MR.pcsdec = pcs_decode;
00208   u_avr32_spi_mr.MR.dlybcs = delay;
00209   spi->mr = u_avr32_spi_mr.mr;
00210 
00211   return SPI_OK;
00212 }

spi_status_t spi_setupChipReg ( volatile avr32_spi_t *  spi,
const spi_options_t options,
unsigned int  pba_hz 
)

Sets options for a specific slave chip.

The baudrate field has to be written before transfer in master mode. Four similar registers exist, one for each slave. When using encoded slave addressing, reg=0 sets options for slaves 0 to 3, reg=1 for slaves 4 to 7 and so on.

Parameters:
spi Base address of the SPI instance.
options Pointer to a structure containing initialization options for an SPI channel.
pba_hz SPI module input clock frequency (PBA clock, Hz).
Returns:
Status.
Return values:
SPI_OK Success.
SPI_ERROR_ARGUMENT Invalid argument(s) passed.

Definition at line 267 of file spi.c.

References spi_options_t::bits, u_avr32_spi_csr_t::CSR, u_avr32_spi_csr_t::csr, getBaudDiv(), spi_options_t::reg, spi_options_t::spck_delay, SPI_ERROR_ARGUMENT, spi_options_t::spi_mode, SPI_OK, spi_options_t::stay_act, and spi_options_t::trans_delay.

Referenced by at45dbx_init(), init_spiMaster(), and init_spiSlave().

00270 {
00271   u_avr32_spi_csr_t u_avr32_spi_csr;
00272 
00273   if (options->spi_mode > 3 ||
00274       options->stay_act > 1 ||
00275       options->bits < 8 || options->bits > 16) {
00276     return SPI_ERROR_ARGUMENT;
00277   }
00278 
00279   int baudDiv = getBaudDiv(options, pba_hz);
00280 
00281   if (baudDiv < 0) {
00282     return SPI_ERROR_ARGUMENT;
00283   }
00284 
00285   // Will use CSR0 offsets; these are the same for CSR0 to CSR3.
00286   u_avr32_spi_csr.csr = 0;
00287   u_avr32_spi_csr.CSR.cpol = options->spi_mode >> 1;
00288   u_avr32_spi_csr.CSR.ncpha = (options->spi_mode & 0x1) ^ 0x1;
00289   u_avr32_spi_csr.CSR.csaat = options->stay_act;
00290   u_avr32_spi_csr.CSR.bits = options->bits - 8;
00291   u_avr32_spi_csr.CSR.scbr = baudDiv;
00292   u_avr32_spi_csr.CSR.dlybs = options->spck_delay;
00293   u_avr32_spi_csr.CSR.dlybct = options->trans_delay;
00294 
00295   switch(options->reg) {
00296     case 0:
00297       spi->csr0 = u_avr32_spi_csr.csr;
00298       break;
00299     case 1:
00300       spi->csr1 = u_avr32_spi_csr.csr;
00301       break;
00302     case 2:
00303       spi->csr2 = u_avr32_spi_csr.csr;
00304       break;
00305     case 3:
00306       spi->csr3 = u_avr32_spi_csr.csr;
00307       break;
00308     default:
00309       return SPI_ERROR_ARGUMENT;
00310   }
00311 
00312 #ifdef FREERTOS_USED
00313   if (!xSPIMutex)
00314   {
00315     // Create the SPI mutex.
00316     vSemaphoreCreateBinary(xSPIMutex);
00317     if (!xSPIMutex)
00318     {
00319       while(1);
00320     }
00321   }
00322 #endif
00323 
00324   return SPI_OK;
00325 }

spi_status_t spi_unselectChip ( volatile avr32_spi_t *  spi,
unsigned char  chip 
)

Unselects slave chip.

Parameters:
spi Base address of the SPI instance.
chip Slave chip number (normal: 0 to 3, extarnally decoded signal: 0 to 14).
Returns:
Status.
Return values:
SPI_OK Success.
SPI_ERROR_TIMEOUT Time-out.
Note:
Will block program execution until time-out occurs if last transmission is not complete. Invoke spi_writeEndCheck beforehand if needed.

Definition at line 243 of file spi.c.

References SPI_ERROR_TIMEOUT, SPI_OK, and SPI_TIMEOUT.

Referenced by at45dbx_chipselect_df().

00244 {
00245   unsigned int timeout = SPI_TIMEOUT;
00246 
00247   while (!(spi->sr & AVR32_SPI_SR_TXEMPTY_MASK)) {
00248     if (!timeout--) {
00249       return SPI_ERROR_TIMEOUT;
00250     }
00251   }
00252 
00253   // Assert all lines; no peripheral is selected.
00254   spi->mr |= AVR32_SPI_MR_PCS_MASK;
00255 
00256   // Last transfer, so deassert the current NPCS if CSAAT is set.
00257   spi->cr = AVR32_SPI_CR_LASTXFER_MASK;
00258 
00259 #ifdef FREERTOS_USED
00260   xSemaphoreGive(xSPIMutex);
00261 #endif
00262 
00263   return SPI_OK;
00264 }

spi_status_t spi_variableSlaveWrite ( volatile avr32_spi_t *  spi,
unsigned short  data,
unsigned char  pcs,
unsigned char  lastxfer 
)

Selects a slave in master variable peripheral select mode and writes one data word to it.

Parameters:
spi Base address of the SPI instance.
data The data word to write.
pcs Slave selector (bit 0 -> nCS line 0, bit 1 -> nCS line 1, etc.).
lastxfer Boolean indicating whether this is the last data word transfer.
Returns:
Status.
Return values:
SPI_OK Success.
SPI_ERROR_TIMEOUT Time-out.
SPI_ERROR_ARGUMENT Invalid argument(s) passed.
Note:
Will block program execution until time-out occurs if transmitter is busy and transmit buffer is full. Invoke spi_writeRegisterEmptyCheck beforehand if needed.

Once the data has been written to the transmit buffer, the end of transmission is not waited for. Invoke spi_writeEndCheck if needed.

Definition at line 368 of file spi.c.

References SPI_ERROR_ARGUMENT, SPI_ERROR_TIMEOUT, SPI_OK, and SPI_TIMEOUT.

00370 {
00371   unsigned int timeout = SPI_TIMEOUT;
00372 
00373   if (pcs > 14 || lastxfer > 1) {
00374     return SPI_ERROR_ARGUMENT;
00375   }
00376 
00377   while (!(spi->sr & AVR32_SPI_SR_TDRE_MASK)) {
00378     if (!timeout--) {
00379       return SPI_ERROR_TIMEOUT;
00380     }
00381   }
00382 
00383   spi->tdr = (data << AVR32_SPI_TDR_TD_OFFSET) |
00384              (pcs << AVR32_SPI_TDR_PCS_OFFSET) |
00385              (lastxfer << AVR32_SPI_TDR_LASTXFER_OFFSET);
00386 
00387   return SPI_OK;
00388 }

spi_status_t spi_write ( volatile avr32_spi_t *  spi,
unsigned short  data 
)

Writes one data word in master fixed peripheral select mode or in slave mode.

Parameters:
spi Base address of the SPI instance.
data The data word to write.
Returns:
Status.
Return values:
SPI_OK Success.
SPI_ERROR_TIMEOUT Time-out.
Note:
Will block program execution until time-out occurs if transmitter is busy and transmit buffer is full. Invoke spi_writeRegisterEmptyCheck beforehand if needed.

Once the data has been written to the transmit buffer, the end of transmission is not waited for. Invoke spi_writeEndCheck if needed.

Definition at line 352 of file spi.c.

References SPI_ERROR_TIMEOUT, SPI_OK, and SPI_TIMEOUT.

Referenced by at45dbx_mem_check(), at45dbx_read_open(), at45dbx_wait_ready(), at45dbx_write_byte(), at45dbx_write_close(), at45dbx_write_open(), at45dbx_write_sector_from_ram(), and spi_masterSend().

00353 {
00354   unsigned int timeout = SPI_TIMEOUT;
00355 
00356   while (!(spi->sr & AVR32_SPI_SR_TDRE_MASK)) {
00357     if (!timeout--) {
00358       return SPI_ERROR_TIMEOUT;
00359     }
00360   }
00361 
00362   spi->tdr = data << AVR32_SPI_TDR_TD_OFFSET;
00363 
00364   return SPI_OK;
00365 }

unsigned char spi_writeEndCheck ( volatile avr32_spi_t *  spi  ) 

Checks if all transmissions are complete.

Parameters:
spi Base address of the SPI instance.
Returns:
Status.
Return values:
1 All transmissions complete.
0 Transmissions not complete.

Definition at line 391 of file spi.c.

00392 {
00393   return ((spi->sr & AVR32_SPI_SR_TXEMPTY_MASK) != 0);
00394 }

unsigned char spi_writeRegisterEmptyCheck ( volatile avr32_spi_t *  spi  ) 

Checks if there is no data in the transmit register.

Parameters:
spi Base address of the SPI instance.
Returns:
Status.
Return values:
1 No data in TDR.
0 Some data in TDR.

Definition at line 346 of file spi.c.

00347 {
00348   return ((spi->sr & AVR32_SPI_SR_TDRE_MASK) != 0);
00349 }


Generated on Thu Dec 17 19:57:41 2009 for AVR32 - AT45DBX Data Flash Driver by  doxygen 1.5.5