diff --git a/scripts/pylib/twister/twisterlib/environment.py b/scripts/pylib/twister/twisterlib/environment.py index daa691c19d0..86770eb4bf8 100644 --- a/scripts/pylib/twister/twisterlib/environment.py +++ b/scripts/pylib/twister/twisterlib/environment.py @@ -178,6 +178,12 @@ Artificially long but functional example: when flash operation also executes test case on the platform. """) + parser.add_argument("--flash-before", action="store_true", default=False, + help="""Flash device before attaching to serial port. + This is useful for devices that share the same port for programming + and serial console, where flash must come first. + """) + test_or_build.add_argument( "-b", "--build-only", action="store_true", default="--prep-artifacts-for-testing" in sys.argv, help="Only build the code, do not attempt to run the code on targets.") @@ -796,6 +802,14 @@ def parse_arguments(parser, args, options = None): logger.error("--device-flash-with-test requires --device_testing") sys.exit(1) + if options.flash_before and options.device_flash_with_test: + 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) diff --git a/scripts/pylib/twister/twisterlib/handlers.py b/scripts/pylib/twister/twisterlib/handlers.py index 8a732f28ad4..ed0ee9003b1 100755 --- a/scripts/pylib/twister/twisterlib/handlers.py +++ b/scripts/pylib/twister/twisterlib/handlers.py @@ -378,6 +378,10 @@ class DeviceHandler(Handler): # from the test. harness.capture_coverage = True + # Wait for serial connection + while not ser.isOpen(): + time.sleep(0.1) + # Clear serial leftover. ser.reset_input_buffer() @@ -647,9 +651,13 @@ class DeviceHandler(Handler): 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( - serial_device, + serial_port, hardware.baud, flash_timeout, serial_pty, @@ -703,6 +711,15 @@ class DeviceHandler(Handler): if post_flash_script: self.run_custom_script(post_flash_script, 30) + # Connect to device after flashing it + if hardware.flash_before: + try: + logger.debug(f"Attach serial device {serial_device} @ {hardware.baud} baud") + ser.port = serial_device + ser.open() + except serial.SerialException: + return + if not flash_error: # Always wait at most the test timeout here after flashing. t.join(self.get_test_timeout()) diff --git a/scripts/pylib/twister/twisterlib/hardwaremap.py b/scripts/pylib/twister/twisterlib/hardwaremap.py index 27bca007185..2ef780c3838 100644 --- a/scripts/pylib/twister/twisterlib/hardwaremap.py +++ b/scripts/pylib/twister/twisterlib/hardwaremap.py @@ -49,7 +49,8 @@ class DUT(object): post_flash_script=None, runner=None, flash_timeout=60, - flash_with_test=False): + flash_with_test=False, + flash_before=False): self.serial = serial self.baud = serial_baud or 115200 @@ -63,6 +64,7 @@ class DUT(object): self.product = product self.runner = runner self.runner_params = runner_params + self.flash_before = flash_before self.fixtures = [] self.post_flash_script = post_flash_script self.post_script = post_script @@ -177,7 +179,8 @@ class HardwareMap: False, baud=self.options.device_serial_baud, flash_timeout=self.options.device_flash_timeout, - flash_with_test=self.options.device_flash_with_test + flash_with_test=self.options.device_flash_with_test, + flash_before=self.options.flash_before, ) elif self.options.device_serial_pty: @@ -186,7 +189,8 @@ class HardwareMap: self.options.pre_script, True, flash_timeout=self.options.device_flash_timeout, - flash_with_test=self.options.device_flash_with_test + flash_with_test=self.options.device_flash_with_test, + flash_before=False, ) # the fixtures given by twister command explicitly should be assigned to each DUT @@ -207,9 +211,9 @@ class HardwareMap: print(tabulate(table, headers=header, tablefmt="github")) - def add_device(self, serial, platform, pre_script, is_pty, baud=None, flash_timeout=60, flash_with_test=False): + def add_device(self, serial, platform, pre_script, is_pty, baud=None, flash_timeout=60, flash_with_test=False, flash_before=False): device = DUT(platform=platform, connected=True, pre_script=pre_script, serial_baud=baud, - flash_timeout=flash_timeout, flash_with_test=flash_with_test + flash_timeout=flash_timeout, flash_with_test=flash_with_test, flash_before=flash_before ) if is_pty: device.serial_pty = serial @@ -229,6 +233,9 @@ class HardwareMap: flash_with_test = dut.get('flash_with_test') if flash_with_test is None: flash_with_test = self.options.device_flash_with_test + flash_before = dut.get('flash_before') + if flash_before is None: + flash_before = self.options.flash_before and (not (flash_with_test or serial_pty)) platform = dut.get('platform') id = dut.get('id') runner = dut.get('runner') @@ -251,6 +258,7 @@ class HardwareMap: serial_baud=baud, connected=connected, pre_script=pre_script, + flash_before=flash_before, post_script=post_script, post_flash_script=post_flash_script, flash_timeout=flash_timeout, diff --git a/scripts/schemas/twister/hwmap-schema.yaml b/scripts/schemas/twister/hwmap-schema.yaml index 3ecb064ddfc..1865462fc46 100644 --- a/scripts/schemas/twister/hwmap-schema.yaml +++ b/scripts/schemas/twister/hwmap-schema.yaml @@ -61,3 +61,6 @@ sequence: "flash_with_test": type: bool required: false + "flash_before": + type: bool + required: false