Adjust I2C tests and update UART script - Moved I2C tests from i2c1 to i2c2 to work with the EVB harness. - Moved the device from 0x2e to 0x42 to work with the Zephyr reference. - Updated the UART script to automatically detokenize UART output from pigweed when requested, as well as allow it to operate on systems without a full pigweed tree.
diff --git a/.gitignore b/.gitignore index 61dddb1..c1d1ee0 100644 --- a/.gitignore +++ b/.gitignore
@@ -133,6 +133,3 @@ # Build scripts build.rs.bk - -# Cargo build output -target/
diff --git a/services/i2c/server/src/main.rs b/services/i2c/server/src/main.rs index ceac19f..3a757d6 100644 --- a/services/i2c/server/src/main.rs +++ b/services/i2c/server/src/main.rs
@@ -109,6 +109,7 @@ response: &mut [u8], backend: &mut AspeedI2cBackend, ) -> usize { + pw_log::info!("I2C server dispatch"); // Parse header let Some(header) = I2cRequestHeader::from_bytes(request) else { return encode_error(response, ResponseCode::ServerError); @@ -125,6 +126,7 @@ // Write: header.write_len bytes from payload → device // ------------------------------------------------------------------ I2cOp::Write => { + pw_log::info!("I2C dispatch write"); let wlen = header.write_len as usize; if payload.len() < wlen { return encode_error(response, ResponseCode::BufferTooSmall); @@ -139,6 +141,7 @@ // Read: header.read_len bytes from device → response payload // ------------------------------------------------------------------ I2cOp::Read => { + pw_log::info!("I2C dispatch read"); let rlen = header.read_len as usize; let avail = response.len().saturating_sub(I2cResponseHeader::SIZE); if rlen > avail { @@ -156,6 +159,7 @@ // WriteRead: write then read with repeated START // ------------------------------------------------------------------ I2cOp::WriteRead => { + pw_log::info!("I2C dispatch writeread"); let wlen = header.write_len as usize; let rlen = header.read_len as usize; if payload.len() < wlen { @@ -178,6 +182,9 @@ // Probe: write 0 bytes — ACK means device present // ------------------------------------------------------------------ I2cOp::Probe => { + pw_log::info!("I2C dispatch probe"); + + match backend.write(header.bus, header.address, &[]) { Ok(()) => encode_success(response, 0), Err(code) => encode_error(response, code), @@ -188,6 +195,7 @@ // RecoverBus: attempt to unstick SDA via clock pulses // ------------------------------------------------------------------ I2cOp::RecoverBus => { + pw_log::info!("I2C dispatch recover bus"); match backend.recover_bus(header.bus) { Ok(()) => encode_success(response, 0), Err(code) => encode_error(response, code),
diff --git a/target/ast1060-evb/harness/uart_test_exec.py b/target/ast1060-evb/harness/uart_test_exec.py index 76f8cd0..fb759e9 100644 --- a/target/ast1060-evb/harness/uart_test_exec.py +++ b/target/ast1060-evb/harness/uart_test_exec.py
@@ -17,6 +17,35 @@ from pathlib import Path from typing import Optional, Tuple +def _find_pw_tokenizer() -> bool: + """Attempt to locate and add pw_tokenizer to sys.path. + + Checks PW_TOK_ROOT first, then falls back to the Bazel output base. + Returns True if pw_tokenizer was found and added to sys.path. + """ + pw_tok_root = os.environ.get("PW_TOK_ROOT") + if pw_tok_root: + sys.path.insert(0, os.path.join(pw_tok_root, "pw_tokenizer", "py")) + return True + + try: + output_base = subprocess.check_output( + ["bazel", "info", "output_base"], text=True, stderr=subprocess.DEVNULL + ).strip() + candidate = os.path.join(output_base, "external", "pigweed+", "pw_tokenizer", "py") + if os.path.isdir(candidate): + sys.path.insert(0, candidate) + return True + except (subprocess.CalledProcessError, FileNotFoundError): + pass + + return False + +_PW_TOKENIZER_AVAILABLE = _find_pw_tokenizer() + +if _PW_TOKENIZER_AVAILABLE: + from pw_tokenizer import Detokenizer + try: import serial except ImportError: @@ -36,12 +65,22 @@ self.serial_port: Optional[serial.Serial] = None self.log_file = getattr(args, "log_file", None) or f"uart-test-{os.getpid()}.log" self.log_file_handle = None + elf = getattr(args, "elf", None) + self.detokenizer = Detokenizer(elf) if (elf and _PW_TOKENIZER_AVAILABLE) else None def log(self, message: str): """Print message unless in quiet mode.""" if not self.args.quiet: print(message, flush=True) + def print_uart_data(self, data: str): + """Print UART data, with detokenized output on the following line in green.""" + print(data, end="", flush=True) + if self.detokenizer: + detokenized = self.detokenizer.detokenize_text(data) + if detokenized != data: + print(f"\033[32m{detokenized}\033[0m", end="", flush=True) + def run_command(self, cmd: list, check: bool = True) -> Tuple[int, str, str]: """Run command and return (returncode, stdout, stderr).""" try: @@ -221,7 +260,7 @@ if data: buffer += data if not self.args.quiet: - print(data, end="", flush=True) + self.print_uart_data(data) # Look for 'U' character if "U" in buffer: @@ -304,7 +343,7 @@ if data: buffer += data if not self.args.quiet: - print(data, end="", flush=True) + self.print_uart_data(data) lines = buffer.split("\n") for line in lines: @@ -387,6 +426,7 @@ "uart_device", nargs="?", help="UART device path (e.g., /dev/ttyUSB0)" ) parser.add_argument("firmware", nargs="?", help="Firmware binary file path") + parser.add_argument("--elf", help="ELF file for pw_tokenizer detokenization") # GPIO control parser.add_argument( @@ -460,6 +500,20 @@ args = parser.parse_args() + # Validate pw_tokenizer / --elf argument consistency + if os.environ.get("PW_TOK_ROOT") and not args.elf: + print( + "Error: PW_TOK_ROOT is set but --elf was not provided. " + "Detokenization requires an ELF file." + ) + sys.exit(1) + if args.elf and not _PW_TOKENIZER_AVAILABLE: + print( + "Error: --elf was provided but pw_tokenizer could not be located. " + "Set PW_TOK_ROOT to the Pigweed root or ensure Bazel has fetched it." + ) + sys.exit(1) + # Validate arguments if args.upload_only: if not args.uart_device or not args.firmware:
diff --git a/target/ast1060-evb/i2c/i2c_client_test.rs b/target/ast1060-evb/i2c/i2c_client_test.rs index 8986bbb..06ace72 100644 --- a/target/ast1060-evb/i2c/i2c_client_test.rs +++ b/target/ast1060-evb/i2c/i2c_client_test.rs
@@ -40,10 +40,10 @@ // ============================================================================ /// I2C bus for master tests (I2C1 — connected to ADT7490 on the EVB) -const I2C_BUS: BusIndex = BusIndex::BUS_1; +const I2C_BUS: BusIndex = BusIndex::BUS_2; /// ADT7490 temperature sensor 7-bit address (on-board) -const ADT7490_ADDR: u8 = 0x2E; +const ADT7490_ADDR: u8 = 0x42; /// ADT7490 register addresses and their expected power-on-reset defaults. /// From ADT7490 datasheet — these are read-only default values. @@ -226,7 +226,7 @@ pw_log::info!("========================================"); pw_log::info!("I2C Hardware Tests (IPC → ADT7490)"); - pw_log::info!("Bus: I2C1 Addr: 0x2E"); + pw_log::info!("Bus: I2C2 Addr: 0x42"); pw_log::info!("========================================"); test_probe_adt7490(&mut client, &mut results);