From 7cdfd6cc133eae67c6261ec79397274c45e91d04 Mon Sep 17 00:00:00 2001 From: Maska989 Date: Wed, 17 Jan 2024 15:40:26 +0100 Subject: [PATCH] trunner: add Sparcv8Leon3 target support JIRA: CI-249 --- psh/test.yaml | 14 ++-- runner.py | 14 ++-- trunner/target/__init__.py | 2 + trunner/target/sparcv8.py | 139 +++++++++++++++++++++++++++++++++++++ 4 files changed, 160 insertions(+), 9 deletions(-) create mode 100644 trunner/target/sparcv8.py diff --git a/psh/test.yaml b/psh/test.yaml index 9c0254e92..c79aab478 100644 --- a/psh/test.yaml +++ b/psh/test.yaml @@ -1,4 +1,8 @@ test: + targets: + #TODO: remove when sparcv8leon3-gr716-mimas target will stop being experimental + include: [sparcv8leon3-gr716-mimas] + tests: - name: gibber harness: test-gibber.py @@ -13,7 +17,7 @@ test: - name: pshlogin harness: test-pshlogin.py targets: - exclude: [armv7m7-imxrt106x-evk, armv7m7-imxrt117x-evk, armv7m4-stm32l4x6-nucleo] + exclude: [armv7m7-imxrt106x-evk, armv7m7-imxrt117x-evk, armv7m4-stm32l4x6-nucleo, sparcv8leon3-gr716-mimas] - name: echo harness: test-echo.py @@ -36,7 +40,7 @@ test: - name: cat-shells harness: test-cat-shells.py targets: - exclude: [armv7m7-imxrt106x-evk, armv7m7-imxrt117x-evk, armv7m4-stm32l4x6-nucleo] + exclude: [armv7m7-imxrt106x-evk, armv7m7-imxrt117x-evk, armv7m4-stm32l4x6-nucleo, sparcv8leon3-gr716-mimas] - name: kill harness: test-kill.py @@ -50,7 +54,7 @@ test: - name: touch-rootfs harness: test-touch-rootfs.py targets: - exclude: [armv7m7-imxrt106x-evk, armv7m7-imxrt117x-evk, armv7m4-stm32l4x6-nucleo] + exclude: [armv7m7-imxrt106x-evk, armv7m7-imxrt117x-evk, armv7m4-stm32l4x6-nucleo, sparcv8leon3-gr716-mimas] - name: ls harness: test-ls.py @@ -58,13 +62,13 @@ test: - name: ls-rootfs harness: test-ls-rootfs.py targets: - exclude: [armv7m7-imxrt106x-evk, armv7m7-imxrt117x-evk, armv7m4-stm32l4x6-nucleo] + exclude: [armv7m7-imxrt106x-evk, armv7m7-imxrt117x-evk, armv7m4-stm32l4x6-nucleo, sparcv8leon3-gr716-mimas] - name: runfile harness: test-runfile.py targets: # runfile applet is not intended for non-rootfs targets - exclude: [armv7m7-imxrt106x-evk, armv7m7-imxrt117x-evk, armv7m4-stm32l4x6-nucleo] + exclude: [armv7m7-imxrt106x-evk, armv7m7-imxrt117x-evk, armv7m4-stm32l4x6-nucleo, sparcv8leon3-gr716-mimas] - name: history harness: test-history.py diff --git a/runner.py b/runner.py index 731feed33..bf4766545 100755 --- a/runner.py +++ b/runner.py @@ -22,6 +22,7 @@ STM32L4x6Target, Zynq7000ZedboardTarget, IMX6ULLEvkTarget, + MimasSparcV8EvkTarget, ) from trunner.ctx import TestContext from trunner.target.base import TargetBase @@ -109,9 +110,11 @@ def parse_args(targets: Dict[str, Type[TargetBase]], hosts: Dict[str, Type[Host] "--output", action="store", const="report.xml", - nargs='?', - help=("Write machine-readable test results as csv and xml file. " - "When no value is provided uses %(const)s"), + nargs="?", + help=( + "Write machine-readable test results as csv and xml file. " + "When no value is provided uses %(const)s" + ), ) parser.add_argument( @@ -218,7 +221,9 @@ def __call__(self, parser, namespace, values, option_string=None): return args -def resolve_targets_and_hosts() -> Tuple[Dict[str, Type[TargetBase]], Dict[str, Type[Host]]]: +def resolve_targets_and_hosts() -> ( + Tuple[Dict[str, Type[TargetBase]], Dict[str, Type[Host]]] +): """ Returns a tuple of dictionaries that map host and target names to an equivalent class. @@ -236,6 +241,7 @@ def resolve_targets_and_hosts() -> Tuple[Dict[str, Type[TargetBase]], Dict[str, IMXRT117xEvkTarget, Zynq7000ZedboardTarget, IMX6ULLEvkTarget, + MimasSparcV8EvkTarget, ] hosts: List[Type[Host]] = [EmulatorHost, RpiHost] diff --git a/trunner/target/__init__.py b/trunner/target/__init__.py index 096c953d3..12422c879 100644 --- a/trunner/target/__init__.py +++ b/trunner/target/__init__.py @@ -3,6 +3,7 @@ from .armv7m4 import STM32L4x6Target from .armv7a7 import IMX6ULLEvkTarget from .armv7a9 import Zynq7000ZedboardTarget +from .sparcv8 import MimasSparcV8EvkTarget from .emulated import ( IA32GenericQemuTarget, RISCV64GenericQemuTarget, @@ -23,4 +24,5 @@ "TargetBase", "find_port", "IMX6ULLEvkTarget", + "MimasSparcV8EvkTarget", ] diff --git a/trunner/target/sparcv8.py b/trunner/target/sparcv8.py new file mode 100644 index 000000000..4f33e08db --- /dev/null +++ b/trunner/target/sparcv8.py @@ -0,0 +1,139 @@ +import subprocess +import time +from typing import Callable, Optional + +import pexpect +import pexpect.fdpexpect +import usb.core + +from trunner.dut import SerialDut +from trunner.harness import ( + HarnessBuilder, + PloPhoenixdAppLoader, + PloHarness, + Rebooter, + ShellHarness, + FlashError, + TestStartRunningHarness, +) +from trunner.host import Host +from trunner.tools import Phoenixd +from trunner.types import TestResult, TestOptions +from .base import TargetBase, find_port + + +class GR716Rebooter(Rebooter): + def _reboot_soft(self): + self._reboot_hard() + # TODO implement soft restarts after implementing flash memory + # self.host.set_reset(1) + # time.sleep(0.5) + # self.dut.clear_buffer() + # self.host.set_reset(0) + # time.sleep(0.25) + + def _reboot_hard(self): + # Make sure that that reset pin is in low state + self.host.set_reset(0) + self.host.set_power(False) + time.sleep(0.75) + self.host.set_power(True) + time.sleep(0.5) + + +class GR716Target(TargetBase): + def __init__(self, host: Host, port: str, baudrate: int = 115200): + self.dut = SerialDut(port, baudrate, encoding="utf-8", codec_errors="ignore") + self.rebooter = GR716Rebooter(host, self.dut) + super().__init__() + + @classmethod + def from_context(cls, ctx): + return cls(ctx.host, ctx.port, ctx.baudrate) + + def MimasCustomUpload(self, boot_dir: str, image: str, vid: hex, pid: hex): + # using usb.core to fully reset device responsible for phoenixd + usb.core.find(idVendor=vid, idProduct=pid).reset() + + self.rebooter() + + # parsing passed hex values as string for find_port + port = str(hex(vid))[2:] + ":" + str(hex(pid))[2:] + + subprocess.Popen( + f"phoenixd -p {find_port(port)} -b 115200 -s {str(boot_dir)}/.", + shell=True, + cwd=".", + start_new_session=True, + stdin=subprocess.PIPE, + stdout=subprocess.DEVNULL, + stderr=subprocess.STDOUT, + text=True, + ) + + while True: + inChar = self.dut.read() + inChar += inChar + + if "Bootloader" in inChar: + with open(f"{boot_dir}/{image}", "rb") as fd: + filebuff = fd.read() + time.sleep(1) + self.dut.serial.write(filebuff) + + try: + self.dut.expect_exact("(psh)%", timeout=80) + fd.close() + break + + except pexpect.TIMEOUT as e: + fd.close() + raise FlashError( + msg=str(e), + output=e.stdout.decode("ascii") if e.stdout else None, + ) from e + + def flash_dut(self): + self.MimasCustomUpload( + boot_dir=self.boot_dir(), image="plo.img", vid=0x067B, pid=0x2303 + ) + + def build_test(self, test: TestOptions) -> Callable[[TestResult], TestResult]: + builder = HarnessBuilder() + + if test.should_reboot: + # TODO implement soft restarts after implementing flash memory + self.dut.send("\r\n") + + if test.bootloader is not None: + app_loader = None + + if test.bootloader.apps: + app_loader = PloPhoenixdAppLoader( + dut=self.dut, + apps=test.bootloader.apps, + phoenixd=Phoenixd(directory=self.root_dir() / test.shell.path), + ) + + builder.add(PloHarness(self.dut, app_loader=app_loader)) + + if test.shell is not None: + builder.add(ShellHarness(self.dut, self.shell_prompt, test.shell.cmd)) + else: + builder.add(TestStartRunningHarness()) + + builder.add(test.harness) + + return builder.get_harness() + + +class MimasSparcV8EvkTarget(GR716Target): + name = "sparcv8leon3-gr716-mimas" + rootfs = False + experimental = True + + def __init__(self, host: Host, port: Optional[str] = None, baudrate: int = 115200): + if not port: + port = find_port("10c4:ea60") # vid:pid for communication (PLO usb/uart) + + super().__init__(host, port, baudrate)