avr32_spi.c File Reference

#include <gpio.h>
#include <intc.h>
#include <avr32/io.h>
#include <compiler.h>
#include <string.h>
#include <board.h>
#include "printf-stdarg.h"
#include "platform_spi.h"

Go to the source code of this file.

Defines

#define ARRAY_SIZE(a)   sizeof(a) / sizeof(a[0])

Functions

void avr32_irq_handler (void)
static void dma_txrx (const U8 *in, U8 *out, U16 len)
static void fifo_txrx (const U8 *in, U8 *out, U16 len)
void platform_init (U8 *flags)
void platform_reset (void)
void platform_spi_cs (U8 enable)
void platform_spi_irq (U8 enable)
void platform_txrx (const U8 *in, U8 *out, U16 len)


Define Documentation

#define ARRAY_SIZE (  )     sizeof(a) / sizeof(a[0])

Definition at line 74 of file avr32_spi.c.


Function Documentation

void avr32_irq_handler ( void   ) 

Definition at line 343 of file avr32_spi.c.

References spi_irq_handler(), and SPI_IRQ_RX.

00344 {
00345     uint8_t irq_status = 0;
00346 #ifndef WITH_NO_DMA
00347     volatile avr32_pdca_channel_t *pdca_tx = &AVR32_PDCA.channel[0];
00348     volatile avr32_pdca_channel_t *pdca_rx = &AVR32_PDCA.channel[1];
00349 #endif
00350 
00351         if (gpio_get_pin_interrupt_flag(GPIO_IRQ_PIN)) {
00352         gpio_clear_pin_interrupt_flag(GPIO_IRQ_PIN);
00353         irq_status |= SPI_IRQ_RX;
00354     }
00355 #ifndef WITH_NO_DMA
00356         
00357         /* tx xfer complete */
00358     if (pdca_tx->IMR.trc && pdca_tx->ISR.trc) {
00359                 pdca_tx->IDR.trc = 1;
00360                 pdca_tx->CR.tdis = 1;  /* disable tx xfer */
00361     }
00362 
00363         /* rx xfer complete */
00364     if (pdca_rx->IMR.trc && pdca_rx->ISR.trc) {
00365                 pdca_rx->IDR.trc = 1;
00366                 pdca_rx->CR.tdis = 1;  /* disable rx xfer */
00367     }
00368 
00369 #if 0
00370         /* tx and rx complete */
00371         if (pdca_tx->ISR.trc && pdca_rx->ISR.trc)
00372                 irq_status |= SPI_IRQ_XFER_COMPLETE;
00373 #endif
00374                 
00375 #endif
00376     if (irq_status)
00377         spi_irq_handler(irq_status);
00378 }

static void dma_txrx ( const U8 *  in,
U8 *  out,
U16  len 
) [static]

Definition at line 205 of file avr32_spi.c.

Referenced by platform_txrx().

00206 {
00207     volatile avr32_pdca_channel_t *pdca_tx = &AVR32_PDCA.channel[0];
00208     volatile avr32_pdca_channel_t *pdca_rx = &AVR32_PDCA.channel[1];
00209         
00210         /* setup tx */
00211         pdca_tx->mar = (U32) in;
00212         pdca_tx->PSR.pid = AVR32_PDCA_PID_TX;
00213     pdca_tx->tcr = len / 2;
00214     pdca_tx->MR.size = 1; /* 2-byte */
00215         pdca_tx->IER.trc = 1;
00216 
00217         /* setup rx */
00218         pdca_rx->mar = (U32) out;
00219     pdca_rx->PSR.pid = AVR32_PDCA_PID_RX;
00220     pdca_rx->tcr = len / 2;
00221     pdca_rx->MR.size = 1; /* 2-byte */
00222         pdca_rx->IER.trc = 1;
00223 
00224         /* start dma's. for some reason rx must be started prior to tx */
00225     pdca_rx->CR.ten = 1;
00226     pdca_tx->CR.ten = 1;
00227 
00228         /* blocking wait until transfer is completed */
00229         while (!(pdca_tx->ISR.trc && pdca_rx->ISR.trc));
00230 }

static void fifo_txrx ( const U8 *  in,
U8 *  out,
U16  len 
) [static]

Definition at line 237 of file avr32_spi.c.

Referenced by platform_txrx().

