Nut/OS  4.10.3
API Reference
spibus.c
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                          /* SPIBUS0_DOUBLE_BUFFER */
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     /* Query peripheral clock. */
00115     clk = NutClockGet(NUT_HWCLK_PERIPHERAL_A);
00116     /* Calculate the SPI clock divider. Avoid rounding errors. */
00117     clkdiv = (clk + node->node_rate - 1) / node->node_rate;
00118     /* The divider value minimum is 1. */
00119     if (clkdiv < 1) {
00120         clkdiv++;
00121     }
00122     /* The divider value maximum is 255. */
00123     else if (clkdiv > 255) {
00124         clkdiv = 255;
00125     }
00126     spireg->csr |= clkdiv << AVR32_SPI_CSR0_SCBR_OFFSET;
00127 
00128     /* Update interface parameters. */
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     /* Sanity check. */
00151     NUTASSERT(node != NULL);
00152     NUTASSERT(node->node_bus != NULL);
00153     bus = node->node_bus;
00154 
00155     /* Try to deactivate the node's chip select. */
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     /* It should not hurt us being called more than once. Thus, we
00164      ** check whether any initialization had been taken place already. */
00165     if (rc == 0 && node->node_stat == NULL) {
00166         /* Allocate and set our shadow registers. */
00167         AVR32SPIREG *spireg = malloc(sizeof(AVR32SPIREG));
00168         if (spireg) {
00169             /* Set interface defaults. */
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             /* Update with node's defaults. */
00174             node->node_stat = (void *) spireg;
00175             Avr32SpiSetup(node);
00176 
00177             /* 
00178              * Register and enable SPI interrupt handler. 
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                          /* !SPIBUS1_POLLING_MODE */
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                          /* !SPIBUS0_POLLING_MODE */
00202             }
00203         } else {
00204             /* Out of memory? */
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     /* Sanity check. */
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         /* Transmission starts by writing the transmit data. */
00244         outr(base + AVR32_SPI_TDR, (b << AVR32_SPI_TDR_TD_OFFSET));
00245         /* Wait for receiver data register full. */
00246         while ((inr(base + AVR32_SPI_SR) & AVR32_SPI_RDRF_MASK) == 0);
00247         /* Read incoming data. */
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                          /* SPIBUS_POLLING_MODE */