@@ -88,7 +88,6 @@ void serialEventRun(void)
8888void UartClass::_tx_data_empty_irq (void )
8989{
9090 // Check if tx buffer already empty.
91- // This interrupt-handler can be called "manually" from flush();
9291 if (_tx_buffer_head == _tx_buffer_tail) {
9392 // Buffer empty, so disable "data register empty" interrupt
9493 (*_hwserial_module).CTRLA &= (~USART_DREIE_bm);
@@ -107,8 +106,6 @@ void UartClass::_tx_data_empty_irq(void)
107106
108107 (*_hwserial_module).TXDATAL = c;
109108
110- while (!((*_hwserial_module).STATUS & USART_DREIF_bm));
111-
112109 if (_tx_buffer_head == _tx_buffer_tail) {
113110 // Buffer empty, so disable "data register empty" interrupt
114111 (*_hwserial_module).CTRLA &= (~USART_DREIE_bm);
@@ -121,6 +118,23 @@ void UartClass::_tx_data_empty_irq(void)
121118 }
122119}
123120
121+ // To invoke data empty "interrupt" via a call, use this method
122+ void UartClass::_poll_tx_data_empty (void )
123+ {
124+ if ( (!(SREG & CPU_I_bm)) || (!((*_hwserial_module).CTRLA & USART_DREIE_bm)) ) {
125+ // Interrupts are disabled either globally or for data register empty,
126+ // so we'll have to poll the "data register empty" flag ourselves.
127+ // If it is set, pretend an interrupt has happened and call the handler
128+ // to free up space for us.
129+
130+ // Invoke interrupt handler only if conditions data register is empty
131+ if ((*_hwserial_module).STATUS & USART_DREIF_bm) {
132+ _tx_data_empty_irq ();
133+ }
134+ }
135+ // In case interrupts are enabled, the interrupt routine will be invoked by itself
136+ }
137+
124138// Public Methods //////////////////////////////////////////////////////////////
125139
126140void UartClass::begin (unsigned long baud, uint16_t config)
@@ -253,9 +267,7 @@ void UartClass::flush()
253267
254268 // If interrupts are globally disabled or the and DR empty interrupt is disabled,
255269 // poll the "data register empty" interrupt flag to prevent deadlock
256- if ( (!(SREG & CPU_I_bm)) || (!((*_hwserial_module).CTRLA & USART_DREIE_bm)) ) {
257- _tx_data_empty_irq ();
258- }
270+ _poll_tx_data_empty ();
259271 }
260272 // If we get here, nothing is queued anymore (DREIE is disabled) and
261273 // the hardware finished transmission (TXCIF is set).
@@ -294,18 +306,9 @@ size_t UartClass::write(uint8_t c)
294306 tx_buffer_index_t i = (_tx_buffer_head + 1 ) % SERIAL_TX_BUFFER_SIZE;
295307
296308 // If the output buffer is full, there's nothing for it other than to
297- // wait for the interrupt handler to empty it a bit
309+ // wait for the interrupt handler to empty it a bit (or emulate interrupts)
298310 while (i == _tx_buffer_tail) {
299- if ( ( !(SREG & CPU_I_bm) ) || ( !((*_hwserial_module).CTRLA & USART_DREIE_bm) ) ) {
300- // Interrupts are disabled either globally or for data register empty,
301- // so we'll have to poll the "data register empty" flag ourselves.
302- // If it is set, pretend an interrupt has happened and call the handler
303- // to free up space for us.
304-
305- _tx_data_empty_irq ();
306- } else {
307- // nop, the interrupt handler will free up space for us
308- }
311+ _poll_tx_data_empty ();
309312 }
310313
311314 _tx_buffer[_tx_buffer_head] = c;
0 commit comments