Skip to content

Commit

Permalink
mcu: Enhance RetryAsyncCommand to handle low-level retransmits
Browse files Browse the repository at this point in the history
The RetryAsyncCommand code needs to ensure that any response messages
are not from a previous (unrelated) query.  To do that it compares the
'#sent_time' from potential responses to ensure they are not from a
previous session.  However, if there are any low-level serial
retransmits then the low-level code sets the '#sent_time' to zero (to
indicate that the query send time is not strictly known).  That could
result in a valid response not being accepted by RetryAsyncCommand.

If a low-level connection is experiencing a small amount of periodic
retransmits it could result in multiple high-level retry attempts
failing to the point that there is a user-facing error.  This could
result in "Timeout on wait for 'tmcuart_response' response" errors.

Fix by accepting responses even if there is a low-level retransmit
once the code can confirm that there can be no previous query still in
progress.

Signed-off-by: Kevin O'Connor <[email protected]>
  • Loading branch information
KevinOConnor committed Sep 21, 2023
1 parent 8ef0f7d commit e9bf2d4
Showing 1 changed file with 4 additions and 2 deletions.
6 changes: 4 additions & 2 deletions klippy/mcu.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,16 @@ def __init__(self, serial, name, oid=None):
self.reactor = serial.get_reactor()
self.completion = self.reactor.completion()
self.min_query_time = self.reactor.monotonic()
self.need_response = True
self.serial.register_response(self.handle_callback, name, oid)
def handle_callback(self, params):
if params['#sent_time'] >= self.min_query_time:
self.min_query_time = self.reactor.NEVER
if self.need_response and params['#sent_time'] >= self.min_query_time:
self.need_response = False
self.reactor.async_complete(self.completion, params)
def get_response(self, cmds, cmd_queue, minclock=0, reqclock=0):
cmd, = cmds
self.serial.raw_send_wait_ack(cmd, minclock, reqclock, cmd_queue)
self.min_query_time = 0.
first_query_time = query_time = self.reactor.monotonic()
while 1:
params = self.completion.wait(query_time + self.RETRY_TIME)
Expand Down

0 comments on commit e9bf2d4

Please sign in to comment.