@@ -88,7 +88,6 @@ void serialEventRun(void)
88
88
void UartClass::_tx_data_empty_irq (void )
89
89
{
90
90
// Check if tx buffer already empty.
91
- // This interrupt-handler can be called "manually" from flush();
92
91
if (_tx_buffer_head == _tx_buffer_tail) {
93
92
// Buffer empty, so disable "data register empty" interrupt
94
93
(*_hwserial_module).CTRLA &= (~USART_DREIE_bm);
@@ -107,8 +106,6 @@ void UartClass::_tx_data_empty_irq(void)
107
106
108
107
(*_hwserial_module).TXDATAL = c;
109
108
110
- while (!((*_hwserial_module).STATUS & USART_DREIF_bm));
111
-
112
109
if (_tx_buffer_head == _tx_buffer_tail) {
113
110
// Buffer empty, so disable "data register empty" interrupt
114
111
(*_hwserial_module).CTRLA &= (~USART_DREIE_bm);
@@ -121,6 +118,23 @@ void UartClass::_tx_data_empty_irq(void)
121
118
}
122
119
}
123
120
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
+
124
138
// Public Methods //////////////////////////////////////////////////////////////
125
139
126
140
void UartClass::begin (unsigned long baud, uint16_t config)
@@ -253,9 +267,7 @@ void UartClass::flush()
253
267
254
268
// If interrupts are globally disabled or the and DR empty interrupt is disabled,
255
269
// 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 ();
259
271
}
260
272
// If we get here, nothing is queued anymore (DREIE is disabled) and
261
273
// the hardware finished transmission (TXCIF is set).
@@ -294,18 +306,9 @@ size_t UartClass::write(uint8_t c)
294
306
tx_buffer_index_t i = (_tx_buffer_head + 1 ) % SERIAL_TX_BUFFER_SIZE;
295
307
296
308
// 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)
298
310
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 ();
309
312
}
310
313
311
314
_tx_buffer[_tx_buffer_head] = c;
0 commit comments