ser_at91.c

Go to the documentation of this file.
00001 
00041 #include <io/arm.h>
00042 
00043 #include <cpu/attr.h>
00044 #include <drv/ser.h>
00045 #include <drv/ser_p.h>
00046 
00047 #include <hw/hw_ser.h>  /* Required for bus macros overrides */
00048 #include <hw/hw_cpu.h>  /* CLOCK_FREQ */
00049 
00050 #include <mware/fifobuf.h>
00051 #include <cfg/debug.h>
00052 
00053 #include <appconfig.h>
00054 
00055 #define SERIRQ_PRIORITY 4 
00056 
00057 
00078 #ifndef SER_UART0_BUS_TXINIT
00079 
00084     #if !CPU_ARM_AT91SAM7S256 && !CPU_ARM_AT91SAM7X256 && !CPU_ARM_AT91SAM7X128
00085         #warning Check USART0 pins!
00086     #endif
00087     #define SER_UART0_BUS_TXINIT do { \
00088         PIOA_PDR = BV(RXD0) | BV(TXD0); \
00089     } while (0)
00090 
00091 #endif
00092 
00093 #ifndef SER_UART0_BUS_TXBEGIN
00094 
00097     #define SER_UART0_BUS_TXBEGIN
00098 #endif
00099 
00100 #ifndef SER_UART0_BUS_TXCHAR
00101 
00104     #define SER_UART0_BUS_TXCHAR(c) do { \
00105         US0_THR = (c); \
00106     } while (0)
00107 #endif
00108 
00109 #ifndef SER_UART0_BUS_TXEND
00110 
00113     #define SER_UART0_BUS_TXEND
00114 #endif
00115 
00116 /* End USART0 macros */
00117 
00118 #ifndef SER_UART1_BUS_TXINIT
00119 
00124     #if !CPU_ARM_AT91SAM7S256 && !CPU_ARM_AT91SAM7X256 && !CPU_ARM_AT91SAM7X128
00125         #warning Check USART1 pins!
00126     #endif
00127     #define SER_UART1_BUS_TXINIT do { \
00128         PIOA_PDR = BV(RXD1) | BV(TXD1); \
00129     } while (0)
00130 
00131 #endif
00132 
00133 #ifndef SER_UART1_BUS_TXBEGIN
00134 
00137     #define SER_UART1_BUS_TXBEGIN
00138 #endif
00139 
00140 #ifndef SER_UART1_BUS_TXCHAR
00141 
00144     #define SER_UART1_BUS_TXCHAR(c) do { \
00145         US1_THR = (c); \
00146     } while (0)
00147 #endif
00148 
00149 #ifndef SER_UART1_BUS_TXEND
00150 
00153     #define SER_UART1_BUS_TXEND
00154 #endif
00155 
00165 #ifndef SER_SPI0_BUS_TXINIT
00166 
00170     #define SER_SPI0_BUS_TXINIT
00171 #endif
00172 
00173 #ifndef SER_SPI0_BUS_TXCLOSE
00174 
00178     #define SER_SPI0_BUS_TXCLOSE
00179 #endif
00180 
00181 #if CPU_ARM_AT91SAM7X128 || CPU_ARM_AT91SAM7X256
00182 
00183     #ifndef SER_SPI1_BUS_TXINIT
00184 
00188         #define SER_SPI1_BUS_TXINIT
00189     #endif
00190 
00191     #ifndef SER_SPI1_BUS_TXCLOSE
00192 
00196         #define SER_SPI1_BUS_TXCLOSE
00197     #endif
00198 #endif
00199 /*\}*/
00200 
00201 
00212 #if !defined(CONFIG_SER_STROBE) || !CONFIG_SER_STROBE
00213     #define SER_STROBE_ON    do {/*nop*/} while(0)
00214     #define SER_STROBE_OFF   do {/*nop*/} while(0)
00215     #define SER_STROBE_INIT  do {/*nop*/} while(0)
00216 #endif
00217 
00218 
00219 /* From the high-level serial driver */
00220 extern struct Serial ser_handles[SER_CNT];
00221 
00222 /* TX and RX buffers */
00223 static unsigned char uart0_txbuffer[CONFIG_UART0_TXBUFSIZE];
00224 static unsigned char uart0_rxbuffer[CONFIG_UART0_RXBUFSIZE];
00225 
00226 static unsigned char uart1_txbuffer[CONFIG_UART1_TXBUFSIZE];
00227 static unsigned char uart1_rxbuffer[CONFIG_UART1_RXBUFSIZE];
00228 
00229 static unsigned char spi0_txbuffer[CONFIG_SPI0_TXBUFSIZE];
00230 static unsigned char spi0_rxbuffer[CONFIG_SPI0_RXBUFSIZE];
00231 #if CPU_ARM_AT91SAM7X128 || CPU_ARM_AT91SAM7X256
00232 static unsigned char spi1_txbuffer[CONFIG_SPI1_TXBUFSIZE];
00233 static unsigned char spi1_rxbuffer[CONFIG_SPI1_RXBUFSIZE];
00234 #endif
00235 
00252 struct ArmSerial
00253 {
00254     struct SerialHardware hw;
00255     volatile bool sending;
00256 };
00257 
00258 
00259 /*
00260  * These are to trick GCC into *not* using absolute addressing mode
00261  * when accessing ser_handles, which is very expensive.
00262  *
00263  * Accessing through these pointers generates much shorter
00264  * (and hopefully faster) code.
00265  */
00266 struct Serial *ser_uart0 = &ser_handles[SER_UART0];
00267 struct Serial *ser_uart1 = &ser_handles[SER_UART1];
00268 
00269 struct Serial *ser_spi0 = &ser_handles[SER_SPI0];
00270 #if CPU_ARM_AT91SAM7X128 || CPU_ARM_AT91SAM7X256
00271 struct Serial *ser_spi1 = &ser_handles[SER_SPI1];
00272 #endif
00273 
00274 static void uart0_irq_dispatcher(void);
00275 static void uart1_irq_dispatcher(void);
00276 static void spi0_irq_handler(void);
00277 #if CPU_ARM_AT91SAM7X128 || CPU_ARM_AT91SAM7X256
00278 static void spi1_irq_handler(void);
00279 #endif
00280 /*
00281  * Callbacks for USART0
00282  */
00283 static void uart0_init(
00284     UNUSED_ARG(struct SerialHardware *, _hw),
00285     UNUSED_ARG(struct Serial *, ser))
00286 {
00287     US0_IDR = 0xFFFFFFFF;
00288     /* Set the vector. */
00289     AIC_SVR(US0_ID) = uart0_irq_dispatcher;
00290     /* Initialize to level sensitive with defined priority. */
00291     AIC_SMR(US0_ID) = AIC_SRCTYPE_INT_LEVEL_SENSITIVE | SERIRQ_PRIORITY;
00292     PMC_PCER = BV(US0_ID);
00293 
00294     /*
00295      * - Reset USART0
00296      * - Set serial param: mode Normal, 8bit data, 1bit stop, parity none
00297      * - Enable both the receiver and the transmitter
00298      * - Enable only the RX complete interrupt
00299      */
00300     US0_CR = BV(US_RSTRX) | BV(US_RSTTX);
00301     US0_MR = US_CHMODE_NORMAL | US_CHRL_8 | US_NBSTOP_1 | US_PAR_NO;
00302     US0_CR = BV(US_RXEN) | BV(US_TXEN);
00303     US0_IER = BV(US_RXRDY);
00304 
00305     SER_UART0_BUS_TXINIT;
00306 
00307     /* Enable the USART IRQ */
00308     AIC_IECR = BV(US0_ID);
00309 
00310     SER_STROBE_INIT;
00311 }
00312 
00313 static void uart0_cleanup(UNUSED_ARG(struct SerialHardware *, _hw))
00314 {
00315     US0_CR = BV(US_RSTRX) | BV(US_RSTTX) | BV(US_RXDIS) | BV(US_TXDIS) | BV(US_RSTSTA);
00316 }
00317 
00318 static void uart0_enabletxirq(struct SerialHardware *_hw)
00319 {
00320     struct ArmSerial *hw = (struct ArmSerial *)_hw;
00321 
00322     /*
00323      * WARNING: racy code here!  The tx interrupt sets hw->sending to false
00324      * when it runs with an empty fifo.  The order of statements in the
00325      * if-block matters.
00326      */
00327     if (!hw->sending)
00328     {
00329         hw->sending = true;
00330         /*
00331          * - Enable the transmitter
00332          * - Enable TX empty interrupt
00333          */
00334         SER_UART0_BUS_TXBEGIN;
00335         US0_IER = BV(US_TXEMPTY);
00336     }
00337 }
00338 
00339 static void uart0_setbaudrate(UNUSED_ARG(struct SerialHardware *, _hw), unsigned long rate)
00340 {
00341     /* Compute baud-rate period */
00342     US0_BRGR = CLOCK_FREQ / (16 * rate);
00343     //DB(kprintf("uart0_setbaudrate(rate=%lu): period=%d\n", rate, period);)
00344 }
00345 
00346 static void uart0_setparity(UNUSED_ARG(struct SerialHardware *, _hw), int parity)
00347 {
00348     US0_MR &= ~US_PAR_MASK;
00349     /* Set UART parity */
00350     switch(parity)
00351     {
00352         case SER_PARITY_NONE:
00353         {
00354             /* Parity none. */
00355             US0_MR |= US_PAR_NO;
00356             break;
00357         }
00358         case SER_PARITY_EVEN:
00359         {
00360             /* Even parity. */
00361             US0_MR |= US_PAR_EVEN;
00362             break;
00363         }
00364         case SER_PARITY_ODD:
00365         {
00366             /* Odd parity. */
00367             US0_MR |= US_PAR_ODD;
00368             break;
00369         }
00370         default:
00371             ASSERT(0);
00372     }
00373 
00374 }
00375 /*
00376  * Callbacks for USART1
00377  */
00378 static void uart1_init(
00379     UNUSED_ARG(struct SerialHardware *, _hw),
00380     UNUSED_ARG(struct Serial *, ser))
00381 {
00382     US1_IDR = 0xFFFFFFFF;
00383     /* Set the vector. */
00384     AIC_SVR(US1_ID) = uart1_irq_dispatcher;
00385     /* Initialize to level sensitive with defined priority. */
00386     AIC_SMR(US1_ID) = AIC_SRCTYPE_INT_LEVEL_SENSITIVE | SERIRQ_PRIORITY;
00387     PMC_PCER = BV(US1_ID);
00388 
00389     /*
00390      * - Reset USART1
00391      * - Set serial param: mode Normal, 8bit data, 1bit stop, parity none
00392      * - Enable both the receiver and the transmitter
00393      * - Enable only the RX complete interrupt
00394      */
00395     US1_CR = BV(US_RSTRX) | BV(US_RSTTX);
00396     US1_MR = US_CHMODE_NORMAL | US_CHRL_8 | US_NBSTOP_1 | US_PAR_NO;
00397     US1_CR = BV(US_RXEN) | BV(US_TXEN);
00398     US1_IER = BV(US_RXRDY);
00399 
00400     SER_UART1_BUS_TXINIT;
00401 
00402     /* Enable the USART IRQ */
00403     AIC_IECR = BV(US1_ID);
00404 
00405     SER_STROBE_INIT;
00406 }
00407 
00408 static void uart1_cleanup(UNUSED_ARG(struct SerialHardware *, _hw))
00409 {
00410     US1_CR = BV(US_RSTRX) | BV(US_RSTTX) | BV(US_RXDIS) | BV(US_TXDIS) | BV(US_RSTSTA);
00411 }
00412 
00413 static void uart1_enabletxirq(struct SerialHardware *_hw)
00414 {
00415     struct ArmSerial *hw = (struct ArmSerial *)_hw;
00416 
00417     /*
00418      * WARNING: racy code here!  The tx interrupt sets hw->sending to false
00419      * when it runs with an empty fifo.  The order of statements in the
00420      * if-block matters.
00421      */
00422     if (!hw->sending)
00423     {
00424         hw->sending = true;
00425         /*
00426          * - Enable the transmitter
00427          * - Enable TX empty interrupt
00428          */
00429         SER_UART1_BUS_TXBEGIN;
00430         US1_IER = BV(US_TXEMPTY);
00431     }
00432 }
00433 
00434 static void uart1_setbaudrate(UNUSED_ARG(struct SerialHardware *, _hw), unsigned long rate)
00435 {
00436     /* Compute baud-rate period */
00437     US1_BRGR = CLOCK_FREQ / (16 * rate);
00438     //DB(kprintf("uart0_setbaudrate(rate=%lu): period=%d\n", rate, period);)
00439 }
00440 
00441 static void uart1_setparity(UNUSED_ARG(struct SerialHardware *, _hw), int parity)
00442 {
00443     US1_MR &= ~US_PAR_MASK;
00444     /* Set UART parity */
00445     switch(parity)
00446     {
00447         case SER_PARITY_NONE:
00448         {
00449             /* Parity none. */
00450             US1_MR |= US_PAR_NO;
00451             break;
00452         }
00453         case SER_PARITY_EVEN:
00454         {
00455             /* Even parity. */
00456             US1_MR |= US_PAR_EVEN;
00457             break;
00458         }
00459         case SER_PARITY_ODD:
00460         {
00461             /* Odd parity. */
00462             US1_MR |= US_PAR_ODD;
00463             break;
00464         }
00465         default:
00466             ASSERT(0);
00467     }
00468 
00469 }
00470 
00471 /* SPI driver */
00472 static void spi0_init(UNUSED_ARG(struct SerialHardware *, _hw), UNUSED_ARG(struct Serial *, ser))
00473 {
00474     /* Disable PIO on SPI pins */
00475     PIOA_PDR = BV(SPI0_SPCK) | BV(SPI0_MOSI) | BV(SPI0_MISO);
00476 
00477     /* Reset device */
00478     SPI0_CR = BV(SPI_SWRST);
00479 
00480     /*
00481      * Set SPI to master mode, fixed peripheral select, chip select directly connected to a peripheral device,
00482      * SPI clock set to MCK, mode fault detection disabled, loopback disable, NPCS0 active, Delay between CS = 0
00483      */
00484     SPI0_MR = BV(SPI_MSTR) | BV(SPI_MODFDIS);
00485 
00486     /*
00487      * Set SPI mode.
00488      * At reset clock division factor is set to 0, that is
00489      * *forbidden*. Set SPI clock to minimum to keep it valid.
00490      */
00491     SPI0_CSR0 = BV(SPI_NCPHA) | (255 << SPI_SCBR_SHIFT);
00492 
00493     /* Disable all irqs */
00494     SPI0_IDR = 0xFFFFFFFF;
00495     /* Set the vector. */
00496     AIC_SVR(SPI0_ID) = spi0_irq_handler;
00497     /* Initialize to edge triggered with defined priority. */
00498     AIC_SMR(SPI0_ID) = AIC_SRCTYPE_INT_EDGE_TRIGGERED | SERIRQ_PRIORITY;
00499     /* Enable the USART IRQ */
00500     AIC_IECR = BV(SPI0_ID);
00501     PMC_PCER = BV(SPI0_ID);
00502 
00503     /* Enable interrupt on tx buffer empty */
00504     SPI0_IER = BV(SPI_TXEMPTY);
00505 
00506     /* Enable SPI */
00507     SPI0_CR = BV(SPI_SPIEN);
00508 
00509 
00510     SER_SPI0_BUS_TXINIT;
00511 
00512     SER_STROBE_INIT;
00513 }
00514 
00515 static void spi0_cleanup(UNUSED_ARG(struct SerialHardware *, _hw))
00516 {
00517     /* Disable SPI */
00518     SPI0_CR = BV(SPI_SPIDIS);
00519 
00520     /* Disable all irqs */
00521     SPI0_IDR = 0xFFFFFFFF;
00522 
00523     SER_SPI0_BUS_TXCLOSE;
00524 
00525     /* Enable PIO on SPI pins */
00526     PIOA_PER = BV(SPI0_SPCK) | BV(SPI0_MOSI) | BV(SPI0_MISO);
00527 }
00528 
00529 static void spi0_starttx(struct SerialHardware *_hw)
00530 {
00531     struct ArmSerial *hw = (struct ArmSerial *)_hw;
00532 
00533     cpuflags_t flags;
00534     IRQ_SAVE_DISABLE(flags);
00535 
00536     /* Send data only if the SPI is not already transmitting */
00537     if (!hw->sending && !fifo_isempty(&ser_spi0->txfifo))
00538     {
00539         hw->sending = true;
00540         SPI0_TDR = fifo_pop(&ser_spi0->txfifo);
00541     }
00542 
00543     IRQ_RESTORE(flags);
00544 }
00545 
00546 static void spi0_setbaudrate(UNUSED_ARG(struct SerialHardware *, _hw), unsigned long rate)
00547 {
00548     SPI0_CSR0 &= ~SPI_SCBR;
00549 
00550     ASSERT((uint8_t)DIV_ROUND(CLOCK_FREQ, rate));
00551     SPI0_CSR0 |= DIV_ROUND(CLOCK_FREQ, rate) << SPI_SCBR_SHIFT;
00552 }
00553 
00554 #if CPU_ARM_AT91SAM7X128 || CPU_ARM_AT91SAM7X256
00555 /* SPI driver */
00556 static void spi1_init(UNUSED_ARG(struct SerialHardware *, _hw), UNUSED_ARG(struct Serial *, ser))
00557 {
00558     /* Disable PIO on SPI pins */
00559     PIOA_PDR = BV(SPI1_SPCK) | BV(SPI1_MOSI) | BV(SPI1_MISO);
00560 
00561     /* Reset device */
00562     SPI1_CR = BV(SPI_SWRST);
00563 
00564 /*
00565      * Set SPI to master mode, fixed peripheral select, chip select directly connected to a peripheral device,
00566      * SPI clock set to MCK, mode fault detection disabled, loopback disable, NPCS0 active, Delay between CS = 0
00567      */
00568     SPI1_MR = BV(SPI_MSTR) | BV(SPI_MODFDIS);
00569 
00570     /*
00571      * Set SPI mode.
00572      * At reset clock division factor is set to 0, that is
00573      * *forbidden*. Set SPI clock to minimum to keep it valid.
00574      */
00575     SPI1_CSR0 = BV(SPI_NCPHA) | (255 << SPI_SCBR_SHIFT);
00576 
00577     /* Disable all irqs */
00578     SPI1_IDR = 0xFFFFFFFF;
00579     /* Set the vector. */
00580     AIC_SVR(SPI1_ID) = spi1_irq_handler;
00581     /* Initialize to edge triggered with defined priority. */
00582     AIC_SMR(SPI1_ID) = AIC_SRCTYPE_INT_EDGE_TRIGGERED | SERIRQ_PRIORITY;
00583     /* Enable the USART IRQ */
00584     AIC_IECR = BV(SPI1_ID);
00585     PMC_PCER = BV(SPI1_ID);
00586 
00587     /* Enable interrupt on tx buffer empty */
00588     SPI1_IER = BV(SPI_TXEMPTY);
00589 
00590     /* Enable SPI */
00591     SPI1_CR = BV(SPI_SPIEN);
00592 
00593 
00594     SER_SPI1_BUS_TXINIT;
00595 
00596     SER_STROBE_INIT;
00597 }
00598 
00599 static void spi1_cleanup(UNUSED_ARG(struct SerialHardware *, _hw))
00600 {
00601     /* Disable SPI */
00602     SPI1_CR = BV(SPI_SPIDIS);
00603 
00604     /* Disable all irqs */
00605     SPI1_IDR = 0xFFFFFFFF;
00606 
00607     SER_SPI1_BUS_TXCLOSE;
00608 
00609     /* Enable PIO on SPI pins */
00610     PIOA_PER = BV(SPI1_SPCK) | BV(SPI1_MOSI) | BV(SPI1_MISO);
00611 }
00612 
00613 static void spi1_starttx(struct SerialHardware *_hw)
00614 {
00615     struct ArmSerial *hw = (struct ArmSerial *)_hw;
00616 
00617     cpuflags_t flags;
00618     IRQ_SAVE_DISABLE(flags);
00619 
00620     /* Send data only if the SPI is not already transmitting */
00621     if (!hw->sending && !fifo_isempty(&ser_spi1->txfifo))
00622     {
00623         hw->sending = true;
00624         SPI1_TDR = fifo_pop(&ser_spi1->txfifo);
00625     }
00626 
00627     IRQ_RESTORE(flags);
00628 }
00629 
00630 static void spi1_setbaudrate(UNUSED_ARG(struct SerialHardware *, _hw), unsigned long rate)
00631 {
00632     SPI1_CSR0 &= ~SPI_SCBR;
00633 
00634     ASSERT((uint8_t)DIV_ROUND(CLOCK_FREQ, rate));
00635     SPI1_CSR0 |= DIV_ROUND(CLOCK_FREQ, rate) << SPI_SCBR_SHIFT;
00636 }
00637 #endif
00638 
00639 static void spi_setparity(UNUSED_ARG(struct SerialHardware *, _hw), UNUSED_ARG(int, parity))
00640 {
00641     // nop
00642 }
00643 
00644 
00645 static bool tx_sending(struct SerialHardware* _hw)
00646 {
00647     struct ArmSerial *hw = (struct ArmSerial *)_hw;
00648     return hw->sending;
00649 }
00650 
00651 // FIXME: move into compiler.h?  Ditch?
00652 #if COMPILER_C99
00653     #define C99INIT(name,val) .name = val
00654 #elif defined(__GNUC__)
00655     #define C99INIT(name,val) name: val
00656 #else
00657     #warning No designated initializers, double check your code
00658     #define C99INIT(name,val) (val)
00659 #endif
00660 
00661 /*
00662  * High-level interface data structures
00663  */
00664 static const struct SerialHardwareVT UART0_VT =
00665 {
00666     C99INIT(init, uart0_init),
00667     C99INIT(cleanup, uart0_cleanup),
00668     C99INIT(setBaudrate, uart0_setbaudrate),
00669     C99INIT(setParity, uart0_setparity),
00670     C99INIT(txStart, uart0_enabletxirq),
00671     C99INIT(txSending, tx_sending),
00672 };
00673 
00674 static const struct SerialHardwareVT UART1_VT =
00675 {
00676     C99INIT(init, uart1_init),
00677     C99INIT(cleanup, uart1_cleanup),
00678     C99INIT(setBaudrate, uart1_setbaudrate),
00679     C99INIT(setParity, uart1_setparity),
00680     C99INIT(txStart, uart1_enabletxirq),
00681     C99INIT(txSending, tx_sending),
00682 };
00683 
00684 static const struct SerialHardwareVT SPI0_VT =
00685 {
00686     C99INIT(init, spi0_init),
00687     C99INIT(cleanup, spi0_cleanup),
00688     C99INIT(setBaudrate, spi0_setbaudrate),
00689     C99INIT(setParity, spi_setparity),
00690     C99INIT(txStart, spi0_starttx),
00691     C99INIT(txSending, tx_sending),
00692 };
00693 #if CPU_ARM_AT91SAM7X128 || CPU_ARM_AT91SAM7X256
00694 static const struct SerialHardwareVT SPI1_VT =
00695 {
00696     C99INIT(init, spi1_init),
00697     C99INIT(cleanup, spi1_cleanup),
00698     C99INIT(setBaudrate, spi1_setbaudrate),
00699     C99INIT(setParity, spi_setparity),
00700     C99INIT(txStart, spi1_starttx),
00701     C99INIT(txSending, tx_sending),
00702 };
00703 #endif
00704 
00705 static struct ArmSerial UARTDescs[SER_CNT] =
00706 {
00707     {
00708         C99INIT(hw, ) {
00709             C99INIT(table, &UART0_VT),
00710             C99INIT(txbuffer, uart0_txbuffer),
00711             C99INIT(rxbuffer, uart0_rxbuffer),
00712             C99INIT(txbuffer_size, sizeof(uart0_txbuffer)),
00713             C99INIT(rxbuffer_size, sizeof(uart0_rxbuffer)),
00714         },
00715         C99INIT(sending, false),
00716     },
00717     {
00718         C99INIT(hw, ) {
00719             C99INIT(table, &UART1_VT),
00720             C99INIT(txbuffer, uart1_txbuffer),
00721             C99INIT(rxbuffer, uart1_rxbuffer),
00722             C99INIT(txbuffer_size, sizeof(uart1_txbuffer)),
00723             C99INIT(rxbuffer_size, sizeof(uart1_rxbuffer)),
00724         },
00725         C99INIT(sending, false),
00726     },
00727 
00728     {
00729         C99INIT(hw, ) {
00730             C99INIT(table, &SPI0_VT),
00731             C99INIT(txbuffer, spi0_txbuffer),
00732             C99INIT(rxbuffer, spi0_rxbuffer),
00733             C99INIT(txbuffer_size, sizeof(spi0_txbuffer)),
00734             C99INIT(rxbuffer_size, sizeof(spi0_rxbuffer)),
00735         },
00736         C99INIT(sending, false),
00737     },
00738     #if CPU_ARM_AT91SAM7X128 || CPU_ARM_AT91SAM7X256
00739     {
00740         C99INIT(hw, ) {
00741             C99INIT(table, &SPI1_VT),
00742             C99INIT(txbuffer, spi1_txbuffer),
00743             C99INIT(rxbuffer, spi1_rxbuffer),
00744             C99INIT(txbuffer_size, sizeof(spi1_txbuffer)),
00745             C99INIT(rxbuffer_size, sizeof(spi1_rxbuffer)),
00746         },
00747         C99INIT(sending, false),
00748     }
00749 
00750     #endif
00751 };
00752 
00753 struct SerialHardware *ser_hw_getdesc(int unit)
00754 {
00755     ASSERT(unit < SER_CNT);
00756     return &UARTDescs[unit].hw;
00757 }
00758 
00762 static void uart0_irq_tx(void)
00763 {
00764     SER_STROBE_ON;
00765 
00766     struct FIFOBuffer * const txfifo = &ser_uart0->txfifo;
00767 
00768     if (fifo_isempty(txfifo))
00769     {
00770         /*
00771          * - Disable the TX empty interrupts
00772          */
00773         US0_IDR = BV(US_TXEMPTY);
00774         SER_UART0_BUS_TXEND;
00775         UARTDescs[SER_UART0].sending = false;
00776     }
00777     else
00778     {
00779         char c = fifo_pop(txfifo);
00780         SER_UART0_BUS_TXCHAR(c);
00781     }
00782 
00783     SER_STROBE_OFF;
00784 }
00785 
00789 static void uart0_irq_rx(void)
00790 {
00791     SER_STROBE_ON;
00792 
00793     /* Should be read before US_CRS */
00794     ser_uart0->status |= US0_CSR & (SERRF_RXSROVERRUN | SERRF_FRAMEERROR);
00795     US0_CR = BV(US_RSTSTA);
00796 
00797     char c = US0_RHR;
00798     struct FIFOBuffer * const rxfifo = &ser_uart0->rxfifo;
00799 
00800     if (fifo_isfull(rxfifo))
00801         ser_uart0->status |= SERRF_RXFIFOOVERRUN;
00802     else
00803         fifo_push(rxfifo, c);
00804 
00805     SER_STROBE_OFF;
00806 }
00807 
00811 static void uart0_irq_dispatcher(void) __attribute__ ((interrupt));
00812 static void uart0_irq_dispatcher(void)
00813 {
00814     if (US0_CSR & BV(US_RXRDY))
00815         uart0_irq_rx();
00816 
00817     if (US0_CSR & BV(US_TXEMPTY))
00818         uart0_irq_tx();
00819 
00820     /* Inform hw that we have served the IRQ */
00821     AIC_EOICR = 0;
00822 }
00823 
00827 static void uart1_irq_tx(void)
00828 {
00829     SER_STROBE_ON;
00830 
00831     struct FIFOBuffer * const txfifo = &ser_uart1->txfifo;
00832 
00833     if (fifo_isempty(txfifo))
00834     {
00835         /*
00836          * - Disable the TX empty interrupts
00837          */
00838         US1_IDR = BV(US_TXEMPTY);
00839         SER_UART1_BUS_TXEND;
00840         UARTDescs[SER_UART1].sending = false;
00841     }
00842     else
00843     {
00844         char c = fifo_pop(txfifo);
00845         SER_UART1_BUS_TXCHAR(c);
00846     }
00847 
00848     SER_STROBE_OFF;
00849 }
00850 
00854 static void uart1_irq_rx(void)
00855 {
00856     SER_STROBE_ON;
00857 
00858     /* Should be read before US_CRS */
00859     ser_uart1->status |= US1_CSR & (SERRF_RXSROVERRUN | SERRF_FRAMEERROR);
00860     US1_CR = BV(US_RSTSTA);
00861 
00862     char c = US1_RHR;
00863     struct FIFOBuffer * const rxfifo = &ser_uart1->rxfifo;
00864 
00865     if (fifo_isfull(rxfifo))
00866         ser_uart1->status |= SERRF_RXFIFOOVERRUN;
00867     else
00868         fifo_push(rxfifo, c);
00869 
00870     SER_STROBE_OFF;
00871 }
00872 
00876 static void uart1_irq_dispatcher(void) __attribute__ ((interrupt));
00877 static void uart1_irq_dispatcher(void)
00878 {
00879     if (US1_CSR & BV(US_RXRDY))
00880         uart1_irq_rx();
00881 
00882     if (US1_CSR & BV(US_TXEMPTY))
00883         uart1_irq_tx();
00884 
00885     /* Inform hw that we have served the IRQ */
00886     AIC_EOICR = 0;
00887 }
00888 
00892 static void spi0_irq_handler(void) __attribute__ ((interrupt));
00893 static void spi0_irq_handler(void)
00894 {
00895     SER_STROBE_ON;
00896 
00897     char c = SPI0_RDR;
00898     /* Read incoming byte. */
00899     if (!fifo_isfull(&ser_spi0->rxfifo))
00900         fifo_push(&ser_spi0->rxfifo, c);
00901     /*
00902      * FIXME
00903     else
00904         ser_spi0->status |= SERRF_RXFIFOOVERRUN;
00905     */
00906 
00907     /* Send */
00908     if (!fifo_isempty(&ser_spi0->txfifo))
00909         SPI0_TDR = fifo_pop(&ser_spi0->txfifo);
00910     else
00911         UARTDescs[SER_SPI0].sending = false;
00912 
00913     /* Inform hw that we have served the IRQ */
00914     AIC_EOICR = 0;
00915     SER_STROBE_OFF;
00916 }
00917 
00918 
00919 #if CPU_ARM_AT91SAM7X128 || CPU_ARM_AT91SAM7X256
00920 
00923 static void spi1_irq_handler(void) __attribute__ ((interrupt));
00924 static void spi1_irq_handler(void)
00925 {
00926     SER_STROBE_ON;
00927 
00928     char c = SPI1_RDR;
00929     /* Read incoming byte. */
00930     if (!fifo_isfull(&ser_spi1->rxfifo))
00931         fifo_push(&ser_spi1->rxfifo, c);
00932     /*
00933      * FIXME
00934     else
00935         ser_spi1->status |= SERRF_RXFIFOOVERRUN;
00936     */
00937 
00938     /* Send */
00939     if (!fifo_isempty(&ser_spi1->txfifo))
00940         SPI1_TDR = fifo_pop(&ser_spi1->txfifo);
00941     else
00942         UARTDescs[SER_SPI1].sending = false;
00943 
00944     /* Inform hw that we have served the IRQ */
00945     AIC_EOICR = 0;
00946     SER_STROBE_OFF;
00947 }
00948 #endif