Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix for issue #27 "Could not enter raw REPL" #161

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
--------

Expand Down
23 changes: 19 additions & 4 deletions rshell/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -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'):
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -2975,13 +2978,25 @@ 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,
help="Optional command to execute"
)
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

Expand Down
38 changes: 21 additions & 17 deletions rshell/pyboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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)
Expand All @@ -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()
Expand All @@ -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:
Expand Down