diff options
| author | Hans Maerki <buhtig.hans.maerki@ergoinfo.ch> | 2025-01-27 07:29:44 +0100 |
|---|---|---|
| committer | Damien George <damien@micropython.org> | 2025-01-29 10:45:08 +1100 |
| commit | 03fe9c55ea8a3ef8bede5547476f37d7fca20119 (patch) | |
| tree | 5e5d62665dd4794d81efa2f7cd89167e13a55e6e | |
| parent | 0d46e45a1f72ee61a153c41aaaf6c63818ccffb0 (diff) | |
tools/mpremote: Introduce timeout_overall for read_until().
And use it in `enter_raw_repl()`. This prevents waiting forever for a
serial device that does not respond to the Ctrl-C/Ctrl-D/etc commands and
is constantly outputting data.
Signed-off-by: Hans Maerki <buhtig.hans.maerki@ergoinfo.ch>
| -rw-r--r-- | tools/mpremote/mpremote/transport_serial.py | 23 |
1 files changed, 17 insertions, 6 deletions
diff --git a/tools/mpremote/mpremote/transport_serial.py b/tools/mpremote/mpremote/transport_serial.py index 449708a5e..d3148f9ac 100644 --- a/tools/mpremote/mpremote/transport_serial.py +++ b/tools/mpremote/mpremote/transport_serial.py @@ -98,11 +98,14 @@ class SerialTransport(Transport): def close(self): self.serial.close() - def read_until(self, min_num_bytes, ending, timeout=10, data_consumer=None): + def read_until( + self, min_num_bytes, ending, timeout=10, data_consumer=None, timeout_overall=None + ): """ min_num_bytes: Obsolete. ending: Return if 'ending' matches. timeout [s]: Return if timeout between characters. None: Infinite timeout. + timeout_overall [s]: Return not later than timeout_overall. None: Infinite timeout. data_consumer: Use callback for incoming characters. If data_consumer is used then data is not accumulated and the ending must be 1 byte long @@ -110,9 +113,10 @@ class SerialTransport(Transport): """ assert data_consumer is None or len(ending) == 1 assert isinstance(timeout, (type(None), int, float)) + assert isinstance(timeout_overall, (type(None), int, float)) data = b"" - begin_char_s = time.monotonic() + begin_overall_s = begin_char_s = time.monotonic() while True: if data.endswith(ending): break @@ -127,10 +131,15 @@ class SerialTransport(Transport): else: if timeout is not None and time.monotonic() >= begin_char_s + timeout: break + if ( + timeout_overall is not None + and time.monotonic() >= begin_overall_s + timeout_overall + ): + break time.sleep(0.01) return data - def enter_raw_repl(self, soft_reset=True): + def enter_raw_repl(self, soft_reset=True, timeout_overall=10): self.serial.write(b"\r\x03") # ctrl-C: interrupt any running program # flush input (without relying on serial.flushInput()) @@ -142,7 +151,9 @@ class SerialTransport(Transport): self.serial.write(b"\r\x01") # ctrl-A: enter raw REPL if soft_reset: - data = self.read_until(1, b"raw REPL; CTRL-B to exit\r\n>") + data = self.read_until( + 1, b"raw REPL; CTRL-B to exit\r\n>", timeout_overall=timeout_overall + ) if not data.endswith(b"raw REPL; CTRL-B to exit\r\n>"): print(data) raise TransportError("could not enter raw repl") @@ -152,12 +163,12 @@ class SerialTransport(Transport): # Waiting for "soft reboot" independently to "raw REPL" (done below) # allows boot.py to print, which will show up after "soft reboot" # and before "raw REPL". - data = self.read_until(1, b"soft reboot\r\n") + data = self.read_until(1, b"soft reboot\r\n", timeout_overall=timeout_overall) if not data.endswith(b"soft reboot\r\n"): print(data) raise TransportError("could not enter raw repl") - data = self.read_until(1, b"raw REPL; CTRL-B to exit\r\n") + data = self.read_until(1, b"raw REPL; CTRL-B to exit\r\n", timeout_overall=timeout_overall) if not data.endswith(b"raw REPL; CTRL-B to exit\r\n"): print(data) raise TransportError("could not enter raw repl") |
