-
-
Notifications
You must be signed in to change notification settings - Fork 725
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Serial.flush() blocks forever #597
Comments
See arduino-libraries/MKRWAN@0493918 . This PR #541 is the root cause, and it's not been analyzed well enough before merging. Sorry for that. Can we find a workaround to fix both the issues? @aentinger @cmaglie |
Revert #541? (Sounds cheap but as I see it clearly a bug was introduced). |
I haven't looked closely, but I remember that on AVR, there was the problem that TXC is only set after all pending data was sent and cleared when new data was queued. This left the problem that on startup, when no data was written yet, no data was pending, but TXC was not set either, so just waiting for TXC in flush would wait indefinitely. From the SAMD datasheet, the TXC bit seems to behave the same here. I haven't looked close enough if this explains the problems in this issue, but I suspect it might. On AVR, IIRC we solved this by simply keeping a variable that says whether or not data has been written at all and use that to bypass TXC if needed, I think the same approach would be valid here too. |
I've made some changes that seems to have fixed this issue, but I'd appreciate if others could test. You can checkout the changes in the latest commit from my old PR #535 a744583 . It was a mistake to to push to that branch - sorry for the mess, but anyway the specific changes relating to this issue are clearly visible. |
@facchinm this bug is critical in my view. In my case it causes RS485 library to hang (sendBreak calls flush). Like @aentinger I'd suggest to revert PR #541 and make a release based on 1.8.11 with just this fixed. I'd address the solution (@acicuc) in a separate release. What do you think? |
@coffeemachine was @matthijskooijman suggestion that I implemented in a744583 helpful in your case? |
* 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.
@acicuc I pushed your patch (rebased) on #652 . Tested reflashing an ESP32 up to 1.5Mbaud, with flush() added here and there. |
fix Serial.flush() blocks forever #597
Was the fix (#652) for this rolled out for the Arduino Due (SAM) board library, or was it specific only to the SAMD ? |
@WanaGo, currently it doesn't look like it, but you may be able to implement a similar approach in the SAM core? |
Using the latest version of the SAMD core, doing a Serial.flush() will hang forever.
Problem can be reproduced using this sketch:
Which will only print:
Tracing the issue down takes me to
Serial.flush()
, which is defined in Uart.cpp. This callssercom->flushUART();
in SERCOM.cpp.The previous versions of this core had the following code:
The current version has the
if(isDataRegisterEmptyUART())
commented out:ArduinoCore-samd/cores/arduino/SERCOM.cpp
Lines 115 to 116 in 0b60a79
I don't understand why this is commented out, as clearly the
while(!sercom->USART.INTFLAG.bit.TXC);
will never return ifflush()
is called when the TX buffer is already empty.The text was updated successfully, but these errors were encountered: