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     /* Reset device */
00534     SPI1_CR = BV(SPI_SWRST);
00535 
00536 /*
00537      * Set SPI to master mode, fixed peripheral select, chip select directly connected to a peripheral device,
00538      * SPI clock set to MCK, mode fault detection disabled, loopback disable, NPCS0 active, Delay between CS = 0
00539      */
00540     SPI1_MR = BV(SPI_MSTR) | BV(SPI_MODFDIS);
00541 
00542     /*
00543      * Set SPI mode.
00544      * At reset clock division factor is set to 0, that is
00545      * *forbidden*. Set SPI clock to minimum to keep it valid.
00546      */
00547     SPI1_CSR0 = BV(SPI_NCPHA) | (255 << SPI_SCBR_SHIFT);
00548 
00549     /* Disable all irqs */
00550     SPI1_IDR = 0xFFFFFFFF;
00551     /* Set the vector. */
00552     AIC_SVR(SPI1_ID) = spi1_irq_handler;
00553     /* Initialize to edge triggered with defined priority. */
00554     AIC_SMR(SPI1_ID) = AIC_SRCTYPE_INT_EDGE_TRIGGERED | SERIRQ_PRIORITY;
00555     /* Enable the USART IRQ */
00556     AIC_IECR = BV(SPI1_ID);
00557     PMC_PCER = BV(SPI1_ID);
00558 
00559     /* Enable interrupt on tx buffer empty */
00560     SPI1_IER = BV(SPI_TXEMPTY);
00561 
00562     /* Enable SPI */
00563     SPI1_CR = BV(SPI_SPIEN);
00564 
00565 
00566     SER_SPI1_BUS_TXINIT;
00567 
00568     SER_STROBE_INIT;
00569 }
00570 
00571 static void spi1_cleanup(UNUSED_ARG(struct SerialHardware *, _hw))
00572 {
00573     /* Disable SPI */
00574     SPI1_CR = BV(SPI_SPIDIS);
00575 
00576     /* Disable all irqs */
00577     SPI1_IDR = 0xFFFFFFFF;
00578 
00579     SER_SPI1_BUS_TXCLOSE;
00580 
00581     /* Enable PIO on SPI pins */
00582     PIOA_PER = BV(SPI1_SPCK) | BV(SPI1_MOSI) | BV(SPI1_MISO);
00583 }
00584 
00585 static void spi1_starttx(struct SerialHardware *_hw)
00586 {
00587     struct ArmSerial *hw = (struct ArmSerial *)_hw;
00588 
00589     cpu_flags_t flags;
00590     IRQ_SAVE_DISABLE(flags);
00591 
00592     /* Send data only if the SPI is not already transmitting */
00593     if (!hw->sending && !fifo_isempty(&ser_handles[SER_SPI1]->txfifo))
00594     {
00595         hw->sending = true;
00596         SPI1_TDR = fifo_pop(&ser_handles[SER_SPI1]->txfifo);
00597     }
00598 
00599     IRQ_RESTORE(flags);
00600 }
00601 
00602 static void spi1_setbaudrate(UNUSED_ARG(struct SerialHardware *, _hw), unsigned long rate)
00603 {
00604     SPI1_CSR0 &= ~SPI_SCBR;
00605 
00606     ASSERT((uint8_t)DIV_ROUND(CPU_FREQ, rate));
00607     SPI1_CSR0 |= DIV_ROUND(CPU_FREQ, rate) << SPI_SCBR_SHIFT;
00608 }
00609 #endif
00610 
00611 static void spi_setparity(UNUSED_ARG(struct SerialHardware *, _hw), UNUSED_ARG(int, parity))
00612 {
00613     // nop
00614 }
00615 
00616 
00617 static bool tx_sending(struct SerialHardware* _hw)
00618 {
00619     struct ArmSerial *hw = (struct ArmSerial *)_hw;
00620     return hw->sending;
00621 }
00622 
00623 // FIXME: move into compiler.h?  Ditch?
00624 #if COMPILER_C99
00625     #define C99INIT(name,val) .name = val
00626 #elif defined(__GNUC__)
00627     #define C99INIT(name,val) name: val
00628 #else
00629     #warning No designated initializers, double check your code
00630     #define C99INIT(name,val) (val)
00631 #endif
00632 
00633 /*
00634  * High-level interface data structures
00635  */
00636 static const struct SerialHardwareVT UART0_VT =
00637 {
00638     C99INIT(init, uart0_init),
00639     C99INIT(cleanup, uart0_cleanup),
00640     C99INIT(setBaudrate, uart0_setbaudrate),
00641     C99INIT(setParity, uart0_setparity),
00642     C99INIT(txStart, uart0_enabletxirq),
00643     C99INIT(txSending, tx_sending),
00644 };
00645 
00646 static const struct SerialHardwareVT UART1_VT =
00647 {
00648     C99INIT(init, uart1_init),
00649     C99INIT(cleanup, uart1_cleanup),
00650     C99INIT(setBaudrate, uart1_setbaudrate),
00651     C99INIT(setParity, uart1_setparity),
00652     C99INIT(txStart, uart1_enabletxirq),
00653     C99INIT(txSending, tx_sending),
00654 };
00655 
00656 static const struct SerialHardwareVT SPI0_VT =
00657 {
00658     C99INIT(init, spi0_init),
00659     C99INIT(cleanup, spi0_cleanup),
00660     C99INIT(setBaudrate, spi0_setbaudrate),
00661     C99INIT(setParity, spi_setparity),
00662     C99INIT(txStart, spi0_starttx),
00663     C99INIT(txSending, tx_sending),
00664 };
00665 #if CPU_ARM_SAM7X
00666 static const struct SerialHardwareVT SPI1_VT =
00667 {
00668     C99INIT(init, spi1_init),
00669     C99INIT(cleanup, spi1_cleanup),
00670     C99INIT(setBaudrate, spi1_setbaudrate),
00671     C99INIT(setParity, spi_setparity),
00672     C99INIT(txStart, spi1_starttx),
00673     C99INIT(txSending, tx_sending),
00674 };
00675 #endif
00676 
00677 static struct ArmSerial UARTDescs[SER_CNT] =
00678 {
00679     {
00680         C99INIT(hw, ) {
00681             C99INIT(table, &UART0_VT),
00682             C99INIT(txbuffer, uart0_txbuffer),
00683             C99INIT(rxbuffer, uart0_rxbuffer),
00684             C99INIT(txbuffer_size, sizeof(uart0_txbuffer)),
00685             C99INIT(rxbuffer_size, sizeof(uart0_rxbuffer)),
00686         },
00687         C99INIT(sending, false),
00688     },
00689     {
00690         C99INIT(hw, ) {
00691             C99INIT(table, &UART1_VT),
00692             C99INIT(txbuffer, uart1_txbuffer),
00693             C99INIT(rxbuffer, uart1_rxbuffer),
00694             C99INIT(txbuffer_size, sizeof(uart1_txbuffer)),
00695             C99INIT(rxbuffer_size, sizeof(uart1_rxbuffer)),
00696         },
00697         C99INIT(sending, false),
00698     },
00699 
00700     {
00701         C99INIT(hw, ) {
00702             C99INIT(table, &SPI0_VT),
00703             C99INIT(txbuffer, spi0_txbuffer),
00704             C99INIT(rxbuffer, spi0_rxbuffer),
00705             C99INIT(txbuffer_size, sizeof(spi0_txbuffer)),
00706             C99INIT(rxbuffer_size, sizeof(spi0_rxbuffer)),
00707         },
00708         C99INIT(sending, false),
00709     },
00710     #if CPU_ARM_SAM7X
00711     {
00712         C99INIT(hw, ) {
00713             C99INIT(table, &SPI1_VT),
00714             C99INIT(txbuffer, spi1_txbuffer),
00715             C99INIT(rxbuffer, spi1_rxbuffer),
00716             C99INIT(txbuffer_size, sizeof(spi1_txbuffer)),
00717             C99INIT(rxbuffer_size, sizeof(spi1_rxbuffer)),
00718         },
00719         C99INIT(sending, false),
00720     }
00721 
00722     #endif
00723 };
00724 
00725 struct SerialHardware *ser_hw_getdesc(int unit)
00726 {
00727     ASSERT(unit < SER_CNT);
00728     return &UARTDescs[unit].hw;
00729 }
00730 
00734 static void uart0_irq_tx(void)
00735 {
00736     SER_STROBE_ON;
00737 
00738     struct FIFOBuffer * const txfifo = &ser_handles[SER_UART0]->txfifo;
00739 
00740     if (fifo_isempty(txfifo))
00741     {
00742         /*
00743          * - Disable the TX empty interrupts
00744          */
00745         US0_IDR = BV(US_TXEMPTY);
00746         SER_UART0_BUS_TXEND;
00747         UARTDescs[SER_UART0].sending = false;
00748     }
00749     else
00750     {
00751         char c = fifo_pop(txfifo);
00752         SER_UART0_BUS_TXCHAR(c);
00753     }
00754 
00755     SER_STROBE_OFF;
00756 }
00757 
00761 static void uart0_irq_rx(void)
00762 {
00763     SER_STROBE_ON;
00764 
00765     /* Should be read before US_CRS */
00766     ser_handles[SER_UART0]->status |= US0_CSR & (SERRF_RXSROVERRUN | SERRF_FRAMEERROR);
00767     US0_CR = BV(US_RSTSTA);
00768 
00769     char c = US0_RHR;
00770     struct FIFOBuffer * const rxfifo = &ser_handles[SER_UART0]->rxfifo;
00771 
00772     if (fifo_isfull(rxfifo))
00773         ser_handles[SER_UART0]->status |= SERRF_RXFIFOOVERRUN;
00774     else
00775         fifo_push(rxfifo, c);
00776 
00777     SER_STROBE_OFF;
00778 }
00779 
00783 static void uart0_irq_dispatcher(void) __attribute__ ((interrupt));
00784 static void uart0_irq_dispatcher(void)
00785 {
00786     if (US0_CSR & BV(US_RXRDY))
00787         uart0_irq_rx();
00788 
00789     if (US0_CSR & BV(US_TXEMPTY))
00790         uart0_irq_tx();
00791 
00792     /* Inform hw that we have served the IRQ */
00793     AIC_EOICR = 0;
00794 }
00795 
00799 static void uart1_irq_tx(void)
00800 {
00801     SER_STROBE_ON;
00802 
00803     struct FIFOBuffer * const txfifo = &ser_handles[SER_UART1]->txfifo;
00804 
00805     if (fifo_isempty(txfifo))
00806     {
00807         /*
00808          * - Disable the TX empty interrupts
00809          */
00810         US1_IDR = BV(US_TXEMPTY);
00811         SER_UART1_BUS_TXEND;
00812         UARTDescs[SER_UART1].sending = false;
00813     }
00814     else
00815     {
00816         char c = fifo_pop(txfifo);
00817         SER_UART1_BUS_TXCHAR(c);
00818     }
00819 
00820     SER_STROBE_OFF;
00821 }
00822 
00826 static void uart1_irq_rx(void)
00827 {
00828     SER_STROBE_ON;
00829 
00830     /* Should be read before US_CRS */
00831     ser_handles[SER_UART1]->status |= US1_CSR & (SERRF_RXSROVERRUN | SERRF_FRAMEERROR);
00832     US1_CR = BV(US_RSTSTA);
00833 
00834     char c = US1_RHR;
00835     struct FIFOBuffer * const rxfifo = &ser_handles[SER_UART1]->rxfifo;
00836 
00837     if (fifo_isfull(rxfifo))
00838         ser_handles[SER_UART1]->status |= SERRF_RXFIFOOVERRUN;
00839     else
00840         fifo_push(rxfifo, c);
00841 
00842     SER_STROBE_OFF;
00843 }
00844 
00848 static void uart1_irq_dispatcher(void) __attribute__ ((interrupt));
00849 static void uart1_irq_dispatcher(void)
00850 {
00851     if (US1_CSR & BV(US_RXRDY))
00852         uart1_irq_rx();
00853 
00854     if (US1_CSR & BV(US_TXEMPTY))
00855         uart1_irq_tx();
00856 
00857     /* Inform hw that we have served the IRQ */
00858     AIC_EOICR = 0;
00859 }
00860 
00864 static void spi0_irq_handler(void) __attribute__ ((interrupt));
00865 static void spi0_irq_handler(void)
00866 {
00867     SER_STROBE_ON;
00868 
00869     char c = SPI0_RDR;
00870     /* Read incoming byte. */
00871     if (!fifo_isfull(&ser_handles[SER_SPI0]->rxfifo))
00872         fifo_push(&ser_handles[SER_SPI0]->rxfifo, c);
00873     /*
00874      * FIXME
00875     else
00876         ser_handles[SER_SPI0]->status |= SERRF_RXFIFOOVERRUN;
00877     */
00878 
00879     /* Send */
00880     if (!fifo_isempty(&ser_handles[SER_SPI0]->txfifo))
00881         SPI0_TDR = fifo_pop(&ser_handles[SER_SPI0]->txfifo);
00882     else
00883         UARTDescs[SER_SPI0].sending = false;
00884 
00885     /* Inform hw that we have served the IRQ */
00886     AIC_EOICR = 0;
00887     SER_STROBE_OFF;
00888 }
00889 
00890 
00891 #if CPU_ARM_SAM7X
00892 
00895 static void spi1_irq_handler(void) __attribute__ ((interrupt));
00896 static void spi1_irq_handler(void)
00897 {
00898     SER_STROBE_ON;
00899 
00900     char c = SPI1_RDR;
00901     /* Read incoming byte. */
00902     if (!fifo_isfull(&ser_handles[SER_SPI1]->rxfifo))
00903         fifo_push(&ser_handles[SER_SPI1]->rxfifo, c);
00904     /*
00905      * FIXME
00906     else
00907         ser_handles[SER_SPI1]->status |= SERRF_RXFIFOOVERRUN;
00908     */
00909 
00910     /* Send */
00911     if (!fifo_isempty(&ser_handles[SER_SPI1]->txfifo))
00912         SPI1_TDR = fifo_pop(&ser_handles[SER_SPI1]->txfifo);
00913     else
00914         UARTDescs[SER_SPI1].sending = false;
00915 
00916     /* Inform hw that we have served the IRQ */
00917     AIC_EOICR = 0;
00918     SER_STROBE_OFF;
00919 }
00920 #endif