Nut/OS  4.10.3
API Reference
spibus1.c
Go to the documentation of this file.
00001 
00047 #include <cfg/spi.h>
00048 
00049 #include <arch/avr32.h>
00050 #include <arch/avr32/gpio.h>
00051 
00052 #include <dev/spibus_avr32.h>
00053 #include <dev/irqreg.h>
00054 #include <dev/gpio.h>
00055 #include <sys/event.h>
00056 #include <sys/nutdebug.h>
00057 
00058 #include <stdlib.h>
00059 #include <errno.h>
00060 
00061 #include <avr32/io.h>
00062 
00063 #if defined(AVR32_SPI1_SCK_0_0_PIN)
00064 #define AVR32_SPI1_SCK_PIN          AVR32_SPI1_SCK_0_0_PIN
00065 #define AVR32_SPI1_SCK_FUNCTION     AVR32_SPI1_SCK_0_0_FUNCTION
00066 #define AVR32_SPI1_MISO_PIN         AVR32_SPI1_MISO_0_0_PIN
00067 #define AVR32_SPI1_MISO_FUNCTION    AVR32_SPI1_MISO_0_0_FUNCTION
00068 #define AVR32_SPI1_MOSI_PIN         AVR32_SPI1_MOSI_0_0_PIN
00069 #define AVR32_SPI1_MOSI_FUNCTION    AVR32_SPI1_MOSI_0_0_FUNCTION
00070 #define AVR32_SPI1_NPCS_PIN         AVR32_SPI1_NPCS_0_0_PIN
00071 #define AVR32_SPI1_NPCS_FUNCTION    AVR32_SPI1_NPCS_0_0_FUNCTION
00072 #elif defined(AVR32_SPI1_SCK_0_PIN)
00073 #define AVR32_SPI1_SCK_PIN          AVR32_SPI1_SCK_0_PIN
00074 #define AVR32_SPI1_SCK_FUNCTION     AVR32_SPI1_SCK_0_FUNCTION
00075 #define AVR32_SPI1_MISO_PIN         AVR32_SPI1_MISO_0_PIN
00076 #define AVR32_SPI1_MISO_FUNCTION    AVR32_SPI1_MISO_0_FUNCTION
00077 #define AVR32_SPI1_MOSI_PIN         AVR32_SPI1_MOSI_0_PIN
00078 #define AVR32_SPI1_MOSI_FUNCTION    AVR32_SPI1_MOSI_0_FUNCTION
00079 #define AVR32_SPI1_NPCS_PIN         AVR32_SPI1_NPCS_0_PIN
00080 #define AVR32_SPI1_NPCS_FUNCTION    AVR32_SPI1_NPCS_0_FUNCTION
00081 #endif
00082 
00083 #if defined(SPI1_CS0_PIO_BIT)
00084 #if defined(SPI1_CS0_PIO_ID)
00085 #undef GPIO_ID
00086 #define GPIO_ID SPI1_CS0_PIO_ID
00087 #include <cfg/arch/porttran.h>
00088 static INLINE void SPI1_CS0_LO(void)
00089 {
00090     GPIO_SET_LO(SPI1_CS0_PIO_BIT);
00091 }
00092 
00093 static INLINE void SPI1_CS0_HI(void)
00094 {
00095     GPIO_SET_HI(SPI1_CS0_PIO_BIT);
00096 }
00097 
00098 static INLINE void SPI1_CS0_SO(void)
00099 {
00100     GPIO_ENABLE(SPI1_CS0_PIO_BIT);
00101     GPIO_OUTPUT(SPI1_CS0_PIO_BIT);
00102 }
00103 #else
00104 #define SPI1_CS0_LO()
00105 #define SPI1_CS0_HI()
00106 #define SPI1_CS0_SO()
00107 #endif
00108 #endif
00109 
00110 #if defined(SPI1_CS1_PIO_BIT)
00111 #if defined(SPI1_CS1_PIO_ID)
00112 #undef GPIO_ID
00113 #define GPIO_ID SPI1_CS1_PIO_ID
00114 #include <cfg/arch/porttran.h>
00115 static INLINE void SPI1_CS1_LO(void)
00116 {
00117     GPIO_SET_LO(SPI1_CS1_PIO_BIT);
00118 }
00119 
00120 static INLINE void SPI1_CS1_HI(void)
00121 {
00122     GPIO_SET_HI(SPI1_CS1_PIO_BIT);
00123 }
00124 
00125 static INLINE void SPI1_CS1_SO(void)
00126 {
00127     GPIO_ENABLE(SPI1_CS1_PIO_BIT);
00128     GPIO_OUTPUT(SPI1_CS1_PIO_BIT);
00129 }
00130 #else
00131 #define SPI1_CS1_LO()
00132 #define SPI1_CS1_HI()
00133 #define SPI1_CS1_SO()
00134 #endif
00135 #endif
00136 
00137 #if defined(SPI1_CS2_PIO_BIT)
00138 #if defined(SPI1_CS2_PIO_ID)
00139 #undef GPIO_ID
00140 #define GPIO_ID SPI1_CS2_PIO_ID
00141 #include <cfg/arch/porttran.h>
00142 static INLINE void SPI1_CS2_LO(void)
00143 {
00144     GPIO_SET_LO(SPI1_CS2_PIO_BIT);
00145 }
00146 
00147 static INLINE void SPI1_CS2_HI(void)
00148 {
00149     GPIO_SET_HI(SPI1_CS2_PIO_BIT);
00150 }
00151 
00152 static INLINE void SPI1_CS2_SO(void)
00153 {
00154     GPIO_ENABLE(SPI1_CS2_PIO_BIT);
00155     GPIO_OUTPUT(SPI1_CS2_PIO_BIT);
00156 }
00157 #else
00158 #define SPI1_CS2_LO()
00159 #define SPI1_CS2_HI()
00160 #define SPI1_CS2_SO()
00161 #endif
00162 #endif
00163 
00164 #if defined(SPI1_CS3_PIO_BIT)
00165 #if defined(SPI1_CS3_PIO_ID)
00166 #undef GPIO_ID
00167 #define GPIO_ID SPI1_CS3_PIO_ID
00168 #include <cfg/arch/porttran.h>
00169 static INLINE void SPI1_CS3_LO(void)
00170 {
00171     GPIO_SET_LO(SPI1_CS3_PIO_BIT);
00172 }
00173 
00174 static INLINE void SPI1_CS3_HI(void)
00175 {
00176     GPIO_SET_HI(SPI1_CS3_PIO_BIT);
00177 }
00178 
00179 static INLINE void SPI1_CS3_SO(void)
00180 {
00181     GPIO_ENABLE(SPI1_CS3_PIO_BIT);
00182     GPIO_OUTPUT(SPI1_CS3_PIO_BIT);
00183 }
00184 #else
00185 #define SPI1_CS3_LO()
00186 #define SPI1_CS3_HI()
00187 #define SPI1_CS3_SO()
00188 #endif
00189 #endif
00190 
00194 int Avr32Spi1ChipSelect(uint_fast8_t cs, uint_fast8_t hi)
00195 {
00196     int rc = 0;
00197 
00198     switch (cs) {
00199 #if defined(SPI1_CS0_PIO_BIT)
00200     case 0:
00201         if (hi) {
00202             SPI1_CS0_HI();
00203         } else {
00204             SPI1_CS0_LO();
00205         }
00206         SPI1_CS0_SO();
00207         break;
00208 #endif
00209 #if defined(SPI1_CS1_PIO_BIT)
00210     case 1:
00211         if (hi) {
00212             SPI1_CS1_HI();
00213         } else {
00214             SPI1_CS1_LO();
00215         }
00216         SPI1_CS1_SO();
00217         break;
00218 #endif
00219 #if defined(SPI1_CS2_PIO_BIT)
00220     case 2:
00221         if (hi) {
00222             SPI1_CS2_HI();
00223         } else {
00224             SPI1_CS2_LO();
00225         }
00226         SPI1_CS2_SO();
00227         break;
00228 #endif
00229 #if defined(SPI1_CS3_PIO_BIT)
00230     case 3:
00231         if (hi) {
00232             SPI1_CS3_HI();
00233         } else {
00234             SPI1_CS3_LO();
00235         }
00236         SPI1_CS3_SO();
00237         break;
00238 #endif
00239     default:
00240         errno = EIO;
00241         rc = -1;
00242         break;
00243     }
00244     return rc;
00245 }
00246 
00258 int Avr32SpiBus1Select(NUTSPINODE * node, uint32_t tmo)
00259 {
00260     int rc;
00261 
00262     /* Sanity check. */
00263     NUTASSERT(node != NULL);
00264     NUTASSERT(node->node_bus != NULL);
00265     NUTASSERT(node->node_stat != NULL);
00266 
00267     /* Allocate the bus. */
00268     rc = NutEventWait(&node->node_bus->bus_mutex, tmo);
00269     if (rc) {
00270         errno = EIO;
00271     } else {
00272         AVR32SPIREG *spireg = node->node_stat;
00273 
00274         /* Enable SPI peripherals and clock. */
00275         gpio_enable_module_pin(AVR32_SPI1_SCK_PIN, AVR32_SPI1_SCK_FUNCTION);
00276         gpio_enable_module_pin(AVR32_SPI1_MISO_PIN, AVR32_SPI1_MISO_FUNCTION);
00277         gpio_enable_module_pin(AVR32_SPI1_MOSI_PIN, AVR32_SPI1_MOSI_FUNCTION);
00278         gpio_enable_module_pin(AVR32_SPI1_NPCS_PIN, AVR32_SPI1_NPCS_FUNCTION);
00279 
00280         /* If the mode update bit is set, then update our registers. */
00281         if (node->node_mode & SPI_MODE_UPDATE) {
00282             Avr32SpiSetup(node);
00283         }
00284 
00285         /* Set SPI mode. */
00286         outr(AVR32_SPI1_ADDRESS + AVR32_SPI_MR, spireg->mr);
00287         //outr(AVR32_SPI1_ADDRESS + AVR32_SPI_CSR0 + (node->node_cs * (AVR32_SPI_CSR1 - AVR32_SPI_CSR0)), spireg->csr);
00288         outr(AVR32_SPI1_ADDRESS + AVR32_SPI_CSR0, spireg->csr);
00289 
00290         /* Enable SPI. */
00291         AVR32_SPI1.cr |= AVR32_SPI_CR_SPIEN_MASK;
00292 
00293         /* Finally activate the node's chip select. */
00294         rc = Avr32Spi1ChipSelect(node->node_cs, (node->node_mode & SPI_MODE_CSHIGH) != 0);
00295         if (rc) {
00296             /* Release the bus in case of an error. */
00297             NutEventPost(&node->node_bus->bus_mutex);
00298         }
00299     }
00300     return rc;
00301 }
00302 
00311 int Avr32SpiBus1Deselect(NUTSPINODE * node)
00312 {
00313     /* Sanity check. */
00314     NUTASSERT(node != NULL);
00315     NUTASSERT(node->node_bus != NULL);
00316 
00317 #ifdef SPIBUS1_DOUBLE_BUFFER
00318     Avr32SpiBusWait(node, NUT_WAIT_INFINITE);
00319 #endif
00320     /* Deactivate the node's chip select. */
00321     Avr32Spi1ChipSelect(node->node_cs, (node->node_mode & SPI_MODE_CSHIGH) == 0);
00322 
00323     /* Release the bus. */
00324     NutEventPost(&node->node_bus->bus_mutex);
00325 
00326     return 0;
00327 }
00328 
00329 #if !defined(SPIBUS1_POLLING_MODE) || !defined(SPIBUS1_DOUBLE_BUFFER)
00330 
00331 static uint8_t *volatile spi1_txp;
00332 static uint8_t *volatile spi1_rxp;
00333 static volatile size_t spi1_xc;
00334 
00335 void Avr32SpiBus1Interrupt(void *arg)
00336 {
00337     uint8_t b;
00338 
00339     /* Get the received byte. */
00340     b = (uint8_t) inr(AVR32_SPI1_ADDRESS + AVR32_SPI_RDR) >> AVR32_SPI_RDR_RD_OFFSET;
00341     if (spi1_xc) {
00342         if (spi1_rxp) {
00343             *spi1_rxp++ = b;
00344         }
00345         spi1_xc--;
00346     }
00347     if (spi1_xc) {
00348         if (spi1_txp) {
00349             b = *spi1_txp++;
00350         }
00351         outr(AVR32_SPI1_ADDRESS + AVR32_SPI_TDR, (b << AVR32_SPI_TDR_TD_OFFSET));
00352     } else {
00353         NutEventPostFromIrq((void **) arg);
00354     }
00355 }
00356 
00371 int Avr32SpiBus1Transfer(NUTSPINODE * node, CONST void *txbuf, void *rxbuf, int xlen)
00372 {
00373     uint8_t b = 0xff;
00374     uintptr_t base;
00375 
00376     /* Sanity check. */
00377     NUTASSERT(node != NULL);
00378     NUTASSERT(node->node_bus != NULL);
00379     NUTASSERT(node->node_bus->bus_base != 0);
00380     base = node->node_bus->bus_base;
00381 
00382     if (xlen) {
00383         spi1_txp = (uint8_t *) txbuf;
00384         spi1_rxp = (uint8_t *) rxbuf;
00385         spi1_xc = (size_t) xlen;
00386         if (spi1_txp) {
00387             b = *spi1_txp++;
00388         }
00389         /* Enable and kick interrupts. */
00390         outr(base + AVR32_SPI_IER, AVR32_SPI_IER_RDRF_MASK);
00391         outr(base + AVR32_SPI_TDR, (b << AVR32_SPI_TDR_TD_OFFSET));
00392         /* Wait until transfer has finished. */
00393         NutEventWait(&node->node_bus->bus_ready, NUT_WAIT_INFINITE);
00394         outr(base + AVR32_SPI_IDR, (unsigned int) -1);
00395     }
00396     return 0;
00397 }
00398 #endif
00399 
00403 NUTSPIBUS spiBus1Avr32 = {
00404     NULL,                       
00405     NULL,                       
00406     AVR32_SPI1_ADDRESS,         
00407     &sig_SPI1,                  
00408     Avr32SpiBusNodeInit,        
00409     Avr32SpiBus1Select,         
00410     Avr32SpiBus1Deselect,       
00411 #if defined(SPIBUS1_POLLING_MODE)
00412     Avr32SpiBusPollTransfer,    
00413 #elif defined(SPIBUS1_DOUBLE_BUFFER)
00414     Avr32SpiBusDblBufTransfer,
00415 #else
00416     Avr32SpiBus1Transfer,
00417 #endif
00418 #ifdef SPIBUS1_DOUBLE_BUFFER
00419     Avr32SpiBusWait,
00420 #else
00421     NutSpiBusWait,              
00422 #endif
00423     NutSpiBusSetMode,           
00424     NutSpiBusSetRate,           
00425     NutSpiBusSetBits            
00426 };