Test all feature sets (#2901)
* Mark interconnect as unstable * Explicitly set unstable feature in HIL tests * WIP append feature set name to artifact * Add name to feature sets, build all combinations * Fix tests * Provide a looping executor for stable async tests * Fix usb serial jtag * Hide interconnect types
This commit is contained in:
parent
2b80e4d123
commit
848029b152
18
.github/workflows/hil.yml
vendored
18
.github/workflows/hil.yml
vendored
@ -121,26 +121,10 @@ jobs:
|
||||
- name: Build tests
|
||||
run: cargo xtask build-tests ${{ matrix.target.soc }}
|
||||
|
||||
- name: Prepare artifact
|
||||
run: |
|
||||
# Create the 'tests' directory if it doesn't exist
|
||||
mkdir -p tests
|
||||
|
||||
# Find ELF files in the specified path and move them to 'tests'
|
||||
find "hil-test/target/${{ matrix.target.rust-target }}/release/deps/" -type f -exec file {} + | \
|
||||
grep ELF | \
|
||||
awk -F: '{print $1}' | \
|
||||
xargs -I {} mv {} tests
|
||||
|
||||
# Rename files in 'tests' by removing everything after the first dash
|
||||
for file in tests/*-*; do
|
||||
base_name="$(basename "$file" | cut -d'-' -f1)"
|
||||
mv "$file" "tests/$base_name"
|
||||
done
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: tests-${{ matrix.target.soc }}
|
||||
path: /home/runner/work/esp-hal/esp-hal/tests
|
||||
path: /home/runner/work/esp-hal/esp-hal/target/tests/${{ matrix.target.soc }}
|
||||
if-no-files-found: error
|
||||
overwrite: true
|
||||
|
||||
|
||||
@ -212,6 +212,7 @@ fn disconnect_peripheral_output_from_pin(pin: &mut AnyPin, signal: gpio::OutputS
|
||||
/// A configurable input signal between a peripheral and a GPIO pin.
|
||||
///
|
||||
/// Multiple input signals can be connected to one pin.
|
||||
#[instability::unstable]
|
||||
pub struct InputSignal {
|
||||
pin: AnyPin,
|
||||
is_inverted: bool,
|
||||
@ -347,6 +348,7 @@ impl DirectInputSignal {
|
||||
/// A configurable output signal between a peripheral and a GPIO pin.
|
||||
///
|
||||
/// Multiple pins can be connected to one output signal.
|
||||
#[instability::unstable]
|
||||
pub struct OutputSignal {
|
||||
pin: AnyPin,
|
||||
is_inverted: bool,
|
||||
@ -506,6 +508,7 @@ enum InputConnectionInner {
|
||||
/// This is mainly intended for internal use, but it can be used to connect
|
||||
/// peripherals within the MCU without external hardware.
|
||||
#[derive(Clone)]
|
||||
#[doc(hidden)] // FIXME: replace with `#[unstable]` when we can mark delegated methods https://github.com/Kobzol/rust-delegate/issues/77
|
||||
pub struct InputConnection(InputConnectionInner);
|
||||
|
||||
impl Peripheral for InputConnection {
|
||||
@ -614,6 +617,7 @@ enum OutputConnectionInner {
|
||||
///
|
||||
/// This is mainly intended for internal use, but it can be used to connect
|
||||
/// peripherals within the MCU without external hardware.
|
||||
#[doc(hidden)] // FIXME: replace with `#[unstable]` when we can mark delegated methods https://github.com/Kobzol/rust-delegate/issues/77
|
||||
pub struct OutputConnection(OutputConnectionInner);
|
||||
|
||||
impl Sealed for OutputConnection {}
|
||||
|
||||
@ -79,23 +79,20 @@ use crate::{
|
||||
private::{self, Sealed},
|
||||
};
|
||||
|
||||
pub mod interconnect;
|
||||
mod placeholder;
|
||||
|
||||
pub use placeholder::NoPin;
|
||||
|
||||
#[cfg(soc_etm)]
|
||||
crate::unstable_module! {
|
||||
pub mod interconnect;
|
||||
|
||||
#[cfg(soc_etm)]
|
||||
pub mod etm;
|
||||
}
|
||||
|
||||
#[cfg(lp_io)]
|
||||
crate::unstable_module! {
|
||||
pub mod lp_io;
|
||||
}
|
||||
|
||||
#[cfg(all(rtc_io, not(esp32)))]
|
||||
crate::unstable_module! {
|
||||
pub mod rtc_io;
|
||||
}
|
||||
|
||||
@ -820,6 +817,7 @@ where
|
||||
///
|
||||
/// Peripheral signals allow connecting peripherals together without using
|
||||
/// external hardware.
|
||||
#[instability::unstable]
|
||||
pub fn split(self) -> (interconnect::InputSignal, interconnect::OutputSignal) {
|
||||
(
|
||||
interconnect::InputSignal::new(self.degrade_pin(private::Internal)),
|
||||
@ -1296,6 +1294,8 @@ impl<'d> Output<'d> {
|
||||
///
|
||||
/// Peripheral signals allow connecting peripherals together without using
|
||||
/// external hardware.
|
||||
#[inline]
|
||||
#[instability::unstable]
|
||||
pub fn split(self) -> (interconnect::InputSignal, interconnect::OutputSignal) {
|
||||
self.pin.split()
|
||||
}
|
||||
@ -1305,6 +1305,7 @@ impl<'d> Output<'d> {
|
||||
///
|
||||
/// The input signal can be passed to peripherals in place of an input pin.
|
||||
#[inline]
|
||||
#[instability::unstable]
|
||||
pub fn peripheral_input(&self) -> interconnect::InputSignal {
|
||||
self.pin.peripheral_input()
|
||||
}
|
||||
@ -1315,6 +1316,7 @@ impl<'d> Output<'d> {
|
||||
/// The output signal can be passed to peripherals in place of an output
|
||||
/// pin.
|
||||
#[inline]
|
||||
#[instability::unstable]
|
||||
pub fn into_peripheral_output(self) -> interconnect::OutputSignal {
|
||||
self.pin.into_peripheral_output()
|
||||
}
|
||||
@ -1439,6 +1441,7 @@ impl<'d> Input<'d> {
|
||||
///
|
||||
/// The input signal can be passed to peripherals in place of an input pin.
|
||||
#[inline]
|
||||
#[instability::unstable]
|
||||
pub fn peripheral_input(&self) -> interconnect::InputSignal {
|
||||
self.pin.peripheral_input()
|
||||
}
|
||||
@ -1565,6 +1568,8 @@ impl<'d> Input<'d> {
|
||||
///
|
||||
/// Peripheral signals allow connecting peripherals together without using
|
||||
/// external hardware.
|
||||
#[inline]
|
||||
#[instability::unstable]
|
||||
pub fn split(self) -> (interconnect::InputSignal, interconnect::OutputSignal) {
|
||||
self.pin.split()
|
||||
}
|
||||
@ -1575,6 +1580,7 @@ impl<'d> Input<'d> {
|
||||
/// The output signal can be passed to peripherals in place of an output
|
||||
/// pin.
|
||||
#[inline]
|
||||
#[instability::unstable]
|
||||
pub fn into_peripheral_output(self) -> interconnect::OutputSignal {
|
||||
self.pin.into_peripheral_output()
|
||||
}
|
||||
@ -1654,6 +1660,8 @@ impl<'d> OutputOpenDrain<'d> {
|
||||
///
|
||||
/// Peripheral signals allow connecting peripherals together without using
|
||||
/// external hardware.
|
||||
#[inline]
|
||||
#[instability::unstable]
|
||||
pub fn split(self) -> (interconnect::InputSignal, interconnect::OutputSignal) {
|
||||
self.pin.split()
|
||||
}
|
||||
@ -1663,6 +1671,7 @@ impl<'d> OutputOpenDrain<'d> {
|
||||
///
|
||||
/// The input signal can be passed to peripherals in place of an input pin.
|
||||
#[inline]
|
||||
#[instability::unstable]
|
||||
pub fn peripheral_input(&self) -> interconnect::InputSignal {
|
||||
self.pin.peripheral_input()
|
||||
}
|
||||
@ -1673,6 +1682,7 @@ impl<'d> OutputOpenDrain<'d> {
|
||||
/// The output signal can be passed to peripherals in place of an output
|
||||
/// pin.
|
||||
#[inline]
|
||||
#[instability::unstable]
|
||||
pub fn into_peripheral_output(self) -> interconnect::OutputSignal {
|
||||
self.pin.into_peripheral_output()
|
||||
}
|
||||
@ -1797,6 +1807,7 @@ impl<'d> Flex<'d> {
|
||||
///
|
||||
/// The input signal can be passed to peripherals in place of an input pin.
|
||||
#[inline]
|
||||
#[instability::unstable]
|
||||
pub fn peripheral_input(&self) -> interconnect::InputSignal {
|
||||
self.pin.degrade_pin(private::Internal).split().0
|
||||
}
|
||||
@ -1963,6 +1974,8 @@ impl<'d> Flex<'d> {
|
||||
///
|
||||
/// Peripheral signals allow connecting peripherals together without using
|
||||
/// external hardware.
|
||||
#[inline]
|
||||
#[instability::unstable]
|
||||
pub fn split(self) -> (interconnect::InputSignal, interconnect::OutputSignal) {
|
||||
assert!(self.pin.is_output());
|
||||
self.pin.degrade_pin(private::Internal).split()
|
||||
@ -1974,6 +1987,7 @@ impl<'d> Flex<'d> {
|
||||
/// The output signal can be passed to peripherals in place of an output
|
||||
/// pin.
|
||||
#[inline]
|
||||
#[instability::unstable]
|
||||
pub fn into_peripheral_output(self) -> interconnect::OutputSignal {
|
||||
self.split().1
|
||||
}
|
||||
@ -2028,6 +2042,7 @@ pub(crate) mod internal {
|
||||
/// using external hardware.
|
||||
#[inline]
|
||||
#[allow(unused_braces, reason = "False positive")]
|
||||
#[instability::unstable]
|
||||
pub fn split(self) -> (interconnect::InputSignal, interconnect::OutputSignal) {
|
||||
handle_gpio_input!(self, target, { target.split() })
|
||||
}
|
||||
|
||||
@ -197,6 +197,7 @@ cfg-if = "1.0.0"
|
||||
critical-section = "1.1.3"
|
||||
defmt = "0.3.8"
|
||||
defmt-rtt = { version = "0.4.1", optional = true }
|
||||
embassy-executor = "0.6.0"
|
||||
embassy-futures = "0.1.1"
|
||||
embassy-sync = "0.6.0"
|
||||
embassy-time = "0.3.2"
|
||||
@ -206,7 +207,7 @@ embedded-hal-async = "1.0.0"
|
||||
embedded-hal-nb = "1.0.0"
|
||||
esp-alloc = { path = "../esp-alloc", optional = true }
|
||||
esp-backtrace = { path = "../esp-backtrace", default-features = false, features = ["exception-handler", "defmt", "semihosting"] }
|
||||
esp-hal = { path = "../esp-hal", features = ["digest", "unstable"], optional = true }
|
||||
esp-hal = { path = "../esp-hal", features = ["digest"], optional = true }
|
||||
esp-hal-embassy = { path = "../esp-hal-embassy", optional = true }
|
||||
esp-wifi = { path = "../esp-wifi", optional = true, features = ["wifi"] }
|
||||
portable-atomic = "1.9.0"
|
||||
@ -220,7 +221,7 @@ digest = { version = "0.10.7", default-features = false }
|
||||
elliptic-curve = { version = "0.13.8", default-features = false, features = ["sec1"] }
|
||||
embassy-executor = { version = "0.6.0", default-features = false }
|
||||
# Add the `embedded-test/defmt` feature for more verbose testing
|
||||
embedded-test = { version = "0.5.0", git = "https://github.com/probe-rs/embedded-test.git", rev = "7109473", default-features = false }
|
||||
embedded-test = { version = "0.5.0", git = "https://github.com/probe-rs/embedded-test.git", rev = "7109473", default-features = false, features = ["embassy", "external-executor"] }
|
||||
fugit = "0.3.7"
|
||||
hex-literal = "0.4.1"
|
||||
nb = "1.1.0"
|
||||
@ -234,7 +235,8 @@ esp-build = { path = "../esp-build" }
|
||||
esp-metadata = { path = "../esp-metadata" }
|
||||
|
||||
[features]
|
||||
default = ["embassy"]
|
||||
default = []
|
||||
unstable = ["esp-hal/unstable"]
|
||||
|
||||
defmt = ["dep:defmt-rtt", "esp-hal/defmt", "embedded-test/defmt"]
|
||||
|
||||
@ -286,14 +288,14 @@ esp32s3 = [
|
||||
]
|
||||
# Async & Embassy:
|
||||
embassy = [
|
||||
"embedded-test/embassy",
|
||||
"embedded-test/external-executor",
|
||||
"dep:esp-hal-embassy",
|
||||
]
|
||||
generic-queue = [
|
||||
"embassy",
|
||||
"embassy-time/generic-queue-64"
|
||||
]
|
||||
integrated-timers = [
|
||||
"embassy",
|
||||
"esp-hal-embassy/integrated-timers",
|
||||
]
|
||||
octal-psram = ["esp-hal/octal-psram", "esp-alloc"]
|
||||
|
||||
@ -82,3 +82,42 @@ macro_rules! unconnected_pin {
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
// A simple looping executor to test async code without esp-hal-embassy (which
|
||||
// needs `esp-hal/unstable`).
|
||||
#[cfg(not(feature = "embassy"))]
|
||||
mod executor {
|
||||
use core::marker::PhantomData;
|
||||
|
||||
use embassy_executor::{raw, Spawner};
|
||||
|
||||
#[export_name = "__pender"]
|
||||
fn __pender(_: *mut ()) {}
|
||||
|
||||
pub struct Executor {
|
||||
inner: raw::Executor,
|
||||
not_send: PhantomData<*mut ()>,
|
||||
}
|
||||
|
||||
impl Executor {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
inner: raw::Executor::new(core::ptr::null_mut()),
|
||||
not_send: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run(&'static mut self, init: impl FnOnce(Spawner)) -> ! {
|
||||
init(self.inner.spawner());
|
||||
|
||||
loop {
|
||||
unsafe { self.inner.poll() };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "embassy")]
|
||||
pub use esp_hal_embassy::Executor;
|
||||
#[cfg(not(feature = "embassy"))]
|
||||
pub use executor::Executor;
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
//! AES Test
|
||||
|
||||
//% CHIPS: esp32 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
||||
//% FEATURES: unstable
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
//! AES DMA Test
|
||||
|
||||
//% CHIPS: esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
||||
//% FEATURES: unstable
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
//! Clock Monitor Test
|
||||
|
||||
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
||||
//% FEATURES: unstable
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
//! CRC and MD5 Tests
|
||||
|
||||
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
||||
//% FEATURES: unstable
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
//! Ensure invariants of locks are upheld.
|
||||
|
||||
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
||||
//% FEATURES: unstable
|
||||
|
||||
// TODO: add multi-core tests
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
//! Delay Test
|
||||
|
||||
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
||||
//% FEATURES: unstable
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
//! `embedded_hal_async::delay::DelayNs` trait.
|
||||
|
||||
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
||||
//% FEATURES: unstable
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
@ -69,7 +70,7 @@ async fn test_async_delay_ms(mut timer: impl DelayNs, duration: u32) {
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[embedded_test::tests(default_timeout = 2, executor = esp_hal_embassy::Executor::new())]
|
||||
#[embedded_test::tests(default_timeout = 2, executor = hil_test::Executor::new())]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
//! DMA macro tests
|
||||
|
||||
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
||||
//% FEATURES: unstable
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
//! DMA Mem2Mem Tests
|
||||
|
||||
//% CHIPS: esp32c2 esp32c3 esp32c6 esp32h2 esp32s3
|
||||
//% FEATURES: unstable
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
//! ECC Test
|
||||
|
||||
//% CHIPS: esp32c2 esp32c6 esp32h2
|
||||
//% FEATURES: unstable
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
@ -2,8 +2,8 @@
|
||||
//! code.
|
||||
|
||||
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
||||
//% FEATURES: integrated-timers
|
||||
//% FEATURES: generic-queue
|
||||
//% FEATURES(integrated): unstable embassy integrated-timers
|
||||
//% FEATURES(generic): unstable embassy generic-queue
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
@ -48,7 +48,7 @@ struct Context {
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[embedded_test::tests(default_timeout = 3, executor = esp_hal_embassy::Executor::new())]
|
||||
#[embedded_test::tests(default_timeout = 3, executor = hil_test::Executor::new())]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
//! Reproduction and regression test for a sneaky issue.
|
||||
|
||||
//% CHIPS: esp32 esp32s2 esp32s3 esp32c3 esp32c6 esp32h2
|
||||
//% FEATURES: integrated-timers
|
||||
//% FEATURES: generic-queue
|
||||
//% FEATURES(integrated): unstable embassy integrated-timers
|
||||
//% FEATURES(generic): unstable embassy generic-queue
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
@ -75,7 +75,7 @@ async fn interrupt_driven_task(mut i2s_tx: esp_hal::i2s::master::I2sTx<'static,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[embedded_test::tests(default_timeout = 3, executor = esp_hal_embassy::Executor::new())]
|
||||
#[embedded_test::tests(default_timeout = 3, executor = hil_test::Executor::new())]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
//! Embassy timer and executor Test
|
||||
|
||||
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
||||
//% FEATURES: integrated-timers
|
||||
//% FEATURES: generic-queue
|
||||
//% FEATURES(integrated): unstable embassy integrated-timers
|
||||
//% FEATURES(generic): unstable embassy generic-queue
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
@ -122,7 +122,7 @@ fn set_up_embassy_with_systimer(peripherals: Peripherals) {
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[embedded_test::tests(default_timeout = 3, executor = esp_hal_embassy::Executor::new())]
|
||||
#[embedded_test::tests(default_timeout = 3, executor = hil_test::Executor::new())]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::test_cases::*;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
//! Cp0Disable exception regression test
|
||||
|
||||
//% CHIPS: esp32 esp32s2 esp32s3
|
||||
//% FEATURES: esp-wifi esp-alloc
|
||||
//% FEATURES: unstable esp-wifi esp-alloc
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
//! time::now Test
|
||||
|
||||
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
||||
//% FEATURES: unstable
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
//! GPIO Test
|
||||
|
||||
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
||||
//% FEATURES: generic-queue
|
||||
//% FEATURES: unstable embassy generic-queue
|
||||
//% FEATURES(stable):
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
@ -9,14 +10,22 @@
|
||||
use core::cell::RefCell;
|
||||
|
||||
use critical_section::Mutex;
|
||||
#[cfg(feature = "unstable")]
|
||||
use embassy_time::{Duration, Timer};
|
||||
use esp_hal::{
|
||||
delay::Delay,
|
||||
gpio::{AnyPin, Input, Io, Level, Output, Pin, Pull},
|
||||
interrupt::InterruptConfigurable,
|
||||
gpio::{AnyPin, Input, Level, Output, OutputOpenDrain, Pin, Pull},
|
||||
macros::handler,
|
||||
};
|
||||
#[cfg(feature = "unstable")]
|
||||
use esp_hal::{
|
||||
gpio::{Event, Flex, Io},
|
||||
interrupt::InterruptConfigurable,
|
||||
timer::timg::TimerGroup,
|
||||
};
|
||||
use hil_test as _;
|
||||
#[cfg(feature = "unstable")]
|
||||
use portable_atomic::{AtomicUsize, Ordering};
|
||||
|
||||
static COUNTER: Mutex<RefCell<u32>> = Mutex::new(RefCell::new(0));
|
||||
static INPUT_PIN: Mutex<RefCell<Option<Input>>> = Mutex::new(RefCell::new(None));
|
||||
@ -39,27 +48,28 @@ pub fn interrupt_handler() {
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[embedded_test::tests(default_timeout = 3, executor = esp_hal_embassy::Executor::new())]
|
||||
#[embedded_test::tests(default_timeout = 3, executor = hil_test::Executor::new())]
|
||||
mod tests {
|
||||
use embassy_time::{Duration, Timer};
|
||||
use esp_hal::gpio::{Event, Flex, OutputOpenDrain};
|
||||
use portable_atomic::{AtomicUsize, Ordering};
|
||||
|
||||
use super::*;
|
||||
|
||||
#[init]
|
||||
fn init() -> Context {
|
||||
let peripherals = esp_hal::init(esp_hal::Config::default());
|
||||
|
||||
let mut io = Io::new(peripherals.IO_MUX);
|
||||
io.set_interrupt_handler(interrupt_handler);
|
||||
|
||||
let delay = Delay::new();
|
||||
|
||||
let (gpio1, gpio2) = hil_test::common_test_pins!(peripherals);
|
||||
|
||||
#[cfg(feature = "unstable")]
|
||||
{
|
||||
// Interrupts are unstable
|
||||
let mut io = Io::new(peripherals.IO_MUX);
|
||||
io.set_interrupt_handler(interrupt_handler);
|
||||
|
||||
// Timers are unstable
|
||||
let timg0 = TimerGroup::new(peripherals.TIMG0);
|
||||
esp_hal_embassy::init(timg0.timer0);
|
||||
}
|
||||
|
||||
Context {
|
||||
test_gpio1: gpio1.degrade(),
|
||||
@ -69,6 +79,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "unstable")] // Timers are unstable
|
||||
async fn async_edge(ctx: Context) {
|
||||
let counter = AtomicUsize::new(0);
|
||||
let Context {
|
||||
@ -147,53 +158,6 @@ mod tests {
|
||||
assert_eq!(test_gpio2.is_set_high(), true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gpio_output_embedded_hal_0_2(ctx: Context) {
|
||||
let test_gpio1 = Input::new(ctx.test_gpio1, Pull::Down);
|
||||
let mut test_gpio2 = Output::new(ctx.test_gpio2, Level::Low);
|
||||
|
||||
fn set<T>(pin: &mut T, state: bool)
|
||||
where
|
||||
T: embedded_hal::digital::OutputPin,
|
||||
{
|
||||
if state {
|
||||
pin.set_high().ok();
|
||||
} else {
|
||||
pin.set_low().ok();
|
||||
}
|
||||
}
|
||||
|
||||
fn toggle<T>(pin: &mut T)
|
||||
where
|
||||
T: embedded_hal::digital::StatefulOutputPin,
|
||||
{
|
||||
pin.toggle().ok();
|
||||
}
|
||||
|
||||
// `StatefulOutputPin`:
|
||||
assert_eq!(test_gpio2.is_set_low(), true);
|
||||
assert_eq!(test_gpio2.is_set_high(), false);
|
||||
assert_eq!(test_gpio1.is_low(), true);
|
||||
assert_eq!(test_gpio1.is_high(), false);
|
||||
set(&mut test_gpio2, true);
|
||||
assert_eq!(test_gpio2.is_set_low(), false);
|
||||
assert_eq!(test_gpio2.is_set_high(), true);
|
||||
assert_eq!(test_gpio1.is_low(), false);
|
||||
assert_eq!(test_gpio1.is_high(), true);
|
||||
|
||||
// `ToggleableOutputPin`:
|
||||
toggle(&mut test_gpio2);
|
||||
assert_eq!(test_gpio2.is_set_low(), true);
|
||||
assert_eq!(test_gpio2.is_set_high(), false);
|
||||
assert_eq!(test_gpio1.is_low(), true);
|
||||
assert_eq!(test_gpio1.is_high(), false);
|
||||
toggle(&mut test_gpio2);
|
||||
assert_eq!(test_gpio2.is_set_low(), false);
|
||||
assert_eq!(test_gpio2.is_set_high(), true);
|
||||
assert_eq!(test_gpio1.is_low(), false);
|
||||
assert_eq!(test_gpio1.is_high(), true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gpio_output_embedded_hal_1_0(ctx: Context) {
|
||||
let test_gpio1 = Input::new(ctx.test_gpio1, Pull::Down);
|
||||
@ -242,6 +206,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "unstable")] // Interrupts are unstable
|
||||
fn gpio_interrupt(ctx: Context) {
|
||||
let mut test_gpio1 = Input::new(ctx.test_gpio1, Pull::Down);
|
||||
let mut test_gpio2 = Output::new(ctx.test_gpio2, Level::Low);
|
||||
@ -325,6 +290,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "unstable")]
|
||||
fn gpio_flex(ctx: Context) {
|
||||
let mut test_gpio1 = Flex::new(ctx.test_gpio1);
|
||||
let mut test_gpio2 = Flex::new(ctx.test_gpio2);
|
||||
@ -401,6 +367,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "unstable")]
|
||||
fn interrupt_executor_is_not_frozen(ctx: Context) {
|
||||
use esp_hal::interrupt::{software::SoftwareInterrupt, Priority};
|
||||
use esp_hal_embassy::InterruptExecutor;
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
//! async API works for user handlers automatically.
|
||||
|
||||
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
||||
//% FEATURES: integrated-timers
|
||||
//% FEATURES: unstable integrated-timers
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
@ -66,7 +66,7 @@ async fn drive_pins(gpio1: impl Into<AnyPin>, gpio2: impl Into<AnyPin>) -> usize
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[embedded_test::tests(executor = esp_hal_embassy::Executor::new())]
|
||||
#[embedded_test::tests(executor = hil_test::Executor::new())]
|
||||
mod tests {
|
||||
|
||||
use super::*;
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
//! I2C test
|
||||
|
||||
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
||||
//% FEATURES: unstable
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
//! with loopback mode enabled).
|
||||
|
||||
//% CHIPS: esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
||||
//% FEATURES: generic-queue
|
||||
//% FEATURES: unstable generic-queue
|
||||
// FIXME: re-enable on ESP32 when it no longer fails spuriously
|
||||
|
||||
#![no_std]
|
||||
@ -97,7 +97,7 @@ fn enable_loopback() {
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[embedded_test::tests(default_timeout = 3, executor = esp_hal_embassy::Executor::new())]
|
||||
#[embedded_test::tests(default_timeout = 3, executor = hil_test::Executor::new())]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
//! Initialization tests
|
||||
|
||||
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
||||
//% FEATURES: unstable
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
//! "Disabled" for now - see https://github.com/esp-rs/esp-hal/pull/1635#issuecomment-2137405251
|
||||
|
||||
//% CHIPS: esp32c2 esp32c3 esp32c6 esp32h2
|
||||
//% FEATURES: unstable
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
//! LCD_CAM Camera and DPI tests
|
||||
|
||||
//% CHIPS: esp32s3
|
||||
//% FEATURES: unstable
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
//! lcd_cam i8080 tests
|
||||
|
||||
//% CHIPS: esp32s3
|
||||
//% FEATURES: unstable
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
//! lcd_cam i8080 tests
|
||||
|
||||
//% CHIPS: esp32s3
|
||||
//% FEATURES: generic-queue
|
||||
//% FEATURES: unstable generic-queue
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
@ -28,7 +28,7 @@ struct Context<'d> {
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[embedded_test::tests(default_timeout = 3, executor = esp_hal_embassy::Executor::new())]
|
||||
#[embedded_test::tests(default_timeout = 3, executor = hil_test::Executor::new())]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
//! PARL_IO TX test
|
||||
|
||||
//% CHIPS: esp32c6 esp32h2
|
||||
//% FEATURES: unstable
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
//! PARL_IO TX async test
|
||||
|
||||
//% CHIPS: esp32c6 esp32h2
|
||||
//% FEATURES: generic-queue
|
||||
//% FEATURES: unstable generic-queue
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
@ -43,7 +43,7 @@ struct Context {
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[embedded_test::tests(default_timeout = 3, executor = esp_hal_embassy::Executor::new())]
|
||||
#[embedded_test::tests(default_timeout = 3, executor = hil_test::Executor::new())]
|
||||
mod tests {
|
||||
use defmt::info;
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
//! PCNT tests
|
||||
|
||||
//% CHIPS: esp32 esp32c6 esp32h2 esp32s2 esp32s3
|
||||
//% FEATURES: unstable
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
//! QSPI Test Suite
|
||||
|
||||
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
||||
//% FEATURES: unstable
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
//! RMT Loopback Test
|
||||
|
||||
//% CHIPS: esp32 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
||||
//% FEATURES: unstable
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
//! RSA Test
|
||||
|
||||
//% CHIPS: esp32 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
||||
//% FEATURES: unstable
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
//! Async RSA Test
|
||||
|
||||
//% CHIPS: esp32 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
||||
//% FEATURES: unstable
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
@ -48,7 +49,7 @@ const fn compute_mprime(modulus: &U512) -> u32 {
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[embedded_test::tests(default_timeout = 5, executor = esp_hal_embassy::Executor::new())]
|
||||
#[embedded_test::tests(default_timeout = 5, executor = hil_test::Executor::new())]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
|
||||
@ -1,19 +1,21 @@
|
||||
//! SHA Test
|
||||
|
||||
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
||||
//% FEATURES: unstable
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use digest::{Digest, Update};
|
||||
#[cfg(not(feature = "esp32"))]
|
||||
use esp_hal::clock::CpuClock;
|
||||
#[cfg(not(feature = "esp32"))]
|
||||
use esp_hal::sha::Sha224;
|
||||
#[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))]
|
||||
use esp_hal::sha::{Sha384, Sha512};
|
||||
#[cfg(any(feature = "esp32s2", feature = "esp32s3"))]
|
||||
use esp_hal::sha::{Sha512_224, Sha512_256};
|
||||
use esp_hal::{
|
||||
clock::CpuClock,
|
||||
rng::Rng,
|
||||
sha::{Sha, Sha1, Sha256, ShaAlgorithm, ShaDigest},
|
||||
};
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
//! SPI Full Duplex test suite.
|
||||
|
||||
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
||||
//% FEATURES: generic-queue
|
||||
//% FEATURES: unstable generic-queue
|
||||
|
||||
// FIXME: add async test cases that don't rely on PCNT
|
||||
|
||||
@ -48,7 +48,7 @@ struct Context {
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[embedded_test::tests(default_timeout = 3, executor = esp_hal_embassy::Executor::new())]
|
||||
#[embedded_test::tests(default_timeout = 3, executor = hil_test::Executor::new())]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
//! SPI Half Duplex Read Test
|
||||
|
||||
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
||||
//% FEATURES: unstable
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
//! SPI Half Duplex Write Test
|
||||
|
||||
//% CHIPS: esp32 esp32c6 esp32h2 esp32s2 esp32s3
|
||||
//% FEATURES: unstable
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
//! SPI Half Duplex Write Test
|
||||
//% FEATURES: octal-psram
|
||||
|
||||
//% CHIPS: esp32s3
|
||||
//% FEATURES: unstable octal-psram
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
//! testing Mode 1.
|
||||
|
||||
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
||||
//% FEATURES: unstable
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
@ -94,7 +95,7 @@ impl BitbangSpi {
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[embedded_test::tests(default_timeout = 10, executor = esp_hal_embassy::Executor::new())]
|
||||
#[embedded_test::tests(default_timeout = 10, executor = hil_test::Executor::new())]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
// esp32 disabled as it does not have a systimer
|
||||
//% CHIPS: esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
||||
//% FEATURES: unstable
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
//! TWAI test
|
||||
|
||||
//% CHIPS: esp32 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
||||
//% FEATURES: unstable
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
//! UART Test
|
||||
|
||||
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
||||
//% FEATURES: unstable
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
//! UART Test
|
||||
|
||||
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
||||
//% FEATURES: generic-queue
|
||||
//% FEATURES: unstable embassy generic-queue
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
@ -17,7 +17,7 @@ struct Context {
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[embedded_test::tests(default_timeout = 3, executor = esp_hal_embassy::Executor::new())]
|
||||
#[embedded_test::tests(default_timeout = 3, executor = hil_test::Executor::new())]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
//! Misc UART TX/RX regression tests
|
||||
|
||||
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
||||
//% FEATURES: unstable
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
//! UART TX/RX Test
|
||||
|
||||
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
||||
//% FEATURES: unstable
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
//! UART TX/RX Async Test
|
||||
|
||||
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
||||
//% FEATURES: generic-queue
|
||||
//% FEATURES: unstable generic-queue
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
@ -18,7 +18,7 @@ struct Context {
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[embedded_test::tests(default_timeout = 3, executor = esp_hal_embassy::Executor::new())]
|
||||
#[embedded_test::tests(default_timeout = 3, executor = hil_test::Executor::new())]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
//! USB Serial JTAG tests
|
||||
|
||||
//% CHIPS: esp32c3 esp32c6 esp32h2 esp32s3
|
||||
//% FEATURES: unstable
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
@ -8,16 +9,13 @@
|
||||
#[cfg(test)]
|
||||
#[embedded_test::tests(default_timeout = 3)]
|
||||
mod tests {
|
||||
use esp_hal::{timer::timg::TimerGroup, usb_serial_jtag::UsbSerialJtag};
|
||||
use esp_hal::usb_serial_jtag::UsbSerialJtag;
|
||||
use hil_test as _;
|
||||
|
||||
#[test]
|
||||
fn creating_peripheral_does_not_break_debug_connection() {
|
||||
let peripherals = esp_hal::init(esp_hal::Config::default());
|
||||
|
||||
let timg0 = TimerGroup::new(peripherals.TIMG0);
|
||||
esp_hal_embassy::init(timg0.timer0);
|
||||
|
||||
_ = UsbSerialJtag::new(peripherals.USB_DEVICE)
|
||||
.into_async()
|
||||
.split();
|
||||
|
||||
@ -17,5 +17,6 @@ log = "0.4.22"
|
||||
minijinja = "2.5.0"
|
||||
semver = { version = "1.0.23", features = ["serde"] }
|
||||
serde = { version = "1.0.215", features = ["derive"] }
|
||||
serde_json = "1.0.70"
|
||||
strum = { version = "0.26.3", features = ["derive"] }
|
||||
toml_edit = "0.22.22"
|
||||
|
||||
@ -2,27 +2,39 @@
|
||||
|
||||
use std::{
|
||||
ffi::OsStr,
|
||||
path::Path,
|
||||
path::{Path, PathBuf},
|
||||
process::{Command, Stdio},
|
||||
};
|
||||
|
||||
use anyhow::{bail, Result};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::windows_safe_path;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum CargoAction {
|
||||
Build,
|
||||
Build(PathBuf),
|
||||
Run,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Artifact {
|
||||
pub executable: PathBuf,
|
||||
}
|
||||
|
||||
/// Execute cargo with the given arguments and from the specified directory.
|
||||
pub fn run(args: &[String], cwd: &Path) -> Result<()> {
|
||||
run_with_env::<[(&str, &str); 0], _, _>(args, cwd, [])
|
||||
run_with_env::<[(&str, &str); 0], _, _>(args, cwd, [], false)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Execute cargo with the given arguments and from the specified directory.
|
||||
pub fn run_with_env<I, K, V>(args: &[String], cwd: &Path, envs: I) -> Result<()>
|
||||
pub fn run_and_capture(args: &[String], cwd: &Path) -> Result<String> {
|
||||
run_with_env::<[(&str, &str); 0], _, _>(args, cwd, [], true)
|
||||
}
|
||||
|
||||
/// Execute cargo with the given arguments and from the specified directory.
|
||||
pub fn run_with_env<I, K, V>(args: &[String], cwd: &Path, envs: I, capture: bool) -> Result<String>
|
||||
where
|
||||
I: IntoIterator<Item = (K, V)>,
|
||||
K: AsRef<OsStr>,
|
||||
@ -38,19 +50,26 @@ where
|
||||
// using now or in future!
|
||||
let cwd = windows_safe_path(cwd);
|
||||
|
||||
let status = Command::new(get_cargo())
|
||||
let output = Command::new(get_cargo())
|
||||
.args(args)
|
||||
.current_dir(cwd)
|
||||
.envs(envs)
|
||||
.stdout(Stdio::inherit())
|
||||
.stderr(Stdio::inherit())
|
||||
.stdin(Stdio::inherit())
|
||||
.status()?;
|
||||
.stdout(if capture {
|
||||
Stdio::piped()
|
||||
} else {
|
||||
Stdio::inherit()
|
||||
})
|
||||
.stderr(if capture {
|
||||
Stdio::piped()
|
||||
} else {
|
||||
Stdio::inherit()
|
||||
})
|
||||
.output()?;
|
||||
|
||||
// Make sure that we return an appropriate exit code here, as Github Actions
|
||||
// requires this in order to function correctly:
|
||||
if status.success() {
|
||||
Ok(())
|
||||
if output.status.success() {
|
||||
Ok(String::from_utf8_lossy(&output.stdout).to_string())
|
||||
} else {
|
||||
bail!("Failed to execute cargo subcommand")
|
||||
}
|
||||
@ -145,16 +164,16 @@ impl CargoArgsBuilder {
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn build(self) -> Vec<String> {
|
||||
pub fn build(&self) -> Vec<String> {
|
||||
let mut args = vec![];
|
||||
|
||||
if let Some(toolchain) = self.toolchain {
|
||||
if let Some(ref toolchain) = self.toolchain {
|
||||
args.push(format!("+{toolchain}"));
|
||||
}
|
||||
|
||||
args.push(self.subcommand);
|
||||
args.push(self.subcommand.clone());
|
||||
|
||||
if let Some(target) = self.target {
|
||||
if let Some(ref target) = self.target {
|
||||
args.push(format!("--target={target}"));
|
||||
}
|
||||
|
||||
@ -162,8 +181,8 @@ impl CargoArgsBuilder {
|
||||
args.push(format!("--features={}", self.features.join(",")));
|
||||
}
|
||||
|
||||
for arg in self.args {
|
||||
args.push(arg);
|
||||
for arg in self.args.iter() {
|
||||
args.push(arg.clone());
|
||||
}
|
||||
|
||||
args
|
||||
|
||||
104
xtask/src/lib.rs
104
xtask/src/lib.rs
@ -58,6 +58,7 @@ pub enum Package {
|
||||
pub struct Metadata {
|
||||
example_path: PathBuf,
|
||||
chip: Chip,
|
||||
feature_set_name: String,
|
||||
feature_set: Vec<String>,
|
||||
tag: Option<String>,
|
||||
description: Option<String>,
|
||||
@ -67,6 +68,7 @@ impl Metadata {
|
||||
pub fn new(
|
||||
example_path: &Path,
|
||||
chip: Chip,
|
||||
feature_set_name: String,
|
||||
feature_set: Vec<String>,
|
||||
tag: Option<String>,
|
||||
description: Option<String>,
|
||||
@ -74,6 +76,7 @@ impl Metadata {
|
||||
Self {
|
||||
example_path: example_path.to_path_buf(),
|
||||
chip,
|
||||
feature_set_name,
|
||||
feature_set,
|
||||
tag,
|
||||
description,
|
||||
@ -161,6 +164,7 @@ pub fn build_documentation(workspace: &Path, package: Package, chip: Chip) -> Re
|
||||
&args,
|
||||
&package_path,
|
||||
[("RUSTDOCFLAGS", "--cfg docsrs --cfg not_really_docsrs")],
|
||||
false,
|
||||
)?;
|
||||
|
||||
let docs_path = windows_safe_path(
|
||||
@ -212,7 +216,7 @@ fn apply_feature_rules(package: &Package, config: &Config) -> Vec<String> {
|
||||
}
|
||||
|
||||
/// Load all examples at the given path, and parse their metadata.
|
||||
pub fn load_examples(path: &Path, action: CargoAction) -> Result<Vec<Metadata>> {
|
||||
pub fn load_examples(path: &Path) -> Result<Vec<Metadata>> {
|
||||
let mut examples = Vec::new();
|
||||
|
||||
for entry in fs::read_dir(path)? {
|
||||
@ -248,7 +252,7 @@ pub fn load_examples(path: &Path, action: CargoAction) -> Result<Vec<Metadata>>
|
||||
.split_ascii_whitespace()
|
||||
.map(|s| Chip::from_str(s, false).unwrap())
|
||||
.collect::<Vec<_>>();
|
||||
} else if key == "FEATURES" {
|
||||
} else if let Some(feature_set_name) = key.strip_prefix("FEATURES") {
|
||||
// Base feature set required to run the example.
|
||||
// If multiple are specified, we compile the same example multiple times.
|
||||
let mut values = value
|
||||
@ -259,7 +263,20 @@ pub fn load_examples(path: &Path, action: CargoAction) -> Result<Vec<Metadata>>
|
||||
// Sort the features so they are in a deterministic order:
|
||||
values.sort();
|
||||
|
||||
feature_sets.push(values);
|
||||
let feature_set_name = feature_set_name.trim_matches(&['(', ')']).to_string();
|
||||
|
||||
if feature_sets
|
||||
.iter()
|
||||
.any(|(name, _)| name == &feature_set_name)
|
||||
{
|
||||
bail!(
|
||||
"Duplicate feature set name '{}' in {}",
|
||||
feature_set_name,
|
||||
path.display()
|
||||
);
|
||||
}
|
||||
|
||||
feature_sets.push((feature_set_name, values));
|
||||
} else if key.starts_with("CHIP-FEATURES(") {
|
||||
// Additional features required for specific chips.
|
||||
// These are appended to the base feature set(s).
|
||||
@ -289,15 +306,10 @@ pub fn load_examples(path: &Path, action: CargoAction) -> Result<Vec<Metadata>>
|
||||
}
|
||||
|
||||
if feature_sets.is_empty() {
|
||||
feature_sets.push(Vec::new());
|
||||
feature_sets.push((String::new(), Vec::new()));
|
||||
}
|
||||
if action == CargoAction::Build {
|
||||
// Only build the first feature set for each example.
|
||||
// Rebuilding with a different feature set just wastes time because the latter
|
||||
// one will overwrite the former one(s).
|
||||
feature_sets.truncate(1);
|
||||
}
|
||||
for feature_set in feature_sets {
|
||||
|
||||
for (feature_set_name, feature_set) in feature_sets {
|
||||
for chip in &chips {
|
||||
let mut feature_set = feature_set.clone();
|
||||
if let Some(chip_features) = chip_features.get(chip) {
|
||||
@ -310,6 +322,7 @@ pub fn load_examples(path: &Path, action: CargoAction) -> Result<Vec<Metadata>>
|
||||
examples.push(Metadata::new(
|
||||
&path,
|
||||
*chip,
|
||||
feature_set_name.clone(),
|
||||
feature_set.clone(),
|
||||
tag.clone(),
|
||||
description.clone(),
|
||||
@ -331,7 +344,7 @@ pub fn execute_app(
|
||||
target: &str,
|
||||
app: &Metadata,
|
||||
action: CargoAction,
|
||||
mut repeat: usize,
|
||||
repeat: usize,
|
||||
debug: bool,
|
||||
) -> Result<()> {
|
||||
log::info!(
|
||||
@ -348,53 +361,80 @@ pub fn execute_app(
|
||||
|
||||
let package = app.example_path().strip_prefix(package_path)?;
|
||||
log::info!("Package: {}", package.display());
|
||||
let (bin, subcommand) = if action == CargoAction::Build {
|
||||
repeat = 1; // Do not repeat builds in a loop
|
||||
let bin = if package.starts_with("src/bin") {
|
||||
|
||||
let mut builder = CargoArgsBuilder::default()
|
||||
.target(target)
|
||||
.features(&features);
|
||||
|
||||
let bin_arg = if package.starts_with("src/bin") {
|
||||
format!("--bin={}", app.name())
|
||||
} else if package.starts_with("tests") {
|
||||
format!("--test={}", app.name())
|
||||
} else {
|
||||
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 {
|
||||
(format!("--example={}", app.name()), "run")
|
||||
};
|
||||
builder.add_arg(bin_arg);
|
||||
|
||||
let mut builder = CargoArgsBuilder::default()
|
||||
.subcommand(subcommand)
|
||||
.target(target)
|
||||
.features(&features)
|
||||
.arg(bin);
|
||||
let subcommand = if matches!(action, CargoAction::Build(_)) {
|
||||
"build"
|
||||
} else if package.starts_with("tests") {
|
||||
"test"
|
||||
} else {
|
||||
"run"
|
||||
};
|
||||
builder = builder.subcommand(subcommand);
|
||||
|
||||
if !debug {
|
||||
builder.add_arg("--release");
|
||||
}
|
||||
|
||||
if subcommand == "test" && chip == Chip::Esp32c2 {
|
||||
builder.add_arg("--").add_arg("--speed").add_arg("15000");
|
||||
}
|
||||
|
||||
// If targeting an Xtensa device, we must use the '+esp' toolchain modifier:
|
||||
if target.starts_with("xtensa") {
|
||||
builder = builder.toolchain("esp");
|
||||
builder.add_arg("-Zbuild-std=core,alloc");
|
||||
}
|
||||
|
||||
if subcommand == "test" && chip == Chip::Esp32c2 {
|
||||
builder.add_arg("--").add_arg("--speed").add_arg("15000");
|
||||
}
|
||||
|
||||
let args = builder.build();
|
||||
log::debug!("{args:#?}");
|
||||
|
||||
if let CargoAction::Build(out_dir) = action {
|
||||
cargo::run(&args, package_path)?;
|
||||
|
||||
// Now that the build has succeeded and we printed the output, we can
|
||||
// rerun the build again quickly enough to capture JSON. We'll use this to
|
||||
// copy the binary to the output directory.
|
||||
builder.add_arg("--message-format=json");
|
||||
let args = builder.build();
|
||||
let output = cargo::run_and_capture(&args, package_path)?;
|
||||
for line in output.lines() {
|
||||
if let Ok(artifact) = serde_json::from_str::<cargo::Artifact>(line) {
|
||||
let out_dir = out_dir.join(&chip.to_string());
|
||||
std::fs::create_dir_all(&out_dir)?;
|
||||
|
||||
let basename = app.name();
|
||||
let name = if app.feature_set_name.is_empty() {
|
||||
basename
|
||||
} else {
|
||||
format!("{}_{}", basename, app.feature_set_name)
|
||||
};
|
||||
|
||||
let output_file = out_dir.join(name);
|
||||
std::fs::copy(artifact.executable, &output_file)?;
|
||||
log::info!("Output ready: {}", output_file.display());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for i in 0..repeat {
|
||||
if repeat != 1 {
|
||||
log::info!("Run {}/{}", i + 1, repeat);
|
||||
}
|
||||
cargo::run(&args, package_path)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -181,12 +181,20 @@ fn main() -> Result<()> {
|
||||
|
||||
let workspace = std::env::current_dir()?;
|
||||
|
||||
let out_path = Path::new("target");
|
||||
|
||||
match Cli::parse() {
|
||||
Cli::BuildDocumentation(args) => build_documentation(&workspace, args),
|
||||
Cli::BuildDocumentationIndex(args) => build_documentation_index(&workspace, args),
|
||||
Cli::BuildExamples(args) => examples(&workspace, args, CargoAction::Build),
|
||||
Cli::BuildExamples(args) => examples(
|
||||
&workspace,
|
||||
args,
|
||||
CargoAction::Build(out_path.join("examples")),
|
||||
),
|
||||
Cli::BuildPackage(args) => build_package(&workspace, args),
|
||||
Cli::BuildTests(args) => tests(&workspace, args, CargoAction::Build),
|
||||
Cli::BuildTests(args) => {
|
||||
tests(&workspace, args, CargoAction::Build(out_path.join("tests")))
|
||||
}
|
||||
Cli::BumpVersion(args) => bump_version(&workspace, args),
|
||||
Cli::FmtPackages(args) => fmt_packages(&workspace, args),
|
||||
Cli::GenerateEfuseFields(args) => generate_efuse_src(&workspace, args),
|
||||
@ -227,7 +235,7 @@ fn examples(workspace: &Path, mut args: ExampleArgs, action: CargoAction) -> Res
|
||||
};
|
||||
|
||||
// Load all examples which support the specified chip and parse their metadata:
|
||||
let mut examples = xtask::load_examples(&example_path, action)?
|
||||
let mut examples = xtask::load_examples(&example_path)?
|
||||
.iter()
|
||||
.filter_map(|example| {
|
||||
if example.supports_chip(args.chip) {
|
||||
@ -243,13 +251,18 @@ fn examples(workspace: &Path, mut args: ExampleArgs, action: CargoAction) -> Res
|
||||
|
||||
// Execute the specified action:
|
||||
match action {
|
||||
CargoAction::Build => build_examples(args, examples, &package_path),
|
||||
CargoAction::Build(out_path) => build_examples(args, examples, &package_path, out_path),
|
||||
CargoAction::Run if args.example.is_some() => run_example(args, examples, &package_path),
|
||||
CargoAction::Run => run_examples(args, examples, &package_path),
|
||||
}
|
||||
}
|
||||
|
||||
fn build_examples(args: ExampleArgs, examples: Vec<Metadata>, package_path: &Path) -> Result<()> {
|
||||
fn build_examples(
|
||||
args: ExampleArgs,
|
||||
examples: Vec<Metadata>,
|
||||
package_path: &Path,
|
||||
out_path: PathBuf,
|
||||
) -> Result<()> {
|
||||
// Determine the appropriate build target for the given package and chip:
|
||||
let target = target_triple(args.package, &args.chip)?;
|
||||
|
||||
@ -265,7 +278,7 @@ fn build_examples(args: ExampleArgs, examples: Vec<Metadata>, package_path: &Pat
|
||||
args.chip,
|
||||
target,
|
||||
example,
|
||||
CargoAction::Build,
|
||||
CargoAction::Build(out_path.clone()),
|
||||
1,
|
||||
args.debug,
|
||||
)?;
|
||||
@ -282,7 +295,7 @@ fn build_examples(args: ExampleArgs, examples: Vec<Metadata>, package_path: &Pat
|
||||
args.chip,
|
||||
target,
|
||||
example,
|
||||
CargoAction::Build,
|
||||
CargoAction::Build(out_path.clone()),
|
||||
1,
|
||||
args.debug,
|
||||
)
|
||||
@ -400,7 +413,7 @@ fn tests(workspace: &Path, args: TestArgs, action: CargoAction) -> Result<()> {
|
||||
let target = target_triple(Package::HilTest, &args.chip)?;
|
||||
|
||||
// Load all tests which support the specified chip and parse their metadata:
|
||||
let mut tests = xtask::load_examples(&package_path.join("tests"), action)?
|
||||
let mut tests = xtask::load_examples(&package_path.join("tests"))?
|
||||
.into_iter()
|
||||
.filter(|example| example.supports_chip(args.chip))
|
||||
.collect::<Vec<_>>();
|
||||
@ -420,7 +433,7 @@ fn tests(workspace: &Path, args: TestArgs, action: CargoAction) -> Result<()> {
|
||||
args.chip,
|
||||
target,
|
||||
test,
|
||||
action,
|
||||
action.clone(),
|
||||
args.repeat.unwrap_or(1),
|
||||
false,
|
||||
)?;
|
||||
@ -436,7 +449,7 @@ fn tests(workspace: &Path, args: TestArgs, action: CargoAction) -> Result<()> {
|
||||
args.chip,
|
||||
target,
|
||||
&test,
|
||||
action,
|
||||
action.clone(),
|
||||
args.repeat.unwrap_or(1),
|
||||
false,
|
||||
)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user