- Main Page
- Data Structures
- Files

# spi_example.c

Go to the documentation of this file.

    00001 /*This file has been prepared for Doxygen automatic documentation generation.*/
    00024 /* Copyright (C) 2006-2008, Atmel Corporation All rights reserved.
    00025  *
    00026  * Redistribution and use in source and binary forms, with or without
    00027  * modification, are permitted provided that the following conditions are met:
    00028  *
    00029  * 1. Redistributions of source code must retain the above copyright notice,
    00030  * this list of conditions and the following disclaimer.
    00031  *
    00032  * 2. Redistributions in binary form must reproduce the above copyright notice,
    00033  * this list of conditions and the following disclaimer in the documentation
    00034  * and/or other materials provided with the distribution.
    00035  *
    00036  * 3. The name of ATMEL may not be used to endorse or promote products derived
    00037  * from this software without specific prior written permission.
    00038  *
    00039  * THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED
    00040  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
    00041  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND
    00042  * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
    00043  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
    00044  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
    00045  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    00046  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    00047  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    00048  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    00049  */
    00050
    00146 #ifdef __GNUC__
    00147 #include <avr32/io.h>
    00148 #elif __ICCAVR32__
    00149 #include <avr32/ioap7000.h>
    00150 #else
    00151 #error No known compiler used
    00152 #endif
    00153 #include "spi_at32ap7000.h"
    00154 #include "gpio.h"
    00155
    00156
    00157 /* These defines should be adjusted to match the application */
    00159 #define CPUHZ      20000000
    00160
    00161 #define BUFFERSIZE    64
    00162
    00163 //#define TIMEOUT 150000
    00164 #define TIMEOUT      CPUHZ/200
    00165
    00166 #define SPI_BITS    8
    00167
    00168 #define SPI_SLAVE_SPEED    160000
    00169
    00170 #define SPI_MASTER_SPEED  125000
    00171
    00172 /* This is a work around for the IAR EWAVR32, version 2.10B */
    00173 #ifdef __ICCAVR32__
    00174 #define AVR32_SPI0_MISO_0_PIN              0
    00175 #define AVR32_SPI0_MISO_0_FUNCTION         0
    00176 #define AVR32_SPI0_MOSI_0_PIN              1
    00177 #define AVR32_SPI0_MOSI_0_FUNCTION         0
    00178 #define AVR32_SPI0_NPCS_0_PIN              3
    00179 #define AVR32_SPI0_NPCS_0_FUNCTION         0
    00180 #define AVR32_SPI0_NPCS_1_PIN              4
    00181 #define AVR32_SPI0_NPCS_1_FUNCTION         0
    00182 #define AVR32_SPI0_NPCS_2_PIN              5
    00183 #define AVR32_SPI0_NPCS_2_FUNCTION         0
    00184 #define AVR32_SPI0_NPCS_3_PIN              20
    00185 #define AVR32_SPI0_NPCS_3_FUNCTION         1
    00186 #define AVR32_SPI0_SCK_0_PIN               2
    00187 #define AVR32_SPI0_SCK_0_FUNCTION          0
    00188 #define AVR32_SPI1_MISO_0_PIN              32
    00189 #define AVR32_SPI1_MISO_0_FUNCTION         1
    00190 #define AVR32_SPI1_MOSI_0_PIN              33
    00191 #define AVR32_SPI1_MOSI_0_FUNCTION         1
    00192 #define AVR32_SPI1_NPCS_3_PIN              27
    00193 #define AVR32_SPI1_NPCS_3_FUNCTION         0
    00194 #define AVR32_SPI1_NPCS_0_PIN              34
    00195 #define AVR32_SPI1_NPCS_0_FUNCTION         1
    00196 #define AVR32_SPI1_NPCS_1_PIN              35
    00197 #define AVR32_SPI1_NPCS_1_FUNCTION         1
    00198 #define AVR32_SPI1_NPCS_2_PIN              36
    00199 #define AVR32_SPI1_NPCS_2_FUNCTION         1
    00200 #define AVR32_SPI1_SCK_0_PIN               37
    00201 #define AVR32_SPI1_SCK_0_FUNCTION          1
    00202 #endif
    00203
    00205 typedef unsigned char avr32_piomap_t[][2];
    00206
    00207 void init_spiMaster(volatile avr32_spi_t *spi, long cpuHz);
    00208 void init_spiSlave(volatile avr32_spi_t *spi, long cpuHz);
    00209 void rgb_setColor(volatile avr32_pio_t *pio, unsigned char color);
    00210 void rgb_blinkColor(volatile avr32_pio_t *pio, unsigned char color);
    00211 void spi_masterSend(volatile avr32_spi_t *spi, char *string);
    00212 void spi_slaveReceive_and_compare(volatile avr32_spi_t *spi, char *string);
    00213
    00219 void init_spiMaster(volatile avr32_spi_t *spi, long cpuHz)
    00220 {
    00221   volatile avr32_pio_t *pioc = &AVR32_PIOC;
    00222   spi_options_t spiOptions;
    00223
    00224   spiOptions.reg = 0;
    00225   spiOptions.baudrate = SPI_MASTER_SPEED;
    00226   spiOptions.bits = SPI_BITS;
    00227   spiOptions.spck_delay = 0;
    00228   spiOptions.trans_delay = 4;
    00229   spiOptions.stay_act = 0;
    00230   spiOptions.spi_mode = 1;
    00231   spiOptions.modfdis = 0;
    00232
    00233   /* Initialize as master */
    00234   spi_initMaster(spi, &spiOptions);
    00235
    00236   /* Set master mode; variable_ps, pcs_decode, delay */
    00237   spi_selectionMode(spi, 0, 0, 0);
    00238
    00239   /* Select slave chip 0 (SPI_NPCS0) */
    00240   spi_selectChip(spi, 0);
    00241
    00242   spi_setupChipReg(spi, &spiOptions, cpuHz);
    00243
    00244   spi_enable(spi);
    00245
    00246   pioc->sodr = (1<<AVR32_PIO_P7)|(1<<AVR32_PIO_P0);
    00247   pioc->codr = (1<<AVR32_PIO_P6)|(1<<AVR32_PIO_P1);
    00248   rgb_setColor(pioc, 0);
    00249 }
    00250
    00251
    00257 void init_spiSlave(volatile avr32_spi_t *spi, long cpuHz)
    00258 {
    00259   volatile avr32_pio_t *pioc = &AVR32_PIOC;
    00260
    00261   spi_options_t spiOptions;
    00262
    00263   spiOptions.reg = 0;
    00264   spiOptions.baudrate = SPI_SLAVE_SPEED;
    00265   spiOptions.bits = SPI_BITS;
    00266   spiOptions.spck_delay = 0;
    00267   spiOptions.trans_delay = 4;
    00268   spiOptions.stay_act = 0;
    00269   spiOptions.spi_mode = 1;
    00270   spiOptions.modfdis = 0;
    00271
    00272   /* Initialize as slave; bits, spi_mode */
    00273   spi_initSlave(spi, 8, 1);
    00274
    00275   spi_setupChipReg(spi, &spiOptions, cpuHz);
    00276
    00277   spi_enable(spi);
    00278
    00279   pioc->sodr = (1<<AVR32_PIO_P6)|(1<<AVR32_PIO_P0);
    00280   pioc->codr = (1<<AVR32_PIO_P7)|(1<<AVR32_PIO_P1);
    00281   rgb_setColor(pioc, 0);
    00282 }
    00283
    00284
    00296 void rgb_setColor(volatile avr32_pio_t *pio, unsigned char color)
    00297 {
    00298   pio->codr = 0x00003F00;
    00299
    00300   switch(color) {
    00301     case 0:
    00302       break;
    00303     case 1:
    00304       pio->sodr = 0x00000300;
    00305       break;
    00306     case 2:
    00307       pio->sodr = 0x00000C00;
    00308       break;
    00309     case 3:
    00310       pio->sodr = 0x00003000;
    00311       break;
    00312     case 4:
    00313       pio->sodr = 0x00000F00;
    00314       break;
    00315     case 5:
    00316       pio->sodr = 0x00003F00;
    00317       break;
    00318     default:
    00319       break;
    00320   }
    00321 }
    00322
    00323
    00335 void rgb_blinkColor(volatile avr32_pio_t *pio, unsigned char color)
    00336 {
    00337   volatile int pauseTimer = TIMEOUT/4;
    00338   volatile int pauseRepeat = 10;
    00339
    00340   do{
    00341     do{
    00342       --pauseTimer;
    00343     } while (pauseTimer > 0);
    00344
    00345     pauseTimer = TIMEOUT/4;
    00346
    00347     if ((pauseRepeat % 2) == 1) {
    00348       rgb_setColor(pio, 0);
    00349     } else {
    00350       rgb_setColor(pio, color);
    00351     }
    00352
    00353     --pauseRepeat;
    00354   } while (pauseRepeat > 0);
    00355 }
    00356
    00357
    00363 void spi_masterSend(volatile avr32_spi_t *spi, char *string)
    00364 {
    00365   volatile avr32_pio_t *pioc = &AVR32_PIOC;
    00366   int error;
    00367   char *textStringPtr = string;
    00368
    00369   pioc->codr = (1<<AVR32_PIO_P0);
    00370   pioc->sodr = (1<<AVR32_PIO_P1);
    00371
    00372   do {
    00373     error = spi_write(spi, (unsigned short) *textStringPtr);
    00374   } while (*textStringPtr++ != '\n');
    00375
    00376   pioc->codr = (1<<AVR32_PIO_P1);
    00377   pioc->sodr = (1<<AVR32_PIO_P0);
    00378
    00379   if (error != SPI_OK) {
    00380   }
    00381 }
    00382
    00383
    00390 void spi_slaveReceiveAndCompare(volatile avr32_spi_t *spi, char *string)
    00391 {
    00392   int error = 0;
    00393   int index = 0;
    00394   int receivedChars = 0;
    00395   char *textStringPtr = string;
    00396   unsigned short receiveBuffer[BUFFERSIZE];
    00397   volatile avr32_pio_t *pioc = &AVR32_PIOC;
    00398
    00399   pioc->sodr = AVR32_PIO_P1_MASK|AVR32_PIO_P3_MASK;
    00400   rgb_setColor(pioc, 4);
    00401
    00402   do {
    00403     int errVal = SPI_OK;
    00404
    00405     errVal = spi_read(spi, &receiveBuffer[index]);
    00406
    00407     if (errVal == SPI_OK) {
    00408       ++index;
    00409       ++receivedChars;
    00410     }
    00411
    00412     /* break on buffer overflow */
    00413     if (receivedChars > BUFFERSIZE) {
    00414       error = BUFFERSIZE + 1;
    00415       break;
    00416     }
    00417
    00418   } while (receiveBuffer[index - 1] != '\n');
    00419
    00420   index = 0;
    00421   pioc->codr = AVR32_PIO_P1_MASK;
    00422   rgb_blinkColor(pioc, 4);
    00423
    00424   /* compare received buffer with expected text string */
    00425   do {
    00426     if ((receiveBuffer[index++] & 0x00FF)
    00427         != ((*textStringPtr++) & 0x00FF)) {
    00428       ++error;
    00429     }
    00430   } while (*textStringPtr != '\n');
    00431
    00432   /* print result on RGB LEDs
    00433    * error > BUFFERSIZE - buffer overflow
    00434    * error > 0 - string mismatch
    00435    * error = 0 - no error
    00436    */
    00437   if (error > BUFFERSIZE) {
    00438     rgb_blinkColor(pioc, 1);
    00439     rgb_setColor(pioc, 1);
    00440   }
    00441   else if (error > 0) {
    00442     rgb_setColor(pioc, 1);
    00443   } else {
    00444     rgb_setColor(pioc, 2);
    00445   }
    00446
    00447   pioc->codr = (1<<AVR32_PIO_P3);
    00448 }
    00449
    00450
    00455 int main(void)
    00456 {
    00457   volatile avr32_pio_t *pioa = &AVR32_PIOA;
    00458   volatile avr32_pio_t *piob = &AVR32_PIOB;
    00459   volatile avr32_pio_t *pioc = &AVR32_PIOC;
    00460   volatile avr32_spi_t *spi = &AVR32_SPI0;
    00461   char masterMode = 0;
    00462
    00463   gpio_map_t spi_piomap = {          \
    00464     {AVR32_SPI0_SCK_0_PIN, AVR32_SPI0_SCK_0_FUNCTION},  \
    00465     {AVR32_SPI0_MISO_0_PIN, AVR32_SPI0_MISO_0_FUNCTION},  \
    00466     {AVR32_SPI0_MOSI_0_PIN, AVR32_SPI0_MOSI_0_FUNCTION},  \
    00467     {AVR32_SPI0_NPCS_0_PIN, AVR32_SPI0_NPCS_0_FUNCTION},  \
    00468     {AVR32_SPI0_NPCS_1_PIN, AVR32_SPI0_NPCS_1_FUNCTION},  \
    00469     {AVR32_SPI0_NPCS_2_PIN, AVR32_SPI0_NPCS_2_FUNCTION},  \
    00470     {AVR32_SPI0_NPCS_3_PIN, AVR32_SPI0_NPCS_3_FUNCTION},  \
    00471   };
    00472
    00473   /* Disable all interrupts on PIO */
    00474   pioa->idr = 0xFFFFffff;
    00475   piob->idr = 0xFFFFffff;
    00476   pioc->idr = 0xFFFFffff;
    00477
    00478   /* Enable PIO on PIOB and clear all bits
    00479    * This is used for status information on LEDS and signals from switches
    00480    *
    00481    * LED0 - system is on and ready
    00482    * LED1 - system is receiving/sending data on SPI
    00483    * LED3 - system is comparing received data from SPI with expected data
    00484    * LED6 - system is in slave mode
    00485    * LED7 - system is in master mode
    00486    *
    00487    * PIOB: P0 to P7 is used for switches
    00488    * PIOC: P0 to P7 is used for LEDs
    00489    * PIOC: P8 to P13 is used for RGB LEDs
    00490    */
    00491   piob->per = 0x000000FF;
    00492   piob->odr = 0x000000FF;
    00493   piob->puer = 0x000000FF;
    00494
    00495   pioc->per = 0x0000FFFF;
    00496   pioc->oer = 0x0000FFFF;
    00497   pioc->ower = 0x0000FFFF;
    00498   pioc->codr = 0x0000FFFF;
    00499
    00500   /* Init PIO */
    00501   gpio_enable_module(spi_piomap, 7);
    00502
    00503   pioc->codr = 0x000000FF;
    00504   pioc->sodr = 0x000000AA;
    00505   rgb_setColor(pioc, 1);
    00506
    00507   int buttonTimer = 0;
    00508   char *textString = "Atmel AVR32 SPI test application\r\n";
    00509   char *textStringAlt = "AVR32 SPI Atmel test application\r\n";
    00510   char *textStringToLong = "This string is far to long to be used " \
    00511       "in Atmel AVR32 SPI test application\r\n";
    00512
    00513   rgb_setColor(pioc, 0);
    00514   init_spiSlave(spi, CPUHZ);
    00515
    00516   for (;;) {
    00517     /* SW7 is used to switch between master and slave mode */
    00518     if ((piob->pdsr & AVR32_PIO_P7_MASK) == 0
    00519         && buttonTimer <= 0) {
    00520       buttonTimer = TIMEOUT;
    00521
    00522       if (masterMode == 1) {
    00523         init_spiSlave(spi, CPUHZ);
    00524         masterMode = 0;
    00525       } else {
    00526         init_spiMaster(spi, CPUHZ);
    00527         masterMode = 1;
    00528       }
    00529     }
    00530
    00531     /* Actions for master mode
    00532      * SW5 sends "Atmel AVR32 SPI test application\r\n" on SPI
    00533      * SW4 sends "AVR32 SPI Atmel test application\r\n" on SPI
    00534      * SW3 sends "This string is far to long to be used in Atmel AVR32 SPI test application\r\n"
    00535      */
    00536     if (masterMode == 1) {
    00537       if ((piob->pdsr & AVR32_PIO_P5_MASK) == 0
    00538             && buttonTimer <= 0) {
    00539         buttonTimer = TIMEOUT;
    00540         spi_masterSend(spi, textString);
    00541       } else if ((piob->pdsr & AVR32_PIO_P4_MASK) == 0
    00542           && buttonTimer <= 0) {
    00543         buttonTimer = TIMEOUT;
    00544         spi_masterSend(spi, textStringAlt);
    00545       } else if ((piob->pdsr & AVR32_PIO_P3_MASK) == 0
    00546             && buttonTimer <= 0) {
    00547         buttonTimer = TIMEOUT;
    00548         spi_masterSend(spi, textStringToLong);
    00549       }
    00550
    00551     /* Slave mode polls if there is an incoming message on SPI */
    00552     } else {
    00553       if (spi_readRegisterFullCheck(spi) == 1) {
    00554         spi_slaveReceiveAndCompare(spi, textString);
    00555       }
    00556     }
    00557
    00558     if (buttonTimer > 0) {
    00559       --buttonTimer;
    00560     }
    00561   }
    00562 }