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