BeRTOS
|
00001 00043 #include "hw/hw_ser.h" /* Required for bus macros overrides */ 00044 #include <hw/hw_cpufreq.h> /* CPU_FREQ */ 00045 00046 #include "cfg/cfg_ser.h" /* Serialport configuration settings */ 00047 00048 #include <cfg/macros.h> /* DIV_ROUND */ 00049 #include <cfg/debug.h> /* debug configuration */ 00050 00051 #include <drv/ser.h> 00052 #include <drv/ser_p.h> 00053 #include <drv/timer.h> 00054 00055 #include <struct/fifobuf.h> 00056 00057 #include <avr/io.h> /* AVR IO ports and structures */ 00058 #include <avr/interrupt.h> /* AVR Interrupt methods */ 00059 00060 /* 00061 * Scalefactor to use for computing the baudrate 00062 * this scalefactor should be an integer value between -7 00063 * and 7 00064 */ 00065 #ifndef USART_SCALE_FACTOR 00066 #define USART_SCALE_FACTOR (-7) 00067 #else 00068 #if USART_SCALE_FACTOR > 7 || USART_SCALE_FACTOR < -7 00069 #error USART_SCALE_FACTOR should be an integer between -7 and 7 00070 #endif 00071 #endif 00072 00073 /* Helper macros, mostly taken from the Atmel Examples 00074 * Slightly alterd to match the BeRTOS naming convention 00075 */ 00076 00077 /* \brief Set USART baud rate. 00078 * 00079 * Sets the USART's baud rate register. 00080 * 00081 * UBRR_Value : Value written to UBRR 00082 * ScaleFactor : Time Base Generator Scale Factor 00083 * 00084 * Equation for calculation of BSEL value in asynchronous normal speed mode: 00085 * If ScaleFactor >= 0 00086 * BSEL = ((I/O clock frequency)/(2^(ScaleFactor)*16*Baudrate))-1 00087 * If ScaleFactor < 0 00088 * BSEL = (1/(2^(ScaleFactor)*16))*(((I/O clock frequency)/Baudrate)-1) 00089 * 00090 * \note See XMEGA manual for equations for calculation of BSEL value in other 00091 * modes. 00092 * 00093 * \param _usart Pointer to the USART module. 00094 * \param _bselValue Value to write to BSEL part of Baud control register. 00095 * Use uint16_t type. 00096 * \param _bScaleFactor USART baud rate scale factor. 00097 * Use uint8_t type 00098 */ 00099 #define USART_SET_BAUDRATE(_usart, _bselValue, _bScaleFactor) \ 00100 (_usart)->BAUDCTRLA =(uint8_t)_bselValue; \ 00101 (_usart)->BAUDCTRLB =(_bScaleFactor << USART_BSCALE0_bp)|(_bselValue >> 8) 00102 00103 /* \brief Enable USART receiver. 00104 * 00105 * \param _usart Pointer to the USART module 00106 */ 00107 #define USART_RX_ENABLE(_usart) ((_usart)->CTRLB |= USART_RXEN_bm) 00108 00109 /* \brief Disable USART receiver. 00110 * 00111 * \param _usart Pointer to the USART module. 00112 */ 00113 #define USART_RX_DISABLE(_usart) ((_usart)->CTRLB &= ~USART_RXEN_bm) 00114 00115 /* \brief Enable USART transmitter. 00116 * 00117 * \param _usart Pointer to the USART module. 00118 */ 00119 #define USART_TX_ENABLE(_usart) ((_usart)->CTRLB |= USART_TXEN_bm) 00120 00121 /* \brief Disable USART transmitter. 00122 * 00123 * \param _usart Pointer to the USART module. 00124 */ 00125 #define USART_TX_DISABLE(_usart) ((_usart)->CTRLB &= ~USART_TXEN_bm) 00126 00127 /* \brief Set USART RXD interrupt level. 00128 * 00129 * Sets the interrupt level on RX Complete interrupt. 00130 * 00131 * \param _usart Pointer to the USART module. 00132 * \param _rxdIntLevel Interrupt level of the RXD interrupt. 00133 * Use USART_RXCINTLVL_t type. 00134 */ 00135 #define USART_SET_RX_INTERRUPT_LEVEL(_usart, _rxdIntLevel) \ 00136 ((_usart)->CTRLA = ((_usart)->CTRLA & ~USART_RXCINTLVL_gm) | _rxdIntLevel) 00137 00138 /* \brief Set USART TXD interrupt level. 00139 * 00140 * Sets the interrupt level on TX Complete interrupt. 00141 * 00142 * \param _usart Pointer to the USART module. 00143 * \param _txdIntLevel Interrupt level of the TXD interrupt. 00144 * Use USART_TXCINTLVL_t type. 00145 */ 00146 #define USART_SET_TX_INTERRUPT_LEVEL(_usart, _txdIntLevel) \ 00147 (_usart)->CTRLA = ((_usart)->CTRLA & ~USART_TXCINTLVL_gm) | _txdIntLevel 00148 00149 /* \brief Set USART DRE interrupt level. 00150 * 00151 * Sets the interrupt level on Data Register interrupt. 00152 * 00153 * \param _usart Pointer to the USART module. 00154 * \param _dreIntLevel Interrupt level of the DRE interrupt. 00155 * Use USART_DREINTLVL_t type. 00156 */ 00157 #define USART_SET_DRE_INTERRUPT_LEVEL(_usart, _dreIntLevel) \ 00158 (_usart)->CTRLA = ((_usart)->CTRLA & ~USART_DREINTLVL_gm) | _dreIntLevel 00159 00160 /* \brief Set the mode the USART run in. 00161 * 00162 * Set the mode the USART run in. The default mode is asynchronous mode. 00163 * 00164 * \param _usart Pointer to the USART module register section. 00165 * \param _usartMode Selects the USART mode. Use USART_CMODE_t type. 00166 * 00167 * USART modes: 00168 * - 0x0 : Asynchronous mode. 00169 * - 0x1 : Synchronous mode. 00170 * - 0x2 : IrDA mode. 00171 * - 0x3 : Master SPI mode. 00172 */ 00173 #define USART_SET_MODE(_usart, _usartMode) \ 00174 ((_usart)->CTRLC = ((_usart)->CTRLC & (~USART_CMODE_gm)) | _usartMode) 00175 00176 /* \brief Check if data register empty flag is set. 00177 * 00178 * \param _usart The USART module. 00179 */ 00180 #define USART_IS_TX_DATA_REGISTER_EMPTY(_usart) (((_usart)->STATUS & USART_DREIF_bm) != 0) 00181 00182 /* \brief Put data (5-8 bit character). 00183 * 00184 * Use the macro USART_IsTXDataRegisterEmpty before using this function to 00185 * put data to the TX register. 00186 * 00187 * \param _usart The USART module. 00188 * \param _data The data to send. 00189 */ 00190 #define USART_PUT_CHAR(_usart, _data) ((_usart)->DATA = _data) 00191 00192 /* \brief Checks if the RX complete interrupt flag is set. 00193 * 00194 * Checks if the RX complete interrupt flag is set. 00195 * 00196 * \param _usart The USART module. 00197 */ 00198 #define USART_IS_RX_COMPLETE(_usart) (((_usart)->STATUS & USART_RXCIF_bm) != 0) 00199 00200 /* \brief Get received data (5-8 bit character). 00201 * 00202 * This macro reads out the RX register. 00203 * Use the macro USART_RX_Complete to check if anything is received. 00204 * 00205 * \param _usart The USART module. 00206 * 00207 * \retval Received data. 00208 */ 00209 #define USART_GET_CHAR(_usart) ((_usart)->DATA) 00210 00211 /* configurable macros */ 00212 00213 #if !CONFIG_SER_HWHANDSHAKE 00214 00218 #define RTS_ON do {} while (0) 00219 #define RTS_OFF do {} while (0) 00220 #define IS_CTS_ON true 00221 #define EIMSKF_CTS 0 00222 /*\}*/ 00223 #endif 00224 00225 /* 00226 * \name Overridable serial bus hooks 00227 * 00228 * These can be redefined in hw.h to implement 00229 * special bus policies such as half-duplex, 485, etc. 00230 * 00231 * 00232 * \code 00233 * TXBEGIN TXCHAR TXEND TXOFF 00234 * | __________|__________ | | 00235 * | | | | | | | | | 00236 * v v v v v v v v v 00237 * ______ __ __ __ __ __ __ ________________ 00238 * \/ \/ \/ \/ \/ \/ \/ 00239 * ______/\__/\__/\__/\__/\__/\__/ 00240 * 00241 * \endcode 00242 * 00243 * \{ 00244 */ 00245 00246 #ifndef SER_UART_BUS_TXINIT 00247 /* 00248 * Default TXINIT macro - invoked in uart_init() 00249 * 00250 * - Enable both the receiver and the transmitter 00251 * - Enable only the RX complete interrupt 00252 */ 00253 #define SER_UART_BUS_TXINIT(_usart) do { \ 00254 USART_RX_ENABLE(_usart); \ 00255 USART_TX_ENABLE(_usart); \ 00256 USART_SET_RX_INTERRUPT_LEVEL(_usart, USART_RXCINTLVL_MED_gc); \ 00257 } while (0) 00258 #endif 00259 00260 #ifndef SER_UART_BUS_TXBEGIN 00261 /* 00262 * Invoked before starting a transmission 00263 * 00264 * - Enable both the receiver and the transmitter 00265 * - Enable both the RX complete and UDR empty interrupts 00266 */ 00267 #define SER_UART_BUS_TXBEGIN(_usart) do { \ 00268 USART_SET_RX_INTERRUPT_LEVEL(_usart, USART_RXCINTLVL_MED_gc); \ 00269 USART_SET_DRE_INTERRUPT_LEVEL(_usart, USART_DREINTLVL_MED_gc);\ 00270 } while (0) 00271 #endif 00272 00273 #ifndef SER_UART_BUS_TXCHAR 00274 /* 00275 * Invoked to send one character. 00276 */ 00277 #define SER_UART_BUS_TXCHAR(_usart, c) do { \ 00278 USART_PUT_CHAR(_usart, c); \ 00279 } while (0) 00280 #endif 00281 00282 #ifndef SER_UART_BUS_TXEND 00283 /* 00284 * Invoked as soon as the txfifo becomes empty 00285 * 00286 * - Keep both the receiver and the transmitter enabled 00287 * - Keep the RX complete interrupt enabled 00288 * - Disable the UDR empty interrupt 00289 */ 00290 #define SER_UART_BUS_TXEND(_usart) do { \ 00291 USART_SET_DRE_INTERRUPT_LEVEL(_usart, USART_DREINTLVL_OFF_gc); \ 00292 } while (0) 00293 #endif 00294 00295 #ifndef SER_UART_BUS_TXOFF 00296 /* 00297 * \def SER_UART_BUS_TXOFF 00298 * 00299 * Invoked after the last character has been transmitted 00300 * 00301 * The default is no action. 00302 */ 00303 #ifdef __doxygen__ 00304 #define SER_UART_BUS_TXOFF(_usart) 00305 #endif 00306 #endif 00307 00308 /*\}*/ 00309 00310 /* From the high-level serial driver */ 00311 extern struct Serial *ser_handles[SER_CNT]; 00312 00313 /* TX and RX buffers */ 00314 static unsigned char uart0_txbuffer[CONFIG_UART0_TXBUFSIZE]; 00315 static unsigned char uart0_rxbuffer[CONFIG_UART0_RXBUFSIZE]; 00316 static unsigned char uart1_txbuffer[CONFIG_UART1_TXBUFSIZE]; 00317 static unsigned char uart1_rxbuffer[CONFIG_UART1_RXBUFSIZE]; 00318 #ifdef CPU_AVR_XMEGA_A 00319 static unsigned char uart2_txbuffer[CONFIG_UART2_TXBUFSIZE]; 00320 static unsigned char uart2_rxbuffer[CONFIG_UART2_RXBUFSIZE]; 00321 static unsigned char uart3_txbuffer[CONFIG_UART3_TXBUFSIZE]; 00322 static unsigned char uart3_rxbuffer[CONFIG_UART3_RXBUFSIZE]; 00323 static unsigned char uart4_txbuffer[CONFIG_UART4_TXBUFSIZE]; 00324 static unsigned char uart4_rxbuffer[CONFIG_UART4_RXBUFSIZE]; 00325 #endif 00326 00327 /* 00328 * Internal hardware state structure 00329 * 00330 * The \a sending variable is true while the transmission 00331 * interrupt is retriggering itself. 00332 * 00333 * the \a usart variable will point to the USART_t structure 00334 * that should be used. 00335 * 00336 * the \a port variable will point to the PORT_t structure 00337 * that should be modified to set the tx pin as an output and the 00338 * rx pin as an input 00339 * 00340 * the \a txpin variable will hold the pinnumber of the pin to use 00341 * as the tx output 00342 * 00343 * the \a rxpin variable will hold the pinnumber of the pin to use 00344 * as the rx input 00345 * 00346 * For the USARTs the \a sending flag is useful for taking specific 00347 * actions before sending a burst of data, at the start of a trasmission 00348 * but not before every char sent. 00349 * 00350 * For the SPI, this flag is necessary because the SPI sends and receives 00351 * bytes at the same time and the SPI IRQ is unique for send/receive. 00352 * The only way to start transmission is to write data in SPDR (this 00353 * is done by spi_starttx()). We do this *only* if a transfer is 00354 * not already started. 00355 */ 00356 struct AvrxmegaSerial 00357 { 00358 struct SerialHardware hw; 00359 volatile bool sending; 00360 volatile USART_t* usart; 00361 volatile PORT_t* port; 00362 uint8_t txpin; 00363 uint8_t rxpin; 00364 }; 00365 00366 /* 00367 * Callbacks 00368 * The same callbacks are used for all USARTS. 00369 * By casting the SerialHardware structure to the AvrxmegaSerial 00370 * structure a pointer to the USART_t structure can be obtained, 00371 * to perform the callback for the specific USART. 00372 * This methode might cost some more cpu time, but saves on 00373 * code duplication and code size. 00374 */ 00375 00376 00377 /* 00378 * \brief Initializes the uart 00379 * 00380 * The TX pin of the uart will be set as an outputpin 00381 * The RX pin of the uart will be set as an inputpin 00382 * The usart will be initialized 00383 * \see SER_UART_BUS_TXINIT 00384 * 00385 * \param _hw struct AvrxmegaSerial 00386 * \param ser Unused 00387 */ 00388 static void uart_init(struct SerialHardware * _hw, UNUSED_ARG(struct Serial *, ser)) 00389 { 00390 struct AvrxmegaSerial *hw = (struct AvrxmegaSerial *)_hw; 00391 //set transmit pin as output 00392 hw->port->DIRSET = BV(hw->txpin); 00393 hw->port->OUTCLR = BV(hw->txpin); 00394 //set receive pin as input 00395 hw->port->DIRCLR = BV(hw->rxpin); 00396 //initialize the USART 00397 SER_UART_BUS_TXINIT(hw->usart); 00398 RTS_ON; 00399 SER_STROBE_INIT; 00400 } 00401 00402 /* 00403 * \brief Cleans up / Disables the uart 00404 * 00405 * \param _hw struct AvrxmegaSerial 00406 */ 00407 static void uart_cleanup(struct SerialHardware * _hw) 00408 { 00409 struct AvrxmegaSerial *hw = (struct AvrxmegaSerial *)_hw; 00410 hw->usart->CTRLA = 0; 00411 hw->usart->CTRLB = 0; 00412 } 00413 00414 /* 00415 * \brief Enableds the TX interrupt 00416 * 00417 * \param _hw struct AvrxmegaSerial 00418 */ 00419 static void uart_enabletxirq(struct SerialHardware *_hw) 00420 { 00421 struct AvrxmegaSerial *hw = (struct AvrxmegaSerial *)_hw; 00422 00423 /* 00424 * WARNING: racy code here! The tx interrupt sets hw->sending to false 00425 * when it runs with an empty fifo. The order of statements in the 00426 * if-block matters. 00427 */ 00428 if (!hw->sending) 00429 { 00430 hw->sending = true; 00431 SER_UART_BUS_TXBEGIN(hw->usart); 00432 } 00433 } 00434 00435 /* 00436 * \brief sets the uart to the provided baudrate 00437 * 00438 * For setting the baudrate an scale factor (bscale) and a period 00439 * setting (BSEL) is required. 00440 * 00441 * The scale factor should be privided by defining USART_SCALE_FACTOR 00442 * 00443 * Atmel specifies BSEL for normal speed mode and bscale >= 0 as: 00444 * BSEL = (cpu_freq / ((2^bscale) * 16 * rate)) - 1 00445 * To allow BSEL to be calculated with an power function this can be 00446 * rewriten to: 00447 * BSEL = BSEL = (cpu_freq / ((1 << bscale) * 16 * rate)) - 1 00448 * 00449 * Atmel specifies BSEL for normal speed mode and bscale < 0 as: 00450 * BSEL = (1 / (2^bscale)) * ( (cpu_freq / (16 * rate)) - 1) 00451 * To calculte this float atheritmic is required as the second product will be smaller 00452 * than zero in a lot of cases. 00453 * To allow BSEL to be calculated with interger devision and no power function 00454 * this can be rewriten by folowing simple math rules to: 00455 * BSEL = ((1 << -bscale) * (cpu_freq - (16 * rate)) / (16 * rate) 00456 * 00457 * \param _hw struct AvrxmegaSerial 00458 * \param _rate the required baudrate 00459 * 00460 */ 00461 static void uart_setbaudrate(struct SerialHardware * _hw, unsigned long _rate) 00462 { 00463 struct AvrxmegaSerial *hw = (struct AvrxmegaSerial *)_hw; 00464 /* Compute baud-rate period, this requires a valid USART_SCALE_FACTOR */ 00465 #if USART_SCALE_FACTOR < 0 00466 uint16_t bsel = DIV_ROUND((1 << (-(USART_SCALE_FACTOR))) * (CPU_FREQ - (16 * _rate)), 16 * _rate); 00467 #else 00468 uint16_t bsel = DIV_ROUND(CPU_FREQ, (1 << (USART_SCALE_FACTOR)) * 16 * _rate) - 1; 00469 #endif 00470 USART_SET_BAUDRATE(hw->usart, bsel, USART_SCALE_FACTOR); 00471 } 00472 00473 /* 00474 * \brief Sets the parity of the uart 00475 * 00476 * \param _hw struct AvrxmegaSerial 00477 * \param _parity the parity to set 00478 */ 00479 static void uart_setparity(struct SerialHardware * _hw, int _parity) 00480 { 00481 struct AvrxmegaSerial *hw = (struct AvrxmegaSerial *)_hw; 00482 USART_SET_MODE(hw->usart, _parity); 00483 } 00484 00485 /* 00486 * \brief Returns true if Transmitter is sending 00487 * 00488 * \param _hw struct AvrxmegaSerial 00489 * \return true if transmitter is sending 00490 */ 00491 static bool tx_sending(struct SerialHardware* _hw) 00492 { 00493 struct AvrxmegaSerial *hw = (struct AvrxmegaSerial *)_hw; 00494 return hw->sending; 00495 } 00496 00497 00498 // FIXME: move into compiler.h? Ditch? 00499 #if COMPILER_C99 00500 #define C99INIT(name,val) .name = val 00501 #elif defined(__GNUC__) 00502 #define C99INIT(name,val) name: val 00503 #else 00504 #warning No designated initializers, double check your code 00505 #define C99INIT(name,val) (val) 00506 #endif 00507 00508 /* 00509 * High-level interface data structures 00510 */ 00511 static const struct SerialHardwareVT UART_VT = 00512 { 00513 C99INIT(init, uart_init), 00514 C99INIT(cleanup, uart_cleanup), 00515 C99INIT(setBaudrate, uart_setbaudrate), 00516 C99INIT(setParity, uart_setparity), 00517 C99INIT(txStart, uart_enabletxirq), 00518 C99INIT(txSending, tx_sending) 00519 }; 00520 00521 static struct AvrxmegaSerial UARTDescs[SER_CNT] = 00522 { 00523 { 00524 C99INIT(hw, ) { 00525 C99INIT(table, &UART_VT), 00526 C99INIT(txbuffer, uart0_txbuffer), 00527 C99INIT(rxbuffer, uart0_rxbuffer), 00528 C99INIT(txbuffer_size, sizeof(uart0_txbuffer)), 00529 C99INIT(rxbuffer_size, sizeof(uart0_rxbuffer)), 00530 }, 00531 C99INIT(sending, false), 00532 C99INIT(usart, &USARTC0), 00533 C99INIT(port, &PORTC), 00534 C99INIT(txpin, PIN3_bp), 00535 C99INIT(rxpin, PIN2_bp), 00536 }, 00537 { 00538 C99INIT(hw, ) { 00539 C99INIT(table, &UART_VT), 00540 C99INIT(txbuffer, uart1_txbuffer), 00541 C99INIT(rxbuffer, uart1_rxbuffer), 00542 C99INIT(txbuffer_size, sizeof(uart1_txbuffer)), 00543 C99INIT(rxbuffer_size, sizeof(uart1_rxbuffer)), 00544 }, 00545 C99INIT(sending, false), 00546 C99INIT(usart, &USARTD0), 00547 C99INIT(port, &PORTD), 00548 C99INIT(txpin, PIN3_bp), 00549 C99INIT(rxpin, PIN2_bp), 00550 }, 00551 #ifdef CPU_AVR_XMEGA_A 00552 { 00553 C99INIT(hw, ) { 00554 C99INIT(table, &UART_VT), 00555 C99INIT(txbuffer, uart2_txbuffer), 00556 C99INIT(rxbuffer, uart2_rxbuffer), 00557 C99INIT(txbuffer_size, sizeof(uart2_txbuffer)), 00558 C99INIT(rxbuffer_size, sizeof(uart2_rxbuffer)), 00559 }, 00560 C99INIT(sending, false), 00561 C99INIT(usart, &USARTC1), 00562 C99INIT(port, &PORTC), 00563 C99INIT(txpin, PIN7_bp), 00564 C99INIT(rxpin, PIN6_bp), 00565 }, 00566 { 00567 C99INIT(hw, ) { 00568 C99INIT(table, &UART_VT), 00569 C99INIT(txbuffer, uart3_txbuffer), 00570 C99INIT(rxbuffer, uart3_rxbuffer), 00571 C99INIT(txbuffer_size, sizeof(uart3_txbuffer)), 00572 C99INIT(rxbuffer_size, sizeof(uart3_rxbuffer)), 00573 }, 00574 C99INIT(sending, false), 00575 C99INIT(usart, &USARTD1), 00576 C99INIT(port, &PORTD), 00577 C99INIT(txpin, PIN7_bp), 00578 C99INIT(rxpin, PIN6_bp), 00579 }, 00580 { 00581 C99INIT(hw, ) { 00582 C99INIT(table, &UART_VT), 00583 C99INIT(txbuffer, uart4_txbuffer), 00584 C99INIT(rxbuffer, uart4_rxbuffer), 00585 C99INIT(txbuffer_size, sizeof(uart4_txbuffer)), 00586 C99INIT(rxbuffer_size, sizeof(uart4_rxbuffer)), 00587 }, 00588 C99INIT(sending, false), 00589 C99INIT(usart, &USARTE0), 00590 C99INIT(port, &PORTE), 00591 C99INIT(txpin, PIN3_bp), 00592 C99INIT(rxpin, PIN2_bp), 00593 }, 00594 #endif //CPU_AVR_XMEGA_A 00595 }; 00596 00597 struct SerialHardware *ser_hw_getdesc(int unit) 00598 { 00599 ASSERT(unit < SER_CNT); 00600 return &UARTDescs[unit].hw; 00601 } 00602 00603 00604 /* 00605 * Interrupt handlers 00606 */ 00607 static inline void usart_handleDreInterrupt(uint8_t usartNumber) 00608 { 00609 SER_STROBE_ON; 00610 struct FIFOBuffer * const txfifo = &ser_handles[usartNumber]->txfifo; 00611 if (fifo_isempty(txfifo)) 00612 { 00613 SER_UART_BUS_TXEND(UARTDescs[usartNumber].usart); 00614 #ifndef SER_UART_BUS_TXOFF 00615 UARTDescs[usartNumber].sending = false; 00616 #endif 00617 } 00618 else 00619 { 00620 char c = fifo_pop(txfifo); 00621 SER_UART_BUS_TXCHAR(UARTDescs[usartNumber].usart, c); 00622 } 00623 SER_STROBE_OFF; 00624 } 00625 00626 #define USART_DRE_INTERRUPT_VECTOR(_vector, _usart) \ 00627 DECLARE_ISR(_vector) \ 00628 { \ 00629 usart_handleDreInterrupt( _usart ); \ 00630 } 00631 00632 USART_DRE_INTERRUPT_VECTOR(USARTC0_DRE_vect, SER_UART0) 00633 USART_DRE_INTERRUPT_VECTOR(USARTD0_DRE_vect, SER_UART1) 00634 #ifdef CPU_AVR_XMEGA_A 00635 USART_DRE_INTERRUPT_VECTOR(USARTC1_DRE_vect, SER_UART2) 00636 USART_DRE_INTERRUPT_VECTOR(USARTD1_DRE_VECT, SER_UART3) 00637 USART_DRE_INTERRUPT_VECTOR(USARTE0_DRE_vect, SER_UART4) 00638 #endif 00639 00640 #ifdef SER_UART_BUS_TXOFF 00641 static inline void USART_handleTXCInterrupt(uint8_t usartNumber) 00642 { 00643 SER_STROBE_ON; 00644 struct FIFOBuffer * const txfifo = &ser_handles[usartNumber]->txfifo; 00645 if (fifo_isempty(txfifo)) 00646 { 00647 SER_UART_BUS_TXOFF(UARTDescs[usartNumber].usart); 00648 UARTDescs[usartNumber].sending = false; 00649 } 00650 else 00651 { 00652 SER_UART_BUS_TXBEGIN(UARTDescs[usartNumber].usart); 00653 } 00654 SER_STROBE_OFF; 00655 } 00656 00657 /* 00658 * Serial port 0 TX complete interrupt handler. 00659 * 00660 * This IRQ is usually disabled. The UDR-empty interrupt 00661 * enables it when there's no more data to transmit. 00662 * We need to wait until the last character has been 00663 * transmitted before switching the 485 transceiver to 00664 * receive mode. 00665 * 00666 * The txfifo might have been refilled by putchar() while 00667 * we were waiting for the transmission complete interrupt. 00668 * In this case, we must restart the UDR empty interrupt, 00669 * otherwise we'd stop the serial port with some data 00670 * still pending in the buffer. 00671 */ 00672 #define USART_TXC_INTERRUPT_VECTOR(_vector, _usart) \ 00673 DECLARE_ISR(_vector) \ 00674 { \ 00675 USART_handleTXCInterrupt( _usart ); \ 00676 } 00677 00678 USART_TXC_INTERRUPT_VECTOR(USARTC0_TXC_vect, SER_UART0) 00679 USART_TXC_INTERRUPT_VECTOR(USARTD0_TXC_vect, SER_UART1) 00680 #ifdef CPU_AVR_XMEGA_A 00681 USART_TXC_INTERRUPT_VECTOR(USARTC1_TXC_vect, SER_UART2) 00682 USART_TXC_INTERRUPT_VECTOR(USARTD1_TXC_vect, SER_UART3) 00683 USART_TXC_INTERRUPT_VECTOR(USARTE0_TXC_vect, SER_UART4) 00684 #endif /* CPU_AVR_XMEGA_A */ 00685 #endif /* SER_UART_BUS_TXOFF */ 00686 00687 /* 00688 * Serial RX complete interrupt handler. 00689 * 00690 * This handler is interruptible. 00691 * Interrupt are reenabled as soon as recv complete interrupt is 00692 * disabled. Using INTERRUPT() is troublesome when the serial 00693 * is heavily loaded, because an interrupt could be retriggered 00694 * when executing the handler prologue before RXCIE is disabled. 00695 */ 00696 static inline void USART_handleRXCInterrupt(uint8_t usartNumber) 00697 { 00698 SER_STROBE_ON; 00699 /* read status */ 00700 ser_handles[usartNumber]->status |= (UARTDescs[usartNumber].usart)->STATUS & (SERRF_RXSROVERRUN | SERRF_FRAMEERROR); 00701 /* To clear the RXC flag we must _always_ read the UDR even when we're 00702 * not going to accept the incoming data, otherwise a new interrupt 00703 * will occur once the handler terminates. 00704 */ 00705 char c = (UARTDescs[usartNumber].usart)->DATA; 00706 struct FIFOBuffer * const rxfifo = &ser_handles[usartNumber]->rxfifo; 00707 if (fifo_isfull(rxfifo)) 00708 { 00709 ser_handles[usartNumber]->status |= SERRF_RXFIFOOVERRUN; 00710 } 00711 else 00712 { 00713 fifo_push(rxfifo, c); 00714 #if CONFIG_SER_HWHANDSHAKE 00715 if (fifo_isfull(rxfifo)) 00716 { 00717 RTS_OFF(UARTDescs[usartNumber].usart); 00718 } 00719 #endif 00720 } 00721 SER_STROBE_OFF; 00722 } 00723 00724 #define USART_RXC_INTERRUPT_VECTOR(_vector, _usart) \ 00725 DECLARE_ISR(_vector) \ 00726 { \ 00727 USART_handleRXCInterrupt( _usart ); \ 00728 } 00729 USART_RXC_INTERRUPT_VECTOR(USARTC0_RXC_vect, SER_UART0) 00730 USART_RXC_INTERRUPT_VECTOR(USARTD0_RXC_vect, SER_UART1) 00731 #ifdef CPU_AVR_XMEGA_A 00732 USART_RXC_INTERRUPT_VECTOR(USARTC1_RXC_vect, SER_UART2) 00733 USART_RXC_INTERRUPT_VECTOR(USARTD1_RXC_vect, SER_UART3) 00734 USART_RXC_INTERRUPT_VECTOR(USARTE0_RXC_vect, SER_UART4) 00735 #endif