Nut/OS  4.10.3
API Reference
spibus0.c
Go to the documentation of this file.
00001 
00048 #include <cfg/spi.h>
00049 
00050 #include <arch/avr32.h>
00051 #include <arch/avr32/gpio.h>
00052 
00053 #include <dev/spibus_avr32.h>
00054 #include <dev/irqreg.h>
00055 #include <dev/gpio.h>
00056 #include <sys/event.h>
00057 #include <sys/nutdebug.h>
00058 
00059 #include <stdlib.h>
00060 #include <errno.h>
00061 
00062 #include <avr32/io.h>
00063 
00064 #ifndef AVR32_SPI0_ADDRESS
00065 #define AVR32_SPI0_ADDRESS AVR32_SPI_ADDRESS
00066 #endif
00067 
00068 #ifndef AVR32_SPI0
00069 #define AVR32_SPI0 AVR32_SPI
00070 #endif
00071 
00072 #if defined(AVR32_SPI0_SCK_0_0_PIN)
00073 #define AVR32_SPI0_SCK_PIN          AVR32_SPI0_SCK_0_0_PIN
00074 #define AVR32_SPI0_SCK_FUNCTION     AVR32_SPI0_SCK_0_0_FUNCTION
00075 #define AVR32_SPI0_MISO_PIN         AVR32_SPI0_MISO_0_0_PIN
00076 #define AVR32_SPI0_MISO_FUNCTION    AVR32_SPI0_MISO_0_0_FUNCTION
00077 #define AVR32_SPI0_MOSI_PIN         AVR32_SPI0_MOSI_0_0_PIN
00078 #define AVR32_SPI0_MOSI_FUNCTION    AVR32_SPI0_MOSI_0_0_FUNCTION
00079 #define AVR32_SPI0_NPCS_PIN         AVR32_SPI0_NPCS_0_0_PIN
00080 #define AVR32_SPI0_NPCS_FUNCTION    AVR32_SPI0_NPCS_0_0_FUNCTION
00081 #elif defined(AVR32_SPI0_SCK_0_PIN)
00082 #define AVR32_SPI0_SCK_PIN          AVR32_SPI0_SCK_0_PIN
00083 #define AVR32_SPI0_SCK_FUNCTION     AVR32_SPI0_SCK_0_FUNCTION
00084 #define AVR32_SPI0_MISO_PIN         AVR32_SPI0_MISO_0_PIN
00085 #define AVR32_SPI0_MISO_FUNCTION    AVR32_SPI0_MISO_0_FUNCTION
00086 #define AVR32_SPI0_MOSI_PIN         AVR32_SPI0_MOSI_0_PIN
00087 #define AVR32_SPI0_MOSI_FUNCTION    AVR32_SPI0_MOSI_0_FUNCTION
00088 #define AVR32_SPI0_NPCS_PIN         AVR32_SPI0_NPCS_0_PIN
00089 #define AVR32_SPI0_NPCS_FUNCTION    AVR32_SPI0_NPCS_0_FUNCTION
00090 #elif defined(AVR32_SPI_SCK_0_0_PIN)
00091 #define AVR32_SPI0_SCK_PIN          AVR32_SPI_SCK_0_0_PIN
00092 #define AVR32_SPI0_SCK_FUNCTION     AVR32_SPI_SCK_0_0_FUNCTION
00093 #define AVR32_SPI0_MISO_PIN         AVR32_SPI_MISO_0_0_PIN
00094 #define AVR32_SPI0_MISO_FUNCTION    AVR32_SPI_MISO_0_0_FUNCTION
00095 #define AVR32_SPI0_MOSI_PIN         AVR32_SPI_MOSI_0_0_PIN
00096 #define AVR32_SPI0_MOSI_FUNCTION    AVR32_SPI_MOSI_0_0_FUNCTION
00097 #define AVR32_SPI0_NPCS_PIN         AVR32_SPI_NPCS_0_0_PIN
00098 #define AVR32_SPI0_NPCS_FUNCTION    AVR32_SPI_NPCS_0_0_FUNCTION
00099 #endif
00100 
00101 #if defined(SPI0_CS0_PIO_BIT)
00102 #if defined(SPI0_CS0_PIO_ID)
00103 #undef GPIO_ID
00104 #define GPIO_ID SPI0_CS0_PIO_ID
00105 #include <cfg/arch/porttran.h>
00106 static INLINE void SPI0_CS0_LO(void)
00107 {
00108     GPIO_SET_LO(SPI0_CS0_PIO_BIT);
00109 }
00110 
00111 static INLINE void SPI0_CS0_HI(void)
00112 {
00113     GPIO_SET_HI(SPI0_CS0_PIO_BIT);
00114 }
00115 
00116 static INLINE void SPI0_CS0_SO(void)
00117 {
00118     GPIO_ENABLE(SPI0_CS0_PIO_BIT);
00119     GPIO_OUTPUT(SPI0_CS0_PIO_BIT);
00120 }
00121 #else
00122 #define SPI0_CS0_LO()
00123 #define SPI0_CS0_HI()
00124 #define SPI0_CS0_SO()
00125 #endif
00126 #endif
00127 
00128 #if defined(SPI0_CS1_PIO_BIT)
00129 #if defined(SPI0_CS1_PIO_ID)
00130 #undef GPIO_ID
00131 #define GPIO_ID SPI0_CS1_PIO_ID
00132 #include <cfg/arch/porttran.h>
00133 static INLINE void SPI0_CS1_LO(void)
00134 {
00135     GPIO_SET_LO(SPI0_CS1_PIO_BIT);
00136 }
00137 
00138 static INLINE void SPI0_CS1_HI(void)
00139 {
00140     GPIO_SET_HI(SPI0_CS1_PIO_BIT);
00141 }
00142 
00143 static INLINE void SPI0_CS1_SO(void)
00144 {
00145     GPIO_ENABLE(SPI0_CS1_PIO_BIT);
00146     GPIO_OUTPUT(SPI0_CS1_PIO_BIT);
00147 }
00148 #else
00149 #define SPI0_CS1_LO()
00150 #define SPI0_CS1_HI()
00151 #define SPI0_CS1_SO()
00152 #endif
00153 #endif
00154 
00155 #if defined(SPI0_CS2_PIO_BIT)
00156 #if defined(SPI0_CS2_PIO_ID)
00157 #undef GPIO_ID
00158 #define GPIO_ID SPI0_CS2_PIO_ID
00159 #include <cfg/arch/porttran.h>
00160 static INLINE void SPI0_CS2_LO(void)
00161 {
00162     GPIO_SET_LO(SPI0_CS2_PIO_BIT);
00163 }
00164 
00165 static INLINE void SPI0_CS2_HI(void)
00166 {
00167     GPIO_SET_HI(SPI0_CS2_PIO_BIT);
00168 }
00169 
00170 static INLINE void SPI0_CS2_SO(void)
00171 {
00172     GPIO_ENABLE(SPI0_CS2_PIO_BIT);
00173     GPIO_OUTPUT(SPI0_CS2_PIO_BIT);
00174 }
00175 #else
00176 #define SPI0_CS2_LO()
00177 #define SPI0_CS2_HI()
00178 #define SPI0_CS2_SO()
00179 #endif
00180 #endif
00181 
00182 #if defined(SPI0_CS3_PIO_BIT)
00183 #if defined(SPI0_CS3_PIO_ID)
00184 #undef GPIO_ID
00185 #define GPIO_ID SPI0_CS3_PIO_ID
00186 #include <cfg/arch/porttran.h>
00187 static INLINE void SPI0_CS3_LO(void)
00188 {
00189     GPIO_SET_LO(SPI0_CS3_PIO_BIT);
00190 }
00191 
00192 static INLINE void SPI0_CS3_HI(void)
00193 {
00194     GPIO_SET_HI(SPI0_CS3_PIO_BIT);
00195 }
00196 
00197 static INLINE void SPI0_CS3_SO(void)
00198 {
00199     GPIO_ENABLE(SPI0_CS3_PIO_BIT);
00200     GPIO_OUTPUT(SPI0_CS3_PIO_BIT);
00201 }
00202 #else
00203 #define SPI0_CS3_LO()
00204 #define SPI0_CS3_HI()
00205 #define SPI0_CS3_SO()
00206 #endif
00207 #endif
00208 
00212 int Avr32Spi0ChipSelect(uint_fast8_t cs, uint_fast8_t hi)
00213 {
00214     int rc = 0;
00215 
00216     switch (cs) {
00217 #if defined(SPI0_CS0_PIO_BIT)
00218     case 0:
00219         if (hi) {
00220             SPI0_CS0_HI();
00221         } else {
00222             SPI0_CS0_LO();
00223         }
00224         SPI0_CS0_SO();
00225         break;
00226 #endif
00227 #if defined(SPI0_CS1_PIO_BIT)
00228     case 1:
00229         if (hi) {
00230             SPI0_CS1_HI();
00231         } else {
00232             SPI0_CS1_LO();
00233         }
00234         SPI0_CS1_SO();
00235         break;
00236 #endif
00237 #if defined(SPI0_CS2_PIO_BIT)
00238     case 2:
00239         if (hi) {
00240             SPI0_CS2_HI();
00241         } else {
00242             SPI0_CS2_LO();
00243         }
00244         SPI0_CS2_SO();
00245         break;
00246 #endif
00247 #if defined(SPI0_CS3_PIO_BIT)
00248     case 3:
00249         if (hi) {
00250             SPI0_CS3_HI();
00251         } else {
00252             SPI0_CS3_LO();
00253         }
00254         SPI0_CS3_SO();
00255         break;
00256 #endif
00257     default:
00258         errno = EIO;
00259         rc = -1;
00260         break;
00261     }
00262     return rc;
00263 }
00264 
00276 int Avr32SpiBus0Select(NUTSPINODE * node, uint32_t tmo)
00277 {
00278     int rc;
00279 
00280     /* Sanity check. */
00281     NUTASSERT(node != NULL);
00282     NUTASSERT(node->node_bus != NULL);
00283     NUTASSERT(node->node_stat != NULL);
00284 
00285     /* Allocate the bus. */
00286     rc = NutEventWait(&node->node_bus->bus_mutex, tmo);
00287     if (rc) {
00288         errno = EIO;
00289     } else {
00290         AVR32SPIREG *spireg = node->node_stat;
00291 
00292         /* Enable SPI peripherals and clock. */
00293         gpio_enable_module_pin(AVR32_SPI0_SCK_PIN, AVR32_SPI0_SCK_FUNCTION);
00294         gpio_enable_module_pin(AVR32_SPI0_MISO_PIN, AVR32_SPI0_MISO_FUNCTION);
00295         gpio_enable_module_pin(AVR32_SPI0_MOSI_PIN, AVR32_SPI0_MOSI_FUNCTION);
00296         gpio_enable_module_pin(AVR32_SPI0_NPCS_PIN, AVR32_SPI0_NPCS_FUNCTION);
00297 
00298         /* If the mode update bit is set, then update our registers. */
00299         if (node->node_mode & SPI_MODE_UPDATE) {
00300             Avr32SpiSetup(node);
00301         }
00302 
00303         /* Set SPI mode. */
00304         outr(AVR32_SPI0_ADDRESS + AVR32_SPI_MR, spireg->mr);
00305         //outr(AVR32_SPI0_ADDRESS + AVR32_SPI_CSR0 + (node->node_cs * (AVR32_SPI_CSR0 - AVR32_SPI_CSR0)), spireg->csr);
00306         outr(AVR32_SPI0_ADDRESS + AVR32_SPI_CSR0, spireg->csr);
00307 
00308         /* Enable SPI. */
00309         AVR32_SPI0.cr |= AVR32_SPI_CR_SPIEN_MASK;
00310 
00311         /* Finally activate the node's chip select. */
00312         rc = Avr32Spi0ChipSelect(node->node_cs, (node->node_mode & SPI_MODE_CSHIGH) != 0);
00313         if (rc) {
00314             /* Release the bus in case of an error. */
00315             NutEventPost(&node->node_bus->bus_mutex);
00316         }
00317     }
00318     return rc;
00319 }
00320 
00329 int Avr32SpiBus0Deselect(NUTSPINODE * node)
00330 {
00331     /* Sanity check. */
00332     NUTASSERT(node != NULL);
00333     NUTASSERT(node->node_bus != NULL);
00334 
00335 #ifdef SPIBUS0_DOUBLE_BUFFER
00336     Avr32SpiBusWait(node, NUT_WAIT_INFINITE);
00337 #endif
00338     /* Deactivate the node's chip select. */
00339     Avr32Spi0ChipSelect(node->node_cs, (node->node_mode & SPI_MODE_CSHIGH) == 0);
00340 
00341     /* Release the bus. */
00342     NutEventPost(&node->node_bus->bus_mutex);
00343 
00344     return 0;
00345 }
00346 
00347 #if !defined(SPIBUS0_POLLING_MODE) || !defined(SPIBUS0_DOUBLE_BUFFER)
00348 
00349 static uint8_t *volatile spi0_txp;
00350 static uint8_t *volatile spi0_rxp;
00351 static volatile size_t spi0_xc;
00352 
00353 void Avr32SpiBus0Interrupt(void *arg)
00354 {
00355     uint8_t b;
00356 
00357     /* Get the received byte. */
00358     b = (uint8_t) inr(AVR32_SPI0_ADDRESS + AVR32_SPI_RDR) >> AVR32_SPI_RDR_RD_OFFSET;
00359     if (spi0_xc) {
00360         if (spi0_rxp) {
00361             *spi0_rxp++ = b;
00362         }
00363         spi0_xc--;
00364     }
00365     if (spi0_xc) {
00366         if (spi0_txp) {
00367             b = *spi0_txp++;
00368         }
00369         outr(AVR32_SPI0_ADDRESS + AVR32_SPI_TDR, (b << AVR32_SPI_TDR_TD_OFFSET));
00370     } else {
00371         NutEventPostFromIrq((void **) arg);
00372     }
00373 }
00374 
00389 int Avr32SpiBus0Transfer(NUTSPINODE * node, CONST void *txbuf, void *rxbuf, int xlen)
00390 {
00391     uint8_t b = 0xff;
00392     uintptr_t base;
00393 
00394     /* Sanity check. */
00395     NUTASSERT(node != NULL);
00396     NUTASSERT(node->node_bus != NULL);
00397     NUTASSERT(node->node_bus->bus_base != 0);
00398     base = node->node_bus->bus_base;
00399 
00400     if (xlen) {
00401         spi0_txp = (uint8_t *) txbuf;
00402         spi0_rxp = (uint8_t *) rxbuf;
00403         spi0_xc = (size_t) xlen;
00404         if (spi0_txp) {
00405             b = *spi0_txp++;
00406         }
00407         /* Enable and kick interrupts. */
00408         outr(base + AVR32_SPI_IER, AVR32_SPI_IER_RDRF_MASK);
00409         outr(base + AVR32_SPI_TDR, (b << AVR32_SPI_TDR_TD_OFFSET));
00410         /* Wait until transfer has finished. */
00411         NutEventWait(&node->node_bus->bus_ready, NUT_WAIT_INFINITE);
00412         outr(base + AVR32_SPI_IDR, (unsigned int) -1);
00413     }
00414     return 0;
00415 }
00416 #endif
00417 
00421 NUTSPIBUS spiBus0Avr32 = {
00422     NULL,                       
00423     NULL,                       
00424     AVR32_SPI0_ADDRESS,         
00425     &sig_SPI0,                  
00426     Avr32SpiBusNodeInit,        
00427     Avr32SpiBus0Select,         
00428     Avr32SpiBus0Deselect,       
00429 #if defined(SPIBUS0_POLLING_MODE)
00430     Avr32SpiBusPollTransfer,    
00431 #elif defined(SPIBUS0_DOUBLE_BUFFER)
00432     Avr32SpiBusDblBufTransfer,
00433 #else
00434     Avr32SpiBus0Transfer,
00435 #endif
00436 #ifdef SPIBUS0_DOUBLE_BUFFER
00437     Avr32SpiBusWait,
00438 #else
00439     NutSpiBusWait,              
00440 #endif
00441     NutSpiBusSetMode,           
00442     NutSpiBusSetRate,           
00443     NutSpiBusSetBits            
00444 };