4 * This file is part of BeRTOS.
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.
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.
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
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.
29 * Copyright 2003, 2004, 2010 Develer S.r.l. (http://www.develer.com/)
30 * Copyright 2011 Onno <developer@gorgoz.org>
34 * \brief AVR XMEGA USART driver (Implementation)
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.
40 * \author Onno <developer@gorgoz.org>
44 #include "hw/hw_ser.h" /* Required for bus macros overrides */
45 #include <hw/hw_cpufreq.h> /* CPU_FREQ */
47 #include <cfg/macros.h> /* DIV_ROUND */
48 #include <cfg/debug.h> /* debug configuration */
51 #include <drv/ser_p.h>
52 #include <drv/timer.h>
54 #include <struct/fifobuf.h>
56 #include <avr/io.h> /* AVR IO ports and structures */
57 #include <avr/interrupt.h> /* AVR Interrupt methods */
60 * Scalefactor to use for computing the baudrate
61 * this scalefactor should be an integer value between -7
64 #ifndef USART_SCALE_FACTOR
65 #define USART_SCALE_FACTOR (-7)
67 #if USART_SCALE_FACTOR > 7 || USART_SCALE_FACTOR < -7
68 #error USART_SCALE_FACTOR should be an integer between -7 and 7
72 /* Helper macros, mostly taken from the Atmel Examples
73 * Slightly alterd to match the BeRTOS naming convention
76 /* \brief Set USART baud rate.
78 * Sets the USART's baud rate register.
80 * UBRR_Value : Value written to UBRR
81 * ScaleFactor : Time Base Generator Scale Factor
83 * Equation for calculation of BSEL value in asynchronous normal speed mode:
85 * BSEL = ((I/O clock frequency)/(2^(ScaleFactor)*16*Baudrate))-1
87 * BSEL = (1/(2^(ScaleFactor)*16))*(((I/O clock frequency)/Baudrate)-1)
89 * \note See XMEGA manual for equations for calculation of BSEL value in other
92 * \param _usart Pointer to the USART module.
93 * \param _bselValue Value to write to BSEL part of Baud control register.
95 * \param _bScaleFactor USART baud rate scale factor.
98 #define USART_SET_BAUDRATE(_usart, _bselValue, _bScaleFactor) \
99 (_usart)->BAUDCTRLA =(uint8_t)_bselValue; \
100 (_usart)->BAUDCTRLB =(_bScaleFactor << USART_BSCALE0_bp)|(_bselValue >> 8)
102 /* \brief Enable USART receiver.
104 * \param _usart Pointer to the USART module
106 #define USART_RX_ENABLE(_usart) ((_usart)->CTRLB |= USART_RXEN_bm)
108 /* \brief Disable USART receiver.
110 * \param _usart Pointer to the USART module.
112 #define USART_RX_DISABLE(_usart) ((_usart)->CTRLB &= ~USART_RXEN_bm)
114 /* \brief Enable USART transmitter.
116 * \param _usart Pointer to the USART module.
118 #define USART_TX_ENABLE(_usart) ((_usart)->CTRLB |= USART_TXEN_bm)
120 /* \brief Disable USART transmitter.
122 * \param _usart Pointer to the USART module.
124 #define USART_TX_DISABLE(_usart) ((_usart)->CTRLB &= ~USART_TXEN_bm)
126 /* \brief Set USART RXD interrupt level.
128 * Sets the interrupt level on RX Complete interrupt.
130 * \param _usart Pointer to the USART module.
131 * \param _rxdIntLevel Interrupt level of the RXD interrupt.
132 * Use USART_RXCINTLVL_t type.
134 #define USART_SET_RX_INTERRUPT_LEVEL(_usart, _rxdIntLevel) \
135 ((_usart)->CTRLA = ((_usart)->CTRLA & ~USART_RXCINTLVL_gm) | _rxdIntLevel)
137 /* \brief Set USART TXD interrupt level.
139 * Sets the interrupt level on TX Complete interrupt.
141 * \param _usart Pointer to the USART module.
142 * \param _txdIntLevel Interrupt level of the TXD interrupt.
143 * Use USART_TXCINTLVL_t type.
145 #define USART_SET_TX_INTERRUPT_LEVEL(_usart, _txdIntLevel) \
146 (_usart)->CTRLA = ((_usart)->CTRLA & ~USART_TXCINTLVL_gm) | _txdIntLevel
148 /* \brief Set USART DRE interrupt level.
150 * Sets the interrupt level on Data Register interrupt.
152 * \param _usart Pointer to the USART module.
153 * \param _dreIntLevel Interrupt level of the DRE interrupt.
154 * Use USART_DREINTLVL_t type.
156 #define USART_SET_DRE_INTERRUPT_LEVEL(_usart, _dreIntLevel) \
157 (_usart)->CTRLA = ((_usart)->CTRLA & ~USART_DREINTLVL_gm) | _dreIntLevel
159 /* \brief Set the mode the USART run in.
161 * Set the mode the USART run in. The default mode is asynchronous mode.
163 * \param _usart Pointer to the USART module register section.
164 * \param _usartMode Selects the USART mode. Use USART_CMODE_t type.
167 * - 0x0 : Asynchronous mode.
168 * - 0x1 : Synchronous mode.
170 * - 0x3 : Master SPI mode.
172 #define USART_SET_MODE(_usart, _usartMode) \
173 ((_usart)->CTRLC = ((_usart)->CTRLC & (~USART_CMODE_gm)) | _usartMode)
175 /* \brief Check if data register empty flag is set.
177 * \param _usart The USART module.
179 #define USART_IS_TX_DATA_REGISTER_EMPTY(_usart) (((_usart)->STATUS & USART_DREIF_bm) != 0)
181 /* \brief Put data (5-8 bit character).
183 * Use the macro USART_IsTXDataRegisterEmpty before using this function to
184 * put data to the TX register.
186 * \param _usart The USART module.
187 * \param _data The data to send.
189 #define USART_PUT_CHAR(_usart, _data) ((_usart)->DATA = _data)
191 /* \brief Checks if the RX complete interrupt flag is set.
193 * Checks if the RX complete interrupt flag is set.
195 * \param _usart The USART module.
197 #define USART_IS_RX_COMPLETE(_usart) (((_usart)->STATUS & USART_RXCIF_bm) != 0)
199 /* \brief Get received data (5-8 bit character).
201 * This macro reads out the RX register.
202 * Use the macro USART_RX_Complete to check if anything is received.
204 * \param _usart The USART module.
206 * \retval Received data.
208 #define USART_GET_CHAR(_usart) ((_usart)->DATA)
210 /* configurable macros */
212 #if !CONFIG_SER_HWHANDSHAKE
214 * \name Hardware handshake (RTS/CTS).
217 #define RTS_ON do {} while (0)
218 #define RTS_OFF do {} while (0)
219 #define IS_CTS_ON true
220 #define EIMSKF_CTS 0 /**< Dummy value, must be overridden */
225 * \name Overridable serial bus hooks
227 * These can be redefined in hw.h to implement
228 * special bus policies such as half-duplex, 485, etc.
232 * TXBEGIN TXCHAR TXEND TXOFF
233 * | __________|__________ | |
236 * ______ __ __ __ __ __ __ ________________
237 * \/ \/ \/ \/ \/ \/ \/
238 * ______/\__/\__/\__/\__/\__/\__/
245 #ifndef SER_UART_BUS_TXINIT
247 * Default TXINIT macro - invoked in uart_init()
249 * - Enable both the receiver and the transmitter
250 * - Enable only the RX complete interrupt
252 #define SER_UART_BUS_TXINIT(_usart) do { \
253 USART_RX_ENABLE(_usart); \
254 USART_TX_ENABLE(_usart); \
255 USART_SET_RX_INTERRUPT_LEVEL(_usart, USART_RXCINTLVL_MED_gc); \
259 #ifndef SER_UART_BUS_TXBEGIN
261 * Invoked before starting a transmission
263 * - Enable both the receiver and the transmitter
264 * - Enable both the RX complete and UDR empty interrupts
266 #define SER_UART_BUS_TXBEGIN(_usart) do { \
267 USART_SET_RX_INTERRUPT_LEVEL(_usart, USART_RXCINTLVL_MED_gc); \
268 USART_SET_DRE_INTERRUPT_LEVEL(_usart, USART_DREINTLVL_MED_gc);\
272 #ifndef SER_UART_BUS_TXCHAR
274 * Invoked to send one character.
276 #define SER_UART_BUS_TXCHAR(_usart, c) do { \
277 USART_PUT_CHAR(_usart, c); \
281 #ifndef SER_UART_BUS_TXEND
283 * Invoked as soon as the txfifo becomes empty
285 * - Keep both the receiver and the transmitter enabled
286 * - Keep the RX complete interrupt enabled
287 * - Disable the UDR empty interrupt
289 #define SER_UART_BUS_TXEND(_usart) do { \
290 USART_SET_DRE_INTERRUPT_LEVEL(_usart, USART_DREINTLVL_OFF_gc); \
294 #ifndef SER_UART_BUS_TXOFF
296 * \def SER_UART_BUS_TXOFF
298 * Invoked after the last character has been transmitted
300 * The default is no action.
303 #define SER_UART_BUS_TXOFF(_usart)
309 /* From the high-level serial driver */
310 extern struct Serial *ser_handles[SER_CNT];
312 /* TX and RX buffers */
313 #if IMPLEMENT_SER_UART0
314 static unsigned char uart0_txbuffer[CONFIG_UART0_TXBUFSIZE];
315 static unsigned char uart0_rxbuffer[CONFIG_UART0_RXBUFSIZE];
317 #if IMPLEMENT_SER_UART1
318 static unsigned char uart1_txbuffer[CONFIG_UART1_TXBUFSIZE];
319 static unsigned char uart1_rxbuffer[CONFIG_UART1_RXBUFSIZE];
321 #if IMPLEMENT_SER_UART2
322 static unsigned char uart2_txbuffer[CONFIG_UART2_TXBUFSIZE];
323 static unsigned char uart2_rxbuffer[CONFIG_UART2_RXBUFSIZE];
325 #if IMPLEMENT_SER_UART3
326 static unsigned char uart3_txbuffer[CONFIG_UART3_TXBUFSIZE];
327 static unsigned char uart3_rxbuffer[CONFIG_UART3_RXBUFSIZE];
329 #if IMPLEMENT_SER_UART4
330 static unsigned char uart4_txbuffer[CONFIG_UART4_TXBUFSIZE];
331 static unsigned char uart4_rxbuffer[CONFIG_UART4_RXBUFSIZE];
333 #if IMPLEMENT_SER_UART5
334 static unsigned char uart5_txbuffer[CONFIG_UART5_TXBUFSIZE];
335 static unsigned char uart5_rxbuffer[CONFIG_UART5_RXBUFSIZE];
337 #if IMPLEMENT_SER_UART6
338 static unsigned char uart6_txbuffer[CONFIG_UART6_TXBUFSIZE];
339 static unsigned char uart6_rxbuffer[CONFIG_UART6_RXBUFSIZE];
341 #if IMPLEMENT_SER_UART7
342 static unsigned char uart7_txbuffer[CONFIG_UART7_TXBUFSIZE];
343 static unsigned char uart7_rxbuffer[CONFIG_UART7_RXBUFSIZE];
347 * Internal hardware state structure
349 * The \a sending variable is true while the transmission
350 * interrupt is retriggering itself.
352 * the \a usart variable will point to the USART_t structure
353 * that should be used.
355 * the \a port variable will point to the PORT_t structure
356 * that should be modified to set the tx pin as an output and the
359 * the \a txpin variable will hold the pinnumber of the pin to use
362 * the \a rxpin variable will hold the pinnumber of the pin to use
365 * For the USARTs the \a sending flag is useful for taking specific
366 * actions before sending a burst of data, at the start of a trasmission
367 * but not before every char sent.
369 * For the SPI, this flag is necessary because the SPI sends and receives
370 * bytes at the same time and the SPI IRQ is unique for send/receive.
371 * The only way to start transmission is to write data in SPDR (this
372 * is done by spi_starttx()). We do this *only* if a transfer is
373 * not already started.
375 struct AvrxmegaSerial
377 struct SerialHardware hw;
378 volatile bool sending;
379 volatile USART_t* usart;
380 volatile PORT_t* port;
387 * The same callbacks are used for all USARTS.
388 * By casting the SerialHardware structure to the AvrxmegaSerial
389 * structure a pointer to the USART_t structure can be obtained,
390 * to perform the callback for the specific USART.
391 * This methode might cost some more cpu time, but saves on
392 * code duplication and code size.
397 * \brief Initializes the uart
399 * The TX pin of the uart will be set as an outputpin
400 * The RX pin of the uart will be set as an inputpin
401 * The usart will be initialized
402 * \see SER_UART_BUS_TXINIT
404 * \param _hw struct AvrxmegaSerial
407 static void uart_init(struct SerialHardware * _hw, UNUSED_ARG(struct Serial *, ser))
409 struct AvrxmegaSerial *hw = (struct AvrxmegaSerial *)_hw;
410 //set transmit pin as output
411 hw->port->DIRSET = BV(hw->txpin);
412 hw->port->OUTCLR = BV(hw->txpin);
413 //set receive pin as input
414 hw->port->DIRCLR = BV(hw->rxpin);
415 //initialize the USART
416 SER_UART_BUS_TXINIT(hw->usart);
422 * \brief Cleans up / Disables the uart
424 * \param _hw struct AvrxmegaSerial
426 static void uart_cleanup(struct SerialHardware * _hw)
428 struct AvrxmegaSerial *hw = (struct AvrxmegaSerial *)_hw;
429 hw->usart->CTRLA = 0;
430 hw->usart->CTRLB = 0;
434 * \brief Enableds the TX interrupt
436 * \param _hw struct AvrxmegaSerial
438 static void uart_enabletxirq(struct SerialHardware *_hw)
440 struct AvrxmegaSerial *hw = (struct AvrxmegaSerial *)_hw;
443 * WARNING: racy code here! The tx interrupt sets hw->sending to false
444 * when it runs with an empty fifo. The order of statements in the
450 SER_UART_BUS_TXBEGIN(hw->usart);
455 * \brief sets the uart to the provided baudrate
457 * For setting the baudrate an scale factor (bscale) and a period
458 * setting (BSEL) is required.
460 * The scale factor should be privided by defining USART_SCALE_FACTOR
462 * Atmel specifies BSEL for normal speed mode and bscale >= 0 as:
463 * BSEL = (cpu_freq / ((2^bscale) * 16 * rate)) - 1
464 * To allow BSEL to be calculated with an power function this can be
466 * BSEL = BSEL = (cpu_freq / ((1 << bscale) * 16 * rate)) - 1
468 * Atmel specifies BSEL for normal speed mode and bscale < 0 as:
469 * BSEL = (1 / (2^bscale)) * ( (cpu_freq / (16 * rate)) - 1)
470 * To calculte this float atheritmic is required as the second product will be smaller
471 * than zero in a lot of cases.
472 * To allow BSEL to be calculated with interger devision and no power function
473 * this can be rewriten by folowing simple math rules to:
474 * BSEL = ((1 << -bscale) * (cpu_freq - (16 * rate)) / (16 * rate)
476 * \param _hw struct AvrxmegaSerial
477 * \param _rate the required baudrate
480 static void uart_setbaudrate(struct SerialHardware * _hw, unsigned long _rate)
482 struct AvrxmegaSerial *hw = (struct AvrxmegaSerial *)_hw;
483 /* Compute baud-rate period, this requires a valid USART_SCALE_FACTOR */
484 #if USART_SCALE_FACTOR < 0
485 uint16_t bsel = DIV_ROUND((1 << (-(USART_SCALE_FACTOR))) * (CPU_FREQ - (16 * _rate)), 16 * _rate);
487 uint16_t bsel = DIV_ROUND(CPU_FREQ, (1 << (USART_SCALE_FACTOR)) * 16 * _rate) - 1;
489 USART_SET_BAUDRATE(hw->usart, bsel, USART_SCALE_FACTOR);
493 * \brief Sets the parity of the uart
495 * \param _hw struct AvrxmegaSerial
496 * \param _parity the parity to set
498 static void uart_setparity(struct SerialHardware * _hw, int _parity)
500 struct AvrxmegaSerial *hw = (struct AvrxmegaSerial *)_hw;
501 USART_SET_MODE(hw->usart, _parity);
505 * \brief Returns true if Transmitter is sending
507 * \param _hw struct AvrxmegaSerial
508 * \return true if transmitter is sending
510 static bool tx_sending(struct SerialHardware* _hw)
512 struct AvrxmegaSerial *hw = (struct AvrxmegaSerial *)_hw;
517 // FIXME: move into compiler.h? Ditch?
519 #define C99INIT(name,val) .name = val
520 #elif defined(__GNUC__)
521 #define C99INIT(name,val) name: val
523 #warning No designated initializers, double check your code
524 #define C99INIT(name,val) (val)
528 * High-level interface data structures
530 static const struct SerialHardwareVT UART_VT =
532 C99INIT(init, uart_init),
533 C99INIT(cleanup, uart_cleanup),
534 C99INIT(setBaudrate, uart_setbaudrate),
535 C99INIT(setParity, uart_setparity),
536 C99INIT(txStart, uart_enabletxirq),
537 C99INIT(txSending, tx_sending)
541 * Xmega UARTDesc data structure
542 * Contains all information required to manage a serial port.
544 * Serial ports are assigned (as far as present on the xmega family) as:
545 * SER_UART0 -> USARTC0
546 * SER_UART1 -> USARTD0
547 * SER_UART2 -> USARTE0
548 * SER_UART3 -> USARTC1
549 * SER_UART4 -> USARTD1
550 * SER_UART5 -> USARTE1
551 * SER_UART6 -> USARTF0
552 * SER_UART7 -> USARTF1
554 static struct AvrxmegaSerial UARTDescs[SER_CNT] =
556 #if IMPLEMENT_SER_UART0
559 C99INIT(table, &UART_VT),
560 C99INIT(txbuffer, uart0_txbuffer),
561 C99INIT(rxbuffer, uart0_rxbuffer),
562 C99INIT(txbuffer_size, sizeof(uart0_txbuffer)),
563 C99INIT(rxbuffer_size, sizeof(uart0_rxbuffer)),
565 C99INIT(sending, false),
566 C99INIT(usart, &USARTC0),
567 C99INIT(port, &PORTC),
568 C99INIT(txpin, PIN3_bp),
569 C99INIT(rxpin, PIN2_bp),
572 #if IMPLEMENT_SER_UART1
575 C99INIT(table, &UART_VT),
576 C99INIT(txbuffer, uart1_txbuffer),
577 C99INIT(rxbuffer, uart1_rxbuffer),
578 C99INIT(txbuffer_size, sizeof(uart1_txbuffer)),
579 C99INIT(rxbuffer_size, sizeof(uart1_rxbuffer)),
581 C99INIT(sending, false),
582 C99INIT(usart, &USARTD0),
583 C99INIT(port, &PORTD),
584 C99INIT(txpin, PIN3_bp),
585 C99INIT(rxpin, PIN2_bp),
588 #if IMPLEMENT_SER_UART2
591 C99INIT(table, &UART_VT),
592 C99INIT(txbuffer, uart2_txbuffer),
593 C99INIT(rxbuffer, uart2_rxbuffer),
594 C99INIT(txbuffer_size, sizeof(uart2_txbuffer)),
595 C99INIT(rxbuffer_size, sizeof(uart2_rxbuffer)),
597 C99INIT(sending, false),
598 C99INIT(usart, &USARTE0),
599 C99INIT(port, &PORTE),
600 C99INIT(txpin, PIN3_bp),
601 C99INIT(rxpin, PIN2_bp),
604 #if IMPLEMENT_SER_UART3
607 C99INIT(table, &UART_VT),
608 C99INIT(txbuffer, uart3_txbuffer),
609 C99INIT(rxbuffer, uart3_rxbuffer),
610 C99INIT(txbuffer_size, sizeof(uart3_txbuffer)),
611 C99INIT(rxbuffer_size, sizeof(uart3_rxbuffer)),
613 C99INIT(sending, false),
614 C99INIT(usart, &USARTC1),
615 C99INIT(port, &PORTC),
616 C99INIT(txpin, PIN7_bp),
617 C99INIT(rxpin, PIN6_bp),
620 #if IMPLEMENT_SER_UART4
623 C99INIT(table, &UART_VT),
624 C99INIT(txbuffer, uart4_txbuffer),
625 C99INIT(rxbuffer, uart4_rxbuffer),
626 C99INIT(txbuffer_size, sizeof(uart4_txbuffer)),
627 C99INIT(rxbuffer_size, sizeof(uart4_rxbuffer)),
629 C99INIT(sending, false),
630 C99INIT(usart, &USARTD1),
631 C99INIT(port, &PORTD),
632 C99INIT(txpin, PIN7_bp),
633 C99INIT(rxpin, PIN6_bp),
636 #if IMPLEMENT_SER_UART5
639 C99INIT(table, &UART_VT),
640 C99INIT(txbuffer, uart5_txbuffer),
641 C99INIT(rxbuffer, uart5_rxbuffer),
642 C99INIT(txbuffer_size, sizeof(uart5_txbuffer)),
643 C99INIT(rxbuffer_size, sizeof(uart5_rxbuffer)),
645 C99INIT(sending, false),
646 C99INIT(usart, &USARTE1),
647 C99INIT(port, &PORTE),
648 C99INIT(txpin, PIN7_bp),
649 C99INIT(rxpin, PIN6_bp),
652 #if IMPLEMENT_SER_UART6
655 C99INIT(table, &UART_VT),
656 C99INIT(txbuffer, uart6_txbuffer),
657 C99INIT(rxbuffer, uart6_rxbuffer),
658 C99INIT(txbuffer_size, sizeof(uart6_txbuffer)),
659 C99INIT(rxbuffer_size, sizeof(uart6_rxbuffer)),
661 C99INIT(sending, false),
662 C99INIT(usart, &USARTF0),
663 C99INIT(port, &PORTF),
664 C99INIT(txpin, PIN3_bp),
665 C99INIT(rxpin, PIN2_bp),
668 #if IMPLEMENT_SER_UART7
671 C99INIT(table, &UART_VT),
672 C99INIT(txbuffer, uart7_txbuffer),
673 C99INIT(rxbuffer, uart7_rxbuffer),
674 C99INIT(txbuffer_size, sizeof(uart7_txbuffer)),
675 C99INIT(rxbuffer_size, sizeof(uart7_rxbuffer)),
677 C99INIT(sending, false),
678 C99INIT(usart, &USARTF1),
679 C99INIT(port, &PORTF),
680 C99INIT(txpin, PIN7_bp),
681 C99INIT(rxpin, PIN6_bp),
686 struct SerialHardware *ser_hw_getdesc(int unit)
688 ASSERT(unit < SER_CNT);
689 return &UARTDescs[unit].hw;
696 static inline void usart_handleDreInterrupt(uint8_t usartNumber)
699 struct FIFOBuffer * const txfifo = &ser_handles[usartNumber]->txfifo;
700 if (fifo_isempty(txfifo))
702 SER_UART_BUS_TXEND(UARTDescs[usartNumber].usart);
703 #ifndef SER_UART_BUS_TXOFF
704 UARTDescs[usartNumber].sending = false;
709 char c = fifo_pop(txfifo);
710 SER_UART_BUS_TXCHAR(UARTDescs[usartNumber].usart, c);
715 #define USART_DRE_INTERRUPT_VECTOR(_vector, _usart) \
716 DECLARE_ISR(_vector) \
718 usart_handleDreInterrupt( _usart ); \
722 * Serial RX complete interrupt handler.
724 * This handler is interruptible.
725 * Interrupt are reenabled as soon as recv complete interrupt is
726 * disabled. Using INTERRUPT() is troublesome when the serial
727 * is heavily loaded, because an interrupt could be retriggered
728 * when executing the handler prologue before RXCIE is disabled.
730 static inline void USART_handleRXCInterrupt(uint8_t usartNumber)
734 ser_handles[usartNumber]->status |= (UARTDescs[usartNumber].usart)->STATUS & (SERRF_RXSROVERRUN | SERRF_FRAMEERROR);
735 /* To clear the RXC flag we must _always_ read the UDR even when we're
736 * not going to accept the incoming data, otherwise a new interrupt
737 * will occur once the handler terminates.
739 char c = (UARTDescs[usartNumber].usart)->DATA;
740 struct FIFOBuffer * const rxfifo = &ser_handles[usartNumber]->rxfifo;
741 if (fifo_isfull(rxfifo))
743 ser_handles[usartNumber]->status |= SERRF_RXFIFOOVERRUN;
747 fifo_push(rxfifo, c);
748 #if CONFIG_SER_HWHANDSHAKE
749 if (fifo_isfull(rxfifo))
751 RTS_OFF(UARTDescs[usartNumber].usart);
758 #define USART_RXC_INTERRUPT_VECTOR(_vector, _usart) \
759 DECLARE_ISR(_vector) \
761 USART_handleRXCInterrupt( _usart ); \
764 #if IMPLEMENT_SER_UART0
765 USART_DRE_INTERRUPT_VECTOR(USARTC0_DRE_vect, SER_UART0)
766 USART_RXC_INTERRUPT_VECTOR(USARTC0_RXC_vect, SER_UART0)
768 #if IMPLEMENT_SER_UART1
769 USART_DRE_INTERRUPT_VECTOR(USARTD0_DRE_vect, SER_UART1)
770 USART_RXC_INTERRUPT_VECTOR(USARTD0_RXC_vect, SER_UART1)
772 #if IMPLEMENT_SER_UART2
773 USART_DRE_INTERRUPT_VECTOR(USARTE0_DRE_vect, SER_UART2)
774 USART_RXC_INTERRUPT_VECTOR(USARTE0_RXC_vect, SER_UART2)
776 #if IMPLEMENT_SER_UART3
777 USART_DRE_INTERRUPT_VECTOR(USARTC1_DRE_vect, SER_UART3)
778 USART_RXC_INTERRUPT_VECTOR(USARTC1_RXC_vect, SER_UART3)
780 #if IMPLEMENT_SER_UART4
781 USART_DRE_INTERRUPT_VECTOR(USARTD1_DRE_vect, SER_UART4)
782 USART_RXC_INTERRUPT_VECTOR(USARTD1_RXC_vect, SER_UART4)
784 #if IMPLEMENT_SER_UART5
785 USART_DRE_INTERRUPT_VECTOR(USARTE1_DRE_vect, SER_UART5)
786 USART_RXC_INTERRUPT_VECTOR(USARTE1_RXC_vect, SER_UART5)
788 #if IMPLEMENT_SER_UART6
789 USART_DRE_INTERRUPT_VECTOR(USARTF0_DRE_vect, SER_UART6)
790 USART_RXC_INTERRUPT_VECTOR(USARTF0_RXC_vect, SER_UART6)
792 #if IMPLEMENT_SER_UART7
793 USART_DRE_INTERRUPT_VECTOR(USARTF1_DRE_vect, SER_UART7)
794 USART_RXC_INTERRUPT_VECTOR(USARTF1_RXC_vect, SER_UART7)
797 #ifdef SER_UART_BUS_TXOFF
798 static inline void USART_handleTXCInterrupt(uint8_t usartNumber)
801 struct FIFOBuffer * const txfifo = &ser_handles[usartNumber]->txfifo;
802 if (fifo_isempty(txfifo))
804 SER_UART_BUS_TXOFF(UARTDescs[usartNumber].usart);
805 UARTDescs[usartNumber].sending = false;
809 SER_UART_BUS_TXBEGIN(UARTDescs[usartNumber].usart);
815 * Serial port 0 TX complete interrupt handler.
817 * This IRQ is usually disabled. The UDR-empty interrupt
818 * enables it when there's no more data to transmit.
819 * We need to wait until the last character has been
820 * transmitted before switching the 485 transceiver to
823 * The txfifo might have been refilled by putchar() while
824 * we were waiting for the transmission complete interrupt.
825 * In this case, we must restart the UDR empty interrupt,
826 * otherwise we'd stop the serial port with some data
827 * still pending in the buffer.
829 #define USART_TXC_INTERRUPT_VECTOR(_vector, _usart) \
830 DECLARE_ISR(_vector) \
832 USART_handleTXCInterrupt( _usart ); \
835 #if IMPLEMENT_SER_UART0
836 USART_TXC_INTERRUPT_VECTOR(USARTC0_TXC_vect, SER_UART0)
838 #if IMPLEMENT_SER_UART1
839 USART_TXC_INTERRUPT_VECTOR(USARTD0_TXC_vect, SER_UART1)
841 #if IMPLEMENT_SER_UART2
842 USART_TXC_INTERRUPT_VECTOR(USARTE0_TXC_vect, SER_UART2)
844 #if IMPLEMENT_SER_UART3
845 USART_TXC_INTERRUPT_VECTOR(USARTC1_TXC_vect, SER_UART3)
847 #if IMPLEMENT_SER_UART4
848 USART_TXC_INTERRUPT_VECTOR(USARTD1_TXC_vect, SER_UART4)
850 #if IMPLEMENT_SER_UART5
851 USART_TXC_INTERRUPT_VECTOR(USARTE1_TXC_vect, SER_UART5)
853 #if IMPLEMENT_SER_UART6
854 USART_TXC_INTERRUPT_VECTOR(USARTF0_TXC_vect, SER_UART6)
856 #if IMPLEMENT_SER_UART7
857 USART_TXC_INTERRUPT_VECTOR(USARTF1_TXC_vect, SER_UART7)
859 #endif /* SER_UART_BUS_TXOFF */