ser_xmega.c

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