0e12c39838d0c06cb223f34becd2eeca59046f21
[bertos.git] / bertos / cpu / avr / drv / ser_xmega.c
1 /**
2  * \file
3  * <!--
4  * This file is part of BeRTOS.
5  *
6  * Bertos is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  * As a special exception, you may use this file as part of a free software
21  * library without restriction.  Specifically, if other files instantiate
22  * templates or use macros or inline functions from this file, or you compile
23  * this file and link it with other files to produce an executable, this
24  * file does not by itself cause the resulting executable to be covered by
25  * the GNU General Public License.  This exception does not however
26  * invalidate any other reasons why the executable file might be covered by
27  * the GNU General Public License.
28  *
29  * Copyright 2003, 2004, 2010 Develer S.r.l. (http://www.develer.com/)
30  * Copyright 2011 Onno <developer@gorgoz.org>
31  *
32  * -->
33  *
34  * \brief AVR XMEGA USART driver (Implementation)
35  *
36  * This file is heavily inspired by the AVR implementation for BeRTOS,
37  * but uses a different approach for implementing the different debug
38  * ports, by using the USART_t structs.
39  *
40  * \author Onno <developer@gorgoz.org>
41  */
42
43 #include "hw/hw_ser.h"     /* Required for bus macros overrides */
44 #include <hw/hw_cpufreq.h> /* CPU_FREQ */
45
46 #include "cfg/cfg_ser.h"   /* Serialport configuration settings */
47
48 #include <cfg/macros.h>    /* DIV_ROUND */
49 #include <cfg/debug.h>     /* debug configuration */
50
51 #include <drv/ser.h>
52 #include <drv/ser_p.h>
53 #include <drv/timer.h>
54
55 #include <struct/fifobuf.h>
56
57 #include <avr/io.h>        /* AVR IO ports and structures */
58 #include <avr/interrupt.h> /* AVR Interrupt methods */
59
60 /*
61  * Scalefactor to use for computing the baudrate
62  * this scalefactor should be an integer value between -7
63  * and 7
64  */
65 #ifndef USART_SCALE_FACTOR
66         #define USART_SCALE_FACTOR (-7)
67 #else
68         #if USART_SCALE_FACTOR > 7 || USART_SCALE_FACTOR < -7
69                 #error USART_SCALE_FACTOR should be an integer between -7 and 7
70         #endif
71 #endif
72
73 /* Helper macros, mostly taken from the Atmel Examples
74  * Slightly alterd to match the BeRTOS naming convention
75  */
76
77 /* \brief Set USART baud rate.
78  *
79  *  Sets the USART's baud rate register.
80  *
81  *  UBRR_Value   : Value written to UBRR
82  *  ScaleFactor  : Time Base Generator Scale Factor
83  *
84  *  Equation for calculation of BSEL value in asynchronous normal speed mode:
85  *      If ScaleFactor >= 0
86  *              BSEL = ((I/O clock frequency)/(2^(ScaleFactor)*16*Baudrate))-1
87  *      If ScaleFactor < 0
88  *              BSEL = (1/(2^(ScaleFactor)*16))*(((I/O clock frequency)/Baudrate)-1)
89  *
90  *      \note See XMEGA manual for equations for calculation of BSEL value in other
91  *        modes.
92  *
93  *  \param _usart          Pointer to the USART module.
94  *  \param _bselValue      Value to write to BSEL part of Baud control register.
95  *                         Use uint16_t type.
96  *  \param _bScaleFactor   USART baud rate scale factor.
97  *                         Use uint8_t type
98  */
99 #define USART_SET_BAUDRATE(_usart, _bselValue, _bScaleFactor)                  \
100         (_usart)->BAUDCTRLA =(uint8_t)_bselValue;                                           \
101         (_usart)->BAUDCTRLB =(_bScaleFactor << USART_BSCALE0_bp)|(_bselValue >> 8)
102
103 /* \brief Enable USART receiver.
104  *
105  *  \param _usart    Pointer to the USART module
106  */
107 #define USART_RX_ENABLE(_usart) ((_usart)->CTRLB |= USART_RXEN_bm)
108
109 /* \brief Disable USART receiver.
110  *
111  *  \param _usart Pointer to the USART module.
112  */
113 #define USART_RX_DISABLE(_usart) ((_usart)->CTRLB &= ~USART_RXEN_bm)
114
115 /* \brief Enable USART transmitter.
116  *
117  *  \param _usart Pointer to the USART module.
118  */
119 #define USART_TX_ENABLE(_usart) ((_usart)->CTRLB |= USART_TXEN_bm)
120
121 /* \brief Disable USART transmitter.
122  *
123  *  \param _usart Pointer to the USART module.
124  */
125 #define USART_TX_DISABLE(_usart) ((_usart)->CTRLB &= ~USART_TXEN_bm)
126
127 /* \brief Set USART RXD interrupt level.
128  *
129  *  Sets the interrupt level on RX Complete interrupt.
130  *
131  *  \param _usart        Pointer to the USART module.
132  *  \param _rxdIntLevel  Interrupt level of the RXD interrupt.
133  *                       Use USART_RXCINTLVL_t type.
134  */
135 #define USART_SET_RX_INTERRUPT_LEVEL(_usart, _rxdIntLevel)                      \
136         ((_usart)->CTRLA = ((_usart)->CTRLA & ~USART_RXCINTLVL_gm) | _rxdIntLevel)
137
138 /* \brief Set USART TXD interrupt level.
139  *
140  *  Sets the interrupt level on TX Complete interrupt.
141  *
142  *  \param _usart        Pointer to the USART module.
143  *  \param _txdIntLevel  Interrupt level of the TXD interrupt.
144  *                       Use USART_TXCINTLVL_t type.
145  */
146 #define USART_SET_TX_INTERRUPT_LEVEL(_usart, _txdIntLevel)                      \
147         (_usart)->CTRLA = ((_usart)->CTRLA & ~USART_TXCINTLVL_gm) | _txdIntLevel
148
149 /* \brief Set USART DRE interrupt level.
150  *
151  *  Sets the interrupt level on Data Register interrupt.
152  *
153  *  \param _usart        Pointer to the USART module.
154  *  \param _dreIntLevel  Interrupt level of the DRE interrupt.
155  *                       Use USART_DREINTLVL_t type.
156  */
157 #define USART_SET_DRE_INTERRUPT_LEVEL(_usart, _dreIntLevel)                      \
158         (_usart)->CTRLA = ((_usart)->CTRLA & ~USART_DREINTLVL_gm) | _dreIntLevel
159
160 /* \brief Set the mode the USART run in.
161  *
162  * Set the mode the USART run in. The default mode is asynchronous mode.
163  *
164  *  \param  _usart       Pointer to the USART module register section.
165  *  \param  _usartMode   Selects the USART mode. Use  USART_CMODE_t type.
166  *
167  *  USART modes:
168  *  - 0x0        : Asynchronous mode.
169  *  - 0x1        : Synchronous mode.
170  *  - 0x2        : IrDA mode.
171  *  - 0x3        : Master SPI mode.
172  */
173 #define USART_SET_MODE(_usart, _usartMode)                                      \
174         ((_usart)->CTRLC = ((_usart)->CTRLC & (~USART_CMODE_gm)) | _usartMode)
175
176 /* \brief Check if data register empty flag is set.
177  *
178  *  \param _usart      The USART module.
179  */
180 #define USART_IS_TX_DATA_REGISTER_EMPTY(_usart) (((_usart)->STATUS & USART_DREIF_bm) != 0)
181
182 /* \brief Put data (5-8 bit character).
183  *
184  *  Use the macro USART_IsTXDataRegisterEmpty before using this function to
185  *  put data to the TX register.
186  *
187  *  \param _usart      The USART module.
188  *  \param _data       The data to send.
189  */
190 #define USART_PUT_CHAR(_usart, _data) ((_usart)->DATA = _data)
191
192 /* \brief Checks if the RX complete interrupt flag is set.
193  *
194  *   Checks if the RX complete interrupt flag is set.
195  *
196  *  \param _usart     The USART module.
197  */
198 #define USART_IS_RX_COMPLETE(_usart) (((_usart)->STATUS & USART_RXCIF_bm) != 0)
199
200 /* \brief Get received data (5-8 bit character).
201  *
202  *  This macro reads out the RX register.
203  *  Use the macro USART_RX_Complete to check if anything is received.
204  *
205  *  \param _usart     The USART module.
206  *
207  *  \retval           Received data.
208  */
209 #define USART_GET_CHAR(_usart)  ((_usart)->DATA)
210
211 /* configurable macros */
212
213 #if !CONFIG_SER_HWHANDSHAKE
214         /**
215          * \name Hardware handshake (RTS/CTS).
216          * \{
217          */
218         #define RTS_ON      do {} while (0)
219         #define RTS_OFF     do {} while (0)
220         #define IS_CTS_ON   true
221         #define EIMSKF_CTS  0 /**< Dummy value, must be overridden */
222         /*\}*/
223 #endif
224
225 /*
226  * \name Overridable serial bus hooks
227  *
228  * These can be redefined in hw.h to implement
229  * special bus policies such as half-duplex, 485, etc.
230  *
231  *
232  * \code
233  *  TXBEGIN      TXCHAR      TXEND  TXOFF
234  *    |   __________|__________ |     |
235  *    |   |   |   |   |   |   | |     |
236  *    v   v   v   v   v   v   v v     v
237  * ______  __  __  __  __  __  __  ________________
238  *       \/  \/  \/  \/  \/  \/  \/
239  * ______/\__/\__/\__/\__/\__/\__/
240  *
241  * \endcode
242  *
243  * \{
244  */
245
246 #ifndef SER_UART_BUS_TXINIT
247         /*
248          * Default TXINIT macro - invoked in uart_init()
249          *
250          * - Enable both the receiver and the transmitter
251          * - Enable only the RX complete interrupt
252          */
253         #define SER_UART_BUS_TXINIT(_usart) do { \
254                 USART_RX_ENABLE(_usart); \
255                 USART_TX_ENABLE(_usart); \
256                 USART_SET_RX_INTERRUPT_LEVEL(_usart, USART_RXCINTLVL_MED_gc); \
257         } while (0)
258 #endif
259
260 #ifndef SER_UART_BUS_TXBEGIN
261         /*
262          * Invoked before starting a transmission
263          *
264          * - Enable both the receiver and the transmitter
265          * - Enable both the RX complete and UDR empty interrupts
266          */
267         #define SER_UART_BUS_TXBEGIN(_usart) do { \
268                 USART_SET_RX_INTERRUPT_LEVEL(_usart, USART_RXCINTLVL_MED_gc); \
269                 USART_SET_DRE_INTERRUPT_LEVEL(_usart, USART_DREINTLVL_MED_gc);\
270         } while (0)
271 #endif
272
273 #ifndef SER_UART_BUS_TXCHAR
274         /*
275          * Invoked to send one character.
276          */
277         #define SER_UART_BUS_TXCHAR(_usart, c) do { \
278                 USART_PUT_CHAR(_usart, c); \
279         } while (0)
280 #endif
281
282 #ifndef SER_UART_BUS_TXEND
283         /*
284          * Invoked as soon as the txfifo becomes empty
285          *
286          * - Keep both the receiver and the transmitter enabled
287          * - Keep the RX complete interrupt enabled
288          * - Disable the UDR empty interrupt
289          */
290         #define SER_UART_BUS_TXEND(_usart) do { \
291                 USART_SET_DRE_INTERRUPT_LEVEL(_usart, USART_DREINTLVL_OFF_gc); \
292         } while (0)
293 #endif
294
295 #ifndef SER_UART_BUS_TXOFF
296         /*
297          * \def SER_UART_BUS_TXOFF
298          *
299          * Invoked after the last character has been transmitted
300          *
301          * The default is no action.
302          */
303         #ifdef __doxygen__
304         #define SER_UART_BUS_TXOFF(_usart)
305         #endif
306 #endif
307
308 /*\}*/
309
310 /* From the high-level serial driver */
311 extern struct Serial *ser_handles[SER_CNT];
312
313 /* TX and RX buffers */
314 static unsigned char uart0_txbuffer[CONFIG_UART0_TXBUFSIZE];
315 static unsigned char uart0_rxbuffer[CONFIG_UART0_RXBUFSIZE];
316 static unsigned char uart1_txbuffer[CONFIG_UART1_TXBUFSIZE];
317 static unsigned char uart1_rxbuffer[CONFIG_UART1_RXBUFSIZE];
318 #ifdef CPU_AVR_XMEGA_A
319 static unsigned char uart2_txbuffer[CONFIG_UART2_TXBUFSIZE];
320 static unsigned char uart2_rxbuffer[CONFIG_UART2_RXBUFSIZE];
321 static unsigned char uart3_txbuffer[CONFIG_UART3_TXBUFSIZE];
322 static unsigned char uart3_rxbuffer[CONFIG_UART3_RXBUFSIZE];
323 static unsigned char uart4_txbuffer[CONFIG_UART4_TXBUFSIZE];
324 static unsigned char uart4_rxbuffer[CONFIG_UART4_RXBUFSIZE];
325 #endif
326
327 /*
328  * Internal hardware state structure
329  *
330  * The \a sending variable is true while the transmission
331  * interrupt is retriggering itself.
332  *
333  * the \a usart variable will point to the USART_t structure
334  * that should be used.
335  *
336  * the \a port variable will point to the PORT_t structure
337  * that should be modified to set the tx pin as an output and the
338  * rx pin as an input
339  *
340  * the \a txpin variable will hold the pinnumber of the pin to use
341  * as the tx output
342  *
343  * the \a rxpin variable will hold the pinnumber of the pin to use
344  * as the rx input
345  *
346  * For the USARTs the \a sending flag is useful for taking specific
347  * actions before sending a burst of data, at the start of a trasmission
348  * but not before every char sent.
349  *
350  * For the SPI, this flag is necessary because the SPI sends and receives
351  * bytes at the same time and the SPI IRQ is unique for send/receive.
352  * The only way to start transmission is to write data in SPDR (this
353  * is done by spi_starttx()). We do this *only* if a transfer is
354  * not already started.
355  */
356 struct AvrxmegaSerial
357 {
358         struct SerialHardware hw;
359         volatile bool sending;
360         volatile USART_t* usart;
361         volatile PORT_t* port;
362         uint8_t txpin;
363         uint8_t rxpin;
364 };
365
366 /*
367  * Callbacks
368  * The same callbacks are used for all USARTS.
369  * By casting the SerialHardware structure to the AvrxmegaSerial
370  * structure a pointer to the USART_t structure can be obtained,
371  * to perform the callback for the specific USART.
372  * This methode might cost some more cpu time, but saves on
373  * code duplication and code size.
374  */
375
376
377 /*
378  * \brief Initializes the uart
379  *
380  * The TX pin of the uart will be set as an outputpin
381  * The RX pin of the uart will be set as an inputpin
382  * The usart will be initialized
383  * \see SER_UART_BUS_TXINIT
384  *
385  * \param _hw struct AvrxmegaSerial
386  * \param ser Unused
387  */
388 static void uart_init(struct SerialHardware * _hw, UNUSED_ARG(struct Serial *, ser))
389 {
390         struct AvrxmegaSerial *hw = (struct AvrxmegaSerial *)_hw;
391         //set transmit pin as output
392         hw->port->DIRSET = BV(hw->txpin);
393         hw->port->OUTCLR = BV(hw->txpin);
394         //set receive pin as input
395         hw->port->DIRCLR = BV(hw->rxpin);
396         //initialize the USART
397         SER_UART_BUS_TXINIT(hw->usart);
398         RTS_ON;
399         SER_STROBE_INIT;
400 }
401
402 /*
403  * \brief Cleans up / Disables the uart
404  *
405  * \param _hw struct AvrxmegaSerial
406  */
407 static void uart_cleanup(struct SerialHardware * _hw)
408 {
409         struct AvrxmegaSerial *hw = (struct AvrxmegaSerial *)_hw;
410         hw->usart->CTRLA = 0;
411         hw->usart->CTRLB = 0;
412 }
413
414 /*
415  * \brief Enableds the TX interrupt
416  *
417  * \param _hw struct AvrxmegaSerial
418  */
419 static void uart_enabletxirq(struct SerialHardware *_hw)
420 {
421         struct AvrxmegaSerial *hw = (struct AvrxmegaSerial *)_hw;
422
423         /*
424          * WARNING: racy code here!  The tx interrupt sets hw->sending to false
425          * when it runs with an empty fifo.  The order of statements in the
426          * if-block matters.
427          */
428         if (!hw->sending)
429         {
430                 hw->sending = true;
431                 SER_UART_BUS_TXBEGIN(hw->usart);
432         }
433 }
434
435 /*
436  * \brief  sets the uart to the provided baudrate
437  *
438  * For setting the baudrate an scale factor (bscale) and a period
439  * setting (BSEL) is required.
440  *
441  * The scale factor should be privided by defining USART_SCALE_FACTOR
442  *
443  * Atmel specifies BSEL for normal speed mode and bscale >= 0 as:
444  * BSEL = (cpu_freq / ((2^bscale) * 16 * rate)) - 1
445  * To allow BSEL to be calculated with an power function this can be
446  * rewriten to:
447  * BSEL = BSEL = (cpu_freq / ((1 << bscale) * 16 * rate)) - 1
448  *
449  * Atmel specifies BSEL for normal speed mode and bscale < 0 as:
450  * BSEL = (1 / (2^bscale)) * ( (cpu_freq / (16 * rate)) - 1)
451  * To calculte this float atheritmic is required as the second product will be smaller
452  * than zero in a lot of cases.
453  * To allow BSEL to be calculated with interger devision and no power function
454  * this can be rewriten by folowing simple math rules to:
455  * BSEL = ((1 << -bscale) * (cpu_freq - (16 * rate)) / (16 * rate)
456  *
457  * \param _hw struct AvrxmegaSerial
458  * \param _rate the required baudrate
459  *
460  */
461 static void uart_setbaudrate(struct SerialHardware * _hw, unsigned long _rate)
462 {
463         struct AvrxmegaSerial *hw = (struct AvrxmegaSerial *)_hw;
464         /* Compute baud-rate period, this requires a valid USART_SCALE_FACTOR */
465         #if USART_SCALE_FACTOR < 0
466                 uint16_t bsel = DIV_ROUND((1 << (-(USART_SCALE_FACTOR))) * (CPU_FREQ - (16 * _rate)), 16 * _rate);
467         #else
468                 uint16_t bsel = DIV_ROUND(CPU_FREQ, (1 << (USART_SCALE_FACTOR)) * 16 * _rate) - 1;
469         #endif
470         USART_SET_BAUDRATE(hw->usart, bsel, USART_SCALE_FACTOR);
471 }
472
473 /*
474  * \brief Sets the parity of the uart
475  *
476  * \param _hw struct AvrxmegaSerial
477  * \param _parity the parity to set
478  */
479 static void uart_setparity(struct SerialHardware * _hw, int _parity)
480 {
481         struct AvrxmegaSerial *hw = (struct AvrxmegaSerial *)_hw;
482         USART_SET_MODE(hw->usart, _parity);
483 }
484
485 /*
486  * \brief Returns true if Transmitter is sending
487  *
488  * \param _hw struct AvrxmegaSerial
489  * \return true if transmitter is sending
490  */
491 static bool tx_sending(struct SerialHardware* _hw)
492 {
493         struct AvrxmegaSerial *hw = (struct AvrxmegaSerial *)_hw;
494         return hw->sending;
495 }
496
497
498 // FIXME: move into compiler.h?  Ditch?
499 #if COMPILER_C99
500         #define C99INIT(name,val) .name = val
501 #elif defined(__GNUC__)
502         #define C99INIT(name,val) name: val
503 #else
504         #warning No designated initializers, double check your code
505         #define C99INIT(name,val) (val)
506 #endif
507
508 /*
509  * High-level interface data structures
510  */
511 static const struct SerialHardwareVT UART_VT =
512 {
513         C99INIT(init, uart_init),
514         C99INIT(cleanup, uart_cleanup),
515         C99INIT(setBaudrate, uart_setbaudrate),
516         C99INIT(setParity, uart_setparity),
517         C99INIT(txStart, uart_enabletxirq),
518         C99INIT(txSending, tx_sending)
519 };
520
521 static struct AvrxmegaSerial UARTDescs[SER_CNT] =
522 {
523         {
524                 C99INIT(hw, /**/) {
525                         C99INIT(table, &UART_VT),
526                         C99INIT(txbuffer, uart0_txbuffer),
527                         C99INIT(rxbuffer, uart0_rxbuffer),
528                         C99INIT(txbuffer_size, sizeof(uart0_txbuffer)),
529                         C99INIT(rxbuffer_size, sizeof(uart0_rxbuffer)),
530                 },
531                 C99INIT(sending, false),
532                 C99INIT(usart, &USARTC0),
533                 C99INIT(port, &PORTC),
534                 C99INIT(txpin, PIN3_bp),
535                 C99INIT(rxpin, PIN2_bp),
536         },
537         {
538                 C99INIT(hw, /**/) {
539                         C99INIT(table, &UART_VT),
540                         C99INIT(txbuffer, uart1_txbuffer),
541                         C99INIT(rxbuffer, uart1_rxbuffer),
542                         C99INIT(txbuffer_size, sizeof(uart1_txbuffer)),
543                         C99INIT(rxbuffer_size, sizeof(uart1_rxbuffer)),
544                 },
545                 C99INIT(sending, false),
546                 C99INIT(usart, &USARTD0),
547                 C99INIT(port, &PORTD),
548                 C99INIT(txpin, PIN3_bp),
549                 C99INIT(rxpin, PIN2_bp),
550         },
551 #ifdef CPU_AVR_XMEGA_A
552         {
553                 C99INIT(hw, /**/) {
554                         C99INIT(table, &UART_VT),
555                         C99INIT(txbuffer, uart2_txbuffer),
556                         C99INIT(rxbuffer, uart2_rxbuffer),
557                         C99INIT(txbuffer_size, sizeof(uart2_txbuffer)),
558                         C99INIT(rxbuffer_size, sizeof(uart2_rxbuffer)),
559                 },
560                 C99INIT(sending, false),
561                 C99INIT(usart, &USARTC1),
562                 C99INIT(port, &PORTC),
563                 C99INIT(txpin, PIN7_bp),
564                 C99INIT(rxpin, PIN6_bp),
565         },
566         {
567                 C99INIT(hw, /**/) {
568                         C99INIT(table, &UART_VT),
569                         C99INIT(txbuffer, uart3_txbuffer),
570                         C99INIT(rxbuffer, uart3_rxbuffer),
571                         C99INIT(txbuffer_size, sizeof(uart3_txbuffer)),
572                         C99INIT(rxbuffer_size, sizeof(uart3_rxbuffer)),
573                 },
574                 C99INIT(sending, false),
575                 C99INIT(usart, &USARTD1),
576                 C99INIT(port, &PORTD),
577                 C99INIT(txpin, PIN7_bp),
578                 C99INIT(rxpin, PIN6_bp),
579         },
580         {
581                 C99INIT(hw, /**/) {
582                         C99INIT(table, &UART_VT),
583                         C99INIT(txbuffer, uart4_txbuffer),
584                         C99INIT(rxbuffer, uart4_rxbuffer),
585                         C99INIT(txbuffer_size, sizeof(uart4_txbuffer)),
586                         C99INIT(rxbuffer_size, sizeof(uart4_rxbuffer)),
587                 },
588                 C99INIT(sending, false),
589                 C99INIT(usart, &USARTE0),
590                 C99INIT(port, &PORTE),
591                 C99INIT(txpin, PIN3_bp),
592                 C99INIT(rxpin, PIN2_bp),
593         },
594 #endif //CPU_AVR_XMEGA_A
595 };
596
597 struct SerialHardware *ser_hw_getdesc(int unit)
598 {
599         ASSERT(unit < SER_CNT);
600         return &UARTDescs[unit].hw;
601 }
602
603
604 /*
605  * Interrupt handlers
606  */
607 static inline void usart_handleDreInterrupt(uint8_t usartNumber)
608 {
609         SER_STROBE_ON;
610         struct FIFOBuffer * const txfifo = &ser_handles[usartNumber]->txfifo;
611         if (fifo_isempty(txfifo))
612         {
613                 SER_UART_BUS_TXEND(UARTDescs[usartNumber].usart);
614                 #ifndef SER_UART_BUS_TXOFF
615                         UARTDescs[usartNumber].sending = false;
616                 #endif
617         }
618         else
619         {
620                 char c = fifo_pop(txfifo);
621                 SER_UART_BUS_TXCHAR(UARTDescs[usartNumber].usart, c);
622         }
623         SER_STROBE_OFF;
624 }
625
626 #define USART_DRE_INTERRUPT_VECTOR(_vector, _usart)             \
627 DECLARE_ISR(_vector)                                                                            \
628 {                                                                                                                       \
629         usart_handleDreInterrupt( _usart );     \
630 }
631
632 USART_DRE_INTERRUPT_VECTOR(USARTC0_DRE_vect, SER_UART0)
633 USART_DRE_INTERRUPT_VECTOR(USARTD0_DRE_vect, SER_UART1)
634 #ifdef CPU_AVR_XMEGA_A
635         USART_DRE_INTERRUPT_VECTOR(USARTC1_DRE_vect, SER_UART2)
636         USART_DRE_INTERRUPT_VECTOR(USARTD1_DRE_VECT, SER_UART3)
637         USART_DRE_INTERRUPT_VECTOR(USARTE0_DRE_vect, SER_UART4)
638 #endif
639
640 #ifdef SER_UART_BUS_TXOFF
641         static inline void USART_handleTXCInterrupt(uint8_t usartNumber)
642         {
643                 SER_STROBE_ON;
644                 struct FIFOBuffer * const txfifo = &ser_handles[usartNumber]->txfifo;
645                 if (fifo_isempty(txfifo))
646                 {
647                         SER_UART_BUS_TXOFF(UARTDescs[usartNumber].usart);
648                         UARTDescs[usartNumber].sending = false;
649                 }
650                 else
651                 {
652                         SER_UART_BUS_TXBEGIN(UARTDescs[usartNumber].usart);
653                 }
654                 SER_STROBE_OFF;
655         }
656
657         /*
658          * Serial port 0 TX complete interrupt handler.
659          *
660          * This IRQ is usually disabled.  The UDR-empty interrupt
661          * enables it when there's no more data to transmit.
662          * We need to wait until the last character has been
663          * transmitted before switching the 485 transceiver to
664          * receive mode.
665          *
666          * The txfifo might have been refilled by putchar() while
667          * we were waiting for the transmission complete interrupt.
668          * In this case, we must restart the UDR empty interrupt,
669          * otherwise we'd stop the serial port with some data
670          * still pending in the buffer.
671          */
672         #define USART_TXC_INTERRUPT_VECTOR(_vector, _usart)     \
673         DECLARE_ISR(_vector)                                                            \
674         {                                                                                                       \
675                 USART_handleTXCInterrupt( _usart );                             \
676         }
677
678         USART_TXC_INTERRUPT_VECTOR(USARTC0_TXC_vect, SER_UART0)
679         USART_TXC_INTERRUPT_VECTOR(USARTD0_TXC_vect, SER_UART1)
680         #ifdef CPU_AVR_XMEGA_A
681                 USART_TXC_INTERRUPT_VECTOR(USARTC1_TXC_vect, SER_UART2)
682                 USART_TXC_INTERRUPT_VECTOR(USARTD1_TXC_vect, SER_UART3)
683                 USART_TXC_INTERRUPT_VECTOR(USARTE0_TXC_vect, SER_UART4)
684         #endif /* CPU_AVR_XMEGA_A */
685 #endif /* SER_UART_BUS_TXOFF */
686
687 /*
688  * Serial RX complete interrupt handler.
689  *
690  * This handler is interruptible.
691  * Interrupt are reenabled as soon as recv complete interrupt is
692  * disabled. Using INTERRUPT() is troublesome when the serial
693  * is heavily loaded, because an interrupt could be retriggered
694  * when executing the handler prologue before RXCIE is disabled.
695  */
696 static inline void USART_handleRXCInterrupt(uint8_t usartNumber)
697 {
698         SER_STROBE_ON;
699         /* read status */
700         ser_handles[usartNumber]->status |=     (UARTDescs[usartNumber].usart)->STATUS & (SERRF_RXSROVERRUN | SERRF_FRAMEERROR);
701         /* To clear the RXC flag we must _always_ read the UDR even when we're
702          * not going to accept the incoming data, otherwise a new interrupt
703          * will occur once the handler terminates.
704          */
705         char c = (UARTDescs[usartNumber].usart)->DATA;
706         struct FIFOBuffer * const rxfifo = &ser_handles[usartNumber]->rxfifo;
707         if (fifo_isfull(rxfifo))
708         {
709                 ser_handles[usartNumber]->status |= SERRF_RXFIFOOVERRUN;
710         }
711         else
712         {
713                 fifo_push(rxfifo, c);
714                 #if CONFIG_SER_HWHANDSHAKE
715                         if (fifo_isfull(rxfifo))
716                         {
717                                 RTS_OFF(UARTDescs[usartNumber].usart);
718                         }
719                 #endif
720         }
721         SER_STROBE_OFF;
722 }
723
724 #define USART_RXC_INTERRUPT_VECTOR(_vector, _usart)     \
725 DECLARE_ISR(_vector)                                                            \
726 {                                                                                                       \
727         USART_handleRXCInterrupt( _usart );                             \
728 }
729 USART_RXC_INTERRUPT_VECTOR(USARTC0_RXC_vect, SER_UART0)
730 USART_RXC_INTERRUPT_VECTOR(USARTD0_RXC_vect, SER_UART1)
731 #ifdef CPU_AVR_XMEGA_A
732         USART_RXC_INTERRUPT_VECTOR(USARTC1_RXC_vect, SER_UART2)
733         USART_RXC_INTERRUPT_VECTOR(USARTD1_RXC_vect, SER_UART3)
734         USART_RXC_INTERRUPT_VECTOR(USARTE0_RXC_vect, SER_UART4)
735 #endif