Skip to content

v1.3.2

Choose a tag to compare

@github-actions github-actions released this 14 Jun 14:15
· 12 commits to master since this release
fix: flush the RTU receive buffer before each transaction

A transient line glitch (a single bad-CRC frame) permanently wedged a
shared RTU bus: every device on it went unavailable and never recovered,
needing a restart. Observed at least daily on a two-slave bus.

Once a corrupted or short frame leaves unread bytes in the serial input
buffer, the bus desynchronises by one frame -- each read returns the
previous request's reply, so every transaction fails "response not from
requested slave" (or bad CRC on the partial frame). The trigger is
TRANSIENT (a CRC/timeout/wrong-slave error is not FATAL, by design, so a
USB-serial hiccup does not tear down the bus), which means the bus is
never reconnected -- and reconnect was the only place modbus_flush() ran.
Nothing drained the stale bytes, so the one-off glitch became permanent.

Flush the input buffer before issuing each request on an RTU bus, so a
transaction always starts from a clean buffer. The flush must precede the
request, not follow a failed read: when a stale-frame read fails it
returns instantly while the genuine reply is still in flight, so flushing
afterwards only discards the current stale frame and lets the in-flight
one become the next -- the lag survives. Flushing before the send drops
the stale frame and lets the read block for this request's own reply,
resynchronising on the next poll. On a healthy bus the buffer is already
empty (a successful read consumes its frame exactly), so this discards
nothing. TCP is unaffected and skipped.