BeRTOS
|
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