diff --git a/README.rst b/README.rst index 86f04ed..b1ca627 100644 --- a/README.rst +++ b/README.rst @@ -140,6 +140,8 @@ following displayed: --binary Enable binary file transfer --timing Print timing information about each command --quiet Turns off some output (useful for testing) + -s, --suppress-reset Supresses soft-reset when entering raw REPL. Fixes + 'could not enter raw repl' You can specify the default serial port using the RSHELL_PORT environment variable. @@ -227,6 +229,16 @@ also be defaulted from the RSHELL_RTS environment variable. This option causes the Connecting messages printed when rshell starts to be suppressed. This is mostly useful for the test scripts. +-s, --suppress-reset +-------------------- + +Rshell will soft-reboot the board in the process of getting to a raw REPL +prompt. Sometimes something will not unload properly and the soft-boot +escalates to a hard reset. This will cause rshell to never reach the prompt, +even though the raw REPL functionality works fine. If you see 'could not +enter raw repl', try this option to see if supressing rshell's Ctrl-D +soft-reset helps. + --timing -------- diff --git a/rshell/main.py b/rshell/main.py index 23b64d3..33d5551 100755 --- a/rshell/main.py +++ b/rshell/main.py @@ -1383,10 +1383,12 @@ def connect(port, baud=115200, user='micro', password='python', wait=0): ip_address = socket.gethostbyname(port) #print('Connecting to ip', ip_address) connect_telnet(port, ip_address, user=user, password=password) + return except socket.gaierror: - # Doesn't look like a hostname or IP-address, assume its a serial port - #print('connecting to serial', port) - connect_serial(port, baud=baud, wait=wait) + pass + # Doesn't look like a hostname or IP-address, assume its a serial port + #print('connecting to serial', port) + connect_serial(port, baud=baud, wait=wait) def connect_telnet(name, ip_address=None, user='micro', password='python'): @@ -1693,7 +1695,8 @@ def __init__(self, port, baud, wait): self.dev_name_long = '%s at %d baud' % (port, baud) try: - pyb = Pyboard(port, baudrate=baud, wait=wait, rts=RTS, dtr=DTR) + global suppress_reset + pyb = Pyboard(port, baudrate=baud, wait=wait, rts=RTS, dtr=DTR, suppress_reset=suppress_reset) except PyboardError as err: print(err) sys.exit(1) @@ -2975,6 +2978,13 @@ def real_main(): help="Turns off some output (useful for testing)", default=False ) + parser.add_argument( + "-s", "--suppress-reset", + dest="suppress_reset", + action="store_true", + help="Supresses soft-reset when entering raw REPL. Fixes 'could not enter raw repl'", + default=False + ) parser.add_argument( "cmd", nargs=argparse.REMAINDER, @@ -2982,6 +2992,11 @@ def real_main(): ) args = parser.parse_args(sys.argv[1:]) + # Globals are bad. But the alternative here is to pass this around many, + # many, many, many times before it gets to the one spot where it's used. + global suppress_reset + suppress_reset = args.suppress_reset + if args.buffer_size is not None: BUFFER_SIZE = args.buffer_size diff --git a/rshell/pyboard.py b/rshell/pyboard.py index 3e35c0b..85933bd 100644 --- a/rshell/pyboard.py +++ b/rshell/pyboard.py @@ -120,7 +120,8 @@ def parse_bool(str): return str == '1' or str.lower() == 'true' class Pyboard: - def __init__(self, device, baudrate=115200, user='micro', password='python', wait=0, rts='', dtr=''): + def __init__(self, device, baudrate=115200, user='micro', password='python', wait=0, rts='', dtr='', suppress_reset=False): + self.suppress_reset = suppress_reset if device and device[0].isdigit() and device[-1].isdigit() and device.count('.') == 3: # device looks like an IP address self.serial = TelnetToSerial(device, user, password, read_timeout=10) @@ -191,23 +192,25 @@ def enter_raw_repl(self): n = self.serial.inWaiting() self.serial.write(b'\r\x01') # ctrl-A: enter raw REPL - data = self.read_until(1, b'raw REPL; CTRL-B to exit\r\n>') - if not data.endswith(b'raw REPL; CTRL-B to exit\r\n>'): - print(data) - raise PyboardError('could not enter raw repl') - - self.serial.write(b'\x04') # ctrl-D: soft reset - data = self.read_until(1, b'soft reboot\r\n') - if not data.endswith(b'soft reboot\r\n'): - print(data) - raise PyboardError('could not enter raw repl') - # By splitting this into 2 reads, it allows boot.py to print stuff, - # which will show up after the soft reboot and before the raw REPL. data = self.read_until(1, b'raw REPL; CTRL-B to exit\r\n') if not data.endswith(b'raw REPL; CTRL-B to exit\r\n'): print(data) raise PyboardError('could not enter raw repl') + if not self.suppress_reset: + + self.serial.write(b'\x04') # ctrl-D: soft reset + data = self.read_until(1, b'soft reboot\r\n') + if not data.endswith(b'soft reboot\r\n'): + print(data) + raise PyboardError('could not enter raw repl') + # By splitting this into 2 reads, it allows boot.py to print stuff, + # which will show up after the soft reboot and before the raw REPL. + data = self.read_until(1, b'raw REPL; CTRL-B to exit\r\n') + if not data.endswith(b'raw REPL; CTRL-B to exit\r\n'): + print(data) + raise PyboardError('could not enter raw repl') + def exit_raw_repl(self): self.serial.write(b'\r\x02') # ctrl-B: enter friendly REPL @@ -277,8 +280,8 @@ def get_time(self): # but for Python3 we want to provide the nicer version "exec" setattr(Pyboard, "exec", Pyboard.exec_) -def execfile(filename, device='/dev/ttyACM0', baudrate=115200, user='micro', password='python'): - pyb = Pyboard(device, baudrate, user, password) +def execfile(filename, device='/dev/ttyACM0', baudrate=115200, user='micro', password='python', suppress_reset=False): + pyb = Pyboard(device, baudrate, user, password, suppress_reset=suppress_reset) pyb.enter_raw_repl() output = pyb.execfile(filename) stdout_write_bytes(output) @@ -295,12 +298,13 @@ def main(): cmd_parser.add_argument('-c', '--command', help='program passed in as string') cmd_parser.add_argument('-w', '--wait', default=0, type=int, help='seconds to wait for USB connected board to become available') cmd_parser.add_argument('--follow', action='store_true', help='follow the output after running the scripts [default if no scripts given]') + cmd_parser.add_argument('-s', '--suppress-reset', action='store_true', help='Suppress soft-reset when entering raw REPL, fixes "could not enter raw repl"') cmd_parser.add_argument('files', nargs='*', help='input files') args = cmd_parser.parse_args() def execbuffer(buf): try: - pyb = Pyboard(args.device, args.baudrate, args.user, args.password, args.wait) + pyb = Pyboard(args.device, args.baudrate, args.user, args.password, args.wait, suppress_reset=args.suppress_reset) pyb.enter_raw_repl() ret, ret_err = pyb.exec_raw(buf, timeout=None, data_consumer=stdout_write_bytes) pyb.exit_raw_repl() @@ -324,7 +328,7 @@ def execbuffer(buf): if args.follow or (args.command is None and len(args.files) == 0): try: - pyb = Pyboard(args.device, args.baudrate, args.user, args.password, args.wait) + pyb = Pyboard(args.device, args.baudrate, args.user, args.password, args.wait, suppress_reset=args.suppress_reset) ret, ret_err = pyb.follow(timeout=None, data_consumer=stdout_write_bytes) pyb.close() except PyboardError as er: