My main issue with the flush command is why it's even provided in the first place?
Lefty
Unix has had this capability in the serial port drivers long before streams and long
before C++ ever existed. They are there because, both can be very useful and are actually necessary
for certain situations.
(Even Windows implemented both in its serial drivers)
The answer as to how it can be used depends on if you are talking about the pre 1.0 flush() (which flushed
the RX buffer) vs the 1.0 flush() (which drains the TX output buffer)
and I'll give answers to both because it can be useful to flush() input queues as well
as drain output queues.
Often it comes down to synchronizing between the two ends during some type of protocol.
Depending on what is going on and the protocol, it can require draining the TX buffer,
purging the RX buffer or both.
Sometimes it can affect overall throughput and latency.
First the need to flush an input queue.(purge/throw away any RX buffered bytes)
There are times when you want to start synchronization over and it is helpful
to toss everything in one clean flush.
Lets say you are debugging and want to have a diagnostic message that pushes out a message
to the user and then waits for a key to be pressed.
But you want to always ensure that the user sees the message and must press a key to
continue.
The safest way to do this is to push out your message and then flush the input Q
before you hang your read for the character to continue on.
That way you never allow any buffered RX characters to continue on.
It ensures that there will be a pause before continuing on.
In this case it is often useful to also drain out the TX side so you know when to flush the RX side.
So the normal sequence for something like this would be
- send message
- drain output buffer to ensure user can see it
- flush RX buffers to remove any keys pressed in advance or left over from last time
- read RX for "continue" key press.
This same thing happens in more complex machine to machine data protocols.
There are times when you need to ensure the state of the TX and RX buffers.
Now lets look at the output drain.
Consider a case of using something like a serial device that takes serial commands but requires
throttling (pauses) between commands.
The normal sequence would be:
- send message
- pause before next message
(repeat)
[ I have seen Arduino serial LCD backpack libraries that do this ]
Now if you don't have any TX buffering that works.
As soon as you have TX buffering, you can't do this because your pause is happening
while characters are still going out and your throttling delay will not be as long as you want/need.
While you could account for this by taking into consideration the length of the message and
the data rate of the message transfer, it easier to simply ask for the characters to be drained out
so that you know when to start your throttling delay.
These are just 2 very simple examples of why you need both RX flush and TX drain.
You also have to keep in mind that a serial read/write API can be used on top of many types
of different hardware.
Suppose it is very expensive to transmit a message and the cost is more based sending a message
vs the size of the message.
So in that case the character/message handler might queue up the characters and wait for an end of message terminator
or a certain amount of characters in the buffer before sending any of the message.
Now in the case of short message, there might be a timeout period that will push out short messages.
But if the application wants or needs to push out all the bytes sent *NOW* it could call a drain routine to force
out all the characters buffered up.
And maybe the hardware does not provide a timeout for short messages.
In that case, none of the characters in the buffer would be sent until a drain() was done.
These are the kinds of things that happen in real OS environments with higher level data protocols
and believe it or not this same kind of thing happens inside the FTDI chip.
The FTDI chip has all kinds of buffer handing parameters to optimize the data transfers across the USB.
And how you deal with this kind of stuff affects transfer rates and latencies.
It is not always optimum to push out characters as soon as they arrive.
When designing APIs it always useful to take a broader view about services needed.
And that is why it is useful to support both RX flush and TX drain as the same API
is often used on multiple different hardware implementations and you never know what
type of protocols will be built on top of the API.
It is unfortunate that Arduino does not support being able to purge out the RX Q and
drain out the TX Q and that the flush() API call works differently on 1.0 and pre 1.0
and ti works differently on 1.0 between SoftSerial and HardwareSerial.
--- bill