Skip to content

Commit 7eaca45

Browse files
szczysnashif
authored andcommitted
twister: fix serial connection for flash_before
The --flash-before flag allows devices to be flashed before the serial connection is established. However, the implementation was incomplete and only worked if the port address already existed at the start of the run. This is incompatible with devices that implement the USB in software (eg: USB-CDC). This commit fixes the implementation to delay setting up the connection until after the device is flashed, and to retry the connection for two seconds after flashing to give the device time to enumerate as a USB device. Signed-off-by: Mike Szczys <[email protected]>
1 parent d082cd2 commit 7eaca45

File tree

5 files changed

+40
-5
lines changed

5 files changed

+40
-5
lines changed

scripts/pylib/pytest-twister-harness/src/twister_harness/device/device_adapter.py

+27-4
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import time
1515
from datetime import datetime
1616
from pathlib import Path
17+
from serial import SerialException
1718

1819
from twister_harness.exceptions import (
1920
TwisterHarnessException,
@@ -69,14 +70,23 @@ def launch(self) -> None:
6970

7071
if self.device_config.type != 'hardware':
7172
self._flash_and_run()
73+
self._device_run.set()
74+
self._start_reader_thread()
75+
self.connect()
76+
return
7277

7378
self._device_run.set()
7479
self._start_reader_thread()
75-
self.connect()
7680

77-
if self.device_config.type == 'hardware':
81+
if self.device_config.flash_before:
82+
# For hardware devices with shared USB or software USB, connect after flashing.
83+
# Retry for up to 10 seconds for USB-CDC based devices to enumerate.
84+
self._flash_and_run()
85+
self.connect(retry_s = 10)
86+
else:
7887
# On hardware, flash after connecting to COM port, otherwise some messages
7988
# from target can be lost.
89+
self.connect()
8090
self._flash_and_run()
8191

8292
def close(self) -> None:
@@ -89,7 +99,7 @@ def close(self) -> None:
8999
self._device_run.clear()
90100
self._join_reader_thread()
91101

92-
def connect(self) -> None:
102+
def connect(self, retry_s: int = 0) -> None:
93103
"""Connect to device - allow for output gathering."""
94104
if self.is_device_connected():
95105
logger.debug('Device already connected')
@@ -98,7 +108,20 @@ def connect(self) -> None:
98108
msg = 'Cannot connect to not working device'
99109
logger.error(msg)
100110
raise TwisterHarnessException(msg)
101-
self._connect_device()
111+
112+
if retry_s > 0:
113+
retry_cycles = retry_s * 10
114+
for i in range(retry_cycles):
115+
try:
116+
self._connect_device()
117+
break
118+
except SerialException:
119+
if i == retry_cycles - 1:
120+
raise
121+
time.sleep(0.1)
122+
else:
123+
self._connect_device()
124+
102125
self._device_connected.set()
103126

104127
def disconnect(self) -> None:

scripts/pylib/pytest-twister-harness/src/twister_harness/plugin.py

+7
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,13 @@ def pytest_addoption(parser: pytest.Parser):
8484
'--device-serial-pty',
8585
help='Script for controlling pseudoterminal.'
8686
)
87+
twister_harness_group.addoption(
88+
'--flash-before',
89+
type=bool,
90+
help='Flash device before attaching to serial port'
91+
'This is useful for devices that share the same port for programming'
92+
'and serial console, or use soft-USB, where flash must come first.'
93+
)
8794
twister_harness_group.addoption(
8895
'--west-flash-extra-args',
8996
help='Extend parameters for west flash. '

scripts/pylib/pytest-twister-harness/src/twister_harness/twister_harness_config.py

+2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ class DeviceConfig:
2626
id: str = ''
2727
product: str = ''
2828
serial_pty: str = ''
29+
flash_before: bool = False
2930
west_flash_extra_args: list[str] = field(default_factory=list, repr=False)
3031
name: str = ''
3132
pre_script: Path | None = None
@@ -62,6 +63,7 @@ def create(cls, config: pytest.Config) -> TwisterHarnessConfig:
6263
id=config.option.device_id,
6364
product=config.option.device_product,
6465
serial_pty=config.option.device_serial_pty,
66+
flash_before=bool(config.option.flash_before),
6567
west_flash_extra_args=west_flash_extra_args,
6668
pre_script=_cast_to_path(config.option.pre_script),
6769
post_script=_cast_to_path(config.option.post_script),

scripts/pylib/twister/twisterlib/environment.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ def add_parse_arguments(parser = None):
178178
parser.add_argument("--flash-before", action="store_true", default=False,
179179
help="""Flash device before attaching to serial port.
180180
This is useful for devices that share the same port for programming
181-
and serial console, where flash must come first.
181+
and serial console, or use soft-USB, where flash must come first.
182182
""")
183183

184184
test_or_build.add_argument(

scripts/pylib/twister/twisterlib/harness.py

+3
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,9 @@ def _generate_parameters_for_hardware(self, handler: Handler):
408408
if hardware.post_script:
409409
command.append(f'--post-script={hardware.post_script}')
410410

411+
if hardware.flash_before:
412+
command.append(f'--flash-before={hardware.flash_before}')
413+
411414
return command
412415

413416
def run_command(self, cmd, timeout):

0 commit comments

Comments
 (0)