diff --git a/sw/device/tests/BUILD b/sw/device/tests/BUILD index 92ec251ad07d01..71d3dde6503625 100644 --- a/sw/device/tests/BUILD +++ b/sw/device/tests/BUILD @@ -3593,6 +3593,30 @@ cc_library( ], ) +opentitan_test( + name = "spi_device_ottf_console_test", + srcs = ["spi_device_ottf_console_test.c"], + exec_env = dicts.add( + EARLGREY_TEST_ENVS, + EARLGREY_CW340_TEST_ENVS, + ), + fpga = fpga_params( + tags = ["manual"], + test_cmd = """ + --bootstrap="{firmware}" + "{firmware:elf}" + """, + test_harness = "//sw/host/tests/chip/spi_device_ottf_console", + ), + deps = [ + "//hw/top_earlgrey/sw/autogen:top_earlgrey", + "//sw/device/lib/dif:spi_device", + "//sw/device/lib/runtime:log", + "//sw/device/lib/testing:spi_flash_testutils", + "//sw/device/lib/testing/test_framework:ottf_main", + ], +) + opentitan_test( name = "sram_ctrl_sleep_sram_ret_contents_no_scramble_test", srcs = ["sram_ctrl_sleep_sram_ret_contents_no_scramble_test.c"], diff --git a/sw/device/tests/spi_device_ottf_console_test.c b/sw/device/tests/spi_device_ottf_console_test.c new file mode 100644 index 00000000000000..2471b81803dffe --- /dev/null +++ b/sw/device/tests/spi_device_ottf_console_test.c @@ -0,0 +1,24 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#include "sw/device/lib/dif/dif_spi_device.h" +#include "sw/device/lib/runtime/log.h" +#include "sw/device/lib/testing/test_framework/check.h" +#include "sw/device/lib/testing/test_framework/ottf_main.h" + +#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h" + +OTTF_DEFINE_TEST_CONFIG(.console.type = kOttfConsoleSpiDevice, + .console.base_addr = TOP_EARLGREY_SPI_DEVICE_BASE_ADDR, + .console.test_may_clobber = false, ); + +static const char test_str[] = "This is a SPI device OTTF console test."; + +bool test_main(void) { + for (int i = 0; i < 100; i++) { + LOG_INFO("%s round: %d", test_str, i); + } + + return true; +} diff --git a/sw/host/tests/chip/spi_device_ottf_console/BUILD b/sw/host/tests/chip/spi_device_ottf_console/BUILD new file mode 100644 index 00000000000000..b71930f34095a4 --- /dev/null +++ b/sw/host/tests/chip/spi_device_ottf_console/BUILD @@ -0,0 +1,22 @@ +# Copyright lowRISC contributors (OpenTitan project). +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +load("@rules_rust//rust:defs.bzl", "rust_binary") + +package(default_visibility = ["//visibility:public"]) + +rust_binary( + name = "spi_device_ottf_console", + srcs = [ + "src/main.rs", + ], + deps = [ + "//sw/host/opentitanlib", + "//third_party/rust/crates:anyhow", + "//third_party/rust/crates:clap", + "//third_party/rust/crates:humantime", + "//third_party/rust/crates:log", + "//third_party/rust/crates:regex", + ], +) diff --git a/sw/host/tests/chip/spi_device_ottf_console/src/main.rs b/sw/host/tests/chip/spi_device_ottf_console/src/main.rs new file mode 100644 index 00000000000000..f0b406f00fc07e --- /dev/null +++ b/sw/host/tests/chip/spi_device_ottf_console/src/main.rs @@ -0,0 +1,83 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +use anyhow::{anyhow, Result}; +use clap::Parser; +use regex::Regex; +use std::path::PathBuf; +use std::time::Duration; + +use opentitanlib::app::TransportWrapper; +use opentitanlib::console::spi::SpiConsoleDevice; +use opentitanlib::execute_test; +use opentitanlib::test_utils::init::InitializeTest; +use opentitanlib::uart::console::{ExitStatus, UartConsole}; + +#[derive(Debug, Parser)] +struct Opts { + #[command(flatten)] + init: InitializeTest, + + /// Console receive timeout. + #[arg(long, value_parser = humantime::parse_duration, default_value = "20s")] + timeout: Duration, + + /// Name of the SPI interface to connect to the OTTF console. + #[arg(long, default_value = "BOOTSTRAP")] + console_spi: String, + + /// Path to the firmware's ELF file, for querying symbol addresses. + #[arg(value_name = "FIRMWARE_ELF")] + firmware_elf: PathBuf, +} + +fn spi_device_console_test(opts: &Opts, transport: &TransportWrapper) -> Result<()> { + let mut console = UartConsole { + timeout: Some(opts.timeout), + exit_success: Some(Regex::new(r"PASS.*\n")?), + exit_failure: Some(Regex::new(r"(FAIL|FAULT).*\n")?), + newline: true, + ..Default::default() + }; + let mut stdout = std::io::stdout(); + let spi = transport.spi(&opts.console_spi)?; + + + let spi_console_device = SpiConsoleDevice::new(&*spi)?; + let _ = UartConsole::wait_for(&spi_console_device, r"Running [^\r\n]*", opts.timeout)?; + + let result = console.interact(&spi_console_device, None, Some(&mut stdout))?; + match result { + ExitStatus::None | ExitStatus::CtrlC => Ok(()), + ExitStatus::Timeout => { + if console.exit_success.is_some() { + Err(anyhow!("Console timeout exceeded")) + } else { + Ok(()) + } + } + ExitStatus::ExitSuccess => { + log::info!( + "ExitSuccess({:?})", + console.captures(result).unwrap().get(0).unwrap().as_str() + ); + Ok(()) + } + ExitStatus::ExitFailure => { + log::info!( + "ExitFailure({:?})", + console.captures(result).unwrap().get(0).unwrap().as_str() + ); + Err(anyhow!("Matched exit_failure expression")) + } + } +} + +fn main() -> Result<()> { + let opts = Opts::parse(); + opts.init.init_logging(); + let transport = opts.init.init_target()?; + execute_test!(spi_device_console_test, &opts, &transport); + Ok(()) +}