ser_at91.c

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