Skip to content

Commit a744583

Browse files
author
Andrew Cunningham
committed
fix Serial.flush() blocks forever #597
* The aynchronous nature of the DRE and TXC interrupt flags causes issues (lockups) when the TX DATA register is empty on start and a flush is issued. Simply looking at the DRE prior to waiting for TXC is insufficient because the data register may well be empty but the shift register could still contain data, in this case SERCOM::flushUART() would return before TXC has been raised thus before flushing is complete. * bool added to SERCOM.h to indicate when it is ok for SERCOM::flushUART() to wait for the TXC flag. This flag is set when any data is written to the data register via SERCOM::writeDataUART(). It is cleared when a flush is done.
1 parent e576493 commit a744583

File tree

2 files changed

+13
-6
lines changed

2 files changed

+13
-6
lines changed

Diff for: cores/arduino/SERCOM.cpp

+7-5
Original file line numberDiff line numberDiff line change
@@ -113,12 +113,10 @@ void SERCOM::enableUART()
113113

114114
void SERCOM::flushUART()
115115
{
116-
// Skip checking transmission completion if data register is empty
117-
if(isDataRegisterEmptyUART())
118-
return;
116+
// Wait for transmission to complete, if ok to do so.
117+
while(!sercom->USART.INTFLAG.bit.TXC && onFlushWaitUartTXC);
119118

120-
// Wait for transmission to complete
121-
while(!sercom->USART.INTFLAG.bit.TXC);
119+
onFlushWaitUartTXC = false;
122120
}
123121

124122
void SERCOM::clearStatusUART()
@@ -185,6 +183,10 @@ int SERCOM::writeDataUART(uint8_t data)
185183

186184
//Put data into DATA register
187185
sercom->USART.DATA.reg = (uint16_t)data;
186+
187+
// indicate it's ok to wait for TXC flag when flushing
188+
onFlushWaitUartTXC = true;
189+
188190
return 1;
189191
}
190192

Diff for: cores/arduino/SERCOM.h

+6-1
Original file line numberDiff line numberDiff line change
@@ -230,8 +230,13 @@ class SERCOM
230230
void initTimeout( void );
231231
bool testTimeout( void );
232232
uint16_t timeoutInterval;
233-
uint32_t timeoutRef, restartTX_cnt, restartTX_limit = 5;
233+
uint32_t timeoutRef, restartTX_cnt, restartTX_limit = 10;
234234
bool timeoutOccurred;
235+
236+
// Flag set when data is loaded into sercom->USART.DATA.reg.
237+
// Helps with preventing UART lockups when flushing on startup
238+
// and the asyncronous nature of the DRE and TXC interrupt flags.
239+
bool onFlushWaitUartTXC = false;
235240
};
236241

237242
#endif

0 commit comments

Comments
 (0)