spi_example.c

Go to the documentation of this file.
00001 /*This file has been prepared for Doxygen automatic documentation generation.*/
00026 /* Copyright (c) 2006, Atmel Corporation All rights reserved.
00027  *
00028  * Redistribution and use in source and binary forms, with or without
00029  * modification, are permitted provided that the following conditions are met:
00030  *
00031  * 1. Redistributions of source code must retain the above copyright notice,
00032  * this list of conditions and the following disclaimer.
00033  *
00034  * 2. Redistributions in binary form must reproduce the above copyright notice,
00035  * this list of conditions and the following disclaimer in the documentation
00036  * and/or other materials provided with the distribution.
00037  *
00038  * 3. The name of ATMEL may not be used to endorse or promote products derived
00039  * from this software without specific prior written permission.
00040  *
00041  * THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED
00042  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00043  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND
00044  * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
00045  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00046  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00047  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00048  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00049  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00050  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00051  */
00052 
00053 #ifdef __GNUC__
00054 #include <avr32/io.h>
00055 #elif __ICCAVR32__
00056 #include <avr32/ioap7000.h>
00057 #else
00058 #error No known compiler used
00059 #endif
00060 #include "settings.h"
00061 #include "spi.h"
00062 
00063 /* This is a work around for the IAR EWAVR32, version 2.10B */
00064 #ifdef __ICCAVR32__
00065 #if __PART__ == __AP7000__
00066 #define AVR32_SPI0_MISO_0_PIN              0
00067 #define AVR32_SPI0_MISO_0_FUNCTION         0
00068 #define AVR32_SPI0_MOSI_0_PIN              1
00069 #define AVR32_SPI0_MOSI_0_FUNCTION         0
00070 #define AVR32_SPI0_NPCS_0_PIN              3
00071 #define AVR32_SPI0_NPCS_0_FUNCTION         0
00072 #define AVR32_SPI0_NPCS_1_PIN              4
00073 #define AVR32_SPI0_NPCS_1_FUNCTION         0
00074 #define AVR32_SPI0_NPCS_2_PIN              5
00075 #define AVR32_SPI0_NPCS_2_FUNCTION         0
00076 #define AVR32_SPI0_NPCS_3_PIN              20
00077 #define AVR32_SPI0_NPCS_3_FUNCTION         1
00078 #define AVR32_SPI0_SCK_0_PIN               2
00079 #define AVR32_SPI0_SCK_0_FUNCTION          0
00080 #define AVR32_SPI1_MISO_0_PIN              32
00081 #define AVR32_SPI1_MISO_0_FUNCTION         1
00082 #define AVR32_SPI1_MOSI_0_PIN              33
00083 #define AVR32_SPI1_MOSI_0_FUNCTION         1
00084 #define AVR32_SPI1_NPCS_3_PIN              27
00085 #define AVR32_SPI1_NPCS_3_FUNCTION         0
00086 #define AVR32_SPI1_NPCS_0_PIN              34
00087 #define AVR32_SPI1_NPCS_0_FUNCTION         1
00088 #define AVR32_SPI1_NPCS_1_PIN              35
00089 #define AVR32_SPI1_NPCS_1_FUNCTION         1
00090 #define AVR32_SPI1_NPCS_2_PIN              36
00091 #define AVR32_SPI1_NPCS_2_FUNCTION         1
00092 #define AVR32_SPI1_SCK_0_PIN               37
00093 #define AVR32_SPI1_SCK_0_FUNCTION          1
00094 #else
00095 #error No PIO definitions for the IAR compiler and the cpu chosen
00096 #endif
00097 #endif
00098 
00100 typedef unsigned char avr32_piomap_t[][2];
00101 
00102 void init_spiMaster(volatile avr32_spi_t *spi, long cpuHz);
00103 void init_spiSlave(volatile avr32_spi_t *spi, long cpuHz);
00104 void rgb_setColor(volatile avr32_pio_t *pio, unsigned char color);
00105 void rgb_blinkColor(volatile avr32_pio_t *pio, unsigned char color);
00106 void spi_masterSend(volatile avr32_spi_t *spi, char *string);
00107 void spi_slaveReceive_and_compare(volatile avr32_spi_t *spi, char *string);
00108 int pio_enable_module(avr32_piomap_t piomap, unsigned int size);
00109 
00110 
00116 void init_spiMaster(volatile avr32_spi_t *spi, long cpuHz)
00117 {
00118     volatile avr32_pio_t *pioc = &AVR32_PIOC;
00119 
00120     struct spi_options_t spiOptions;
00121 
00122     spiOptions.reg = 0;
00123     spiOptions.baudrate = SPI_MASTER_SPEED;
00124     spiOptions.bits = SPI_BITS;
00125     spiOptions.spck_delay = 0;
00126     spiOptions.trans_delay = 4;
00127     spiOptions.stay_act = 0;
00128     spiOptions.spi_mode = 1;
00129     spiOptions.fdiv = 0;
00130     spiOptions.modfdis = 0;
00131 
00132     /* Initialize as master */
00133     spi_initMaster(spi, &spiOptions);
00134 
00135     /* Set master mode; variable_ps, pcs_decode, delay */
00136     spi_selectionMode(spi, 0, 0, 0);
00137 
00138     /* Select slave chip 0 (SPI_NPCS0) */
00139     spi_selectChip(spi, 0);
00140 
00141     spi_setupChipReg(spi, &spiOptions, cpuHz);
00142 
00143     spi_enable(spi);
00144 
00145     pioc->sodr = (1<<AVR32_PIO_P7)|(1<<AVR32_PIO_P0);
00146     pioc->codr = (1<<AVR32_PIO_P6)|(1<<AVR32_PIO_P1);
00147     rgb_setColor(pioc, 0);
00148 }
00149 
00150 
00156 void init_spiSlave(volatile avr32_spi_t *spi, long cpuHz)
00157 {
00158     volatile avr32_pio_t *pioc = &AVR32_PIOC;
00159 
00160     struct spi_options_t spiOptions;
00161 
00162     spiOptions.reg = 0;
00163     spiOptions.baudrate = SPI_SLAVE_SPEED;
00164     spiOptions.bits = SPI_BITS;
00165     spiOptions.spck_delay = 0;
00166     spiOptions.trans_delay = 4;
00167     spiOptions.stay_act = 0;
00168     spiOptions.spi_mode = 1;
00169     spiOptions.fdiv = 0;
00170     spiOptions.modfdis = 0;
00171 
00172     /* Initialize as slave; bits, spi_mode */
00173     spi_initSlave(spi, 8, 1);
00174 
00175     spi_setupChipReg(spi, &spiOptions, cpuHz);
00176 
00177     spi_enable(spi);
00178 
00179     pioc->sodr = (1<<AVR32_PIO_P6)|(1<<AVR32_PIO_P0);
00180     pioc->codr = (1<<AVR32_PIO_P7)|(1<<AVR32_PIO_P1);
00181     rgb_setColor(pioc, 0);
00182 }
00183 
00184 
00196 void rgb_setColor(volatile avr32_pio_t *pio, unsigned char color)
00197 {
00198     pio->codr = 0x00003F00;
00199 
00200     switch(color) {
00201         case 0:
00202             break;
00203         case 1:
00204             pio->sodr = 0x00000300;
00205             break;
00206         case 2:
00207             pio->sodr = 0x00000C00;
00208             break;
00209         case 3:
00210             pio->sodr = 0x00003000;
00211             break;
00212         case 4:
00213             pio->sodr = 0x00000F00;
00214             break;
00215         case 5:
00216             pio->sodr = 0x00003F00;
00217             break;
00218         default:
00219             break;
00220     }
00221 }
00222 
00223 
00235 void rgb_blinkColor(volatile avr32_pio_t *pio, unsigned char color)
00236 {
00237     volatile int pauseTimer = TIMEOUT/4;
00238     volatile int pauseRepeat = 10;
00239 
00240     do{
00241         do{
00242             --pauseTimer;
00243         } while (pauseTimer > 0);
00244 
00245         pauseTimer = TIMEOUT/4;
00246 
00247         if ((pauseRepeat % 2) == 1) {
00248             rgb_setColor(pio, 0);
00249         } else {
00250             rgb_setColor(pio, color);
00251         }
00252 
00253         --pauseRepeat;
00254     } while (pauseRepeat > 0);
00255 }
00256 
00257 
00263 void spi_masterSend(volatile avr32_spi_t *spi, char *string)
00264 {
00265     volatile avr32_pio_t *pioc = &AVR32_PIOC;
00266     int error;
00267     char *textStringPtr = string;
00268 
00269     pioc->codr = (1<<AVR32_PIO_P0);
00270     pioc->sodr = (1<<AVR32_PIO_P1);
00271 
00272     do {
00273         error = spi_write(spi, (unsigned short) *textStringPtr);
00274     } while (*textStringPtr++ != '\n');
00275 
00276     pioc->codr = (1<<AVR32_PIO_P1);
00277     pioc->sodr = (1<<AVR32_PIO_P0);
00278 
00279     if (error != SPI_OK) {
00280     }
00281 }
00282 
00283 
00290 void spi_slaveReceiveAndCompare(volatile avr32_spi_t *spi, char *string)
00291 {
00292     int error = 0;
00293     int index = 0;
00294     int receivedChars = 0;
00295     char *textStringPtr = string;
00296     unsigned short receiveBuffer[BUFFERSIZE];
00297     volatile avr32_pio_t *pioc = &AVR32_PIOC;
00298 
00299     pioc->sodr = AVR32_PIO_P1_MASK|AVR32_PIO_P3_MASK;
00300     rgb_setColor(pioc, 4);
00301 
00302     do {
00303         int errVal = SPI_OK;
00304 
00305         errVal = spi_read(spi, &receiveBuffer[index]);
00306 
00307         if (errVal == SPI_OK) {
00308             ++index;
00309             ++receivedChars;
00310         }
00311 
00312         /* break on buffer overflow */
00313         if (receivedChars > BUFFERSIZE) {
00314             error = BUFFERSIZE + 1;
00315             break;
00316         }
00317 
00318     } while (receiveBuffer[index - 1] != '\n');
00319 
00320     index = 0;
00321     pioc->codr = AVR32_PIO_P1_MASK;
00322     rgb_blinkColor(pioc, 4);
00323 
00324     /* compare received buffer with expected text string */
00325     do {
00326         if ((receiveBuffer[index++] & 0x00FF)
00327                 != ((*textStringPtr++) & 0x00FF)) {
00328             ++error;
00329         }
00330     } while (*textStringPtr != '\n');
00331 
00332     /* print result on RGB LEDs
00333      * error > BUFFERSIZE - buffer overflow
00334      * error > 0 - string mismatch
00335      * error = 0 - no error
00336      */
00337     if (error > BUFFERSIZE) {
00338         rgb_blinkColor(pioc, 1);
00339         rgb_setColor(pioc, 1);
00340     }
00341     else if (error > 0) {
00342         rgb_setColor(pioc, 1);
00343     } else {
00344         rgb_setColor(pioc, 2);
00345     }
00346 
00347     pioc->codr = (1<<AVR32_PIO_P3);
00348 }
00349 
00350 
00355 int main(void)
00356 {
00357     volatile avr32_pio_t *pioa = &AVR32_PIOA;
00358     volatile avr32_pio_t *piob = &AVR32_PIOB;
00359     volatile avr32_pio_t *pioc = &AVR32_PIOC;
00360     volatile avr32_spi_t *spi = &AVR32_SPI0;
00361     char masterMode = 0;
00362     int retval = SPI_OK;
00363 
00364     avr32_piomap_t spi_piomap = {                   \
00365         {AVR32_SPI0_SCK_0_PIN, AVR32_SPI0_SCK_0_FUNCTION},  \
00366         {AVR32_SPI0_MISO_0_PIN, AVR32_SPI0_MISO_0_FUNCTION},    \
00367         {AVR32_SPI0_MOSI_0_PIN, AVR32_SPI0_MOSI_0_FUNCTION},    \
00368         {AVR32_SPI0_NPCS_0_PIN, AVR32_SPI0_NPCS_0_FUNCTION},    \
00369         {AVR32_SPI0_NPCS_1_PIN, AVR32_SPI0_NPCS_1_FUNCTION},    \
00370         {AVR32_SPI0_NPCS_2_PIN, AVR32_SPI0_NPCS_2_FUNCTION},    \
00371         {AVR32_SPI0_NPCS_3_PIN, AVR32_SPI0_NPCS_3_FUNCTION},    \
00372     };
00373 
00374     /* Disable all interrupts on PIO */
00375     pioa->idr = 0xFFFFffff;
00376     piob->idr = 0xFFFFffff;
00377     pioc->idr = 0xFFFFffff;
00378 
00379     /* Enable PIO on PIOB and clear all bits
00380      * This is used for status information on LEDS and signals from switches
00381      *
00382      * LED0 - system is on and ready
00383      * LED1 - system is receiving/sending data on SPI
00384      * LED3 - system is comparing received data from SPI with expected data
00385      * LED6 - system is in slave mode
00386      * LED7 - system is in master mode
00387      *
00388      * PIOB: P0 to P7 is used for switches
00389      * PIOC: P0 to P7 is used for LEDs
00390      * PIOC: P8 to P13 is used for RGB LEDs
00391      */
00392     piob->per = 0x000000FF;
00393     piob->odr = 0x000000FF;
00394     piob->puer = 0x000000FF;
00395 
00396     pioc->per = 0x0000FFFF;
00397     pioc->oer = 0x0000FFFF;
00398     pioc->ower = 0x0000FFFF;
00399     pioc->codr = 0x0000FFFF;
00400 
00401     /* Init PIO */
00402     retval = pio_enable_module(spi_piomap, 7);
00403 
00404     if (retval != SPI_OK) {
00405         pioc->codr = 0x000000FF;
00406         pioc->sodr = 0x000000AA;
00407         rgb_setColor(pioc, 1);
00408         return -1;
00409     }
00410 
00411     int buttonTimer = 0;
00412     char *textString = "Atmel AVR32 SPI test application\r\n";
00413     char *textStringAlt = "AVR32 SPI Atmel test application\r\n";
00414     char *textStringToLong = "This string is far to long to be used " \
00415             "in Atmel AVR32 SPI test application\r\n";
00416 
00417     rgb_setColor(pioc, 0);
00418     init_spiSlave(spi, CPUHZ);
00419 
00420     for (;;) {
00421         /* SW7 is used to switch between master and slave mode */
00422         if ((piob->pdsr & AVR32_PIO_P7_MASK) == 0
00423                 && buttonTimer <= 0) {
00424             buttonTimer = TIMEOUT;
00425 
00426             if (masterMode == 1) {
00427                 init_spiSlave(spi, CPUHZ);
00428                 masterMode = 0;
00429             } else {
00430                 init_spiMaster(spi, CPUHZ);
00431                 masterMode = 1;
00432             }
00433         }
00434 
00435         /* Actions for master mode
00436          * SW5 sends "Atmel AVR32 SPI test application\r\n" on SPI
00437          * SW4 sends "AVR32 SPI Atmel test application\r\n" on SPI
00438          * SW3 sends "This string is far to long to be used in Atmel AVR32 SPI test application\r\n"
00439          */
00440         if (masterMode == 1) {
00441             if ((piob->pdsr & AVR32_PIO_P5_MASK) == 0
00442                         && buttonTimer <= 0) {
00443                 buttonTimer = TIMEOUT;
00444                 spi_masterSend(spi, textString);
00445             } else if ((piob->pdsr & AVR32_PIO_P4_MASK) == 0
00446                     && buttonTimer <= 0) {
00447                 buttonTimer = TIMEOUT;
00448                 spi_masterSend(spi, textStringAlt);
00449             } else if ((piob->pdsr & AVR32_PIO_P3_MASK) == 0
00450                         && buttonTimer <= 0) {
00451                 buttonTimer = TIMEOUT;
00452                 spi_masterSend(spi, textStringToLong);
00453             }
00454 
00455         /* Slave mode polls if there is an incoming message on SPI */
00456         } else {
00457             if (spi_readRegisterFullCheck(spi) == 1) {
00458                 spi_slaveReceiveAndCompare(spi, textString);
00459             }
00460         }
00461 
00462         if (buttonTimer > 0) {
00463             --buttonTimer;
00464         }
00465     }
00466 }
00467 
00468 
00478 int pio_enable_module(avr32_piomap_t piomap, unsigned int size)
00479 {
00480     int i;
00481     volatile struct avr32_pio_t *pio;
00482 
00483     /* get the base address for the port */
00484     switch(**piomap/32) {
00485 
00486         case 0:
00487             pio = &AVR32_PIOA;
00488             break;
00489         case 1:
00490             pio = &AVR32_PIOB;
00491             break;
00492         case 2:
00493             pio = &AVR32_PIOC;
00494             break;
00495         case 3:
00496             pio = &AVR32_PIOD;
00497             break;
00498         case 4:
00499             pio = &AVR32_PIOE;
00500             break;
00501         default :
00502             return SPI_ERROR_ARGUMENT;
00503 
00504     }
00505 
00506     for (i = 0; i < size; i++) {
00507 
00508         pio->pdr |= (1<<((**piomap) % 32));
00509         pio->pudr |= (1<<((**piomap) % 32));
00510 
00511         switch(*(*piomap+1)) {
00512             case 0:
00513                 pio->asr |= (1<<((**piomap) % 32));
00514                 break;
00515             case 1:
00516                 pio->bsr |= (1<<((**piomap) % 32));
00517                 break;
00518             default:
00519                 return SPI_ERROR_ARGUMENT;
00520         }
00521 
00522         ++piomap;
00523 
00524     }
00525 
00526     return SPI_OK;
00527 }
00528 

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