tools/pyboard.py: Introduce timeout_overall for read_until().
This applies the mpremote commit 03fe9c55ea
to pyboard.py.
The `timeout_overall` is used in `enter_raw_repl()`. It 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: Damien George <damien@micropython.org>
This commit is contained in:
@@ -334,11 +334,14 @@ class Pyboard:
|
|||||||
def close(self):
|
def close(self):
|
||||||
self.serial.close()
|
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.
|
min_num_bytes: Obsolete.
|
||||||
ending: Return if 'ending' matches.
|
ending: Return if 'ending' matches.
|
||||||
timeout [s]: Return if timeout between characters. None: Infinite timeout.
|
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.
|
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
|
If data_consumer is used then data is not accumulated and the ending must be 1 byte long
|
||||||
|
|
||||||
@@ -346,9 +349,10 @@ class Pyboard:
|
|||||||
"""
|
"""
|
||||||
assert data_consumer is None or len(ending) == 1
|
assert data_consumer is None or len(ending) == 1
|
||||||
assert isinstance(timeout, (type(None), int, float))
|
assert isinstance(timeout, (type(None), int, float))
|
||||||
|
assert isinstance(timeout_overall, (type(None), int, float))
|
||||||
|
|
||||||
data = b""
|
data = b""
|
||||||
begin_char_s = time.monotonic()
|
begin_overall_s = begin_char_s = time.monotonic()
|
||||||
while True:
|
while True:
|
||||||
if data.endswith(ending):
|
if data.endswith(ending):
|
||||||
break
|
break
|
||||||
@@ -363,10 +367,15 @@ class Pyboard:
|
|||||||
else:
|
else:
|
||||||
if timeout is not None and time.monotonic() >= begin_char_s + timeout:
|
if timeout is not None and time.monotonic() >= begin_char_s + timeout:
|
||||||
break
|
break
|
||||||
|
if (
|
||||||
|
timeout_overall is not None
|
||||||
|
and time.monotonic() >= begin_overall_s + timeout_overall
|
||||||
|
):
|
||||||
|
break
|
||||||
time.sleep(0.01)
|
time.sleep(0.01)
|
||||||
return data
|
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
|
self.serial.write(b"\r\x03") # ctrl-C: interrupt any running program
|
||||||
|
|
||||||
# flush input (without relying on serial.flushInput())
|
# flush input (without relying on serial.flushInput())
|
||||||
@@ -378,7 +387,9 @@ class Pyboard:
|
|||||||
self.serial.write(b"\r\x01") # ctrl-A: enter raw REPL
|
self.serial.write(b"\r\x01") # ctrl-A: enter raw REPL
|
||||||
|
|
||||||
if soft_reset:
|
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>"):
|
if not data.endswith(b"raw REPL; CTRL-B to exit\r\n>"):
|
||||||
print(data)
|
print(data)
|
||||||
raise PyboardError("could not enter raw repl")
|
raise PyboardError("could not enter raw repl")
|
||||||
@@ -388,12 +399,12 @@ class Pyboard:
|
|||||||
# Waiting for "soft reboot" independently to "raw REPL" (done below)
|
# Waiting for "soft reboot" independently to "raw REPL" (done below)
|
||||||
# allows boot.py to print, which will show up after "soft reboot"
|
# allows boot.py to print, which will show up after "soft reboot"
|
||||||
# and before "raw REPL".
|
# 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"):
|
if not data.endswith(b"soft reboot\r\n"):
|
||||||
print(data)
|
print(data)
|
||||||
raise PyboardError("could not enter raw repl")
|
raise PyboardError("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"):
|
if not data.endswith(b"raw REPL; CTRL-B to exit\r\n"):
|
||||||
print(data)
|
print(data)
|
||||||
raise PyboardError("could not enter raw repl")
|
raise PyboardError("could not enter raw repl")
|
||||||
|
|||||||
Reference in New Issue
Block a user