diff --git a/benchmark/runner/README.md b/benchmark/runner/README.md index 19b61f70..211251db 100644 --- a/benchmark/runner/README.md +++ b/benchmark/runner/README.md @@ -10,6 +10,23 @@ ### Device Under Test (L4R5ZI) ![DUT Wiring](img/L4R5ZI.png) +### Interface Board (USB-UART) +The USB-UART interface can replace the Interface Board (STM32H573I-DK) and run benchmarks requiring only UART communication, such as IC and AD. + +Most USB-UART interfaces should work fine; however, the current tests were conducted using an interface based on the PL2303GS controller. + +The interface used and the connection details are shown in the figure below. +![DUT Wiring](img/usb-uart2.png) +#### Configuration +To use the USB-UART interface, choose `iouart` in the `devices. yaml` file. See the sample entry below. +```yaml +- name: iouart + type: interface + preference: 3 + usb: + 0x067b:0x23a3 # USB-UART device VID and PID +``` + ## Test Runner The test runner connects to the interface board and the power board and the dut. It will execute test scripts. Test script is determined by the configuration of the hardware. diff --git a/benchmark/runner/device_manager.py b/benchmark/runner/device_manager.py index 7988fa0d..b8d34bfa 100644 --- a/benchmark/runner/device_manager.py +++ b/benchmark/runner/device_manager.py @@ -3,6 +3,7 @@ from serial.tools import list_ports from device_under_test import DUT +from io_uart import IOUart from io_manager import IOManager from io_manager_enhanced import IOManagerEnhanced from power_manager import PowerManager @@ -41,8 +42,12 @@ def _instantiate(self, definition): if definition.get("baud"): args["baud_rate"] = definition.get("baud") if definition.get("type") == "interface": - definition["instance"] = IOManagerEnhanced(**args) if definition.get("name") == "stm32h573i-dk" \ - else IOManager(**args) + if definition.get("name") == "stm32h573i-dk": + definition["instance"] = IOManagerEnhanced(**args) + elif definition.get("name") == "iouart": + definition["instance"] = IOUart(**args) + else: + definition["instance"] = IOManager(**args) elif definition.get("type") == "power": definition["instance"] = PowerManager(**args) elif definition.get("type") == "dut": diff --git a/benchmark/runner/devices.yaml b/benchmark/runner/devices.yaml index b9decc15..27233686 100644 --- a/benchmark/runner/devices.yaml +++ b/benchmark/runner/devices.yaml @@ -3,6 +3,11 @@ preference: 2 usb: 0x0483: 0x374E +- name: iouart + type: interface + preference: 3 + usb: + 0x067b: 0x23a3 - name: arduino type: interface preference: 1 diff --git a/benchmark/runner/img/usb-uart2.png b/benchmark/runner/img/usb-uart2.png new file mode 100644 index 00000000..96e7f85f Binary files /dev/null and b/benchmark/runner/img/usb-uart2.png differ diff --git a/benchmark/runner/io_uart.py b/benchmark/runner/io_uart.py new file mode 100644 index 00000000..fc2825be --- /dev/null +++ b/benchmark/runner/io_uart.py @@ -0,0 +1,87 @@ +from typing import Optional, Union, List +from interface_device import InterfaceDevice +from serial_device import SerialDevice + + +class IOUart(InterfaceDevice): + """Represents an UART interface for communication over a serial device. + + This class provides a high-level interface for sending commands to and + receiving responses from a DUT. + """ + + def __init__(self, port_device: str, baud_rate: int = 115200) -> None: + """Initializes the IOUart interface. + + Args: + port_device: The device port. + baud_rate: The baud rate for communication. + + Raises: + RuntimeError: If the initialization of the SerialDevice fails. + """ + try: + self.port: SerialDevice = SerialDevice(port_device, baud_rate, "m-ready", '%') + self.is_port_open = False + except Exception as e: + raise RuntimeError(f"Failed to initialize SerialDevice on port {port_device}: {e}") + + def __enter__(self) -> "IOUart": + """Enters the context for the IOUart interface. + + Opens the underlying serial port if it is not already open. + + Returns: + The IOUart instance for use in the context. + + Raises: + RuntimeError: If the port could not be opened successfully. + """ + if not self.is_port_open: + try: + self.port.__enter__() + self.is_port_open = True + except Exception as e: + raise RuntimeError(f"Failed to open the port: {e}") from e + return self + + def __exit__(self, *args) -> None: + """Exits the context for the IOUart interface. + + Closes the underlying serial port if it is open. + + Args: + *args: Arguments passed to the `__exit__` method. + """ + if self.is_port_open: + try: + self.port.__exit__(*args) + except Exception as e: + print(f"Error while closing the port: {e}") + raise + finally: + self.is_port_open = False + + def send_command( + self, + command: str + ) -> Union[str, List[str]]: + """Sends a command to the serial device and retrieves the response. + + Args: + command: The command string to send. + + Returns: + str | list[str]: The response(s) from the serial device. + + Raises: + ValueError: If no response is received for the command. + RuntimeError: If an error occurs during communication with the serial device. + """ + try: + resp: List[str] = self.port.send_command(command) + if not resp: + raise ValueError(f"IOUart: No response received for command: {command}") + return resp if len(resp) != 1 else resp[0] + except Exception as e: + raise RuntimeError(f"IOUart: Failed to send command '{command}': {e}") diff --git a/benchmark/runner/serial_device.py b/benchmark/runner/serial_device.py index 52eb09c7..80f1ff1f 100644 --- a/benchmark/runner/serial_device.py +++ b/benchmark/runner/serial_device.py @@ -18,6 +18,8 @@ def __init__(self, port_device, baud_rate, end_of_response="", delimiter="\n", e def __enter__(self): self._port.__enter__() + self._port.reset_input_buffer() + self._port.reset_output_buffer() self._start_read_thread() return self