mirror of
https://github.com/esp-rs/esp-hal.git
synced 2025-09-29 21:30:39 +00:00
HIL updates (#1412)
* docs: Document new xtask features * style: format deps * feat: enable all the aliases * feat: Update embedded-tests executors * feat: Enable running only one test * feat: Exit if a test fails * docs: Fix typo in command * build: Enable xtensa-semihosting in xtensa targets * feat: Handle probe-rs esp32 chip name * style: Clippy lints * revert: Exit if a test fails * chore: Remove aliases * feat: Remove unnecesary toogle * feat: Error if a test fails and print failed tests
This commit is contained in:
parent
dfc6d86a58
commit
a22b817ee5
@ -1,13 +1,3 @@
|
||||
[alias]
|
||||
# esp32 = "test --release --features=esp32 --target=xtensa-esp32-none-elf -- --chip esp32-3.3v"
|
||||
# esp32c2 = "test --release --features=esp32c2 --target=riscv32imc-unknown-none-elf -- --chip esp32c2"
|
||||
esp32c3 = "test --release --features=esp32c3 --target=riscv32imc-unknown-none-elf -- --chip esp32c3"
|
||||
esp32c6 = "test --release --features=esp32c6 --target=riscv32imac-unknown-none-elf -- --chip esp32c6"
|
||||
esp32h2 = "test --release --features=esp32h2 --target=riscv32imac-unknown-none-elf -- --chip esp32h2"
|
||||
# esp32p4 = "test --release --features=esp32p4 --target=riscv32imafc-unknown-none-elf -- --chip esp32p4"
|
||||
# esp32s2 = "test --release --features=esp32s2 --target=xtensa-esp32s2-none-elf -- --chip esp32s2"
|
||||
esp32s3 = "test --release --features=esp32s3 --target=xtensa-esp32s3-none-elf -- --chip esp32s3"
|
||||
|
||||
[target.'cfg(target_arch = "riscv32")']
|
||||
runner = "probe-rs run"
|
||||
rustflags = [
|
||||
|
@ -29,8 +29,8 @@ name = "uart"
|
||||
harness = false
|
||||
|
||||
[[test]]
|
||||
name = "uart_async"
|
||||
harness = false
|
||||
name = "uart_async"
|
||||
harness = false
|
||||
required-features = ["async", "embassy"]
|
||||
|
||||
[[test]]
|
||||
@ -38,54 +38,69 @@ name = "ecc"
|
||||
harness = false
|
||||
|
||||
[dependencies]
|
||||
defmt = { version = "0.3.6" }
|
||||
defmt-rtt = { version = "0.4.0" }
|
||||
cfg-if = "1.0.0"
|
||||
critical-section = "1.1.2"
|
||||
defmt = "0.3.6"
|
||||
defmt-rtt = "0.4.0"
|
||||
embassy-futures = "0.1.1"
|
||||
embassy-time = { version = "0.3.0", features = ["generic-queue-64"] }
|
||||
embassy-futures = { version = "0.1" }
|
||||
embedded-hal = { version = "1.0.0" }
|
||||
embedded-hal = "1.0.0"
|
||||
embedded-hal-02 = { version = "0.2.7", package = "embedded-hal", features = ["unproven"] }
|
||||
embedded-hal-async = { version = "1.0.0", optional = true }
|
||||
embedded-hal-nb = { version = "1.0.0", optional = true }
|
||||
esp-backtrace = { version = "0.11.1", git = "https://github.com/esp-rs/esp-backtrace", rev = "edff83c3945e8aa11081d8467af65803a82434ba", default-features = false, features = ["exception-handler", "panic-handler", "defmt", "semihosting"] }
|
||||
esp-hal = { path = "../esp-hal", features = ["defmt", "embedded-hal", "embedded-hal-02"], optional = true }
|
||||
esp-backtrace = { version = "0.11.1", git = "https://github.com/esp-rs/esp-backtrace", rev = "edff83c3945e8aa11081d8467af65803a82434ba", default-features = false, features = ["exception-handler", "panic-handler", "defmt", "semihosting"] }
|
||||
critical-section = { version = "1.1.2" }
|
||||
portable-atomic = "1"
|
||||
cfg-if = "1"
|
||||
portable-atomic = "1.6.0"
|
||||
|
||||
[dev-dependencies]
|
||||
embassy-executor = { version = "0.5.0", default-features = false, features = ["executor-thread", "arch-riscv32"] }
|
||||
crypto-bigint = { version = "0.5.5", default-features = false }
|
||||
elliptic-curve = { version = "0.13.8", default-features = false, features = ["sec1"] }
|
||||
embassy-executor = { version = "0.5.0", default-features = false }
|
||||
# Add the `embedded-test/defmt` feature for more verbose testing
|
||||
embedded-test = { git = "https://github.com/probe-rs/embedded-test", rev = "b67dec33992f5bd79d414a0e70220dc4142278cf", default-features = false }
|
||||
crypto-bigint = { version = "0.5.5", default-features = false }
|
||||
nb = "1.1.0"
|
||||
hex-literal = "0.4.1"
|
||||
p192 = { version = "0.13.0", default-features = false, features = ["arithmetic"] }
|
||||
p256 = { version = "0.13.2", default-features = false, features = ["arithmetic"] }
|
||||
elliptic-curve = { version = "0.13.8", default-features = false, features = ["sec1"] }
|
||||
embedded-test = { git = "https://github.com/probe-rs/embedded-test", rev = "1aa5a426d6b29ae2b509c5876dd33523b03e107c", default-features = false }
|
||||
hex-literal = "0.4.1"
|
||||
nb = "1.1.0"
|
||||
p192 = { version = "0.13.0", default-features = false, features = ["arithmetic"] }
|
||||
p256 = { version = "0.13.2", default-features = false, features = ["arithmetic"] }
|
||||
|
||||
[features]
|
||||
default = ["async", "embassy", "embassy-time-timg0"]
|
||||
default = ["async", "embassy", "embassy-executor-thread", "embassy-time-timg0"]
|
||||
|
||||
# Device support (required!):
|
||||
esp32 = ["esp-hal/esp32", "esp-backtrace/esp32"]
|
||||
esp32c2 = ["esp-hal/esp32c2", "esp-backtrace/esp32c2"]
|
||||
esp32c3 = ["esp-hal/esp32c3", "esp-backtrace/esp32c3"]
|
||||
esp32c6 = ["esp-hal/esp32c6", "esp-backtrace/esp32c6"]
|
||||
esp32h2 = ["esp-hal/esp32h2", "esp-backtrace/esp32h2"]
|
||||
esp32s2 = ["esp-hal/esp32s2", "esp-backtrace/esp32s2"]
|
||||
esp32s3 = ["esp-hal/esp32s3", "esp-backtrace/esp32s3"]
|
||||
esp32 = [
|
||||
"embedded-test/xtensa-semihosting",
|
||||
"esp-backtrace/esp32",
|
||||
"esp-hal/esp32",
|
||||
]
|
||||
esp32c2 = ["esp-backtrace/esp32c2", "esp-hal/esp32c2"]
|
||||
esp32c3 = ["esp-backtrace/esp32c3", "esp-hal/esp32c3"]
|
||||
esp32c6 = ["esp-backtrace/esp32c6", "esp-hal/esp32c6"]
|
||||
esp32h2 = ["esp-backtrace/esp32h2", "esp-hal/esp32h2"]
|
||||
esp32s2 = [
|
||||
"embedded-test/xtensa-semihosting",
|
||||
"esp-backtrace/esp32s2",
|
||||
"esp-hal/esp32s2",
|
||||
]
|
||||
esp32s3 = [
|
||||
"embedded-test/xtensa-semihosting",
|
||||
"esp-backtrace/esp32s3",
|
||||
"esp-hal/esp32s3",
|
||||
]
|
||||
# Async & Embassy:
|
||||
async = ["dep:embedded-hal-async", "esp-hal?/async"]
|
||||
embassy = ["esp-hal?/embassy", "embedded-test/embassy"]
|
||||
async = ["dep:embedded-hal-async", "esp-hal?/async"]
|
||||
embassy = [
|
||||
"embedded-test/embassy",
|
||||
"embedded-test/external-executor",
|
||||
"esp-hal?/embassy",
|
||||
]
|
||||
embassy-executor-interrupt = ["esp-hal?/embassy-executor-interrupt"]
|
||||
embassy-executor-thread = ["esp-hal?/embassy-executor-thread"]
|
||||
embassy-executor-thread = ["esp-hal?/embassy-executor-thread"]
|
||||
embassy-time-systick-16mhz = ["esp-hal?/embassy-time-systick-16mhz"]
|
||||
embassy-time-systick-80mhz = ["esp-hal?/embassy-time-systick-80mhz"]
|
||||
embassy-time-timg0 = ["esp-hal?/embassy-time-timg0"]
|
||||
embassy-time-timg0 = ["esp-hal?/embassy-time-timg0"]
|
||||
|
||||
# https://doc.rust-lang.org/cargo/reference/profiles.html#test
|
||||
# Test and bench profiles inherit from dev and release respectively.
|
||||
|
||||
[profile.dev]
|
||||
codegen-units = 1
|
||||
debug = 2
|
||||
|
@ -28,23 +28,27 @@ cargo install probe-rs \
|
||||
|
||||
Target device **MUST** connected via its USB-Serial-JTAG port, or if unavailable (eg. ESP32, ESP32-C2, ESP32-S2) then you must connect a compatible debug probe such as an [ESP-Prog].
|
||||
|
||||
You can run all test for a given device using:
|
||||
You can run all tests for a given device by running the following command from the `xtask` folder:
|
||||
|
||||
```shell
|
||||
cargo +nightly esp32c6
|
||||
# or
|
||||
cargo +esp esp32s3
|
||||
cargo xtask run-tests $CHIP
|
||||
```
|
||||
|
||||
For running a single test on a target:
|
||||
For running a single test on a target, from the `xtask` folder run:
|
||||
|
||||
```shell
|
||||
# Run GPIO tests for ESP32-C6
|
||||
cargo xtask run-tests esp32c6 --test gpio
|
||||
```
|
||||
|
||||
Another alternative way of running a single test is, from the `hil-tests` folder:
|
||||
```shell
|
||||
# Run GPIO tests for ESP32-C6
|
||||
CARGO_BUILD_TARGET=riscv32imac-unknown-none-elf \
|
||||
PROBE_RS_CHIP=esp32c6 \
|
||||
cargo +nightly test --features=esp32c6 --test=gpio
|
||||
```
|
||||
- If the `--test` argument is omitted, then all tests will be run.
|
||||
- If the `--test` argument is omitted, then all tests will be run, independently if the tests are supported for that target, for this reason, we encourage using the `xtask` approach.
|
||||
- The build target **MUST** be specified via the `CARGO_BUILD_TARGET` environment variable or as an argument (`--target`).
|
||||
- The chip **MUST** be specified via the `PROBE_RS_CHIP` environment variable or as an argument of `probe-rs` (`--chip`).
|
||||
|
||||
@ -57,15 +61,15 @@ Our Virtual Machines have the following setup:
|
||||
- ESP32-C3 (`rustboard`):
|
||||
- Devkit: `ESP32-C3-DevKit-RUST-1` connected via USB-Serial-JTAG.
|
||||
- `GPIO2` and `GPIO4` are connected.
|
||||
- VM: Configured with the following [setup](#vm-setup)
|
||||
- VM: Ubuntu 20.04.5 configured with the following [setup](#vm-setup)
|
||||
- ESP32-C6 (`esp32c6-usb`):
|
||||
- Devkit: `ESP32-C6-DevKitC-1 V1.2` connected via USB-Serial-JTAG (`USB` port).
|
||||
- `GPIO2` and `GPIO4` are connected.
|
||||
- VM: Configured with the following [setup](#vm-setup)
|
||||
- VM: Ubuntu 20.04.5 configured with the following [setup](#vm-setup)
|
||||
- ESP32-H2 (`esp32h2-usb`):
|
||||
- Devkit: `ESP32-H2-DevKitM-1` connected via USB-Serial-JTAG (`USB` port).
|
||||
- `GPIO2` and `GPIO4` are connected.
|
||||
- VM: Configured with the following [setup](#vm-setup)
|
||||
- VM: Ubuntu 20.04.5 configured with the following [setup](#vm-setup)
|
||||
|
||||
[`hil.yml`]: https://github.com/esp-rs/esp-hal/blob/main/.github/workflows/hil.yml
|
||||
|
||||
@ -83,7 +87,8 @@ cargo install probe-rs --git=https://github.com/probe-rs/probe-rs --rev=ddd59fa
|
||||
wget -O - https://probe.rs/files/69-probe-rs.rules | sudo tee /etc/udev/rules.d/69-probe-rs.rules > /dev/null
|
||||
# Add the user to plugdev group
|
||||
sudo usermod -a -G plugdev $USER
|
||||
# Reboot the VM
|
||||
# Reboot the
|
||||
sudo reboot
|
||||
```
|
||||
|
||||
## Adding New Tests
|
||||
@ -92,4 +97,11 @@ sudo usermod -a -G plugdev $USER
|
||||
2. Add a corresponding `[[test]]` entry to `Cargol.toml` (**MUST** set `harness = false`)
|
||||
3. Write the tests
|
||||
4. Document any necessary physical connections on boards connected to self-hosted runners
|
||||
5. Write some documentation at the top of the `tests/$PERIPHERAL.rs` file with the pins being used and the required connections, if applicable.
|
||||
5. Add a header in the test stating which targets support the given tests. Eg:
|
||||
```rust
|
||||
//! AES Test
|
||||
|
||||
//% CHIPS: esp32 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
||||
```
|
||||
If the test is supported by all the targets, you can omit the header.
|
||||
6. Write some documentation at the top of the `tests/$PERIPHERAL.rs` file with the pins being used and the required connections, if applicable.
|
||||
|
@ -69,7 +69,7 @@ pub fn interrupt_handler() {
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[embedded_test::tests]
|
||||
#[embedded_test::tests(executor = esp_hal::embassy::executor::thread::Executor::new())]
|
||||
mod tests {
|
||||
use defmt::assert_eq;
|
||||
use embassy_time::{Duration, Timer};
|
||||
@ -148,8 +148,6 @@ mod tests {
|
||||
ctx.io4.toggle();
|
||||
assert_eq!(ctx.io4.is_set_low(), false);
|
||||
assert_eq!(ctx.io4.is_set_high(), true);
|
||||
// Leave in initial state for next test
|
||||
ctx.io4.toggle();
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -56,7 +56,7 @@ impl Context {
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[embedded_test::tests]
|
||||
#[embedded_test::tests(executor = esp_hal::embassy::executor::thread::Executor::new())]
|
||||
mod tests {
|
||||
use defmt::assert_eq;
|
||||
|
||||
|
@ -14,6 +14,7 @@ Commands:
|
||||
bump-version Bump the version of the specified package(s)
|
||||
generate-efuse-fields Generate the eFuse fields source file from a CSV
|
||||
run-example Run the given example for the specified chip
|
||||
run-tests Run all applicable tests or the specified test for a specified chip
|
||||
help Print this message or the help of the given subcommand(s)
|
||||
|
||||
Options:
|
||||
|
@ -35,7 +35,7 @@ pub fn run_with_input(args: &[String], cwd: &Path) -> Result<()> {
|
||||
bail!("The `cwd` argument MUST be a directory");
|
||||
}
|
||||
|
||||
let _status = Command::new(get_cargo())
|
||||
let status = Command::new(get_cargo())
|
||||
.args(args)
|
||||
.current_dir(cwd)
|
||||
.stdout(std::process::Stdio::inherit())
|
||||
@ -43,7 +43,11 @@ pub fn run_with_input(args: &[String], cwd: &Path) -> Result<()> {
|
||||
.stdin(std::process::Stdio::inherit())
|
||||
.status()?;
|
||||
|
||||
Ok(())
|
||||
if status.success() {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(anyhow::anyhow!("Failed to execute cargo subcommand"))
|
||||
}
|
||||
}
|
||||
|
||||
fn get_cargo() -> String {
|
||||
|
@ -320,7 +320,11 @@ pub fn run_example(
|
||||
// probe-rs cannot currently do auto detection, so we need to tell probe-rs run
|
||||
// which chip we are testing
|
||||
if subcommand == "test" {
|
||||
builder = builder.arg("--").arg("--chip").arg(format!("{}", chip));
|
||||
if chip == Chip::Esp32 {
|
||||
builder = builder.arg("--").arg("--chip").arg("esp32-3.3v");
|
||||
} else {
|
||||
builder = builder.arg("--").arg("--chip").arg(format!("{}", chip));
|
||||
}
|
||||
}
|
||||
|
||||
// If targeting an Xtensa device, we must use the '+esp' toolchain modifier:
|
||||
@ -331,8 +335,7 @@ pub fn run_example(
|
||||
let args = builder.build();
|
||||
log::debug!("{args:#?}");
|
||||
|
||||
cargo::run_with_input(&args, package_path)?;
|
||||
Ok(())
|
||||
cargo::run_with_input(&args, package_path)
|
||||
}
|
||||
|
||||
/// Build the specified package, using the given toolchain/target/features if
|
||||
@ -427,7 +430,7 @@ const EFUSE_FIELDS_RS_HEADER: &str = r#"
|
||||
//!
|
||||
//! For information on how to regenerate these files, please refer to the
|
||||
//! `xtask` package's `README.md` file.
|
||||
//!
|
||||
//!
|
||||
//! Generated on: $DATE
|
||||
//! ESP-IDF Commit: $HASH
|
||||
|
||||
@ -459,8 +462,8 @@ pub fn generate_efuse_table(
|
||||
// Determine the commit (short) hash of the HEAD commit in the
|
||||
// provided ESP-IDF repository:
|
||||
let output = Command::new("git")
|
||||
.args(&["rev-parse", "HEAD"])
|
||||
.current_dir(&idf_path)
|
||||
.args(["rev-parse", "HEAD"])
|
||||
.current_dir(idf_path)
|
||||
.output()?;
|
||||
let idf_hash = String::from_utf8_lossy(&output.stdout[0..=7]).to_string();
|
||||
|
||||
|
@ -25,7 +25,7 @@ enum Cli {
|
||||
GenerateEfuseFields(GenerateEfuseFieldsArgs),
|
||||
/// Run the given example for the specified chip.
|
||||
RunExample(RunExampleArgs),
|
||||
/// Run all applicable tests for a specified chip.
|
||||
/// Run all applicable tests or the specified test for a specified chip.
|
||||
RunTests(RunTestsArgs),
|
||||
}
|
||||
|
||||
@ -98,15 +98,18 @@ struct RunExampleArgs {
|
||||
/// Which chip to run the examples for.
|
||||
#[arg(value_enum)]
|
||||
chip: Chip,
|
||||
/// Which example to run
|
||||
/// Which example to run.
|
||||
example: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Args)]
|
||||
struct RunTestsArgs {
|
||||
/// Which chip to run the examples for.
|
||||
/// Which chip to run the tests for.
|
||||
#[arg(value_enum)]
|
||||
chip: Chip,
|
||||
/// Which example to run.
|
||||
#[arg(short = 't', long)]
|
||||
test: Option<String>,
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -139,7 +142,7 @@ fn build_documentation(workspace: &Path, args: BuildDocumentationArgs) -> Result
|
||||
let resources = workspace.join("resources");
|
||||
|
||||
let package = args.package.to_string();
|
||||
let version = xtask::package_version(&workspace, args.package)?;
|
||||
let version = xtask::package_version(workspace, args.package)?;
|
||||
|
||||
let mut crates = Vec::new();
|
||||
|
||||
@ -185,10 +188,7 @@ fn build_documentation(workspace: &Path, args: BuildDocumentationArgs) -> Result
|
||||
}
|
||||
|
||||
// Copy any additional assets to the documentation's output path:
|
||||
fs::copy(
|
||||
&resources.join("esp-rs.svg"),
|
||||
&output_path.join("esp-rs.svg"),
|
||||
)?;
|
||||
fs::copy(resources.join("esp-rs.svg"), output_path.join("esp-rs.svg"))?;
|
||||
|
||||
// Render the index and write it out to the documentaiton's output path:
|
||||
let source = fs::read_to_string(resources.join("index.html.jinja"))?;
|
||||
@ -277,7 +277,7 @@ fn generate_efuse_src(workspace: &Path, args: GenerateEfuseFieldsArgs) -> Result
|
||||
|
||||
// Generate the Rust source file from the CSV file, and write it out to
|
||||
// the appropriate path:
|
||||
xtask::generate_efuse_table(&args.chip, &idf_path, out_path)?;
|
||||
xtask::generate_efuse_table(&args.chip, idf_path, out_path)?;
|
||||
|
||||
// Format the generated code:
|
||||
xtask::cargo::run(&["fmt".into()], &esp_hal)?;
|
||||
@ -334,7 +334,7 @@ fn run_example(workspace: &Path, mut args: RunExampleArgs) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn run_tests(workspace: &PathBuf, args: RunTestsArgs) -> Result<(), anyhow::Error> {
|
||||
fn run_tests(workspace: &Path, args: RunTestsArgs) -> Result<(), anyhow::Error> {
|
||||
// Absolute path of the package's root:
|
||||
let package_path = xtask::windows_safe_path(&workspace.join("hil-test"));
|
||||
|
||||
@ -343,12 +343,33 @@ fn run_tests(workspace: &PathBuf, args: RunTestsArgs) -> Result<(), anyhow::Erro
|
||||
|
||||
// Load all examples and parse their metadata:
|
||||
let tests = xtask::load_examples(&package_path.join("tests"))?;
|
||||
let tests = tests.iter()
|
||||
let mut supported_tests = tests
|
||||
.iter()
|
||||
// Filter down the examples to only those for which the specified chip is supported:
|
||||
.filter(|example| example.supports_chip(args.chip));
|
||||
|
||||
for test in tests {
|
||||
xtask::run_example(&package_path, args.chip, target, &test)?;
|
||||
if let Some(test_name) = &args.test {
|
||||
let test = supported_tests.find_map(|example| {
|
||||
if &example.name() == test_name {
|
||||
Some(example.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
if let Some(test) = test {
|
||||
xtask::run_example(&package_path, args.chip, target, &test)?;
|
||||
} else {
|
||||
log::error!("Test not found or unsupported for the given chip");
|
||||
}
|
||||
} else {
|
||||
let mut failed_tests: Vec<String> = Vec::new();
|
||||
for test in supported_tests {
|
||||
if xtask::run_example(&package_path, args.chip, target, test).is_err() {
|
||||
failed_tests.push(test.name());
|
||||
}
|
||||
}
|
||||
if !failed_tests.is_empty() {
|
||||
bail!("Failed tests: {:?}", failed_tests);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
Loading…
x
Reference in New Issue
Block a user