#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 ARRAY_SIZE | ( | a | ) | sizeof(a) / sizeof(a[0]) |
Definition at line 74 of file avr32_spi.c.
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 }