-
Notifications
You must be signed in to change notification settings - Fork 6.9k
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
twister: support segger real-time-transfer (rtt) for serial_pty via west #81837
Changes from all commits
30d1500
24686de
d8626cf
5e91f54
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -873,6 +873,18 @@ def parse_arguments( | |
logger.error("west-flash requires device-testing to be enabled") | ||
sys.exit(1) | ||
|
||
if options.device_serial_pty and options.device_serial_pty == "rtt": | ||
if options.west_flash is None: | ||
logger.error("--device-serial-pty rtt requires --west-flash") | ||
sys.exit(1) | ||
|
||
# add the following options | ||
cfriedt marked this conversation as resolved.
Show resolved
Hide resolved
|
||
options.extra_args += ['CONFIG_USE_SEGGER_RTT=y', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not a fan of injecting HW related kconfigs into twister like this, this should be done on the platform/hardware map/ or test level, not in twister. Using a snippet for example is an option. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've found actually that this works better with a snippet specified in testcase.yml. I think this can be removed. |
||
'CONFIG_RTT_CONSOLE=y', 'CONFIG_CONSOLE=y', | ||
# This option is needed to ensure the uart console is not selected | ||
# when CONFIG_RTT_CONSOLE is enabled due to #81798 | ||
'CONFIG_UART_CONSOLE=n'] | ||
|
||
if not options.testsuite_root: | ||
# if we specify a test scenario which is part of a suite directly, do | ||
# not set testsuite root to default, just point to the test directory | ||
|
@@ -939,10 +951,6 @@ def parse_arguments( | |
logger.error("--device-flash-with-test does not apply when --flash-before is used") | ||
sys.exit(1) | ||
|
||
if options.flash_before and options.device_serial_pty: | ||
logger.error("--device-serial-pty cannot be used when --flash-before is set (for now)") | ||
sys.exit(1) | ||
|
||
if options.shuffle_tests and options.subset is None: | ||
logger.error("--shuffle-tests requires --subset") | ||
sys.exit(1) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,6 +16,7 @@ | |
import select | ||
import shlex | ||
import signal | ||
import stat | ||
import subprocess | ||
import sys | ||
import threading | ||
|
@@ -706,6 +707,23 @@ def _get_serial_device(self, serial_pty, hardware_serial): | |
|
||
return serial_device, ser_pty_process | ||
|
||
def _create_serial_pty_script(self, runner): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok, so you are creating the pty script on the fly, if I understand this correctly, it is an abuse of the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "abuse" is probably a strong term. I prefer "reuse" - we're simply reusing west's rtt integration. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Not using a script here is wrong usage. If you want to use a built-in rtt support you are adding, you need to find another way, maybe yet another option that deals with |
||
serial_pty = self.build_dir + '/rtt.sh' | ||
|
||
rtt_cmd = f'west -qqqqq rtt -d {self.build_dir} --skip-rebuild --rtt-quiet' | ||
if runner: | ||
rtt_cmd += f' -r {runner}' | ||
|
||
with open(serial_pty, 'w') as f: | ||
f.write(f'#!/bin/sh\n{rtt_cmd}\n') | ||
|
||
st = os.stat(serial_pty) | ||
os.chmod(serial_pty, st.st_mode | stat.S_IEXEC) | ||
|
||
logger.debug(f'RTT command is "{rtt_cmd}"') | ||
|
||
return serial_pty | ||
|
||
def handle(self, harness): | ||
runner = None | ||
hardware = self.get_hardware() | ||
|
@@ -717,9 +735,14 @@ def handle(self, harness): | |
runner = hardware.runner or self.options.west_runner | ||
serial_pty = hardware.serial_pty | ||
|
||
serial_device, ser_pty_process = self._get_serial_device(serial_pty, hardware.serial) | ||
if serial_pty == 'rtt': | ||
serial_pty = self._create_serial_pty_script(runner) | ||
logger.debug(f'Created RTT script {serial_pty}') | ||
|
||
logger.debug(f"Using serial device {serial_device} @ {hardware.baud} baud") | ||
if not hardware.flash_before: | ||
serial_device, ser_pty_process = self._get_serial_device( | ||
serial_pty, hardware.serial) | ||
logger.debug(f"Using serial device {serial_device} @ {hardware.baud} baud") | ||
|
||
command = self._create_command(runner, hardware) | ||
|
||
|
@@ -738,28 +761,27 @@ def handle(self, harness): | |
if hardware.flash_with_test: | ||
flash_timeout += self.get_test_timeout() | ||
|
||
serial_port = None | ||
if hardware.flash_before is False: | ||
serial_port = serial_device | ||
|
||
try: | ||
ser = self._create_serial_connection( | ||
hardware, | ||
serial_port, | ||
hardware.baud, | ||
flash_timeout, | ||
serial_pty, | ||
ser_pty_process | ||
) | ||
except serial.SerialException: | ||
return | ||
halt_monitor_evt = None | ||
t = None | ||
if not hardware.flash_before: | ||
try: | ||
ser = self._create_serial_connection( | ||
hardware, | ||
serial_device, | ||
hardware.baud, | ||
flash_timeout, | ||
serial_pty, | ||
ser_pty_process | ||
) | ||
except serial.SerialException: | ||
return | ||
|
||
halt_monitor_evt = threading.Event() | ||
halt_monitor_evt = threading.Event() | ||
|
||
t = threading.Thread(target=self.monitor_serial, daemon=True, | ||
args=(ser, halt_monitor_evt, harness)) | ||
start_time = time.time() | ||
t.start() | ||
t = threading.Thread(target=self.monitor_serial, daemon=True, | ||
args=(ser, halt_monitor_evt, harness)) | ||
start_time = time.time() | ||
t.start() | ||
|
||
d_log = f"{self.instance.build_dir}/device.log" | ||
logger.debug(f'Flash command: {command}', ) | ||
|
@@ -778,7 +800,8 @@ def handle(self, harness): | |
flash_error = True | ||
with open(d_log, "w") as dlog_fp: | ||
dlog_fp.write(stderr.decode()) | ||
halt_monitor_evt.set() | ||
if halt_monitor_evt: | ||
halt_monitor_evt.set() | ||
except subprocess.TimeoutExpired: | ||
logger.warning("Flash operation timed out.") | ||
self.terminate(proc) | ||
|
@@ -791,7 +814,8 @@ def handle(self, harness): | |
dlog_fp.write(stderr.decode()) | ||
|
||
except subprocess.CalledProcessError: | ||
halt_monitor_evt.set() | ||
if halt_monitor_evt: | ||
halt_monitor_evt.set() | ||
self.instance.status = TwisterStatus.ERROR | ||
self.instance.reason = "Device issue (Flash error)" | ||
flash_error = True | ||
|
@@ -802,28 +826,45 @@ def handle(self, harness): | |
timeout = script_param.get("post_flash_timeout", timeout) | ||
self.run_custom_script(post_flash_script, timeout) | ||
|
||
# Connect to device after flashing it | ||
if hardware.flash_before: | ||
serial_device, ser_pty_process = self._get_serial_device( | ||
serial_pty, hardware.serial) | ||
logger.debug(f"Using serial device {serial_device} @ {hardware.baud} baud") | ||
|
||
try: | ||
logger.debug(f"Attach serial device {serial_device} @ {hardware.baud} baud") | ||
ser.port = serial_device | ||
ser.open() | ||
ser = self._create_serial_connection( | ||
hardware, | ||
serial_device, | ||
hardware.baud, | ||
flash_timeout, | ||
serial_pty, | ||
ser_pty_process | ||
) | ||
except serial.SerialException as e: | ||
self._handle_serial_exception(e, hardware, serial_pty, ser_pty_process) | ||
return | ||
|
||
halt_monitor_evt = threading.Event() | ||
|
||
t = threading.Thread(target=self.monitor_serial, daemon=True, | ||
args=(ser, halt_monitor_evt, harness)) | ||
start_time = time.time() | ||
t.start() | ||
|
||
if not flash_error: | ||
# Always wait at most the test timeout here after flashing. | ||
t.join(self.get_test_timeout()) | ||
if t: | ||
t.join(self.get_test_timeout()) | ||
else: | ||
# When the flash error is due exceptions, | ||
# twister tell the monitor serial thread | ||
# to close the serial. But it is necessary | ||
# for this thread being run first and close | ||
# have the change to close the serial. | ||
t.join(0.1) | ||
if t: | ||
t.join(0.1) | ||
|
||
if t.is_alive(): | ||
if t and t.is_alive(): | ||
logger.debug( | ||
f"Timed out while monitoring serial output on {self.instance.platform.name}" | ||
) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
--device-serial-pty
accept a script name, can be anything, here you assume that the script name (is this a script?) is always going to be rtt, or asking that if someone want to use this, they have to call their script rtt?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, in this case rtt is a keyword, and twister simply re-uses west's rtt integration.
Normally, the argument for device-serial-pty is a script through, so that hasn't changed.