00238 {
00239         volatile avr32_spi_t *spi = &AVR32_SPI;
00240         UnionCPtr in_ptr;
00241         UnionPtr out_ptr;
00242         U32 sr;
00243 
00244         Assert(len);
00245 
00246         in_ptr.u8ptr = in;
00247         out_ptr.u8ptr = out;
00248 
00249         while (len) {
00250                 U16 rdr;
00251         union {
00252             avr32_spi_tdr_t TDR;
00253             U32 tdr;
00254         } reg = { { 0 } };
00255                 
00256                 while (!spi->SR.tdre);
00257                 while (!spi->SR.txempty);
00258 
00259         /* prepare tx data register contents */
00260                 if (in_ptr.u8ptr) {
00261                         reg.TDR.td |= (in_ptr.u8ptr[0] << 8) | in_ptr.u8ptr[1];
00262                         in_ptr.u16ptr++;
00263                 }
00264                 else
00265                         reg.TDR.td |= 0xffff;
00266                 
00267         /* perform tx */
00268                 spi->tdr = reg.tdr;
00269 
00270         /* wait until rx is ready */
00271                 while (!spi->SR.rdrf);
00272 
00273         /* fetch rx data */
00274                 rdr = spi->RDR.rd;
00275                 if (out_ptr.u8ptr) {
00276                         out_ptr.u8ptr[0] = (rdr >> 8) & 0xff;
00277                         out_ptr.u8ptr[1] = rdr & 0xff;
00278                         out_ptr.u16ptr++;
00279                 }
00280                 
00281         /* adjust remaining length. handle the case where len is not 
00282          * a multiple of 2 bytes.
00283          */
00284                 if (len >= 2)
00285                         len -= 2;
00286                 else
00287                         len = 0;
00288         }
00289         
00290         sr = spi->sr;
00291         Assert(!(sr & AVR32_SPI_SR_OVRES_MASK));
00292         Assert(!(sr & AVR32_SPI_SR_MODF_MASK));
00293 }

void platform_init ( U8 *  flags  ) 

Definition at line 78 of file avr32_spi.c.

References ARRAY_SIZE, avr32_irq_handler(), and SPI_FLAG_POLL.

00079 {
00080 #ifdef _ASSERT_ENABLE_ /* To silence warning if Assert() macro is empty */
00081         volatile avr32_pm_t *pm = &AVR32_PM;
00082 #endif
00083     const gpio_map_t GPIO_MAP = {
00084 
00085                 /* EVK1100 pin configuration */
00086 #if BOARD == EVK1100
00087                 { AVR32_SPI1_NPCS_0_0_PIN, AVR32_SPI1_NPCS_0_0_FUNCTION },
00088         { AVR32_SPI1_NPCS_1_0_PIN, AVR32_SPI1_NPCS_1_0_FUNCTION },
00089         { AVR32_SPI1_MISO_0_0_PIN, AVR32_SPI1_MISO_0_0_FUNCTION },
00090         { AVR32_SPI1_MOSI_0_0_PIN, AVR32_SPI1_MOSI_0_0_FUNCTION },
00091         { AVR32_SPI1_SCK_0_0_PIN, AVR32_SPI1_SCK_0_0_FUNCTION },
00092 
00093                 /* EVK1101 pin configuration */
00094 #elif BOARD == EVK1101
00095                 { AVR32_SPI_NPCS_0_0_PIN, AVR32_SPI_NPCS_0_0_FUNCTION },
00096         { AVR32_SPI_NPCS_1_0_PIN, AVR32_SPI_NPCS_1_0_FUNCTION },
00097         { AVR32_SPI_MISO_0_0_PIN, AVR32_SPI_MISO_0_0_FUNCTION },
00098         { AVR32_SPI_MOSI_0_0_PIN, AVR32_SPI_MOSI_0_0_FUNCTION },
00099         { AVR32_SPI_SCK_0_0_PIN, AVR32_SPI_SCK_0_0_FUNCTION },
00100 
00101                 /* EVK1105 pin configuration */
00102 #elif BOARD == EVK1105
00103                 { AVR32_SPI0_NPCS_0_0_PIN, AVR32_SPI0_NPCS_0_0_FUNCTION },
00104 #if SPI_CS == 1
00105         { AVR32_SPI0_NPCS_1_0_PIN, AVR32_SPI0_NPCS_1_0_FUNCTION },
00106 #elif SPI_CS == 2
00107                 { AVR32_SPI0_NPCS_2_0_PIN, AVR32_SPI0_NPCS_2_0_FUNCTION },
00108 #endif
00109         { AVR32_SPI0_MISO_0_0_PIN, AVR32_SPI0_MISO_0_0_FUNCTION },
00110         { AVR32_SPI0_MOSI_0_0_PIN, AVR32_SPI0_MOSI_0_0_FUNCTION },
00111         { AVR32_SPI0_SCK_0_0_PIN, AVR32_SPI0_SCK_0_0_FUNCTION },
00112 #else
00113 #error
00114 #endif
00115     };
00116         U32 i;
00117         
00118 #ifndef WITH_NO_DMA
00119     volatile avr32_pdca_channel_t *pdca_tx = &AVR32_PDCA.channel[0];
00120     volatile avr32_pdca_channel_t *pdca_rx = &AVR32_PDCA.channel[1];
00121 #endif
00122         
00123 #ifdef USE_POLL
00124         *flags = SPI_FLAG_POLL;
00125 #else
00126         *flags = 0;
00127 #endif
00128 
00129         gpio_enable_module(GPIO_MAP, ARRAY_SIZE(GPIO_MAP));
00130 
00131         for (i = 0; i < ARRAY_SIZE(GPIO_MAP); i++)
00132                 gpio_enable_pin_pull_up(GPIO_MAP[i].pin);
00133 
00134         /* input, irq */
00135         gpio_enable_gpio_pin(GPIO_IRQ_PIN);
00136         gpio_enable_pin_pull_up(GPIO_IRQ_PIN);
00137 
00138         /* Note: SPI0 clock enabled at reset in pm->pbamask (see 13.6.3) */
00139         Assert(pm->pbamask & (1 << 5));
00140 
00141         /* Note: GPIO clock enabled at reset in pm->pbamask (see 13.6.3) */
00142         Assert(pm->pbamask & (1 << 1));
00143 
00144         /* 22.4.7: "In every port there are four interrupt lines
00145          * connected to the interrupt controller. Every eigth
00146          * interrupts in the port are ored together to form an
00147          * interrupt line."
00148          *
00149          * GPIO_IRQ_# = (GPIO_IRQ_PIN / 32) * 4 + (GPIO_IRQ_PIN / 8) % 4
00150          * 62 => 1 * 4 + 3 = 7
00151          */
00152         INTC_register_interrupt(&avr32_irq_handler, GPIO_IRQ, AVR32_INTC_INT0);
00153 
00154 #ifndef WITH_NO_DMA
00155         INTC_register_interrupt(&avr32_irq_handler, AVR32_PDCA_IRQ_0,
00156                                 AVR32_INTC_INT0);
00157         INTC_register_interrupt(&avr32_irq_handler, AVR32_PDCA_IRQ_1,
00158                                 AVR32_INTC_INT0);
00159         pdca_tx->IER.terr = 1;
00160         pdca_rx->IER.terr = 1;
00161 #endif
00162 }

