@bperrybap, shouldn't the flush at the beginning wait till there is only one byte left to send? At that point, there should only be 1 byte, so shouldn't it work fine? If not, can you please post the changes you made to the HardwareSerial library?
flush() currently waits until there are no characters in the s/w queue,
but there are still up to two characters still in the USART remaining to be transmitted.
One in the transmit shift register that is currently being shifted and transmitted
out and one in the transmit data buffer register (TXB).
I don't like the way Atmel implemented their TXCn bit.
It marks a transition and isn't a state. The only automatic clearing of this
bit is by execution of a TXCI interrupt, which not normally an interrupt
that is used or needed for interrupt driven transmission.
(UDR interrupts are used to allow for the double buffering to ensure back to back transmission)
This makes TXCn status kind of a pain to use.
s/w has to clear it for the hardware to set it
but it has do it in a way that doesn't create a race condition.
A robust flush() solution has to handle all conditions when called.
- A character in the transmit shift register and no character in TXB.
- A character in TXB and in the transmit shift register
- No characters in TXB or the shift register.
What I found is that some potential solutions didn't handle all of the
above situations or couldn't handle them more than once.