spi.c

Go to the documentation of this file.
00001 /*This file has been prepared for Doxygen automatic documentation generation.*/
00023 /* Copyright (c) 2006, Atmel Corporation All rights reserved.
00024  *
00025  * Redistribution and use in source and binary forms, with or without
00026  * modification, are permitted provided that the following conditions are met:
00027  *
00028  * 1. Redistributions of source code must retain the above copyright notice,
00029  * this list of conditions and the following disclaimer.
00030  *
00031  * 2. Redistributions in binary form must reproduce the above copyright notice,
00032  * this list of conditions and the following disclaimer in the documentation
00033  * and/or other materials provided with the distribution.
00034  *
00035  * 3. The name of ATMEL may not be used to endorse or promote products derived
00036  * from this software without specific prior written permission.
00037  *
00038  * THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED
00039  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00040  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND
00041  * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
00042  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00043  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00044  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00045  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00046  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00047  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00048  */
00049 
00050 #include "spi.h"
00051 
00052 int getBaudDiv(struct spi_options_t * options, int cpuHz);
00053 
00054 
00059 void spi_reset(volatile avr32_spi_t * spi)
00060 {
00061         spi->cr = AVR32_SPI_CR_SWRST_MASK;
00062 }
00063 
00064 
00075 int spi_initSlave(volatile avr32_spi_t * spi,
00076                 unsigned char bits,
00077                 unsigned char spi_mode)
00078 {
00079         /* Reset */
00080         spi->cr = (1<<AVR32_SPI_CR_SWRST_OFFSET);
00081 
00082         /* The number of bits and clock polarity/phase have to be set in
00083            csr0 for the SPI to communcate in slave mode */
00084         if (bits > 16 || bits < 8) {
00085                 return SPI_ERROR_ARGUMENT;
00086         }
00087 
00088         spi->csr0 = (bits - 8) << AVR32_SPI_CSR0_BITS_OFFSET;
00089 
00090         switch(spi_mode) {
00091                 case 0:
00092                         spi->csr0 |= (1 << AVR32_SPI_CSR0_NCPHA_OFFSET);
00093                 case 1:
00094                         break;
00095                 case 2:
00096                         spi->csr0 |= (1<<AVR32_SPI_CSR0_NCPHA_OFFSET);
00097                 case 3:
00098                         spi->csr0 |= (1<<AVR32_SPI_CSR0_CPOL_OFFSET);
00099                         break;
00100                 default: /* Not in legal range */
00101                         return SPI_ERROR_ARGUMENT;
00102         }
00103 
00104         return SPI_OK;
00105 }
00106 
00107 
00116 int spi_initTest(volatile avr32_spi_t * spi)
00117 {
00118         /* Reset */
00119         spi->cr = (1<<AVR32_SPI_CR_SWRST_OFFSET);
00120         /* Master Mode */
00121         spi->mr |= (1<<AVR32_SPI_MR_MSTR_OFFSET);
00122         /* Local Loopback */
00123         spi->mr |= (1<<AVR32_SPI_MR_LLB_OFFSET);
00124 
00125         return SPI_OK;
00126 }
00127 
00128 
00138 int spi_initMaster(volatile avr32_spi_t * spi, struct spi_options_t * options)
00139 {
00140         if (options->modfdis > 1) {
00141                 return SPI_ERROR_ARGUMENT;
00142         }
00143 
00144         if (options->fdiv > 1) {
00145                 return SPI_ERROR_ARGUMENT;
00146         }
00147 
00148         /* Reset */
00149         spi->cr = AVR32_SPI_CR_SWRST_MASK;
00150 
00151         /* Master Mode */
00152         spi->mr = AVR32_SPI_MR_MSTR_MASK|
00153                 (options->fdiv<<AVR32_SPI_MR_FDIV_OFFSET)|
00154                 (options->modfdis<<AVR32_SPI_MR_MODFDIS_OFFSET);
00155 
00156         return SPI_OK;
00157 }
00158 
00159 
00173 int spi_selectionMode(volatile avr32_spi_t * spi,
00174                 unsigned char variable_ps,
00175                 unsigned char pcs_decode,
00176                 unsigned char delay)
00177 {
00178         if (variable_ps > 1) {
00179                 return SPI_ERROR_ARGUMENT;
00180         }
00181 
00182         if (pcs_decode > 1) {
00183                 return SPI_ERROR_ARGUMENT;
00184         }
00185 
00186         spi->mr |=
00187                 (variable_ps<<AVR32_SPI_MR_PS_OFFSET)|
00188                 (pcs_decode<<AVR32_SPI_MR_PCSDEC_OFFSET)|
00189                 (delay<<AVR32_SPI_MR_DLYBCS_OFFSET);
00190 
00191         return SPI_OK;
00192 }
00193 
00194 
00205 int spi_selectChip(volatile avr32_spi_t * spi, unsigned char chip)
00206 {
00207         /* Assert all lines; no peripheral is selected */
00208         spi->mr |= (0xF << AVR32_SPI_MR_PCS_OFFSET);
00209 
00210         if ((spi->mr & (1<<AVR32_SPI_MR_PCSDEC_OFFSET)) != 0) {
00211                 /* The signal is decoded; allow up to 16 chips */
00212                 if (chip > 15) {
00213                         return SPI_ERROR_ARGUMENT;
00214                 }
00215 
00216                 spi->mr |= chip << AVR32_SPI_MR_PCS_OFFSET;
00217         } else {
00218                 if (chip > 3) {
00219                         return SPI_ERROR_ARGUMENT;
00220                 }
00221 
00222                 spi->mr &= ~(1<<(AVR32_SPI_MR_PCS_OFFSET + chip));
00223         }
00224 
00225         return SPI_OK;
00226 }
00227 
00228 
00243 int spi_setupChipReg(volatile avr32_spi_t * spi,
00244                 struct spi_options_t * options,
00245                 unsigned int cpuHz)
00246 {
00247         unsigned long csr;
00248 
00249         if (options->bits > 16 || options->bits < 8) {
00250                 return SPI_ERROR_ARGUMENT;
00251         }
00252 
00253         if (options->stay_act > 1) {
00254                 return SPI_ERROR_ARGUMENT;
00255         }
00256 
00257         int baudDiv = getBaudDiv(options, cpuHz);
00258 
00259         if (baudDiv < 0) {
00260                 return -baudDiv;
00261         }
00262 
00263         /* Will use CSR0 offsets; these are the same for CSR0 - CSR3 */
00264         csr = ((options->bits - 8)<<AVR32_SPI_CSR0_BITS_OFFSET)|
00265                 (baudDiv<<AVR32_SPI_CSR0_SCBR_OFFSET)|
00266                 (options->spck_delay<<AVR32_SPI_CSR0_DLYBS_OFFSET)|
00267                 (options->trans_delay<<AVR32_SPI_CSR0_DLYBCT_OFFSET)|
00268                 (options->stay_act<<AVR32_SPI_CSR0_CSAAT_OFFSET);
00269 
00270         switch(options->spi_mode) {
00271                 case 0:
00272                         csr |= (1<<AVR32_SPI_CSR0_NCPHA_OFFSET);
00273                 case 1:
00274                         break;
00275                 case 2:
00276                         csr |= (1<<AVR32_SPI_CSR0_NCPHA_OFFSET);
00277                 case 3:
00278                         csr |= (1<<AVR32_SPI_CSR0_CPOL_OFFSET);
00279                         break;
00280                 default: /* Not in legal range */
00281                         return SPI_ERROR_ARGUMENT;
00282         }
00283 
00284         switch(options->reg) {
00285                 case 0:
00286                         spi->csr0 = csr;
00287                         break;
00288                 case 1:
00289                         spi->csr1 = csr;
00290                         break;
00291                 case 2:
00292                         spi->csr2 = csr;
00293                         break;
00294                 case 3:
00295                         spi->csr3 = csr;
00296                         break;
00297                 default:
00298                         return SPI_ERROR_ARGUMENT;
00299         }
00300 
00301         return SPI_OK;
00302 }
00303 
00304 
00311 void spi_enable(volatile avr32_spi_t * spi)
00312 {
00313         spi->cr = (1<<AVR32_SPI_CR_SPIEN_OFFSET);
00314 }
00315 
00316 
00324 void spi_disable(volatile avr32_spi_t * spi)
00325 {
00326         spi->cr = (1<<AVR32_SPI_CR_SPIDIS_OFFSET);
00327 }
00328 
00329 
00340 int spi_write(volatile avr32_spi_t * spi, unsigned short data)
00341 {
00342         unsigned int timeout = SPI_TIMEOUT;
00343 
00344         while ((spi->sr & AVR32_SPI_SR_TXEMPTY_MASK) == 0 && timeout > 0) {
00345                 --timeout;
00346         }
00347 
00348         if (timeout == 0) {
00349                 return SPI_ERROR_TIMEOUT;
00350         }
00351 
00352         spi->tdr = data & 0x0000FFFF;
00353 
00354         return SPI_OK;
00355 }
00356 
00357 
00375 int spi_variableSlaveWrite(volatile avr32_spi_t * spi, unsigned short data,
00376                 unsigned char pcs, unsigned char lastxfer)
00377 {
00378         unsigned int timeout = SPI_TIMEOUT;
00379 
00380         if (pcs > 15 || lastxfer > 1)
00381                 return SPI_ERROR_ARGUMENT;
00382 
00383         while ((spi->sr & AVR32_SPI_SR_TXEMPTY_MASK) == 0 && --timeout) {
00384         }
00385 
00386         if (timeout == 0) {
00387                 return SPI_ERROR_TIMEOUT;
00388         }
00389 
00390         spi->tdr = (data << AVR32_SPI_TDR_TD_OFFSET) |
00391                 (pcs << AVR32_SPI_TDR_PCS_OFFSET) |
00392                 (lastxfer << AVR32_SPI_TDR_LASTXFER_OFFSET);
00393 
00394         return SPI_OK;
00395 }
00396 
00397 
00406 unsigned char spi_readRegisterFullCheck(volatile avr32_spi_t * spi)
00407 {
00408         if ((spi->sr & AVR32_SPI_SR_RDRF_MASK) != 0) {
00409                 return 1;
00410         } else {
00411                 return 0;
00412         }
00413 }
00414 
00415 
00426 int spi_read(volatile avr32_spi_t * spi, unsigned short * data)
00427 {
00428         unsigned int timeout = SPI_TIMEOUT;
00429 
00430         do {
00431                 --timeout;
00432         } while ((spi->sr & AVR32_SPI_SR_RDRF_MASK) == 0 && timeout > 0);
00433 
00434         if (timeout == 0) {
00435                 return SPI_ERROR_TIMEOUT;
00436         }
00437 
00438         *data = spi->rdr & 0x0000FFFF;
00439 
00440         return SPI_OK;
00441 }
00442 
00443 
00456 unsigned char spi_getStatus(volatile avr32_spi_t * spi)
00457 {
00458         unsigned char ret = 0;
00459 
00460         if ((spi->sr & (1<<AVR32_SPI_SR_OVRES_OFFSET)) != 0) {
00461                 ret = SPI_ERROR_OVERRUN;
00462         }
00463 
00464         if ((spi->sr & (1<<AVR32_SPI_SR_MODF_OFFSET)) != 0) {
00465                 ret += SPI_ERROR_MODE_FAULT;
00466         }
00467 
00468         if (ret == (SPI_ERROR_OVERRUN + SPI_ERROR_MODE_FAULT)) {
00469                 return SPI_ERROR_OVERRUN_AND_MODE_FAULT;
00470         }
00471         else if (ret > 0) {
00472                 return ret;
00473         } else {
00474                 return SPI_OK;
00475         }
00476 }
00477 
00478 
00488 int getBaudDiv(struct spi_options_t * options, int cpuHz) {
00489         int baudDiv = 0;
00490 
00491         if (options->fdiv == 0) {
00492                 baudDiv = cpuHz / (options->baudrate);
00493         } else {
00494                 baudDiv = cpuHz / (32 * options->baudrate);
00495         }
00496 
00497         if (baudDiv > 255 || baudDiv <= 0) {
00498                 return -SPI_ERROR_ARGUMENT;
00499         }
00500 
00501         return baudDiv;
00502 }
00503 

Generated on Wed May 7 16:03:17 2008 for AVR32114 Using the AVR32 LCD Controller by  doxygen 1.5.3-20071008