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 };