mirror of
https://github.com/esp-rs/esp-hal.git
synced 2025-09-27 12:20:56 +00:00
HIL: Multiple featuresets & conditionally enable generic-queue feature (#1989)
* Conditionally enable generic-queue feature * Allow specifying multiple feature sets and run all of them
This commit is contained in:
parent
0e333f7aa2
commit
b4ccb359ef
@ -136,7 +136,7 @@ required-features = ["async", "embassy"]
|
||||
[[test]]
|
||||
name = "embassy_interrupt_executor"
|
||||
harness = false
|
||||
required-features = ["async", "embassy", "integrated-timers"]
|
||||
required-features = ["async", "embassy"]
|
||||
|
||||
[[test]]
|
||||
name = "twai"
|
||||
@ -149,7 +149,7 @@ defmt = "0.3.8"
|
||||
defmt-rtt = { version = "0.4.1", optional = true }
|
||||
embassy-futures = "0.1.1"
|
||||
embassy-sync = "0.6.0"
|
||||
embassy-time = { version = "0.3.1", features = ["generic-queue-64"] }
|
||||
embassy-time = { version = "0.3.1" }
|
||||
embedded-hal = "1.0.0"
|
||||
embedded-hal-02 = { version = "0.2.7", package = "embedded-hal", features = ["unproven"] }
|
||||
embedded-hal-async = { version = "1.0.0", optional = true }
|
||||
@ -214,8 +214,11 @@ embassy = [
|
||||
"embedded-test/external-executor",
|
||||
"dep:esp-hal-embassy",
|
||||
]
|
||||
generic-queue = [
|
||||
"embassy-time/generic-queue-64"
|
||||
]
|
||||
integrated-timers = [
|
||||
"embassy-executor/integrated-timers",
|
||||
"esp-hal-embassy/integrated-timers",
|
||||
]
|
||||
|
||||
# https://doc.rust-lang.org/cargo/reference/profiles.html#test
|
||||
|
@ -3,11 +3,21 @@
|
||||
|
||||
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
||||
//% FEATURES: integrated-timers
|
||||
//% FEATURES: generic-queue
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, signal::Signal};
|
||||
use esp_hal::{
|
||||
clock::ClockControl,
|
||||
interrupt::Priority,
|
||||
peripherals::Peripherals,
|
||||
system::{SoftwareInterrupt, SystemControl},
|
||||
timer::timg::TimerGroup,
|
||||
};
|
||||
use esp_hal_embassy::InterruptExecutor;
|
||||
use hil_test as _;
|
||||
|
||||
macro_rules! mk_static {
|
||||
($t:ty,$val:expr) => {{
|
||||
@ -26,24 +36,19 @@ async fn interrupt_driven_task(signal: &'static Signal<CriticalSectionRawMutex,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[embedded_test::tests]
|
||||
#[embedded_test::tests(executor = esp_hal_embassy::Executor::new())]
|
||||
mod test {
|
||||
use esp_hal::{
|
||||
clock::ClockControl,
|
||||
interrupt::Priority,
|
||||
peripherals::Peripherals,
|
||||
system::{SoftwareInterrupt, SystemControl},
|
||||
};
|
||||
use esp_hal_embassy::InterruptExecutor;
|
||||
use hil_test as _;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[init]
|
||||
fn init() -> SoftwareInterrupt<1> {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = SystemControl::new(peripherals.SYSTEM);
|
||||
let _clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks);
|
||||
esp_hal_embassy::init(&clocks, timg0.timer0);
|
||||
|
||||
system.software_interrupt_control.software_interrupt1
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
//! Embassy timer and executor Test
|
||||
|
||||
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
||||
//% FEATURES: integrated-timers
|
||||
//% FEATURES: generic-queue
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
@ -5,6 +5,7 @@
|
||||
//! GPIO3
|
||||
|
||||
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
||||
//% FEATURES: generic-queue
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
@ -6,6 +6,7 @@
|
||||
//! with loopback mode enabled). It's using circular DMA mode
|
||||
|
||||
//% CHIPS: esp32c3 esp32c6 esp32s3 esp32h2
|
||||
//% FEATURES: generic-queue
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
@ -1,6 +1,7 @@
|
||||
//! lcd_cam i8080 tests
|
||||
|
||||
//% CHIPS: esp32s3
|
||||
//% FEATURES: generic-queue
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
@ -15,6 +15,7 @@
|
||||
//! Connect PCNT (GPIO2) and MOSI (GPIO3) and MISO (GPIO6) and GPIO5 pins.
|
||||
|
||||
//% CHIPS: esp32 esp32c6 esp32h2 esp32s3
|
||||
//% FEATURES: generic-queue
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
@ -7,6 +7,7 @@
|
||||
//! Connect TX (GPIO2) and RX (GPIO3) pins.
|
||||
|
||||
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
||||
//% FEATURES: generic-queue
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
@ -7,6 +7,7 @@
|
||||
//! Connect TX (GPIO2) and RX (GPIO3) pins.
|
||||
|
||||
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
||||
//% FEATURES: generic-queue
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
@ -57,11 +57,11 @@ pub enum Package {
|
||||
pub struct Metadata {
|
||||
example_path: PathBuf,
|
||||
chips: Vec<Chip>,
|
||||
features: Vec<String>,
|
||||
feature_sets: Vec<Vec<String>>,
|
||||
}
|
||||
|
||||
impl Metadata {
|
||||
pub fn new(example_path: &Path, chips: Vec<Chip>, features: Vec<String>) -> Self {
|
||||
pub fn new(example_path: &Path, chips: Vec<Chip>, feature_sets: Vec<Vec<String>>) -> Self {
|
||||
let chips = if chips.is_empty() {
|
||||
Chip::iter().collect()
|
||||
} else {
|
||||
@ -71,7 +71,7 @@ impl Metadata {
|
||||
Self {
|
||||
example_path: example_path.to_path_buf(),
|
||||
chips,
|
||||
features,
|
||||
feature_sets,
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,8 +90,8 @@ impl Metadata {
|
||||
}
|
||||
|
||||
/// A list of all features required for building a given examples.
|
||||
pub fn features(&self) -> &[String] {
|
||||
&self.features
|
||||
pub fn feature_sets(&self) -> &[Vec<String>] {
|
||||
&self.feature_sets
|
||||
}
|
||||
|
||||
/// If the specified chip is in the list of chips, then it is supported.
|
||||
@ -155,7 +155,7 @@ pub fn load_examples(path: &Path) -> Result<Vec<Metadata>> {
|
||||
.with_context(|| format!("Could not read {}", path.display()))?;
|
||||
|
||||
let mut chips = Vec::new();
|
||||
let mut features = Vec::new();
|
||||
let mut feature_sets = Vec::new();
|
||||
|
||||
// We will indicate metadata lines using the `//%` prefix:
|
||||
for line in text.lines().filter(|line| line.starts_with("//%")) {
|
||||
@ -183,13 +183,13 @@ pub fn load_examples(path: &Path) -> Result<Vec<Metadata>> {
|
||||
.map(|s| Chip::from_str(s, false).unwrap())
|
||||
.collect::<Vec<_>>();
|
||||
} else if key == "FEATURES" {
|
||||
features = split.into();
|
||||
feature_sets.push(split.into());
|
||||
} else {
|
||||
log::warn!("Unrecognized metadata key '{key}', ignoring");
|
||||
}
|
||||
}
|
||||
|
||||
examples.push(Metadata::new(&path, chips, features));
|
||||
examples.push(Metadata::new(&path, chips, feature_sets));
|
||||
}
|
||||
|
||||
Ok(examples)
|
||||
@ -202,19 +202,45 @@ pub fn execute_app(
|
||||
target: &str,
|
||||
app: &Metadata,
|
||||
action: CargoAction,
|
||||
mut repeat: usize,
|
||||
repeat: usize,
|
||||
) -> Result<()> {
|
||||
log::info!(
|
||||
"Building example '{}' for '{}'",
|
||||
app.example_path().display(),
|
||||
chip
|
||||
);
|
||||
if !app.features().is_empty() {
|
||||
log::info!(" Features: {}", app.features().join(","));
|
||||
|
||||
let feature_sets = if app.feature_sets().is_empty() {
|
||||
vec![vec![]]
|
||||
} else {
|
||||
app.feature_sets().to_vec()
|
||||
};
|
||||
|
||||
for features in feature_sets {
|
||||
execute_app_with_features(package_path, chip, target, app, action, repeat, features)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Run or build the specified test or example for the specified chip, with the
|
||||
/// specified features enabled.
|
||||
pub fn execute_app_with_features(
|
||||
package_path: &Path,
|
||||
chip: Chip,
|
||||
target: &str,
|
||||
app: &Metadata,
|
||||
action: CargoAction,
|
||||
mut repeat: usize,
|
||||
mut features: Vec<String>,
|
||||
) -> Result<()> {
|
||||
if !features.is_empty() {
|
||||
log::info!("Features: {}", features.join(","));
|
||||
}
|
||||
features.push(chip.to_string());
|
||||
|
||||
let package = app.example_path().strip_prefix(package_path)?;
|
||||
log::info!("Package: {:?}", package);
|
||||
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") {
|
||||
@ -233,9 +259,6 @@ pub fn execute_app(
|
||||
(format!("--example={}", app.name()), "run")
|
||||
};
|
||||
|
||||
let mut features = app.features().to_vec();
|
||||
features.push(chip.to_string());
|
||||
|
||||
let mut builder = CargoArgsBuilder::default()
|
||||
.subcommand(subcommand)
|
||||
.arg("--release")
|
||||
@ -256,7 +279,10 @@ pub fn execute_app(
|
||||
let args = builder.build();
|
||||
log::debug!("{args:#?}");
|
||||
|
||||
for _ in 0..repeat {
|
||||
for i in 0..repeat {
|
||||
if repeat != 1 {
|
||||
log::info!("Run {}/{}", i + 1, repeat);
|
||||
}
|
||||
cargo::run(&args, package_path)?;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user