00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00055 #include <cfg/spi.h>
00056 #include <cfg/arch/gpio.h>
00057 
00058 #include <dev/spibus_avr.h>
00059 #include <dev/irqreg.h>
00060 #include <sys/event.h>
00061 #include <sys/nutdebug.h>
00062 
00063 #include <errno.h>
00064 #include <stdlib.h>
00065 #include <memdebug.h>
00066 
00067 #if defined(SPI0_CS0_PIO_BIT)
00068 #if defined(SPI0_CS0_PIO_ID)
00069 #undef GPIO_ID
00070 #define GPIO_ID SPI0_CS0_PIO_ID
00071 #include <cfg/arch/porttran.h>
00072 static INLINE void SPI0_CS0_LO(void) { GPIO_SET_LO(SPI0_CS0_PIO_BIT); }
00073 static INLINE void SPI0_CS0_HI(void) { GPIO_SET_HI(SPI0_CS0_PIO_BIT); }
00074 static INLINE void SPI0_CS0_SO(void) { GPIO_OUTPUT(SPI0_CS0_PIO_BIT); }
00075 #else
00076 #define SPI0_CS0_LO()
00077 #define SPI0_CS0_HI()
00078 #define SPI0_CS0_SO()
00079 #endif
00080 #endif
00081 
00082 #if defined(SPI0_CS1_PIO_BIT)
00083 #if defined(SPI0_CS1_PIO_ID)
00084 #undef GPIO_ID
00085 #define GPIO_ID SPI0_CS1_PIO_ID
00086 #include <cfg/arch/porttran.h>
00087 static INLINE void SPI0_CS1_LO(void) { GPIO_SET_LO(SPI0_CS1_PIO_BIT); }
00088 static INLINE void SPI0_CS1_HI(void) { GPIO_SET_HI(SPI0_CS1_PIO_BIT); }
00089 static INLINE void SPI0_CS1_SO(void) { GPIO_OUTPUT(SPI0_CS1_PIO_BIT); }
00090 #else
00091 #define SPI0_CS1_LO()
00092 #define SPI0_CS1_HI()
00093 #define SPI0_CS1_SO()
00094 #endif
00095 #endif
00096 
00097 #if defined(SPI0_CS2_PIO_BIT)
00098 #if defined(SPI0_CS2_PIO_ID)
00099 #undef GPIO_ID
00100 #define GPIO_ID SPI0_CS2_PIO_ID
00101 #include <cfg/arch/porttran.h>
00102 static INLINE void SPI0_CS2_LO(void) { GPIO_SET_LO(SPI0_CS2_PIO_BIT); }
00103 static INLINE void SPI0_CS2_HI(void) { GPIO_SET_HI(SPI0_CS2_PIO_BIT); }
00104 static INLINE void SPI0_CS2_SO(void) { GPIO_OUTPUT(SPI0_CS2_PIO_BIT); }
00105 #else
00106 #define SPI0_CS2_LO()
00107 #define SPI0_CS2_HI()
00108 #define SPI0_CS2_SO()
00109 #endif
00110 #endif
00111 
00112 #if defined(SPI0_CS3_PIO_BIT)
00113 #if defined(SPI0_CS3_PIO_ID)
00114 #undef GPIO_ID
00115 #define GPIO_ID SPI0_CS3_PIO_ID
00116 #include <cfg/arch/porttran.h>
00117 static INLINE void SPI0_CS3_LO(void) { GPIO_SET_LO(SPI0_CS3_PIO_BIT); }
00118 static INLINE void SPI0_CS3_HI(void) { GPIO_SET_HI(SPI0_CS3_PIO_BIT); }
00119 static INLINE void SPI0_CS3_SO(void) { GPIO_OUTPUT(SPI0_CS3_PIO_BIT); }
00120 #else
00121 #define SPI0_CS3_LO()
00122 #define SPI0_CS3_HI()
00123 #define SPI0_CS4_SO()
00124 #endif
00125 #endif
00126 
00130 static int AvrSpi0ChipSelect(uint_fast8_t cs, uint_fast8_t hi)
00131 {
00132     int rc = 0;
00133 
00134     switch (cs) {
00135 #if defined(SPI0_CS0_PIO_BIT)
00136     case 0:
00137         if (hi) {
00138             SPI0_CS0_HI();
00139         } else {
00140             SPI0_CS0_LO();
00141         }
00142         SPI0_CS0_SO();
00143         break;
00144 #endif
00145 #if defined(SPI0_CS1_PIO_BIT)
00146     case 1:
00147         if (hi) {
00148             SPI0_CS1_HI();
00149         } else {
00150             SPI0_CS1_LO();
00151         }
00152         SPI0_CS1_SO();
00153         break;
00154 #endif
00155 #if defined(SPI0_CS2_PIO_BIT)
00156     case 2:
00157         if (hi) {
00158             SPI0_CS2_HI();
00159         } else {
00160             SPI0_CS2_LO();
00161         }
00162         SPI0_CS2_SO();
00163         break;
00164 #endif
00165 #if defined(SPI0_CS3_PIO_BIT)
00166     case 3:
00167         if (hi) {
00168             SPI0_CS3_HI();
00169         } else {
00170             SPI0_CS3_LO();
00171         }
00172         SPI0_CS3_SO();
00173         break;
00174 #endif
00175     default:
00176         errno = EIO;
00177         rc = -1;
00178         break;
00179     }
00180     return rc;
00181 }
00182 
00183 static uint8_t * volatile spi0_txp;
00184 static uint8_t * volatile spi0_rxp;
00185 
00186 #ifndef SPIBUS0_POLLING_MODE
00187 
00188 static HANDLE spi0_que;
00189 static volatile size_t spi0_xc;
00190 
00191 #ifdef SPIBUS0_DOUBLE_BUFFER
00192 
00193 static uint8_t * volatile spi0_ntxp;
00194 static uint8_t * volatile spi0_nrxp;
00195 static volatile size_t spi0_nxc;
00196 #endif
00197 
00201 static void AvrSpi0Interrupt(void *arg)
00202 {
00203     uint8_t b;
00204 
00205     
00206     b = inb(SPDR);
00207     if (spi0_xc) {
00208         if (spi0_rxp) {
00209             *spi0_rxp++ = b;
00210         }
00211         spi0_xc--;
00212     }
00213     if (spi0_xc == 0) {
00214 #ifdef SPIBUS0_DOUBLE_BUFFER
00215         if (spi0_nxc) {
00216             
00217             spi0_txp = spi0_ntxp;
00218             spi0_rxp = spi0_nrxp;
00219             spi0_xc = spi0_nxc;
00220             spi0_nxc = 0;
00221         }
00222 #endif
00223         NutEventPostFromIrq(&spi0_que);
00224     }
00225     if (spi0_xc) {
00226         if (spi0_txp) {
00227             b = *spi0_txp++;
00228         }
00229         outb(SPDR, b);
00230     }
00231 }
00232 #endif 
00233 
00255 int AvrSpiBus0Transfer(NUTSPINODE * node, CONST void *txbuf, void *rxbuf, int xlen)
00256 {
00257     uint8_t b = 0xff;
00258 
00259     
00260     NUTASSERT(node != NULL);
00261 
00262 #ifdef SPIBUS0_POLLING_MODE
00263     
00264 
00265 
00266     spi0_txp = (uint8_t *) txbuf;
00267     spi0_rxp = (uint8_t *) rxbuf;
00268 
00269     while (xlen--) {
00270         if (spi0_txp) {
00271             b = *spi0_txp++;
00272         }
00273         outb(SPDR, b);
00274         while ((inb(SPSR) & 0x80) == 0);
00275         b = inb(SPDR);
00276         if (spi0_rxp) {
00277             *spi0_rxp++ = b;
00278         }
00279     }
00280 #else                           
00281     if (xlen) {
00282 #ifdef SPIBUS0_DOUBLE_BUFFER
00283         
00284 
00285 
00286         cbi(SPCR, SPIE);
00287         
00288         while (spi0_nxc) {
00289             sbi(SPCR, SPIE);
00290             NutEventWait(&spi0_que, NUT_WAIT_INFINITE);
00291             cbi(SPCR, SPIE);
00292         }
00293         if (spi0_xc) {
00294             
00295             spi0_ntxp = (uint8_t *) txbuf;
00296             spi0_nrxp = (uint8_t *) rxbuf;
00297             spi0_nxc = (size_t) xlen;
00298             sbi(SPCR, SPIE);
00299         } else {
00300             spi0_txp = (uint8_t *) txbuf;
00301             spi0_rxp = (uint8_t *) rxbuf;
00302             spi0_xc = (size_t) xlen;
00303             if (spi0_txp) {
00304                 b = *spi0_txp++;
00305             }
00306             
00307             sbi(SPCR, SPIE);
00308             outb(SPDR, b);
00309         }
00310 #else                           
00311         
00312 
00313 
00314         spi0_txp = (uint8_t *) txbuf;
00315         spi0_rxp = (uint8_t *) rxbuf;
00316         spi0_xc = (size_t) xlen;
00317         if (spi0_txp) {
00318             b = *spi0_txp++;
00319         }
00320         
00321         sbi(SPCR, SPIE);
00322         outb(SPDR, b);
00323         
00324         NutEventWait(&spi0_que, NUT_WAIT_INFINITE);
00325         cbi(SPCR, SPIE);
00326 #endif                          
00327     }
00328 #endif                          
00329     return 0;
00330 }
00331 
00332 #ifdef SPIBUS0_DOUBLE_BUFFER
00333 
00342 int AvrSpiBus0Wait(NUTSPINODE * node, uint32_t tmo)
00343 {
00344     cbi(SPCR, SPIE);
00345     while (spi0_xc) {
00346         sbi(SPCR, SPIE);
00347         if (NutEventWait(&spi0_que, tmo)) {
00348             return -1;
00349         }
00350         cbi(SPCR, SPIE);
00351     }
00352     return 0;
00353 }
00354 #endif                          
00355 
00366 int AvrSpiBus0NodeInit(NUTSPINODE * node)
00367 {
00368     int rc;
00369 
00370     
00371     NUTASSERT(node != NULL);
00372 
00373     
00374     rc = AvrSpi0ChipSelect(node->node_cs, (node->node_mode & SPI_MODE_CSHIGH) == 0);
00375     
00376 
00377     if (rc == 0 && node->node_stat == NULL) {
00378         
00379         node->node_stat = malloc(sizeof(AVRSPIREG));
00380         if (node->node_stat) {
00381             AvrSpiSetup(node);
00382 #ifndef SPIBUS0_POLLING_MODE
00383             
00384             NutRegisterIrqHandler(node->node_bus->bus_sig, AvrSpi0Interrupt, NULL);
00385 #endif
00386         } else {
00387             
00388             rc = -1;
00389         }
00390     }
00391     return rc;
00392 }
00393 
00405 int AvrSpiBus0Select(NUTSPINODE * node, uint32_t tmo)
00406 {
00407     int rc;
00408 
00409     
00410     NUTASSERT(node != NULL);
00411     NUTASSERT(node->node_stat != NULL);
00412 
00413     
00414     rc = NutEventWait(&node->node_bus->bus_mutex, tmo);
00415     if (rc) {
00416         errno = EIO;
00417     } else {
00418         AVRSPIREG *spireg = node->node_stat;
00419 
00420         
00421         if (node->node_mode & SPI_MODE_UPDATE) {
00422             AvrSpiSetup(node);
00423         }
00424 
00425         
00426 
00427         if (spireg->avrspi_spcr & _BV(CPOL)) {
00428             cbi(PORTB, 1);
00429         } else {
00430             sbi(PORTB, 1);
00431         }
00432         sbi(DDRB, 1);
00433 
00434         
00435         cbi(PORTB, 2);
00436         sbi(DDRB, 2);
00437 
00438         
00439 
00440         if (bit_is_clear(DDRB, 0)) {
00441             sbi(PORTB, 0);
00442         }
00443 
00444         
00445         sbi(PORTB, 3);
00446 
00447         
00448         outb(SPCR, spireg->avrspi_spcr);
00449 #if defined(SPI2X)
00450         outb(SPSR, spireg->avrspi_spsr);
00451 #endif
00452 
00453         
00454         {
00455             uint8_t ix = inb(SPSR);
00456             ix = inb(SPDR);
00457         }
00458 
00459         
00460         rc = AvrSpi0ChipSelect(node->node_cs, (node->node_mode & SPI_MODE_CSHIGH) != 0);
00461         if (rc) {
00462             
00463             NutEventPost(&node->node_bus->bus_mutex);
00464         }
00465     }
00466     return rc;
00467 }
00468 
00477 int AvrSpiBus0Deselect(NUTSPINODE * node)
00478 {
00479     
00480     NUTASSERT(node != NULL);
00481     NUTASSERT(node->node_bus != NULL);
00482 
00483 #ifdef SPIBUS0_DOUBLE_BUFFER
00484     AvrSpiBus0Wait(node, NUT_WAIT_INFINITE);
00485 #endif
00486     
00487     AvrSpi0ChipSelect(node->node_cs, (node->node_mode & SPI_MODE_CSHIGH) == 0);
00488 
00489     
00490     NutEventPost(&node->node_bus->bus_mutex);
00491 
00492     return 0;
00493 }
00494 
00498 NUTSPIBUS spiBus0Avr = {
00499     NULL,                       
00500     NULL,                       
00501     0,                          
00502     &sig_SPI,                   
00503     AvrSpiBus0NodeInit,         
00504     AvrSpiBus0Select,           
00505     AvrSpiBus0Deselect,         
00506     AvrSpiBus0Transfer,         
00507 #ifdef SPIBUS0_DOUBLE_BUFFER
00508     AvrSpiBus0Wait,
00509 #else
00510     NutSpiBusWait,              
00511 #endif
00512     NutSpiBusSetMode,           
00513     NutSpiBusSetRate,           
00514     NutSpiBusSetBits            
00515 };