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