diff --git a/.github/actions/check-esp-hal/action.yml b/.github/actions/check-esp-hal/action.yml index 65991955d29..eb5c84e585f 100644 --- a/.github/actions/check-esp-hal/action.yml +++ b/.github/actions/check-esp-hal/action.yml @@ -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 diff --git a/Cargo.toml b/Cargo.toml index 7186091d691..252e2eeda50 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,6 +21,7 @@ exclude = [ "extras/esp-wifishark", "extras/ieee802154-sniffer", "hil-test", + "qa-test", "xtensa-lx", "xtensa-lx-rt", "xtensa-lx-rt/procmacros", diff --git a/examples/Cargo.toml b/examples/Cargo.toml index d8751a2f2aa..5972c6a3b8b 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -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" @@ -37,7 +36,6 @@ 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 } @@ -45,7 +43,6 @@ 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" diff --git a/qa-test/.cargo/config.toml b/qa-test/.cargo/config.toml new file mode 100644 index 00000000000..8604b2d399e --- /dev/null +++ b/qa-test/.cargo/config.toml @@ -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"] diff --git a/qa-test/Cargo.toml b/qa-test/Cargo.toml new file mode 100644 index 00000000000..8de3da62ec6 --- /dev/null +++ b/qa-test/Cargo.toml @@ -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 diff --git a/qa-test/README.md b/qa-test/README.md new file mode 100644 index 00000000000..85b4b0ccdff --- /dev/null +++ b/qa-test/README.md @@ -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 diff --git a/examples/src/bin/embassy_i2c.rs b/qa-test/src/bin/embassy_i2c.rs similarity index 96% rename from examples/src/bin/embassy_i2c.rs rename to qa-test/src/bin/embassy_i2c.rs index 2b7f467ee53..e48f903944c 100644 --- a/examples/src/bin/embassy_i2c.rs +++ b/qa-test/src/bin/embassy_i2c.rs @@ -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] diff --git a/examples/src/bin/embassy_i2c_bmp180_calibration_data.rs b/qa-test/src/bin/embassy_i2c_bmp180_calibration_data.rs similarity index 91% rename from examples/src/bin/embassy_i2c_bmp180_calibration_data.rs rename to qa-test/src/bin/embassy_i2c_bmp180_calibration_data.rs index 1f7ff1525af..328ee3aa7b4 100644 --- a/examples/src/bin/embassy_i2c_bmp180_calibration_data.rs +++ b/qa-test/src/bin/embassy_i2c_bmp180_calibration_data.rs @@ -1,7 +1,7 @@ //! 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 @@ -9,10 +9,9 @@ //! //! 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] diff --git a/examples/src/bin/embassy_i2s_sound.rs b/qa-test/src/bin/embassy_i2s_sound.rs similarity index 98% rename from examples/src/bin/embassy_i2s_sound.rs rename to qa-test/src/bin/embassy_i2s_sound.rs index fd06eff7a00..05c1040c294 100644 --- a/examples/src/bin/embassy_i2s_sound.rs +++ b/qa-test/src/bin/embassy_i2s_sound.rs @@ -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] diff --git a/examples/src/bin/i2c_bmp180_calibration_data.rs b/qa-test/src/bin/i2c_bmp180_calibration_data.rs similarity index 100% rename from examples/src/bin/i2c_bmp180_calibration_data.rs rename to qa-test/src/bin/i2c_bmp180_calibration_data.rs diff --git a/examples/src/bin/i2c_display.rs b/qa-test/src/bin/i2c_display.rs similarity index 100% rename from examples/src/bin/i2c_display.rs rename to qa-test/src/bin/i2c_display.rs diff --git a/examples/src/bin/i2s_sound.rs b/qa-test/src/bin/i2s_sound.rs similarity index 100% rename from examples/src/bin/i2s_sound.rs rename to qa-test/src/bin/i2s_sound.rs diff --git a/examples/src/bin/lcd_cam_ov2640.rs b/qa-test/src/bin/lcd_cam_ov2640.rs similarity index 98% rename from examples/src/bin/lcd_cam_ov2640.rs rename to qa-test/src/bin/lcd_cam_ov2640.rs index 4a419a5d3f2..798b8bf1eed 100644 --- a/examples/src/bin/lcd_cam_ov2640.rs +++ b/qa-test/src/bin/lcd_cam_ov2640.rs @@ -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 @@ -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; diff --git a/examples/src/bin/lcd_i8080.rs b/qa-test/src/bin/lcd_i8080.rs similarity index 93% rename from examples/src/bin/lcd_i8080.rs rename to qa-test/src/bin/lcd_i8080.rs index 749c5a546ee..1e7b1dc3e92 100644 --- a/examples/src/bin/lcd_i8080.rs +++ b/qa-test/src/bin/lcd_i8080.rs @@ -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)>, } @@ -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; diff --git a/examples/src/bin/qspi_flash.rs b/qa-test/src/bin/qspi_flash.rs similarity index 100% rename from examples/src/bin/qspi_flash.rs rename to qa-test/src/bin/qspi_flash.rs diff --git a/examples/src/bin/spi_halfduplex_read_manufacturer_id.rs b/qa-test/src/bin/spi_halfduplex_read_manufacturer_id.rs similarity index 100% rename from examples/src/bin/spi_halfduplex_read_manufacturer_id.rs rename to qa-test/src/bin/spi_halfduplex_read_manufacturer_id.rs diff --git a/xtask/src/lib.rs b/xtask/src/lib.rs index a6cb19f5ecc..44402fb26cf 100644 --- a/xtask/src/lib.rs +++ b/xtask/src/lib.rs @@ -49,6 +49,7 @@ pub enum Package { EspWifi, Examples, HilTest, + QaTest, XtensaLx, XtensaLxRt, } diff --git a/xtask/src/main.rs b/xtask/src/main.rs index e38c825784d..d2d7c835a1c 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -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"), }; @@ -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)?, @@ -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