I recently was playing around trying to make serial reception work more reliably, and found that the following command was much better about dropping packets and eliminating framing errors than anything I've previously done.
if (Serial.available()) evaluateCommand(Serial.readStringUntil(0x0D));
evaluateCommand() is a string parser that interprets a received command, and this reliably (for now) frames commands terminated with carriage return (0x0D) and interprets them. And fast!
I've been using this for almost a year in all my projects, but I realized today after talking with some friends that this REALLY is strange that it works. Even with interactively typed commands and a 10ms timeout setting. Weirder, it's faster than when I just read bytes upon a Serial.available() and put them one by one in a buffer. Even weirder, the Serial Stream must be reading the data without clearing it from the Serial Stream buffer because the full command is definitely being passed to evaluateCommand()!
For one, readStringUntil() is probably hitting the the timeout constantly, and the return from that as best I can tell should be the string so far as it's been received so far. Yet my evaluateCommand() code is definitely not constantly evaluating partial commands because I'd see them echoed back with an error for the incomplete command.
But the fact that as best I can tell the Stream is keeping the data in its buffer when the readStringUntil() times out is exceedingly weird.
I've been able to use this to get ~1kHz commands over USB serial to parse reliably, but it also works fine interactively. Does anyone know how on earth this is an acceptable situation?
I definitely don't want to rely on undocumented or undefined behavior in my functions, so a better way to do this is also welcome =)