- Main Page
- Data Structures
- Files

# spi_at32ap7000.c

Go to the documentation of this file.

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