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