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