1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

pyterm: add native support

Start RIOT native as a subprocess and communicate to it via a pipe.
This commit is contained in:
Oleg Hahm 2023-05-06 15:22:06 +02:00 committed by Oleg Hahm
parent 59573a8678
commit 66343e3bc7
2 changed files with 40 additions and 14 deletions

View File

@ -14,7 +14,7 @@ RESET ?= $(RIOTBOARD)/native/dist/reset.sh
FLASHER ?=
FLASHFILE ?= $(ELFFILE)
TERMPROG ?= $(FLASHFILE)
TERMFLAGS ?= -n $(FLASHFILE)
export VALGRIND ?= valgrind
export CGANNOTATE ?= cg_annotate

View File

@ -39,6 +39,8 @@ import re
import codecs
import platform
from subprocess import Popen, PIPE
try:
serial.Serial
except AttributeError:
@ -107,10 +109,11 @@ class SerCmd(cmd.Cmd):
port.
"""
def __init__(self, port=None, baudrate=None, toggle=None, tcp_serial=None,
confdir=None, conffile=None, host=None, run_name=None,
log_dir_name=None, newline=None, formatter=None,
set_rts=None, set_dtr=None, serprompt=None,
def __init__(self, port=None, baudrate=None, toggle=None,
tcp_serial=None, native=None, confdir=None, conffile=None,
host=None, run_name=None, log_dir_name=None, newline=None,
formatter=None, set_rts=None, set_dtr=None,
serprompt=None,
repeat_command_on_empty_line=defaultrepeat_cmd_empty_line,
reconnect=defaultreconnect):
"""Constructor.
@ -119,6 +122,7 @@ class SerCmd(cmd.Cmd):
port (str): serial port
baudrate (int): serial baudrate
tcp_serial (iht): TCP port to connect to (alternatively)
native (str): Native instance to run and connect to
confdir (str): configuration directory
conffile (str): configuration file name
host (str): local host name
@ -134,6 +138,7 @@ class SerCmd(cmd.Cmd):
self.set_rts = set_rts
self.set_dtr = set_dtr
self.tcp_serial = tcp_serial
self.native = native
self.configdir = confdir
self.configfile = conffile
self.host = host
@ -204,6 +209,11 @@ class SerCmd(cmd.Cmd):
"""Executed bat program start.
"""
if self.native and (self.port != defaultport or self.tcp_serial):
self.logger.error("Specified a native instance AND a serial "
"port or TCP connection. You probably want "
"to specify only the one or the other.")
sys.exit(1)
# if no serial or TCP is specified use default serial port
if not self.port and not self.tcp_serial:
sys.stderr.write("No port specified, using default (%s)!\n"
@ -253,6 +263,8 @@ class SerCmd(cmd.Cmd):
self.logger.error("Something went wrong connecting to "
"localhost:%s" % self.tcp_serial)
sys.exit(1)
elif self.native:
self.ser = Popen(self.native, stdout=PIPE, stdin=PIPE, stderr=PIPE)
# otherwise go for the serial port
elif self.port:
connected = False
@ -281,7 +293,6 @@ class SerCmd(cmd.Cmd):
# commands to the node
time.sleep(1)
for command in self.init_cmd:
self.logger.debug("WRITE ----->>>>>> '" + command + "'\n")
self.onecmd(self.precmd(command))
# start serial->console thread
@ -316,15 +327,15 @@ class SerCmd(cmd.Cmd):
for tok in line.split(';'):
tok = self.get_alias(tok)
if sys.version_info[0] == 2:
self.ser.write((tok.strip() + "\n").decode("utf-8").encode("utf-8"))
self._write_char((tok.strip() + "\n").decode("utf-8").encode("utf-8"))
else:
self.ser.write((tok.strip() + "\n").encode("utf-8"))
self._write_char((tok.strip() + "\n").encode("utf-8"))
def do_help(self, line):
"""Do not use Cmd's internal help function, but redirect to the
node.
"""
self.ser.write("help\n".encode("utf-8"))
self._write_char("help\n".encode("utf-8"))
def do_EOF(self, line):
"""Handle EOF (Ctrl+D) nicely."""
@ -668,11 +679,22 @@ class SerCmd(cmd.Cmd):
self.ser.setDTR(self.set_dtr)
def _read_char(self):
output_stream = self.ser
if self.native:
output_stream = self.ser.stdout
# check if serial port can be accessed.
sr = codecs.getreader("UTF-8")(self.ser,
sr = codecs.getreader("UTF-8")(output_stream,
errors='replace')
return sr.read(1)
def _write_char(self, output):
input_stream = self.ser
if self.native:
input_stream = self.ser.stdin
input_stream.write(output)
if self.native:
input_stream.flush()
def _handle_serial_exception(self):
self.logger.warning("Serial port disconnected, waiting to "
"get reconnected...")
@ -758,7 +780,7 @@ class PytermProt(Protocol):
if(data.strip() == "/exit"):
reactor.callLater(2, self.factory.shell.do_PYTERM_exit, data)
else:
self.factory.shell.ser.write(data + "\n")
self.factory.shell._write_char(data + "\n")
def sendMessage(self, msg):
self.transport.writeSomeData("%d#%s\n" % (len(msg), msg))
@ -815,6 +837,10 @@ if __name__ == "__main__":
help="Connect to a TCP port instead of a serial port. "
"Format is <hostname>:<port>. If the colon is missing"
" host defaults to \"localhost\"")
parser.add_argument("-n", "--native",
help="Start a RIOT native instance and connect "
"pyterm to its stdio.",
nargs=2)
parser.add_argument("-b", "--baudrate",
help="Specifies baudrate for the serial port, default "
"is %s" % defaultbaud,
@ -900,9 +926,9 @@ if __name__ == "__main__":
if args.noprefix:
args.format = ""
myshell = SerCmd(args.port, args.baudrate, args.toggle, args.tcp_serial,
args.directory, args.config, args.host, args.run_name,
args.log_dir_name, args.newline, args.format,
args.set_rts, args.set_dtr, args.prompt,
args.native, args.directory, args.config, args.host,
args.run_name, args.log_dir_name, args.newline,
args.format, args.set_rts, args.set_dtr, args.prompt,
args.repeat_command_on_empty_line)
myshell.prompt = ''