-
-
Notifications
You must be signed in to change notification settings - Fork 7k
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
Fix buffer retransmission and flush hang problems in hardware serial support #6855
Conversation
Note that I've not included one of the changes in #3865 - making tx_buffer_head == _tx_buffer_tail in write() atomic. This is because
There may of course be other potential problems that this does address but given the slight performance penalty I think it may need further discussion before implementation. Also I've only tested that the specific issues are fixed, and on the Arduino Mega platform only. |
This change is needed when the TX buffer is > 256 bytes. In that case, the head and tail are 2 bytes, so there is potential for reading half of the value before the ISR updates it and half of the value after. In fact, all (read and write) access of tail (which is written by the ISR) should be atomic, and all write access of head and tail (which are read by the ISR) should be atomic (using TX_BUFFER_ATOMIC). It might be even clearer to make all accesses to the head and tail atomic. This is a tricky problem to reproduce, since it will only happen when:
I had a look around the code and it seems there's a lot of head and tail accesses other than the one in I have two more minor remarks:
Other than that, this PR looks great to me! |
I understood the possibility of the ISR changing the second byte of the buffer tail in between a read of the first and second byte, but wasn't sure why only this particular example was fixed since as you say there are several others. Anyway, to avoid making too many changes in the same pull request and causing possible delay I think I'll create a new PR for making buffer pointer accesses atomic where needed for large buffers. Now to figure out how to change commit messages .. |
Agreed! As for changing commit messages, check out interactive rebase (e.g. |
New macro TX_BUFFER_ATOMIC makes the following code block atomic only if the transmit buffer is larger than 256 bytes. SREG is restored on completion. The macro is then used to simplify code for availableForWrite()
Moving the head buffer pointer and setting interrupt flag is now atomic in write(). Previously an intervening ISR could empty the buffer before the second ISR is triggered causing retransmission. Fixes: #3745 (original issue only)
Preserve values of configuration bits MPCMn and U2Xn. Avoid setting other read-only bits for datasheet conformance. See #3745
Changes requested by @matthijskooijman made locally by interactive rebase and forced pushed to the remote - hopefully that's an appropriate workflow? |
Make write to UDR and clearing of TXC bit in flush() atomic to avoid race condition. Fixes #3745 (second different issue introduced later but discussed in the same issue)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that's perfect. This PR looks good to merge to me. @facchinm, perhaps you have some more hardware to test this on?
@matthijskooijman looks good to me too; I'll test it later tomorrow with a handful of boards. It would probably be a good idea to apply it to https://github.com/arduino/arduinocore-avr so we can start using it proficiently |
@facchinm how did the testing go? Anything I might need to do? |
No problem on my side, all tests were just fine 😉 |
@facchinm, I have no clue about the status of that external repository, so can't really comment on that (other than it appears that we have two places for the Arduino AVR core now, which seems like it could cause confusion. If we're going to migrate to there, we should probably remove the avr core here? Merging PR's can then probably be done using |
Hi @facchinm I see this was merged into ArduinoCore-avr a while ago. It isn't appearing in the current beta download yet though (Arduino-PR-beta1.9-BUILD27) even though the AVR core has been removed from the beta branch. Is that how it should be? |
The beta channel currently tracks the latest official release of AVR core (1.6.20). We are working on the infrastructure but, at the moment, we are severely outnumbered compared to the number of projects we are involved in, so some efforts are slowing down "a bit". Sorry for that. |
Fixes #3745 fixes #6821
Based on #3865 by @NicoHood and suggestions from @matthijskooijman
Fixes two separate issues both discussed in #3745: serial buffer re-transmissions under heavy interrupt load and flush hangs at high baud rates. Tested with testcase for the buffer transmission problem and @NicoHood's testcase for the flush hang problem as posted in #3745 with both default buffer size and large buffer size (512 bytes) on Arduino Mega.
Also incorporates suggestions from @matthijskooijman:
setting read-only bits in the USCRnA register