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