BeRTOS
ser_sam3.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 #include <io/cm3.h>
00050 #include <drv/irq_cm3.h>
00051 
00052 #include <cpu/attr.h>
00053 
00054 #include <drv/ser.h>
00055 #include <drv/ser_p.h>
00056 
00057 #include <struct/fifobuf.h>
00058 
00059 
00060 #define SERIRQ_PRIORITY 4 ///< default priority for serial irqs.
00061 
00083 #ifndef SER_UART0_BUS_TXINIT
00084 
00089     #if CPU_ARM_AT91 && !CPU_ARM_SAM7S_LARGE && !CPU_ARM_SAM7X
00090         #warning Check USART0 pins!
00091     #endif
00092     #define SER_UART0_BUS_TXINIT do { \
00093         PIOA_PDR = BV(RXD0) | BV(TXD0); \
00094         PIO_PERIPH_SEL(PIOA_BASE, BV(RXD0) | BV(TXD0), USART0_PERIPH); \
00095     } while (0)
00096 #endif
00097 
00098 #ifndef SER_UART0_BUS_TXBEGIN
00099 
00102     #define SER_UART0_BUS_TXBEGIN
00103 #endif
00104 
00105 #ifndef SER_UART0_BUS_TXCHAR
00106 
00109     #define SER_UART0_BUS_TXCHAR(c) do { \
00110         US0_THR = (c); \
00111     } while (0)
00112 #endif
00113 
00114 #ifndef SER_UART0_BUS_TXEND
00115 
00118     #define SER_UART0_BUS_TXEND
00119 #endif
00120 
00121 /* End USART0 macros */
00122 
00123 #if USART_PORTS > 1
00124 
00125     #ifndef SER_UART1_BUS_TXINIT
00126 
00131         #if CPU_ARM_AT91 && !CPU_ARM_SAM7S_LARGE && !CPU_ARM_SAM7X
00132             #warning Check USART1 pins!
00133         #endif
00134         #define SER_UART1_BUS_TXINIT do { \
00135             PIOA_PDR = BV(RXD1) | BV(TXD1); \
00136             PIO_PERIPH_SEL(PIOA_BASE, BV(RXD1) | BV(TXD1), USART1_PERIPH); \
00137         } while (0)
00138     #endif
00139 
00140     #ifndef SER_UART1_BUS_TXBEGIN
00141 
00144         #define SER_UART1_BUS_TXBEGIN
00145     #endif
00146 
00147     #ifndef SER_UART1_BUS_TXCHAR
00148 
00151         #define SER_UART1_BUS_TXCHAR(c) do { \
00152             US1_THR = (c); \
00153         } while (0)
00154     #endif
00155 
00156     #ifndef SER_UART1_BUS_TXEND
00157 
00160         #define SER_UART1_BUS_TXEND
00161     #endif
00162 
00163 #endif
00164 
00174 #ifndef SER_SPI0_BUS_TXINIT
00175 
00179     #if CPU_CM3_SAM3
00180         #define SER_SPI0_BUS_TXINIT do { \
00181             /* Disable PIO on SPI pins */ \
00182             PIOA_PDR = BV(SPI0_SPCK) | BV(SPI0_MOSI) | BV(SPI0_MISO); \
00183             /* SPI is peripheral A on SAM3X,A,N,S,U */ \
00184             PIO_PERIPH_SEL(PIOA_BASE, BV(SPI0_SPCK) | BV(SPI0_MOSI) | BV(SPI0_MISO), PIO_PERIPH_A); \
00185         } while (0)
00186     #else
00187         #define SER_SPI0_BUS_TXINIT do { \
00188             /* Disable PIO on SPI pins */ \
00189             PIOA_PDR = BV(SPI0_SPCK) | BV(SPI0_MOSI) | BV(SPI0_MISO); \
00190         } while (0)
00191     #endif
00192 #endif
00193 
00194 #ifndef SER_SPI0_BUS_TXCLOSE
00195 
00199     #define SER_SPI0_BUS_TXCLOSE do { \
00200         /* Enable PIO on SPI pins */ \
00201         PIOA_PER = BV(SPI0_SPCK) | BV(SPI0_MOSI) | BV(SPI0_MISO); \
00202     } while (0)
00203 #endif
00204 
00205 #if CPU_ARM_SAM7X
00206 
00207     #ifndef SER_SPI1_BUS_TXINIT
00208 
00212         #define SER_SPI1_BUS_TXINIT do { \
00213             /* Disable PIO on SPI pins */ \
00214             PIOA_PDR = BV(SPI1_SPCK) | BV(SPI1_MOSI) | BV(SPI1_MISO); \
00215             /* SPI1 pins are on B peripheral function! */ \
00216             PIOA_BSR = BV(SPI1_SPCK) | BV(SPI1_MOSI) | BV(SPI1_MISO); \
00217         } while (0)
00218     #endif
00219 
00220     #ifndef SER_SPI1_BUS_TXCLOSE
00221 
00225         #define SER_SPI1_BUS_TXCLOSE do { \
00226             /* Enable PIO on SPI pins */ \
00227             PIOA_PER = BV(SPI1_SPCK) | BV(SPI1_MOSI) | BV(SPI1_MISO); \
00228         } while (0)
00229     #endif
00230 #endif
00231 /*\}*/
00232 
00233 
00244 #if CPU_ARM_AT91
00245 
00246 INLINE void sysirq_setHandler(sysirq_t irq, sysirq_handler_t handler)
00247 {
00248     /* Set the vector. */
00249     AIC_SVR(irq) = uart0_irq_dispatcher;
00250 
00251     /* Initialize to level/edge sensitive with defined priority. */
00252 #if CPU_ARM_SAM7X
00253     if (irq == SPI0_ID || irq == SPI1_ID)
00254 #else
00255     if (irq == SPI0_ID)
00256 #endif
00257         AIC_SMR(irq) = (AIC_SMR(irq) & ~AIC_SRCTYPE_MASK) | AIC_SRCTYPE_INT_EDGE_TRIGGERED;
00258     else // USART/UART
00259         AIC_SMR(irq) = (AIC_SMR(irq) & ~AIC_SRCTYPE_MASK) | AIC_SRCTYPE_INT_LEVEL_SENSITIVE;
00260 
00261     /* Enable IRQ */
00262     AIC_IECR = BV(irq);
00263 }
00264 
00265 INLINE void sysirq_setPriority(sysirq_t irq, int prio)
00266 {
00267     AIC_SMR(irq) = (AIC_SMR(irq) & ~AIC_PRIOR_MASK) | SERIRQ_PRIORITY;
00268 }
00269 
00271 #define SER_INT_ACK do { \
00272     AIC_EOICR = 0; \
00273 } while (0)
00274 
00275 #elif CPU_CM3_SAM3
00276 
00278 #define SER_INT_ACK do { /* nop */ } while (0)
00279 
00280 #else
00281     #error No interrupt handling macros defined for current architecture
00282 #endif
00283 
00284 /*\}*/
00285 
00286 /* From the high-level serial driver */
00287 extern struct Serial *ser_handles[SER_CNT];
00288 
00289 /* TX and RX buffers */
00290 static unsigned char uart0_txbuffer[CONFIG_UART0_TXBUFSIZE];
00291 static unsigned char uart0_rxbuffer[CONFIG_UART0_RXBUFSIZE];
00292 #if USART_PORTS > 1
00293 static unsigned char uart1_txbuffer[CONFIG_UART1_TXBUFSIZE];
00294 static unsigned char uart1_rxbuffer[CONFIG_UART1_RXBUFSIZE];
00295 #endif
00296 static unsigned char spi0_txbuffer[CONFIG_SPI0_TXBUFSIZE];
00297 static unsigned char spi0_rxbuffer[CONFIG_SPI0_RXBUFSIZE];
00298 #if CPU_ARM_SAM7X
00299 static unsigned char spi1_txbuffer[CONFIG_SPI1_TXBUFSIZE];
00300 static unsigned char spi1_rxbuffer[CONFIG_SPI1_RXBUFSIZE];
00301 #endif
00302 
00319 struct ArmSerial
00320 {
00321     struct SerialHardware hw;
00322     volatile bool sending;
00323 };
00324 
00325 static ISR_PROTO(uart0_irq_dispatcher);
00326 #if USART_PORTS > 1
00327 static ISR_PROTO(uart1_irq_dispatcher);
00328 #endif
00329 static ISR_PROTO(spi0_irq_handler);
00330 #if CPU_ARM_SAM7X
00331 static ISR_PROTO(spi1_irq_handler);
00332 #endif
00333 /*
00334  * Callbacks for USART0
00335  */
00336 static void uart0_init(
00337     UNUSED_ARG(struct SerialHardware *, _hw),
00338     UNUSED_ARG(struct Serial *, ser))
00339 {
00340     US0_IDR = 0xFFFFFFFF;
00341     pmc_periphEnable(US0_ID);
00342 
00343     /*
00344      * - Reset USART0
00345      * - Set serial param: mode Normal, 8bit data, 1bit stop, parity none
00346      * - Enable both the receiver and the transmitter
00347      * - Enable only the RX complete interrupt
00348      */
00349     US0_CR = BV(US_RSTRX) | BV(US_RSTTX);
00350     US0_MR = US_CHMODE_NORMAL | US_CHRL_8 | US_NBSTOP_1 | US_PAR_NO;
00351     US0_CR = BV(US_RXEN) | BV(US_TXEN);
00352     US0_IER = BV(US_RXRDY);
00353 
00354     SER_UART0_BUS_TXINIT;
00355 
00356     sysirq_setPriority(INT_US0, SERIRQ_PRIORITY);
00357     sysirq_setHandler(INT_US0, uart0_irq_dispatcher);
00358 
00359     SER_STROBE_INIT;
00360 }
00361 
00362 static void uart0_cleanup(UNUSED_ARG(struct SerialHardware *, _hw))
00363 {
00364     US0_CR = BV(US_RSTRX) | BV(US_RSTTX) | BV(US_RXDIS) | BV(US_TXDIS) | BV(US_RSTSTA);
00365 }
00366 
00367 static void uart0_enabletxirq(struct SerialHardware *_hw)
00368 {
00369     struct ArmSerial *hw = (struct ArmSerial *)_hw;
00370 
00371     /*
00372      * WARNING: racy code here!  The tx interrupt sets hw->sending to false
00373      * when it runs with an empty fifo.  The order of statements in the
00374      * if-block matters.
00375      */
00376     if (!hw->sending)
00377     {
00378         hw->sending = true;
00379         /*
00380          * - Enable the transmitter
00381          * - Enable TX empty interrupt
00382          */
00383         SER_UART0_BUS_TXBEGIN;
00384         US0_IER = BV(US_TXEMPTY);
00385     }
00386 }
00387 
00388 static void uart0_setbaudrate(UNUSED_ARG(struct SerialHardware *, _hw), unsigned long rate)
00389 {
00390     /* Compute baud-rate period */
00391     US0_BRGR = CPU_FREQ / (16 * rate);
00392     //DB(kprintf("uart0_setbaudrate(rate=%lu): period=%d\n", rate, period);)
00393 }
00394 
00395 static void uart0_setparity(UNUSED_ARG(struct SerialHardware *, _hw), int parity)
00396 {
00397     US0_MR &= ~US_PAR_MASK;
00398     /* Set UART parity */
00399     switch(parity)
00400     {
00401         case SER_PARITY_NONE:
00402         {
00403             /* Parity none. */
00404             US0_MR |= US_PAR_NO;
00405             break;
00406         }
00407         case SER_PARITY_EVEN:
00408         {
00409             /* Even parity. */
00410             US0_MR |= US_PAR_EVEN;
00411             break;
00412         }
00413         case SER_PARITY_ODD:
00414         {
00415             /* Odd parity. */
00416             US0_MR |= US_PAR_ODD;
00417             break;
00418         }
00419         default:
00420             ASSERT(0);
00421     }
00422 }
00423 
00424 #if USART_PORTS > 1
00425 
00426 /*
00427  * Callbacks for USART1
00428  */
00429 static void uart1_init(
00430     UNUSED_ARG(struct SerialHardware *, _hw),
00431     UNUSED_ARG(struct Serial *, ser))
00432 {
00433     US1_IDR = 0xFFFFFFFF;
00434     pmc_periphEnable(US1_ID);
00435 
00436     /*
00437      * - Reset USART1
00438      * - Set serial param: mode Normal, 8bit data, 1bit stop, parity none
00439      * - Enable both the receiver and the transmitter
00440      * - Enable only the RX complete interrupt
00441      */
00442     US1_CR = BV(US_RSTRX) | BV(US_RSTTX);
00443     US1_MR = US_CHMODE_NORMAL | US_CHRL_8 | US_NBSTOP_1 | US_PAR_NO;
00444     US1_CR = BV(US_RXEN) | BV(US_TXEN);
00445     US1_IER = BV(US_RXRDY);
00446 
00447     SER_UART1_BUS_TXINIT;
00448 
00449     sysirq_setPriority(INT_US1, SERIRQ_PRIORITY);
00450     sysirq_setHandler(INT_US1, uart1_irq_dispatcher);
00451 
00452     SER_STROBE_INIT;
00453 }
00454 
00455 static void uart1_cleanup(UNUSED_ARG(struct SerialHardware *, _hw))
00456 {
00457     US1_CR = BV(US_RSTRX) | BV(US_RSTTX) | BV(US_RXDIS) | BV(US_TXDIS) | BV(US_RSTSTA);
00458 }
00459 
00460 static void uart1_enabletxirq(struct SerialHardware *_hw)
00461 {
00462     struct ArmSerial *hw = (struct ArmSerial *)_hw;
00463 
00464     /*
00465      * WARNING: racy code here!  The tx interrupt sets hw->sending to false
00466      * when it runs with an empty fifo.  The order of statements in the
00467      * if-block matters.
00468      */
00469     if (!hw->sending)
00470     {
00471         hw->sending = true;
00472         /*
00473          * - Enable the transmitter
00474          * - Enable TX empty interrupt
00475          */
00476         SER_UART1_BUS_TXBEGIN;
00477         US1_IER = BV(US_TXEMPTY);
00478     }
00479 }
00480 
00481 static void uart1_setbaudrate(UNUSED_ARG(struct SerialHardware *, _hw), unsigned long rate)
00482 {
00483     /* Compute baud-rate period */
00484     US1_BRGR = CPU_FREQ / (16 * rate);
00485     //DB(kprintf("uart0_setbaudrate(rate=%lu): period=%d\n", rate, period);)
00486 }
00487 
00488 static void uart1_setparity(UNUSED_ARG(struct SerialHardware *, _hw), int parity)
00489 {
00490     US1_MR &= ~US_PAR_MASK;
00491     /* Set UART parity */
00492     switch(parity)
00493     {
00494         case SER_PARITY_NONE:
00495         {
00496             /* Parity none. */
00497             US1_MR |= US_PAR_NO;
00498             break;
00499         }
00500         case SER_PARITY_EVEN:
00501         {
00502             /* Even parity. */
00503             US1_MR |= US_PAR_EVEN;
00504             break;
00505         }
00506         case SER_PARITY_ODD:
00507         {
00508             /* Odd parity. */
00509             US1_MR |= US_PAR_ODD;
00510             break;
00511         }
00512         default:
00513             ASSERT(0);
00514     }
00515 }
00516 
00517 #endif /* USART_PORTS > 1 */
00518 
00519 /* SPI driver */
00520 static void spi0_init(UNUSED_ARG(struct SerialHardware *, _hw), UNUSED_ARG(struct Serial *, ser))
00521 {
00522     SER_SPI0_BUS_TXINIT;
00523 
00524     /* Reset device */
00525     SPI0_CR = BV(SPI_SWRST);
00526 
00527     /*
00528      * Set SPI to master mode, fixed peripheral select, chip select directly connected to a peripheral device,
00529      * SPI clock set to MCK, mode fault detection disabled, loopback disable, NPCS0 active, Delay between CS = 0
00530      */
00531     SPI0_MR = BV(SPI_MSTR) | BV(SPI_MODFDIS);
00532 
00533     /*
00534      * Set SPI mode.
00535      * At reset clock division factor is set to 0, that is
00536      * *forbidden*. Set SPI clock to minimum to keep it valid.
00537      * Set all possible chip select registers in case user manually
00538      * change CPS field in SPI_MR.
00539      */
00540     SPI0_CSR0 = BV(SPI_NCPHA) | (255 << SPI_SCBR_SHIFT);
00541     SPI0_CSR1 = BV(SPI_NCPHA) | (255 << SPI_SCBR_SHIFT);
00542     SPI0_CSR2 = BV(SPI_NCPHA) | (255 << SPI_SCBR_SHIFT);
00543     SPI0_CSR3 = BV(SPI_NCPHA) | (255 << SPI_SCBR_SHIFT);
00544 
00545     /* Disable all irqs */
00546     SPI0_IDR = 0xFFFFFFFF;
00547 
00548     //sysirq_setPriority(INT_SPI0, SERIRQ_PRIORITY);
00549     sysirq_setHandler(INT_SPI0, spi0_irq_handler);
00550     pmc_periphEnable(SPI0_ID);
00551 
00552     /* Enable SPI */
00553     SPI0_CR = BV(SPI_SPIEN);
00554 
00555     SER_STROBE_INIT;
00556 }
00557 
00558 static void spi0_cleanup(UNUSED_ARG(struct SerialHardware *, _hw))
00559 {
00560     /* Disable SPI */
00561     SPI0_CR = BV(SPI_SPIDIS);
00562 
00563     /* Disable all irqs */
00564     SPI0_IDR = 0xFFFFFFFF;
00565 
00566     SER_SPI0_BUS_TXCLOSE;
00567 }
00568 
00569 static void spi0_starttx(struct SerialHardware *_hw)
00570 {
00571     struct ArmSerial *hw = (struct ArmSerial *)_hw;
00572 
00573     cpu_flags_t flags;
00574     IRQ_SAVE_DISABLE(flags);
00575 
00576     /* Send data only if the SPI is not already transmitting */
00577     if (!hw->sending && !fifo_isempty(&ser_handles[SER_SPI0]->txfifo))
00578     {
00579         hw->sending = true;
00580         SPI0_TDR = fifo_pop(&ser_handles[SER_SPI0]->txfifo);
00581         /* Enable interrupt on tx buffer empty */
00582         SPI0_IER = BV(SPI_TXEMPTY);
00583     }
00584 
00585     IRQ_RESTORE(flags);
00586 }
00587 
00588 static void spi0_setbaudrate(UNUSED_ARG(struct SerialHardware *, _hw), unsigned long rate)
00589 {
00590     SPI0_CSR0 &= ~SPI_SCBR;
00591 
00592     ASSERT((uint8_t)DIV_ROUND(CPU_FREQ, rate));
00593     SPI0_CSR0 |= DIV_ROUND(CPU_FREQ, rate) << SPI_SCBR_SHIFT;
00594 }
00595 
00596 #if CPU_ARM_SAM7X
00597 /* SPI driver */
00598 static void spi1_init(UNUSED_ARG(struct SerialHardware *, _hw), UNUSED_ARG(struct Serial *, ser))
00599 {
00600     SER_SPI1_BUS_TXINIT;
00601 
00602     /* Reset device */
00603     SPI1_CR = BV(SPI_SWRST);
00604 
00605     /*
00606      * Set SPI to master mode, fixed peripheral select, chip select directly connected to a peripheral device,
00607      * SPI clock set to MCK, mode fault detection disabled, loopback disable, NPCS0 active, Delay between CS = 0
00608      */
00609     SPI1_MR = BV(SPI_MSTR) | BV(SPI_MODFDIS);
00610 
00611     /*
00612      * Set SPI mode.
00613      * At reset clock division factor is set to 0, that is
00614      * *forbidden*. Set SPI clock to minimum to keep it valid.
00615      * Set all possible chip select registers in case user manually
00616      * change chip select.
00617      */
00618     SPI1_CSR0 = BV(SPI_NCPHA) | (255 << SPI_SCBR_SHIFT);
00619     SPI1_CSR1 = BV(SPI_NCPHA) | (255 << SPI_SCBR_SHIFT);
00620     SPI1_CSR2 = BV(SPI_NCPHA) | (255 << SPI_SCBR_SHIFT);
00621     SPI1_CSR3 = BV(SPI_NCPHA) | (255 << SPI_SCBR_SHIFT);
00622 
00623     /* Disable all SPI irqs */
00624     SPI1_IDR = 0xFFFFFFFF;
00625 
00626     sysirq_setPriority(INT_SPI1, SERIRQ_PRIORITY);
00627     sysirq_setHandler(INT_SPI1, spi1_irq_dispatcher);
00628     pmc_periphEnable(SPI1_ID);
00629 
00630     /* Enable SPI */
00631     SPI1_CR = BV(SPI_SPIEN);
00632 
00633     SER_STROBE_INIT;
00634 }
00635 
00636 static void spi1_cleanup(UNUSED_ARG(struct SerialHardware *, _hw))
00637 {
00638     /* Disable SPI */
00639     SPI1_CR = BV(SPI_SPIDIS);
00640 
00641     /* Disable all irqs */
00642     SPI1_IDR = 0xFFFFFFFF;
00643 
00644     SER_SPI1_BUS_TXCLOSE;
00645 }
00646 
00647 static void spi1_starttx(struct SerialHardware *_hw)
00648 {
00649     struct ArmSerial *hw = (struct ArmSerial *)_hw;
00650 
00651     cpu_flags_t flags;
00652     IRQ_SAVE_DISABLE(flags);
00653 
00654     /* Send data only if the SPI is not already transmitting */
00655     if (!hw->sending && !fifo_isempty(&ser_handles[SER_SPI1]->txfifo))
00656     {
00657         hw->sending = true;
00658         SPI1_TDR = fifo_pop(&ser_handles[SER_SPI1]->txfifo);
00659         /* Enable interrupt on tx buffer empty */
00660         SPI1_IER = BV(SPI_TXEMPTY);
00661     }
00662 
00663     IRQ_RESTORE(flags);
00664 }
00665 
00666 static void spi1_setbaudrate(UNUSED_ARG(struct SerialHardware *, _hw), unsigned long rate)
00667 {
00668     SPI1_CSR0 &= ~SPI_SCBR;
00669 
00670     ASSERT((uint8_t)DIV_ROUND(CPU_FREQ, rate));
00671     SPI1_CSR0 |= DIV_ROUND(CPU_FREQ, rate) << SPI_SCBR_SHIFT;
00672 }
00673 #endif
00674 
00675 static void spi_setparity(UNUSED_ARG(struct SerialHardware *, _hw), UNUSED_ARG(int, parity))
00676 {
00677     // nop
00678 }
00679 
00680 
00681 static bool tx_sending(struct SerialHardware* _hw)
00682 {
00683     struct ArmSerial *hw = (struct ArmSerial *)_hw;
00684     return hw->sending;
00685 }
00686 
00687 // FIXME: move into compiler.h?  Ditch?
00688 #if COMPILER_C99
00689     #define C99INIT(name,val) .name = val
00690 #elif defined(__GNUC__)
00691     #define C99INIT(name,val) name: val
00692 #else
00693     #warning No designated initializers, double check your code
00694     #define C99INIT(name,val) (val)
00695 #endif
00696 
00697 /*
00698  * High-level interface data structures
00699  */
00700 static const struct SerialHardwareVT UART0_VT =
00701 {
00702     C99INIT(init, uart0_init),
00703     C99INIT(cleanup, uart0_cleanup),
00704     C99INIT(setBaudrate, uart0_setbaudrate),
00705     C99INIT(setParity, uart0_setparity),
00706     C99INIT(txStart, uart0_enabletxirq),
00707     C99INIT(txSending, tx_sending),
00708 };
00709 
00710 #if USART_PORTS > 1
00711 
00712 static const struct SerialHardwareVT UART1_VT =
00713 {
00714     C99INIT(init, uart1_init),
00715     C99INIT(cleanup, uart1_cleanup),
00716     C99INIT(setBaudrate, uart1_setbaudrate),
00717     C99INIT(setParity, uart1_setparity),
00718     C99INIT(txStart, uart1_enabletxirq),
00719     C99INIT(txSending, tx_sending),
00720 };
00721 
00722 #endif /* USART_PORTS > 1 */
00723 
00724 static const struct SerialHardwareVT SPI0_VT =
00725 {
00726     C99INIT(init, spi0_init),
00727     C99INIT(cleanup, spi0_cleanup),
00728     C99INIT(setBaudrate, spi0_setbaudrate),
00729     C99INIT(setParity, spi_setparity),
00730     C99INIT(txStart, spi0_starttx),
00731     C99INIT(txSending, tx_sending),
00732 };
00733 #if CPU_ARM_SAM7X
00734 static const struct SerialHardwareVT SPI1_VT =
00735 {
00736     C99INIT(init, spi1_init),
00737     C99INIT(cleanup, spi1_cleanup),
00738     C99INIT(setBaudrate, spi1_setbaudrate),
00739     C99INIT(setParity, spi_setparity),
00740     C99INIT(txStart, spi1_starttx),
00741     C99INIT(txSending, tx_sending),
00742 };
00743 #endif
00744 
00745 static struct ArmSerial UARTDescs[SER_CNT] =
00746 {
00747     {
00748         C99INIT(hw, ) {
00749             C99INIT(table, &UART0_VT),
00750             C99INIT(txbuffer, uart0_txbuffer),
00751             C99INIT(rxbuffer, uart0_rxbuffer),
00752             C99INIT(txbuffer_size, sizeof(uart0_txbuffer)),
00753             C99INIT(rxbuffer_size, sizeof(uart0_rxbuffer)),
00754         },
00755         C99INIT(sending, false),
00756     },
00757 #if USART_PORTS > 1
00758     {
00759         C99INIT(hw, ) {
00760             C99INIT(table, &UART1_VT),
00761             C99INIT(txbuffer, uart1_txbuffer),
00762             C99INIT(rxbuffer, uart1_rxbuffer),
00763             C99INIT(txbuffer_size, sizeof(uart1_txbuffer)),
00764             C99INIT(rxbuffer_size, sizeof(uart1_rxbuffer)),
00765         },
00766         C99INIT(sending, false),
00767     },
00768 #endif
00769 
00770     {
00771         C99INIT(hw, ) {
00772             C99INIT(table, &SPI0_VT),
00773             C99INIT(txbuffer, spi0_txbuffer),
00774             C99INIT(rxbuffer, spi0_rxbuffer),
00775             C99INIT(txbuffer_size, sizeof(spi0_txbuffer)),
00776             C99INIT(rxbuffer_size, sizeof(spi0_rxbuffer)),
00777         },
00778         C99INIT(sending, false),
00779     },
00780     #if CPU_ARM_SAM7X
00781     {
00782         C99INIT(hw, ) {
00783             C99INIT(table, &SPI1_VT),
00784             C99INIT(txbuffer, spi1_txbuffer),
00785             C99INIT(rxbuffer, spi1_rxbuffer),
00786             C99INIT(txbuffer_size, sizeof(spi1_txbuffer)),
00787             C99INIT(rxbuffer_size, sizeof(spi1_rxbuffer)),
00788         },
00789         C99INIT(sending, false),
00790     }
00791 
00792     #endif
00793 };
00794 
00795 struct SerialHardware *ser_hw_getdesc(int unit)
00796 {
00797     ASSERT(unit < SER_CNT);
00798     return &UARTDescs[unit].hw;
00799 }
00800 
00804 INLINE void uart0_irq_tx(void)
00805 {
00806     SER_STROBE_ON;
00807 
00808     struct FIFOBuffer * const txfifo = &ser_handles[SER_UART0]->txfifo;
00809 
00810     if (fifo_isempty(txfifo))
00811     {
00812         /*
00813          * - Disable the TX empty interrupts
00814          */
00815         US0_IDR = BV(US_TXEMPTY);
00816         SER_UART0_BUS_TXEND;
00817         UARTDescs[SER_UART0].sending = false;
00818     }
00819     else
00820     {
00821         char c = fifo_pop(txfifo);
00822         SER_UART0_BUS_TXCHAR(c);
00823     }
00824 
00825     SER_STROBE_OFF;
00826 }
00827 
00831 INLINE void uart0_irq_rx(void)
00832 {
00833     SER_STROBE_ON;
00834 
00835     /* Should be read before US_CRS */
00836     ser_handles[SER_UART0]->status |= US0_CSR & (SERRF_RXSROVERRUN | SERRF_FRAMEERROR);
00837     US0_CR = BV(US_RSTSTA);
00838 
00839     char c = US0_RHR;
00840     struct FIFOBuffer * const rxfifo = &ser_handles[SER_UART0]->rxfifo;
00841 
00842     if (fifo_isfull(rxfifo))
00843         ser_handles[SER_UART0]->status |= SERRF_RXFIFOOVERRUN;
00844     else
00845         fifo_push(rxfifo, c);
00846 
00847     SER_STROBE_OFF;
00848 }
00849 
00853 static DECLARE_ISR(uart0_irq_dispatcher)
00854 {
00855     if (US0_CSR & BV(US_RXRDY))
00856         uart0_irq_rx();
00857 
00858     if (US0_CSR & BV(US_TXEMPTY))
00859         uart0_irq_tx();
00860 
00861     SER_INT_ACK;
00862 }
00863 
00864 #if USART_PORTS > 1
00865 
00869 INLINE void uart1_irq_tx(void)
00870 {
00871     SER_STROBE_ON;
00872 
00873     struct FIFOBuffer * const txfifo = &ser_handles[SER_UART1]->txfifo;
00874 
00875     if (fifo_isempty(txfifo))
00876     {
00877         /*
00878          * - Disable the TX empty interrupts
00879          */
00880         US1_IDR = BV(US_TXEMPTY);
00881         SER_UART1_BUS_TXEND;
00882         UARTDescs[SER_UART1].sending = false;
00883     }
00884     else
00885     {
00886         char c = fifo_pop(txfifo);
00887         SER_UART1_BUS_TXCHAR(c);
00888     }
00889 
00890     SER_STROBE_OFF;
00891 }
00892 
00896 INLINE void uart1_irq_rx(void)
00897 {
00898     SER_STROBE_ON;
00899 
00900     /* Should be read before US_CRS */
00901     ser_handles[SER_UART1]->status |= US1_CSR & (SERRF_RXSROVERRUN | SERRF_FRAMEERROR);
00902     US1_CR = BV(US_RSTSTA);
00903 
00904     char c = US1_RHR;
00905     struct FIFOBuffer * const rxfifo = &ser_handles[SER_UART1]->rxfifo;
00906 
00907     if (fifo_isfull(rxfifo))
00908         ser_handles[SER_UART1]->status |= SERRF_RXFIFOOVERRUN;
00909     else
00910         fifo_push(rxfifo, c);
00911 
00912     SER_STROBE_OFF;
00913 }
00914 
00918 static DECLARE_ISR(uart1_irq_dispatcher)
00919 {
00920     if (US1_CSR & BV(US_RXRDY))
00921         uart1_irq_rx();
00922 
00923     if (US1_CSR & BV(US_TXEMPTY))
00924         uart1_irq_tx();
00925 
00926     SER_INT_ACK;
00927 }
00928 
00929 #endif /* USART_PORTS > 1 */
00930 
00934 static DECLARE_ISR(spi0_irq_handler)
00935 {
00936     SER_STROBE_ON;
00937 
00938     char c = SPI0_RDR;
00939     /* Read incoming byte. */
00940     if (!fifo_isfull(&ser_handles[SER_SPI0]->rxfifo))
00941         fifo_push(&ser_handles[SER_SPI0]->rxfifo, c);
00942     /*
00943      * FIXME
00944     else
00945         ser_handles[SER_SPI0]->status |= SERRF_RXFIFOOVERRUN;
00946     */
00947 
00948     /* Send */
00949     if (!fifo_isempty(&ser_handles[SER_SPI0]->txfifo))
00950         SPI0_TDR = fifo_pop(&ser_handles[SER_SPI0]->txfifo);
00951     else
00952     {
00953         UARTDescs[SER_SPI0].sending = false;
00954         /* Disable interrupt on tx buffer empty */
00955         SPI0_IDR = BV(SPI_TXEMPTY);
00956     }
00957 
00958     SER_INT_ACK;
00959 
00960     SER_STROBE_OFF;
00961 }
00962 
00963 
00964 #if CPU_ARM_SAM7X
00965 
00968 static DECLARE_ISR(spi1_irq_handler)
00969 {
00970     SER_STROBE_ON;
00971 
00972     char c = SPI1_RDR;
00973     /* Read incoming byte. */
00974     if (!fifo_isfull(&ser_handles[SER_SPI1]->rxfifo))
00975         fifo_push(&ser_handles[SER_SPI1]->rxfifo, c);
00976     /*
00977      * FIXME
00978     else
00979         ser_handles[SER_SPI1]->status |= SERRF_RXFIFOOVERRUN;
00980     */
00981 
00982     /* Send */
00983     if (!fifo_isempty(&ser_handles[SER_SPI1]->txfifo))
00984         SPI1_TDR = fifo_pop(&ser_handles[SER_SPI1]->txfifo);
00985     else
00986     {
00987         UARTDescs[SER_SPI1].sending = false;
00988         /* Disable interrupt on tx buffer empty */
00989         SPI1_IDR = BV(SPI_TXEMPTY);
00990     }
00991 
00992     SER_INT_ACK;
00993 
00994     SER_STROBE_OFF;
00995 }
00996 #endif