Go to the documentation of this file.00001
00045 #include <cfg/spi.h>
00046
00047 #include <sys/timer.h>
00048 #include <sys/nutdebug.h>
00049
00050 #include <stdlib.h>
00051 #include <memdebug.h>
00052
00053 #include <dev/spibus_avr32.h>
00054
00055 #include <avr32/io.h>
00056
00057 #if defined(SPIBUS0_DOUBLE_BUFFER) || defined(SPIBUS1_DOUBLE_BUFFER)
00058 #warning Double buffered SPI not tested for AVR32 targets.
00059
00062 static void Avr32SpiInterrupt(void *arg)
00063 {
00064 NutEventPostFromIrq((void **) arg);
00065 }
00066 #endif
00067
00075 int Avr32SpiSetup(NUTSPINODE * node)
00076 {
00077 uint32_t clk;
00078 uint32_t clkdiv;
00079 AVR32SPIREG *spireg;
00080
00081 NUTASSERT(node != NULL);
00082 NUTASSERT(node->node_stat != NULL);
00083 NUTASSERT(node->node_bus != NULL);
00084 NUTASSERT(node->node_bus->bus_base != 0);
00085 spireg = node->node_stat;
00086
00087 spireg->mr &= ~(AVR32_SPI_MR_MODFDIS_MASK | AVR32_SPI_MR_LLB_MASK | AVR32_SPI_MR_PCSDEC_MASK);
00088
00089 if ((node->node_mode & SPI_MODE_FAULT) == 0) {
00090 spireg->mr |= AVR32_SPI_MR_MODFDIS_MASK;
00091 }
00092 if (node->node_mode & SPI_MODE_LOOPBACK) {
00093 spireg->mr |= AVR32_SPI_MR_LLB_MASK;
00094 }
00095
00096 spireg->mr |= 0xe0 << AVR32_SPI_PCS_OFFSET;
00097
00098 spireg->csr &=
00099 ~(AVR32_SPI_CSR0_BITS_MASK | AVR32_SPI_CSR0_CPOL_MASK | AVR32_SPI_CSR0_NCPHA_MASK | AVR32_SPI_CSR0_CSAAT_MASK |
00100 AVR32_SPI_CSR0_SCBR_MASK);
00101 if (node->node_bits) {
00102 spireg->csr |= ((uint32_t) (node->node_bits - 8) << AVR32_SPI_CSR0_BITS_OFFSET) & AVR32_SPI_CSR0_BITS_MASK;
00103 }
00104 if (node->node_mode & SPI_MODE_CPOL) {
00105 spireg->csr |= AVR32_SPI_CSR0_CPOL_MASK;
00106 }
00107 if ((node->node_mode & SPI_MODE_CPHA) == 0) {
00108 spireg->csr |= AVR32_SPI_CSR0_NCPHA_MASK;
00109 }
00110 if (node->node_mode & SPI_MODE_CSKEEP) {
00111 spireg->csr |= AVR32_SPI_CSR0_CSAAT_MASK;
00112 }
00113
00114
00115 clk = NutClockGet(NUT_HWCLK_PERIPHERAL_A);
00116
00117 clkdiv = (clk + node->node_rate - 1) / node->node_rate;
00118
00119 if (clkdiv < 1) {
00120 clkdiv++;
00121 }
00122
00123 else if (clkdiv > 255) {
00124 clkdiv = 255;
00125 }
00126 spireg->csr |= clkdiv << AVR32_SPI_CSR0_SCBR_OFFSET;
00127
00128
00129 node->node_rate = clk / clkdiv;
00130 node->node_mode &= ~SPI_MODE_UPDATE;
00131
00132 return 0;
00133 }
00134
00145 int Avr32SpiBusNodeInit(NUTSPINODE * node)
00146 {
00147 int rc = 0;
00148 NUTSPIBUS *bus;
00149
00150
00151 NUTASSERT(node != NULL);
00152 NUTASSERT(node->node_bus != NULL);
00153 bus = node->node_bus;
00154
00155
00156 #if defined(AVR32_SPI1_ADDRESS)
00157 if (bus->bus_base == AVR32_SPI1_ADDRESS) {
00158 rc = Avr32Spi1ChipSelect(node->node_cs, (node->node_mode & SPI_MODE_CSHIGH) == 0);
00159 } else
00160 #endif
00161 rc = Avr32Spi0ChipSelect(node->node_cs, (node->node_mode & SPI_MODE_CSHIGH) == 0);
00162
00163
00164
00165 if (rc == 0 && node->node_stat == NULL) {
00166
00167 AVR32SPIREG *spireg = malloc(sizeof(AVR32SPIREG));
00168 if (spireg) {
00169
00170 spireg->mr = AVR32_SPI_MR_MODFDIS_MASK | AVR32_SPI_MR_MSTR_MASK;
00171 spireg->mr |= (1 << (AVR32_SPI_MR_PCS_OFFSET + node->node_cs));
00172 spireg->csr = 0;
00173
00174 node->node_stat = (void *) spireg;
00175 Avr32SpiSetup(node);
00176
00177
00178
00179
00180 #if !defined(SPIBUS1_POLLING_MODE) && defined(AVR32_SPI1_ADDRESS)
00181 if (bus->bus_base == AVR32_SPI1_ADDRESS) {
00182 #if defined(SPIBUS1_DOUBLE_BUFFER)
00183 NutRegisterIrqHandler(bus->bus_sig, Avr32SpiInterrupt, &bus->bus_ready);
00184 #else
00185 NutRegisterIrqHandler(bus->bus_sig, Avr32SpiBus1Interrupt, &bus->bus_ready);
00186 #endif
00187 outr(bus->bus_base + AVR32_SPI_IDR, (unsigned int) -1);
00188 NutIrqEnable(bus->bus_sig);
00189 } else
00190 #endif
00191
00192 {
00193 #if !defined(SPIBUS0_POLLING_MODE)
00194 #if defined(SPIBUS0_DOUBLE_BUFFER)
00195 NutRegisterIrqHandler(bus->bus_sig, Avr32SpiInterrupt, &bus->bus_ready);
00196 #else
00197 NutRegisterIrqHandler(bus->bus_sig, Avr32SpiBus0Interrupt, &bus->bus_ready);
00198 #endif
00199 outr(bus->bus_base + AVR32_SPI_IDR, (unsigned int) -1);
00200 NutIrqEnable(bus->bus_sig);
00201 #endif
00202 }
00203 } else {
00204
00205 rc = -1;
00206 }
00207 }
00208 return rc;
00209 }
00210
00211 #if defined(SPIBUS0_POLLING_MODE) || defined(SPIBUS1_POLLING_MODE)
00212
00226 int Avr32SpiBusPollTransfer(NUTSPINODE * node, CONST void *txbuf, void *rxbuf, int xlen)
00227 {
00228 uint8_t b = 0xff;
00229 uint8_t *txp = (uint8_t *) txbuf;
00230 uint8_t *rxp = (uint8_t *) rxbuf;
00231 uintptr_t base;
00232
00233
00234 NUTASSERT(node != NULL);
00235 NUTASSERT(node->node_bus != NULL);
00236 NUTASSERT(node->node_bus->bus_base != 0);
00237 base = node->node_bus->bus_base;
00238
00239 while (xlen--) {
00240 if (txp) {
00241 b = *txp++;
00242 }
00243
00244 outr(base + AVR32_SPI_TDR, (b << AVR32_SPI_TDR_TD_OFFSET));
00245
00246 while ((inr(base + AVR32_SPI_SR) & AVR32_SPI_RDRF_MASK) == 0);
00247
00248 b = (uint8_t) inr(base + AVR32_SPI_RDR) >> AVR32_SPI_RDR_RD_OFFSET;
00249 if (rxp) {
00250 *rxp++ = b;
00251 }
00252 }
00253 return 0;
00254 }
00255 #endif
00256
00257 #if defined(SPIBUS0_DOUBLE_BUFFER) || defined(SPIBUS1_DOUBLE_BUFFER)
00258
00277 int Avr32SpiBusDblBufTransfer(NUTSPINODE * node, CONST void *txbuf, void *rxbuf, int xlen)
00278 {
00279 #error not implemented
00280 return -1;
00281 }
00282 #endif
00283
00284 #if !defined(SPIBUS0_DOUBLE_BUFFER) || !defined(SPIBUS1_DOUBLE_BUFFER)
00285
00294 int Avr32SpiBusWait(NUTSPINODE * node, uint32_t tmo)
00295 {
00296 while ((inr(node->node_bus->bus_base + AVR32_SPI_SR) & AVR32_SPI_SR_RXBUFF) == 0) {
00297 if (NutEventWait(&node->node_bus->bus_ready, tmo)) {
00298 return -1;
00299 }
00300 }
00301 return 0;
00302 }
00303 #endif