void platform_reset ( void   ) 

Definition at line 164 of file avr32_spi.c.

00165 {
00166         volatile avr32_spi_t *spi = &AVR32_SPI;
00167 #if SPI_CS == 1
00168         volatile avr32_spi_csr1_t* CSR = &spi->CSR1;
00169 #elif SPI_CS == 2
00170         volatile avr32_spi_csr2_t* CSR = &spi->CSR2;
00171 #endif
00172         
00173         /* Disable SPI controller during configuration */
00174         spi->CR.spidis = 1;
00175 
00176         /* SPI master mode */
00177         spi->MR.mstr = 1;
00178 
00179         /* fixed peripheral select */
00180         spi->MR.ps = 0;
00181 #if SPI_CS == 2
00182         spi->MR.pcs = 0x3; /* cs2 */
00183 #elif SPI_CS == 1
00184         spi->MR.pcs = 0x1; /* cs1 */
00185 #endif
00186 
00187         CSR->scbr = 2;
00188 
00189         /* Use max width of TDR register, 16 bit transfers */
00190     CSR->bits = 0x8; 
00191 
00192         /* Make sure that we can hold CS low until transfer is completed, e.g
00193          * LASTXFER is set in TDR.
00194          */
00195         CSR->csaat = 1;
00196 
00197         /* NRG component requires clock polarity high */
00198         CSR->cpol = 1;
00199 
00200         /* Enable SPI controller */
00201         spi->CR.spien = 1;
00202 }

void platform_spi_cs ( U8  enable  ) 

Definition at line 329 of file avr32_spi.c.

00330 {
00331     volatile avr32_spi_t *spi = &AVR32_SPI; 
00332         
00333     if (enable) 
00334 #if SPI_CS == 2 
00335             spi->MR.pcs = 0x3; /* cs2 */ 
00336 #elif SPI_CS == 1 
00337                 spi->MR.pcs = 0x1; /* cs1 */ 
00338 #endif 
00339     else 
00340         spi->MR.pcs = 0xf; 
00341 } 

void platform_spi_irq ( U8  enable  ) 

Definition at line 317 of file avr32_spi.c.

00318 {
00319 #ifdef USE_POLL
00320         return;
00321 #endif
00322 
00323         if (enable)
00324                 gpio_enable_pin_interrupt(GPIO_IRQ_PIN, GPIO_PIN_CHANGE);
00325         else
00326                 gpio_disable_pin_interrupt(GPIO_IRQ_PIN);
00327 }

void platform_txrx ( const U8 *  in,
U8 *  out,
U16  len 
)

Definition at line 295 of file avr32_spi.c.

References dma_txrx(), fifo_txrx(), and MAX_BLOCK_LEN.

00296 {
00297 #ifndef WITH_NO_DMA
00298         static uint8_t buf[MAX_BLOCK_LEN];
00299 
00300         /* unaligned data or odd number of bytes, then skip dma */
00301         if ((U32) in % 4 || (U32) out % 4 || len % 2) {
00302                 fifo_txrx(in, out, len);
00303         } else {
00304                 if (in == NULL) {
00305                         memset(buf, 0xff, len);
00306                         in = buf;
00307                 } else if (out == NULL) {
00308                         out = buf;
00309                 }
00310                 dma_txrx(in, out, len);
00311         }
00312 #else
00313         fifo_txrx(in, out, len);
00314 #endif        
00315 }


Generated on Fri Feb 19 02:24:07 2010 for AVR32 - H&D by  doxygen 1.5.5