spi.c

Go to the documentation of this file.
00001 /*This file has been prepared for Doxygen automatic documentation generation.*/
00021 /* Copyright (c) 2006, Atmel Corporation All rights reserved.
00022  *
00023  * Redistribution and use in source and binary forms, with or without
00024  * modification, are permitted provided that the following conditions are met:
00025  *
00026  * 1. Redistributions of source code must retain the above copyright notice,
00027  * this list of conditions and the following disclaimer.
00028  *
00029  * 2. Redistributions in binary form must reproduce the above copyright notice,
00030  * this list of conditions and the following disclaimer in the documentation
00031  * and/or other materials provided with the distribution.
00032  *
00033  * 3. The name of ATMEL may not be used to endorse or promote products derived
00034  * from this software without specific prior written permission.
00035  *
00036  * THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED
00037  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00038  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND
00039  * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
00040  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00041  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00042  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00043  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00044  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00045  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00046  */
00047 
00048 #include "spi.h"
00049 
00050 int getBaudDiv(struct spi_options_t * options, int cpuHz);
00051 
00052 
00057 void spi_reset(volatile avr32_spi_t *spi)
00058 {
00059     spi->cr = AVR32_SPI_CR_SWRST_MASK;
00060 }
00061 
00062 
00073 int spi_initSlave(volatile avr32_spi_t *spi,
00074         unsigned char bits,
00075         unsigned char spi_mode)
00076 {
00077     /* Reset */
00078     spi->cr = AVR32_SPI_CR_SWRST_MASK;
00079 
00080     /* The number of bits and clock polarity/phase have to be set in
00081        csr0 for the SPI to communcate in slave mode */
00082     if (bits > 16 || bits < 8) {
00083         return SPI_ERROR_ARGUMENT;
00084     }
00085 
00086     spi->csr0 = (bits - 8) << AVR32_SPI_CSR0_BITS_OFFSET;
00087 
00088     switch (spi_mode) {
00089         case 0:
00090             spi->csr0 |= (1 << AVR32_SPI_CSR0_NCPHA_OFFSET);
00091         case 1:
00092             break;
00093         case 2:
00094             spi->csr0 |= (1<<AVR32_SPI_CSR0_NCPHA_OFFSET);
00095         case 3:
00096             spi->csr0 |= (1<<AVR32_SPI_CSR0_CPOL_OFFSET);
00097             break;
00098         default: /* Not in legal range */
00099             return SPI_ERROR_ARGUMENT;
00100     }
00101 
00102     return SPI_OK;
00103 }
00104 
00105 
00114 int spi_initTest(volatile avr32_spi_t *spi)
00115 {
00116     /* Reset */
00117     spi->cr = AVR32_SPI_CR_SWRST_MASK;
00118     /* Master Mode */
00119     spi->mr |= AVR32_SPI_MR_MSTR_MASK;
00120     /* Local Loopback */
00121     spi->mr |= AVR32_SPI_MR_LLB_MASK;
00122 
00123     return SPI_OK;
00124 }
00125 
00126 
00136 int spi_initMaster(volatile avr32_spi_t *spi, struct spi_options_t *options)
00137 {
00138     if (options->modfdis > 1 || options->fdiv > 1) {
00139         return SPI_ERROR_ARGUMENT;
00140     }
00141 
00142     /* Reset */
00143     spi->cr = AVR32_SPI_CR_SWRST_MASK;
00144 
00145     /* Master Mode */
00146     spi->mr = AVR32_SPI_MR_MSTR_MASK|
00147         AVR32_SPI_MR_PCS_MASK|
00148         (options->fdiv<<AVR32_SPI_MR_FDIV_OFFSET)|
00149         (options->modfdis<<AVR32_SPI_MR_MODFDIS_OFFSET);
00150 
00151     return SPI_OK;
00152 }
00153 
00154 
00168 int spi_selectionMode(volatile avr32_spi_t *spi,
00169         unsigned char variable_ps,
00170         unsigned char pcs_decode,
00171         unsigned char delay)
00172 {
00173     if (variable_ps > 1 || pcs_decode > 1) {
00174         return SPI_ERROR_ARGUMENT;
00175     }
00176 
00177     /* Unset bitfields */
00178     spi->mr &= ~(AVR32_SPI_MR_PS_MASK|
00179             AVR32_SPI_MR_PCSDEC_MASK|
00180             AVR32_SPI_MR_DLYBCS_MASK);
00181     /* Set selction bits */
00182     spi->mr |=
00183         (variable_ps<<AVR32_SPI_MR_PS_OFFSET)|
00184         (pcs_decode<<AVR32_SPI_MR_PCSDEC_OFFSET)|
00185         (delay<<AVR32_SPI_MR_DLYBCS_OFFSET);
00186 
00187     return SPI_OK;
00188 }
00189 
00190 
00201 int spi_selectChip(volatile avr32_spi_t *spi, unsigned char chip)
00202 {
00203     /* Assert all lines; no peripheral is selected */
00204     spi->mr |= AVR32_SPI_MR_PCS_MASK;
00205 
00206     if ((spi->mr & AVR32_SPI_MR_PCSDEC_MASK) != 0) {
00207         /* The signal is decoded; allow up to 15 chips */
00208         if (chip > 14) {
00209             return SPI_ERROR_ARGUMENT;
00210         }
00211 
00212         spi->mr = (spi->mr & ~AVR32_SPI_MR_PCS_MASK)|
00213             (chip << AVR32_SPI_MR_PCS_OFFSET);
00214     } else {
00215         if (chip > 3) {
00216             return SPI_ERROR_ARGUMENT;
00217         }
00218 
00219         spi->mr &= ~(1<<(AVR32_SPI_MR_PCS_OFFSET + chip));
00220     }
00221 
00222     return SPI_OK;
00223 }
00224 
00225 
00235 int spi_unselectChip(volatile avr32_spi_t *spi, unsigned char chip)
00236 {
00237     /* Assert all lines; no peripheral is selected */
00238     spi->mr |= AVR32_SPI_MR_PCS_MASK;
00239 
00240     /* Last transfer, so deassert the current NPCS if CSAAT is set */
00241     spi->cr = AVR32_SPI_CR_LASTXFER_MASK;
00242 
00243     return SPI_OK;
00244 }
00245 
00246 
00261 int spi_setupChipReg(volatile avr32_spi_t *spi,
00262         struct spi_options_t *options,
00263         unsigned int cpuHz)
00264 {
00265     int baudDiv = -1;
00266     unsigned long csr = 0;
00267 
00268     if (options->bits > 16 || options->bits < 8 || options->stay_act > 1) {
00269         return SPI_ERROR_ARGUMENT;
00270     }
00271 
00272     baudDiv = getBaudDiv(options, cpuHz);
00273 
00274     if (baudDiv < 0) {
00275         return -baudDiv;
00276     }
00277 
00278     /* Will use CSR0 offsets; these are the same for CSR0 - CSR3 */
00279     csr = ((options->bits - 8)<<AVR32_SPI_CSR0_BITS_OFFSET)|
00280         (baudDiv<<AVR32_SPI_CSR0_SCBR_OFFSET)|
00281         (options->spck_delay<<AVR32_SPI_CSR0_DLYBS_OFFSET)|
00282         (options->trans_delay<<AVR32_SPI_CSR0_DLYBCT_OFFSET)|
00283         (options->stay_act<<AVR32_SPI_CSR0_CSAAT_OFFSET);
00284 
00285     switch (options->spi_mode) {
00286         case 0:
00287             csr |= (1<<AVR32_SPI_CSR0_NCPHA_OFFSET);
00288         case 1:
00289             break;
00290         case 2:
00291             csr |= (1<<AVR32_SPI_CSR0_NCPHA_OFFSET);
00292         case 3:
00293             csr |= (1<<AVR32_SPI_CSR0_CPOL_OFFSET);
00294             break;
00295         default: /* Not in legal range */
00296             return SPI_ERROR_ARGUMENT;
00297     }
00298 
00299     switch (options->reg) {
00300         case 0:
00301             spi->csr0 = csr;
00302             break;
00303         case 1:
00304             spi->csr1 = csr;
00305             break;
00306         case 2:
00307             spi->csr2 = csr;
00308             break;
00309         case 3:
00310             spi->csr3 = csr;
00311             break;
00312         default:
00313             return SPI_ERROR_ARGUMENT;
00314     }
00315 
00316     return SPI_OK;
00317 }
00318 
00319 
00326 void spi_enable(volatile avr32_spi_t *spi)
00327 {
00328     spi->cr = AVR32_SPI_CR_SPIEN_MASK;
00329 }
00330 
00331 
00339 void spi_disable(volatile avr32_spi_t *spi)
00340 {
00341     spi->cr = AVR32_SPI_CR_SPIDIS_MASK;
00342 }
00343 
00344 
00355 int spi_write(volatile avr32_spi_t *spi, unsigned short data)
00356 {
00357     unsigned int timeout = SPI_TIMEOUT;
00358 
00359     while ((spi->sr & AVR32_SPI_SR_TXEMPTY_MASK) == 0 && timeout > 0) {
00360         --timeout;
00361     }
00362 
00363     if (timeout == 0) {
00364         return SPI_ERROR_TIMEOUT;
00365     }
00366 
00367     spi->tdr = data & 0x0000FFFF;
00368 
00369     return SPI_OK;
00370 }
00371 
00372 
00390 int spi_variableSlaveWrite(volatile avr32_spi_t *spi, unsigned short data,
00391         unsigned char pcs, unsigned char lastxfer)
00392 {
00393     unsigned int timeout = SPI_TIMEOUT;
00394 
00395     if (pcs > 14 || lastxfer > 1)
00396         return SPI_ERROR_ARGUMENT;
00397 
00398     while ((spi->sr & AVR32_SPI_SR_TXEMPTY_MASK) == 0 && --timeout) {
00399     }
00400 
00401     if (timeout == 0) {
00402         return SPI_ERROR_TIMEOUT;
00403     }
00404 
00405     spi->tdr = (data << AVR32_SPI_TDR_TD_OFFSET) |
00406         (pcs << AVR32_SPI_TDR_PCS_OFFSET) |
00407         (lastxfer << AVR32_SPI_TDR_LASTXFER_OFFSET);
00408 
00409     return SPI_OK;
00410 }
00411 
00420 unsigned char spi_readRegisterFullCheck(volatile avr32_spi_t * spi)
00421 {
00422     if ((spi->sr & AVR32_SPI_SR_RDRF_MASK) != 0) {
00423         return 1;
00424     } else {
00425         return 0;
00426     }
00427 }
00428 
00429 
00440 int spi_read(volatile avr32_spi_t *spi, unsigned short *data)
00441 {
00442     unsigned int timeout = SPI_TIMEOUT;
00443 
00444     do {
00445         --timeout;
00446     } while ((spi->sr & AVR32_SPI_SR_RDRF_MASK) == 0 && timeout > 0);
00447 
00448     if (timeout == 0) {
00449         return SPI_ERROR_TIMEOUT;
00450     }
00451 
00452     *data = spi->rdr & 0x0000FFFF;
00453 
00454     return SPI_OK;
00455 }
00456 
00457 
00458 #ifdef SPI_ENABLE_PDC
00459 
00463 void spi_disablePDC(volatile avr32_spi_t * spi)
00464 {
00465     volatile spi_pdc_t *pdc = (volatile spi_pdc_t *)spi;
00466     pdc->ptcr |= (1<<1); /* Disable RXT */
00467     pdc->ptcr |= (1<<9); /* Disable TXT */
00468 }
00469 
00470 
00475 void spi_enablePDC(volatile avr32_spi_t * spi)
00476 {
00477     volatile spi_pdc_t *pdc = (volatile spi_pdc_t *)spi;
00478     pdc->ptcr |= (1<<0); /* Enable RXT */
00479     pdc->ptcr |= (1<<8); /* Enable TXT */
00480 }
00481 
00482 
00497 int spi_setRxBuf(volatile avr32_spi_t * spi,
00498         void * rp,
00499         unsigned short rc,
00500         void * rnp,
00501         unsigned short rnc)
00502 {
00503     volatile spi_pdc_t *pdc = (volatile spi_pdc_t *)spi;
00504 
00505     /* Disable RX Transfer */
00506     pdc->ptcr |= (1<<1);
00507 
00508     if (rnp != 0) {
00509         pdc->rnpr = (long) rnp;
00510         pdc->rncr = rnc;
00511     } else {
00512         return SPI_ERROR_ARGUMENT;
00513     }
00514 
00515     if (rp != 0) {
00516         pdc->rpr = (long) rp;
00517         pdc->rcr = rc;
00518     } else {
00519         return SPI_ERROR_ARGUMENT;
00520     }
00521 
00522     /* Enable RX Transfer */
00523     pdc->ptcr |= (1<<0);
00524 
00525     return SPI_OK;
00526 }
00527 
00528 
00543 int spi_setTxBuf(volatile avr32_spi_t * spi,
00544         void * tp,
00545         unsigned short tc,
00546         void * tnp,
00547         unsigned short tnc)
00548 {
00549     volatile spi_pdc_t *pdc = (volatile spi_pdc_t *)spi;
00550 
00551     /* Disable TX Transfer */
00552     pdc->ptcr |= (1<<9);
00553 
00554     if (tnp != 0) {
00555         pdc->tnpr = (long) tnp;
00556         pdc->tncr = tnc;
00557     } else {
00558         return SPI_ERROR_ARGUMENT;
00559     }
00560 
00561     if (tp != 0) {
00562         pdc->tpr = (long) tp;
00563         pdc->tcr = tc;
00564     } else {
00565         return SPI_ERROR_ARGUMENT;
00566     }
00567 
00568     /* Enable TX Transfer */
00569     pdc->ptcr |= (1<<8);
00570 
00571     return SPI_OK;
00572 }
00573 
00574 
00581 unsigned short spi_getRcr(volatile avr32_spi_t * spi)
00582 {
00583     volatile spi_pdc_t *pdc = (volatile spi_pdc_t *)spi;
00584     return pdc->rcr;
00585 }
00586 
00587 
00594 unsigned short spi_getTcr(volatile avr32_spi_t * spi)
00595 {
00596     volatile spi_pdc_t *pdc = (volatile spi_pdc_t *)spi;
00597     return pdc->tcr;
00598 }
00599 #endif /* SPI_ENABLE_PDC */
00600 
00601 
00614 unsigned char spi_getStatus(volatile avr32_spi_t *spi)
00615 {
00616     unsigned char ret = 0;
00617 
00618     if ((spi->sr & AVR32_SPI_SR_OVRES_MASK) != 0) {
00619         ret = SPI_ERROR_OVERRUN;
00620     }
00621 
00622     if ((spi->sr & AVR32_SPI_SR_MODF_MASK) != 0) {
00623         ret += SPI_ERROR_MODE_FAULT;
00624     }
00625 
00626     if (ret == (SPI_ERROR_OVERRUN + SPI_ERROR_MODE_FAULT)) {
00627         return SPI_ERROR_OVERRUN_AND_MODE_FAULT;
00628     }
00629     else if (ret > 0) {
00630         return ret;
00631     } else {
00632         return SPI_OK;
00633     }
00634 }
00635 
00636 
00646 int getBaudDiv(struct spi_options_t * options, int cpuHz) {
00647     int baudDiv = 0;
00648 
00649     if (options->fdiv == 0) {
00650         baudDiv = cpuHz / (options->baudrate);
00651     } else {
00652         baudDiv = cpuHz / (32 * options->baudrate);
00653     }
00654 
00655     if (baudDiv > (AVR32_SPI_CSR0_SCBR_MASK<<AVR32_SPI_CSR0_SCBR_OFFSET)
00656             || baudDiv <= 0) {
00657         return -SPI_ERROR_ARGUMENT;
00658     }
00659 
00660     return baudDiv;
00661 }
00662 

Generated on Mon May 21 20:10:39 2007 for AVR32105 - Master and Slave SPI driver by  doxygen 1.5.1