Skip to content

Commit b0ba1ee

Browse files
Andrew Cunninghamfacchinm
Andrew Cunningham
authored andcommitted
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 eb27f47 commit b0ba1ee

File tree

2 files changed

+12
-4
lines changed

2 files changed

+12
-4
lines changed

cores/arduino/SERCOM.cpp

+7-4
Original file line numberDiff line numberDiff line change
@@ -112,11 +112,10 @@ void SERCOM::enableUART()
112112
void SERCOM::flushUART()
113113
{
114114
// Skip checking transmission completion if data register is empty
115-
// if(isDataRegisterEmptyUART())
116-
// return;
115+
// Wait for transmission to complete, if ok to do so.
116+
while(!sercom->USART.INTFLAG.bit.TXC && onFlushWaitUartTXC);
117117

118-
// Wait for transmission to complete
119-
while(!sercom->USART.INTFLAG.bit.TXC);
118+
onFlushWaitUartTXC = false;
120119
}
121120

122121
void SERCOM::clearStatusUART()
@@ -183,6 +182,10 @@ int SERCOM::writeDataUART(uint8_t data)
183182

184183
//Put data into DATA register
185184
sercom->USART.DATA.reg = (uint16_t)data;
185+
186+
// indicate it's ok to wait for TXC flag when flushing
187+
onFlushWaitUartTXC = true;
188+
186189
return 1;
187190
}
188191

cores/arduino/SERCOM.h

+5
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,11 @@ class SERCOM
218218
uint8_t calculateBaudrateSynchronous(uint32_t baudrate) ;
219219
uint32_t division(uint32_t dividend, uint32_t divisor) ;
220220
void initClockNVIC( void ) ;
221+
222+
// Flag set when data is loaded into sercom->USART.DATA.reg.
223+
// Helps with preventing UART lockups when flushing on startup
224+
// and the asyncronous nature of the DRE and TXC interrupt flags.
225+
bool onFlushWaitUartTXC = false;
221226
};
222227

223228
#endif

0 commit comments

Comments
 (0)