Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable C3, H2, S2 and S3 HIL #1513

Merged
merged 17 commits into from
May 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,7 @@ jobs:
- soc: esp32h2
rust-target: riscv32imac-unknown-none-elf
# Xtensa devices:
- soc: esp32s2
- soc: esp32s3

steps:
Expand All @@ -339,4 +340,4 @@ jobs:
ldproxy: false

- uses: Swatinem/rust-cache@v2
- run: cargo xtask build-examples hil-test ${{ matrix.target.soc }}
- run: cargo xtask build-tests ${{ matrix.target.soc }}
46 changes: 25 additions & 21 deletions .github/workflows/hil.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,21 @@ jobs:
matrix:
target:
# RISC-V devices:
# - soc: esp32c3
# rust-target: riscv32imc-unknown-none-elf
- soc: esp32c3
rust-target: riscv32imc-unknown-none-elf
- soc: esp32c6
rust-target: riscv32imac-unknown-none-elf
# - soc: esp32h2
# rust-target: riscv32imac-unknown-none-elf
- soc: esp32h2
rust-target: riscv32imac-unknown-none-elf
# # Xtensa devices:
# - soc: esp32s3
- soc: esp32s2
rust-target: xtensa-esp32s2-none-elf
- soc: esp32s3
rust-target: xtensa-esp32s3-none-elf

steps:
- uses: actions/checkout@v4
if: github.event_name != 'workflow_dispatch'

- uses: actions/checkout@v4
if: github.event_name == 'workflow_dispatch'
with:
Expand All @@ -59,7 +62,7 @@ jobs:
default: true
ldproxy: false

- name: Run tests
- name: Build tests
run: cargo xtask build-tests ${{ matrix.target.soc }}

- name: Prepare artifact
Expand All @@ -78,12 +81,12 @@ jobs:
base_name="$(basename "$file" | cut -d'-' -f1)"
mv "$file" "tests/$base_name"
done
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've also tested with cargo build --out-dir... but since the elfs are generated under the target/.../deps and are not the "final" artifacts it does not help. My idea was to modify cargo xtast build-tests to add the --out-dir argument and avoid all this bash code.


- uses: actions/upload-artifact@v4
with:
name: tests-${{ matrix.target.soc }}
path: /home/runner/work/esp-hal/esp-hal/tests
if-no-files-found: error
overwrite: true

hil:
name: HIL Test | ${{ matrix.target.soc }}
Expand All @@ -95,24 +98,25 @@ jobs:
matrix:
target:
# RISC-V devices:
# - soc: esp32c3
# runner: rustboard
- soc: esp32c3
runner: esp32c3-usb
- soc: esp32c6
runner: esp32c6-usb
# - soc: esp32h2
# runner: esp32h2-usb
# # Xtensa devices:
# - soc: esp32s3
# runner: esp32s3-usb
- soc: esp32h2
runner: esp32h2-usb
# Xtensa devices:
- soc: esp32s2
runner: esp32s2-jtag
- soc: esp32s3
runner: esp32s3-usb
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: tests-${{ matrix.target.soc }}
path: tests
- name: Run tests
path: tests-${{ matrix.target.soc }}

- name: Run Tests
run: |
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would really like to see this implemented in the xtask instead, please.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Me too, this bash code and the one preparing the artifacts looks quite bad to me. Any suggestions on how to integrate this with xtask other than creating a subcommand that points to a folder, and it executes all the elfs on that folder?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a subcommand to run all the elfs in a folder in daf8746. Here is a HIL run: https://github.com/esp-rs/esp-hal/actions/runs/8924001488 with that changes, it increases the time it takes for the run as it needs to build the xtask package.

