Skip to content

Commit

Permalink
Add the qa-test package (esp-rs#2558)
Browse files Browse the repository at this point in the history
* Teach `xtask` about the `qa-test` package

* Create the `qa-test` package and move some examples to it

* Check `qa-test` package in CI

* Add `README.md`
  • Loading branch information
jessebraham authored Nov 18, 2024
1 parent c6404fe commit 2472e36
Show file tree
Hide file tree
Showing 18 changed files with 159 additions and 24 deletions.
5 changes: 5 additions & 0 deletions .github/actions/check-esp-hal/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,8 @@ runs:
CI: 1
shell: bash
run: cargo +${{ inputs.toolchain }} xtask build-examples esp-hal ${{ inputs.device }} --debug
- name: Build (qa-test)
env:
CI: 1
shell: bash
run: cargo +${{ inputs.toolchain }} xtask build-examples qa-test ${{ inputs.device }} --debug
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ exclude = [
"extras/esp-wifishark",
"extras/ieee802154-sniffer",
"hil-test",
"qa-test",
"xtensa-lx",
"xtensa-lx-rt",
"xtensa-lx-rt/procmacros",
Expand Down
3 changes: 0 additions & 3 deletions examples/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ embassy-sync = "0.6.0"
embassy-time = "0.3.2"
embassy-usb = { version = "0.2.0", default-features = false }
embedded-can = "0.4.1"
embedded-graphics = "0.8.1"
embedded-hal-async = "1.0.0"
embedded-io = { version = "0.6.1", default-features = false }
embedded-io-async = "0.6.1"
Expand All @@ -37,15 +36,13 @@ heapless = "0.8.0"
hmac = { version = "0.12.1", default-features = false }
ieee80211 = { version = "0.4.0", default-features = false }
ieee802154 = "0.6.1"
lis3dh-async = "0.9.3"
log = "0.4.22"
nb = "1.1.0"
portable-atomic = { version = "1.9.0", default-features = false }
sha2 = { version = "0.10.8", default-features = false }
smoltcp = { version = "0.11.0", default-features = false, features = [ "medium-ethernet", "socket-raw"] }
smoltcp-nal = "0.5.1"
embedded-time = "=0.12.1"
ssd1306 = "0.8.4"
static_cell = { version = "2.1.0", features = ["nightly"] }
trouble-host = { git = "https://github.com/embassy-rs/trouble", package = "trouble-host", rev = "4f1114ce58e96fe54f5ed7e726f66e1ad8d9ce54", features = [ "log", "gatt" ] }
usb-device = "0.3.2"
Expand Down
33 changes: 33 additions & 0 deletions qa-test/.cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
[alias]
esp32 = "run --release --features=esp32 --target=xtensa-esp32-none-elf"
esp32c2 = "run --release --features=esp32c2 --target=riscv32imc-unknown-none-elf"
esp32c3 = "run --release --features=esp32c3 --target=riscv32imc-unknown-none-elf"
esp32c6 = "run --release --features=esp32c6 --target=riscv32imac-unknown-none-elf"
esp32h2 = "run --release --features=esp32h2 --target=riscv32imac-unknown-none-elf"
esp32s2 = "run --release --features=esp32s2 --target=xtensa-esp32s2-none-elf"
esp32s3 = "run --release --features=esp32s3 --target=xtensa-esp32s3-none-elf"

[target.'cfg(target_arch = "riscv32")']
runner = "espflash flash --monitor"
rustflags = [
"-C", "link-arg=-Tlinkall.x",
"-C", "force-frame-pointers",
]

[target.'cfg(target_arch = "xtensa")']
runner = "espflash flash --monitor"
rustflags = [
# GNU LD
"-C", "link-arg=-Wl,-Tlinkall.x",
"-C", "link-arg=-nostartfiles",

# LLD
# "-C", "link-arg=-Tlinkall.x",
# "-C", "linker=rust-lld",
]

[env]
ESP_LOG = "info"

[unstable]
build-std = ["alloc", "core"]
36 changes: 36 additions & 0 deletions qa-test/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
[package]
name = "qa-test"
version = "0.0.0"
edition = "2021"
license = "MIT OR Apache-2.0"
publish = false

[dependencies]
cfg-if = "1.0.0"
embassy-executor = { version = "0.6.0", features = ["task-arena-size-12288"] }
embassy-time = "0.3.2"
embedded-graphics = "0.8.1"
embedded-hal-async = "1.0.0"
esp-alloc = { path = "../esp-alloc" }
esp-backtrace = { path = "../esp-backtrace", features = ["exception-handler", "panic-handler", "println"] }
esp-hal = { path = "../esp-hal" }
esp-hal-embassy = { path = "../esp-hal-embassy" }
esp-println = { path = "../esp-println", features = ["log"] }
lis3dh-async = "0.9.3"
ssd1306 = "0.8.4"

[features]
esp32 = ["esp-backtrace/esp32", "esp-hal/esp32", "esp-hal-embassy/esp32", "esp-println/esp32"]
esp32c2 = ["esp-backtrace/esp32c2", "esp-hal/esp32c2", "esp-hal-embassy/esp32c2", "esp-println/esp32c2"]
esp32c3 = ["esp-backtrace/esp32c3", "esp-hal/esp32c3", "esp-hal-embassy/esp32c3", "esp-println/esp32c3"]
esp32c6 = ["esp-backtrace/esp32c6", "esp-hal/esp32c6", "esp-hal-embassy/esp32c6", "esp-println/esp32c6"]
esp32h2 = ["esp-backtrace/esp32h2", "esp-hal/esp32h2", "esp-hal-embassy/esp32h2", "esp-println/esp32h2"]
esp32s2 = ["esp-backtrace/esp32s2", "esp-hal/esp32s2", "esp-hal-embassy/esp32s2", "esp-println/esp32s2"]
esp32s3 = ["esp-backtrace/esp32s3", "esp-hal/esp32s3", "esp-hal-embassy/esp32s3", "esp-println/esp32s3"]

embassy-generic-timers = ["embassy-time/generic-queue-8"]

[profile.release]
debug = 2
lto = "fat"
codegen-units = 1
58 changes: 58 additions & 0 deletions qa-test/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# `qa-test`

This package contains a number of binary applications intended for manual/quality-assurance testing.

Each device has its own unique set of peripherals, and as such not every test will run on every device. We recommend building and flashing the tests using the `xtask` method documented below, which will greatly simplify the process.

To check if a device is compatible with a given test, check the metadata comments above the imports, which will list all supported devices following the `//% CHIPS:` designator. If this metadata is not present, then the test will work on any device supported by `esp-hal`.

As previously stated, we use the [cargo-xtask] pattern for automation. Commands invoking this tool must be run from the root of the repository.

[cargo-xtask]: https://github.com/matklad/cargo-xtask

## Building Tests

You can build all examples for a given device using the `build-examples` subcommand:

```shell
cargo xtask build-examples qa-test esp32
```

Note that we must specify which package to build the tests for, since this repository contains multiple packages.

## Running Tests

You can also build and then subsequently flash and run an test using the `run-example` subcommand. With a target device connected to your host system, run:

```shell
cargo xtask run-example qa-test esp32c6 hello_world
```

Again, note that we must specify which package to build the test from, plus which test to build and flash to the target device.

## Adding Tests

If you are contributing to `esp-hal` and would like to add an test, the process is generally the same as any other project.

One major difference in our case is the metadata comments which state the compatible devices and required features for an test. Both of these designators are optional; if `//% CHIPS:` is omitted then all devices considered to be supported, and if `//% FEATURES:` is omitted then no features are enabled at build time.

To demonstrated, in `src/bin/embassy_hello_world.rs` you will see the following:

```rust
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
//% FEATURES: embassy esp-hal-embassy/integrated-timers
```

Another thing to be aware of is the GPIO pins being used. We have tried to use pins available the DevKit-C boards from Espressif, however this is being done on a best-effort basis.

In general, the following GPIO are recommended for use, though be conscious of whether certain pins are used for UART, strapping pins, etc. on some devices:

- GPIO0
- GPIO1
- GPIO2
- GPIO3
- GPIO4
- GPIO5
- GPIO8
- GPIO9
- GPIO10
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
//! - SCL => GPIO5
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
//% FEATURES: embassy embassy-generic-timers
//% FEATURES: embassy-generic-timers

#![no_std]
#![no_main]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
//! Embassy "async" version of ead calibration data from BMP180 sensor
//!
//! This example dumps the calibration data from a BMP180 sensor by reading by reading
//! with the direct I2C API and the embedded-hal-async I2C API.
//! This example dumps the calibration data from a BMP180 sensor by reading by
//! reading with the direct I2C API and the embedded-hal-async I2C API.
//!
//! Following pins are used:
//! - SDA => GPIO4
//! - SCL => GPIO5
//!
//! Depending on your target and the board you are using you have to change the
//! pins.
//!
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
//% FEATURES: embassy embassy-generic-timers
//% FEATURES: embassy-generic-timers

#![no_std]
#![no_main]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
//! | XSMT | +3V3 |
//% CHIPS: esp32 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
//% FEATURES: embassy embassy-generic-timers
//% FEATURES: embassy-generic-timers

#![no_std]
#![no_main]
Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
//! Drives the camera on a Freenove ESP32-S3 WROOM (also works as is on the ESP32S3-EYE)
//! Drives the camera on a Freenove ESP32-S3 WROOM (also works as is on the
//! ESP32S3-EYE)
//!
//! This example reads a JPEG from an OV2640 and writes it to the console as hex.
//! This example reads a JPEG from an OV2640 and writes it to the console as
//! hex.
//!
//! The following wiring is assumed:
//! - SIOD => GPIO4
Expand Down Expand Up @@ -108,8 +110,8 @@ fn main() -> ! {
let mut transfer = camera.receive(dma_rx_buf).map_err(|e| e.0).unwrap();

// Skip the first 2 images. Each image ends with an EOF.
// We likely missed the first few bytes of the first image and the second image is likely
// garbage from the OV2640 focusing, calibrating, etc.
// We likely missed the first few bytes of the first image and the second image
// is likely garbage from the OV2640 focusing, calibrating, etc.
// Feel free to skip more images if the one captured below is still garbage.
for _ in 0..2 {
let mut total_bytes = 0;
Expand Down
19 changes: 11 additions & 8 deletions examples/src/bin/lcd_i8080.rs → qa-test/src/bin/lcd_i8080.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,11 @@ fn main() -> ! {
)
.with_ctrl_pins(lcd_rs, lcd_wr);

// Note: This isn't provided in the HAL since different drivers may require different
// considerations, like how to manage the CS pin, the CD pin, cancellation semantics,
// 8 vs 16 bit, non-native primitives like Rgb565, Rgb888, etc. This Bus is just provided as
// an example of how to implement your own.
// Note: This isn't provided in the HAL since different drivers may require
// different considerations, like how to manage the CS pin, the CD pin,
// cancellation semantics, 8 vs 16 bit, non-native primitives like Rgb565,
// Rgb888, etc. This Bus is just provided as an example of how to implement
// your own.
struct Bus<'d> {
resources: Option<(I8080<'d, Blocking>, DmaTxBuf)>,
}
Expand Down Expand Up @@ -232,16 +233,18 @@ fn main() -> ! {
chunk.copy_from_slice(&color);
}

// Naive implementation of tear prevention. A more robust implementation would use an
// interrupt handler to start shipping out the next frame the moment the tear effect pin
// goes high. async/await would be too slow and would risk missing the inter-refresh window.
// Naive implementation of tear prevention. A more robust implementation would
// use an interrupt handler to start shipping out the next frame the
// moment the tear effect pin goes high. async/await would be too slow
// and would risk missing the inter-refresh window.
{
// Wait for display to start refreshing.
while tear_effect.is_high() {}
// Wait for display to finish refreshing.
while tear_effect.is_low() {}

// Now we have the maximum amount of time between each refresh available, for drawing.
// Now we have the maximum amount of time between each refresh
// available, for drawing.
}

let mut bytes_left_to_write = total_bytes;
Expand Down
File renamed without changes.
1 change: 1 addition & 0 deletions xtask/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ pub enum Package {
EspWifi,
Examples,
HilTest,
QaTest,
XtensaLx,
XtensaLxRt,
}
Expand Down
6 changes: 3 additions & 3 deletions xtask/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ fn examples(workspace: &Path, mut args: ExampleArgs, action: CargoAction) -> Res
let package_path = xtask::windows_safe_path(&workspace.join(args.package.to_string()));

let example_path = match args.package {
Package::Examples => package_path.join("src").join("bin"),
Package::Examples | Package::QaTest => package_path.join("src").join("bin"),
Package::HilTest => package_path.join("tests"),
_ => package_path.join("examples"),
};
Expand Down Expand Up @@ -749,7 +749,7 @@ fn lint_packages(workspace: &Path, args: LintPackagesArgs) -> Result<()> {

// We will *not* check the following packages with `clippy`; this
// may or may not change in the future:
Package::Examples | Package::HilTest => {}
Package::Examples | Package::HilTest | Package::QaTest => {}

// By default, no `clippy` arguments are required:
_ => lint_package(&path, &[], args.fix)?,
Expand Down Expand Up @@ -788,7 +788,7 @@ fn publish(workspace: &Path, args: PublishArgs) -> Result<()> {

use Package::*;
let mut publish_args = match args.package {
Examples | HilTest => {
Examples | HilTest | QaTest => {
bail!(
"Invalid package '{}' specified, this package should not be published!",
args.package
Expand Down

0 comments on commit 2472e36

Please sign in to comment.