tools/mpremote: Fix special handling of ctrl-D when host FS is mounted.

Changes are:
- decision to remount local filesystem on remote device is made only if
  "MPY: soft reboot" is seen in the output after sending a ctrl-D
- a nice message is printed to the user when the remount occurs
- soft reset during raw REPL is now handled correctly

Fixes issue #7731.

Signed-off-by: Damien George <damien@micropython.org>
This commit is contained in:
Damien George 2022-02-05 23:29:44 +11:00
parent 203ec8ca7f
commit fecfd52696
2 changed files with 49 additions and 20 deletions

View File

@ -304,8 +304,8 @@ def do_repl_main_loop(pyb, console_in, console_out_write, *, code_to_inject, fil
if c == b"\x1d": # ctrl-], quit if c == b"\x1d": # ctrl-], quit
break break
elif c == b"\x04": # ctrl-D elif c == b"\x04": # ctrl-D
# do a soft reset and reload the filesystem hook # special handling needed for ctrl-D if filesystem is mounted
pyb.soft_reset_with_mount(console_out_write) pyb.write_ctrl_d(console_out_write)
elif c == b"\x0a" and code_to_inject is not None: # ctrl-j, inject code elif c == b"\x0a" and code_to_inject is not None: # ctrl-j, inject code
pyb.serial.write(code_to_inject) pyb.serial.write(code_to_inject)
elif c == b"\x0b" and file_to_inject is not None: # ctrl-k, inject script elif c == b"\x0b" and file_to_inject is not None: # ctrl-k, inject script

View File

@ -621,37 +621,66 @@ class PyboardExtended(Pyboard):
self.cmd = PyboardCommand(self.serial, fout, path) self.cmd = PyboardCommand(self.serial, fout, path)
self.serial = SerialIntercept(self.serial, self.cmd) self.serial = SerialIntercept(self.serial, self.cmd)
def soft_reset_with_mount(self, out_callback): def write_ctrl_d(self, out_callback):
self.serial.write(b"\x04") self.serial.write(b"\x04")
if not self.mounted: if not self.mounted:
return return
# Clear flag while board reboots, it will be re-set once mounted. # Read response from the device until it is quiet (with a timeout).
self.mounted = False INITIAL_TIMEOUT = 0.5
QUIET_TIMEOUT = 0.2
# Wait for a response to the soft-reset command. FULL_TIMEOUT = 5
for i in range(10): t_start = t_last_activity = time.monotonic()
if self.serial.inWaiting(): data_all = b""
break while True:
time.sleep(0.05) t = time.monotonic()
n = self.serial.inWaiting()
if n > 0:
data = self.serial.read(n)
out_callback(data)
data_all += data
t_last_activity = t
else:
if len(data_all) == 0:
if t - t_start > INITIAL_TIMEOUT:
return
else:
if t - t_start > FULL_TIMEOUT:
return
if t - t_last_activity > QUIET_TIMEOUT:
break
# Check if a soft reset occurred.
if data_all.find(b"MPY: soft reboot") == -1:
return
if data_all.endswith(b">>> "):
in_friendly_repl = True
elif data_all.endswith(b">"):
in_friendly_repl = False
else: else:
# Device didn't respond so it wasn't in a state to do a soft reset.
return return
out_callback(self.serial.read(1)) # Clear state while board remounts, it will be re-set once mounted.
self.mounted = False
self.serial = self.serial.orig_serial self.serial = self.serial.orig_serial
n = self.serial.inWaiting()
while n > 0: # Provide a message about the remount.
buf = self.serial.read(n) out_callback(bytes(f"\r\nRemount local directory {self.cmd.root} at /remote\r\n", "utf8"))
out_callback(buf)
time.sleep(0.2) # Enter raw REPL and re-mount the remote filesystem.
n = self.serial.inWaiting()
self.serial.write(b"\x01") self.serial.write(b"\x01")
self.exec_(fs_hook_code) self.exec_(fs_hook_code)
self.exec_("__mount()") self.exec_("__mount()")
self.mounted = True self.mounted = True
# Exit raw REPL if needed, and wait for the friendly REPL prompt.
if in_friendly_repl:
self.exit_raw_repl() self.exit_raw_repl()
self.read_until(4, b">>> ") prompt = b">>> "
else:
prompt = b">"
self.read_until(len(prompt), prompt)
out_callback(prompt)
self.serial = SerialIntercept(self.serial, self.cmd) self.serial = SerialIntercept(self.serial, self.cmd)
def umount_local(self): def umount_local(self):