export PATH=$PATH:/home/espressif/.cargo/bin
for file in "tests"/*; do
probe-rs run --chip ${{ matrix.target.soc }} "$file"
done

cargo xtask run-elfs ${{ matrix.target.soc }} tests-${{ matrix.target.soc }}
21 changes: 12 additions & 9 deletions hil-test/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,9 @@ We use [embedded-test] as our testing framework, which relies on [defmt] interna
We use [probe-rs] for flashing and running the tests on a target device, however, this **MUST** be installed from the correct revision, and with the correct features enabled:

```text
cargo install probe-rs \
--git=https://github.com/probe-rs/probe-rs \
--rev=ddd59fa \
--features=cli \
--bin=probe-rs
cargo install probe-rs-tools \
--git https://github.com/probe-rs/probe-rs \
--rev 4dc1701 --force --locked
```

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].
Expand Down Expand Up @@ -61,19 +59,24 @@ 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: Ubuntu 20.04.5 configured with the following [setup](#vm-setup)
- RPi: Raspbian 12 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.
- RPi: Raspbian 12 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: Ubuntu 20.04.5 configured with the following [setup](#vm-setup)
- RPi: Raspbian 12 configured with the following [setup](#vm-setup)
- ESP32-S2 (`esp32s2-jtag`):
- Devkit: `ESP32-S2-Saola-1` connected via UART.
- `GPIO2` and `GPIO4` are connected.
- Probe: `ESP-Prog` connected with the [following connections](https://docs.espressif.com/projects/esp-idf/en/stable/esp32s2/api-guides/jtag-debugging/configure-other-jtag.html#configure-hardware)
- RPi: Raspbian 12 configured with the following [setup](#vm-setup)
- ESP32-S3 (`esp32s3-usb`):
- Devkit: `ESP32-S3-DevKitC-1` connected via USB-Serial-JTAG.
- `GPIO2` and `GPIO4` are connected.
- VM: Ubuntu 22.04.4 configured with the following [setup](#vm-setup)
- RPi: Raspbian 12 configured with the following [setup](#vm-setup)

[`hil.yml`]: https://github.com/esp-rs/esp-hal/blob/main/.github/workflows/hil.yml

Expand All @@ -86,7 +89,7 @@ source "$HOME/.cargo/env"
# Install dependencies
sudo apt install -y pkg-config libudev-dev
# Install probe-rs
cargo install probe-rs --git=https://github.com/probe-rs/probe-rs --rev=ddd59fa --features=cli --bin=probe-rs --locked --force
cargo install probe-rs-tools --git https://github.com/probe-rs/probe-rs --rev 4dc1701 --force
# Add the udev rules
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
Expand Down
2 changes: 2 additions & 0 deletions hil-test/tests/delay.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! Delay Test

//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32s3

#![no_std]
#![no_main]

Expand Down
2 changes: 1 addition & 1 deletion hil-test/tests/get_time.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! current_time Test

//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32s2 esp32s3

#![no_std]
#![no_main]
Expand Down
3 changes: 2 additions & 1 deletion hil-test/tests/gpio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
//! GPIO2
//! GPIO4

//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3

#![no_std]
#![no_main]

Expand Down Expand Up @@ -151,7 +153,6 @@ mod tests {
}

#[test]
// TODO: See https://github.com/esp-rs/esp-hal/issues/1413
#[cfg(not(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3")))]
fn test_gpio_interrupt(mut ctx: Context) {
critical_section::with(|cs| {
Expand Down
2 changes: 2 additions & 0 deletions hil-test/tests/spi_full_duplex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
//!
//! Connect MISO (GPIO2) and MOSI (GPIO4) pins.

//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3

#![no_std]
#![no_main]

Expand Down
4 changes: 2 additions & 2 deletions hil-test/tests/spi_full_duplex_dma.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
//!
//! Connect MISO (GPIO2) and MOSI (GPIO4) pins.

//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s3

#![no_std]
#![no_main]
Expand Down Expand Up @@ -120,7 +120,7 @@ mod tests {

let transfer = spi.dma_transfer(&mut send, &mut receive).unwrap();
transfer.wait().unwrap();
assert_eq!(send[0], receive[0]);
assert_eq!(send[0..1], receive[0..1]);
}

#[test]
Expand Down
55 changes: 39 additions & 16 deletions hil-test/tests/uart.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
//!
//! Connect TX (GPIO2) and RX (GPIO4) pins.

//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3

#![no_std]
#![no_main]

Expand Down Expand Up @@ -106,22 +108,43 @@ mod tests {
// working as expected. We will also using different clock sources
// while we're at it.

// 9600 baud, RC FAST clock source:
ctx.uart.change_baud(9600, ClockSource::RcFast, &ctx.clocks);
ctx.uart.write(7).ok();
let read = block!(ctx.uart.read());
assert_eq!(read, Ok(7));

// 19,200 baud, XTAL clock source:
ctx.uart.change_baud(19_200, ClockSource::Xtal, &ctx.clocks);
ctx.uart.write(55).ok();
let read = block!(ctx.uart.read());
assert_eq!(read, Ok(55));
#[cfg(not(feature = "esp32s2"))]
{
#[cfg(not(feature = "esp32c3"))]
{
// 9600 baud, RC FAST clock source:
ctx.uart.change_baud(9600, ClockSource::RcFast, &ctx.clocks);
ctx.uart.write(7).ok();
let read = block!(ctx.uart.read());
assert_eq!(read, Ok(7));
}

// 921,600 baud, APB clock source:
ctx.uart.change_baud(921_600, ClockSource::Apb, &ctx.clocks);
ctx.uart.write(253).ok();
let read = block!(ctx.uart.read());
assert_eq!(read, Ok(253));
// 19,200 baud, XTAL clock source:
ctx.uart.change_baud(19_200, ClockSource::Xtal, &ctx.clocks);
ctx.uart.write(55).ok();
let read = block!(ctx.uart.read());
assert_eq!(read, Ok(55));

// 921,600 baud, APB clock source:
ctx.uart.change_baud(921_600, ClockSource::Apb, &ctx.clocks);
ctx.uart.write(253).ok();
let read = block!(ctx.uart.read());
assert_eq!(read, Ok(253));
}
#[cfg(feature = "esp32s2")]
{
// 9600 baud, REF TICK clock source:
ctx.uart
.change_baud(9600, ClockSource::RefTick, &ctx.clocks);
ctx.uart.write(7).ok();
let read = block!(ctx.uart.read());
assert_eq!(read, Ok(7));

// 921,600 baud, APB clock source:
ctx.uart.change_baud(921_600, ClockSource::Apb, &ctx.clocks);
ctx.uart.write(253).ok();
let read = block!(ctx.uart.read());
assert_eq!(read, Ok(253));
}
}
}
2 changes: 2 additions & 0 deletions hil-test/tests/uart_async.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
//!
//! Connect TX (GPIO2) and RX (GPIO4) pins.

//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3

#![no_std]
#![no_main]

Expand Down
12 changes: 5 additions & 7 deletions xtask/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,14 +257,12 @@ pub fn execute_app(
format!("--example={}", app.name())
};
(bin, "build")
} else if package.starts_with("src/bin") {
(format!("--bin={}", app.name()), "run")
} else if package.starts_with("tests") {
(format!("--test={}", app.name()), "test")
} else {
if package.starts_with("src/bin") {
(format!("--bin={}", app.name()), "run")
} else if package.starts_with("tests") {
(format!("--test={}", app.name()), "test")
} else {
(format!("--example={}", app.name()), "run")
}
(format!("--example={}", app.name()), "run")
};

let mut features = app.features().to_vec();
Expand Down
45 changes: 45 additions & 0 deletions xtask/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::{
fs,
path::{Path, PathBuf},
process::Command,
};

use anyhow::{bail, Result};
Expand Down Expand Up @@ -29,6 +30,8 @@ enum Cli {
RunExample(RunExampleArgs),
/// Run all applicable tests or the specified test for a specified chip.
RunTests(TestsArgs),
/// Run all ELFs in a folder.
RunElfs(RunElfArgs),
}

#[derive(Debug, Args)]
Expand Down Expand Up @@ -114,6 +117,15 @@ struct TestsArgs {
test: Option<String>,
}

#[derive(Debug, Args)]
struct RunElfArgs {
/// Which chip to run the tests for.
#[arg(value_enum)]
chip: Chip,
/// Path to the ELFs.
path: PathBuf,
}

// ----------------------------------------------------------------------------
// Application

Expand All @@ -134,6 +146,7 @@ fn main() -> Result<()> {
Cli::GenerateEfuseFields(args) => generate_efuse_src(&workspace, args),
Cli::RunExample(args) => run_example(&workspace, args),
Cli::RunTests(args) => execute_tests(&workspace, args, CargoAction::Run),
Cli::RunElfs(args) => run_elfs(args),
}
}

Expand Down Expand Up @@ -396,6 +409,38 @@ fn execute_tests(
Ok(())
}

fn run_elfs(args: RunElfArgs) -> Result<(), anyhow::Error> {
let elfs = fs::read_dir(&args.path)?;
let mut failed_elfs: Vec<String> = Vec::new();
for elf in elfs {
let elf = elf?;
let elf_path = elf.path();
let elf_name = elf_path.file_name().unwrap().to_str().unwrap();
let elf_name = elf_name.split('.').next().unwrap();
let elf_name = elf_name.to_string();
println!("Running '{}' test", elf_name);

let command = Command::new("probe-rs")
.arg("run")
.arg("--chip")
.arg(args.chip.to_string())
.arg(elf_path)
.output()
.expect("Failed to execute probe-rs run command");
let stdout = String::from_utf8_lossy(&command.stdout);
let stderr = String::from_utf8_lossy(&command.stderr);
println!("{}\n{}", stderr, stdout);
if !command.status.success() {
failed_elfs.push(elf_name);
}
}

if !failed_elfs.is_empty() {
bail!("Failed tests: {:?}", failed_elfs);
}

Ok(())
}
// ----------------------------------------------------------------------------
// Helper Functions

Expand Down
Loading