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

Simplify initialization APIs #1957

Merged
merged 6 commits into from
Aug 16, 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
1 change: 1 addition & 0 deletions esp-hal-embassy/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed

- Updated to latest release (`0.6.0`) for `embassy-executor` (#1942)
- Changed `init` to accept timers of multiple types (#1957)

### Fixed

Expand Down
1 change: 1 addition & 0 deletions esp-hal-embassy/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ esp-hal = { version = "0.19.0", path = "../esp-hal" }
log = { version = "0.4.22", optional = true }
macros = { version = "0.12.0", features = ["embassy"], package = "esp-hal-procmacros", path = "../esp-hal-procmacros" }
portable-atomic = "1.6.0"
static_cell = "2.1.0"

[build-dependencies]
cfg-if = "1.0.0"
Expand Down
106 changes: 102 additions & 4 deletions esp-hal-embassy/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,12 @@
// MUST be the first module
mod fmt;

use esp_hal::clock::Clocks;
#[cfg(not(feature = "esp32"))]
use esp_hal::timer::systimer::Alarm;
use esp_hal::{
clock::Clocks,
timer::{timg::Timer as TimgTimer, ErasedTimer},
};
pub use macros::main;

#[cfg(feature = "executors")]
Expand All @@ -47,7 +52,100 @@ use self::time_driver::{EmbassyTimer, Timer};
mod executor;
mod time_driver;

/// Initialize embassy
pub fn init(clocks: &Clocks, time_driver: &'static mut [Timer]) {
EmbassyTimer::init(clocks, time_driver)
macro_rules! mk_static {
($t:ty,$val:expr) => {{
static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new();
#[deny(unused_attributes)]
let x = STATIC_CELL.uninit().write(($val));
x
}};
}

/// A trait to allow better UX for initializing the timers.
///
/// This trait is meant to be used only for the `init` function.
/// Calling `timers()` multiple times may panic.
pub trait TimerCollection {
MabezDev marked this conversation as resolved.
Show resolved Hide resolved
/// Returns the timers as a slice.
fn timers(self) -> &'static mut [Timer];
}

/// Helper trait to reduce boilerplate.
///
/// We can't blanket-implement for `Into<ErasedTimer>` because of possible
/// conflicting implementations.
trait IntoErasedTimer: Into<ErasedTimer> {}

impl IntoErasedTimer for ErasedTimer {}

impl<T, DM> IntoErasedTimer for TimgTimer<T, DM>
where
DM: esp_hal::Mode,
Self: Into<ErasedTimer>,
{
}

#[cfg(not(feature = "esp32"))]
impl<T, DM, COMP, UNIT> IntoErasedTimer for Alarm<'_, T, DM, COMP, UNIT>
where
DM: esp_hal::Mode,
Self: Into<ErasedTimer>,
{
}

impl<T> TimerCollection for T
where
T: IntoErasedTimer,
{
fn timers(self) -> &'static mut [Timer] {
Timer::new(self.into()).timers()
}
}

impl TimerCollection for Timer {
fn timers(self) -> &'static mut [Timer] {
let timers = mk_static!([Timer; 1], [self]);
timers.timers()
}
}

impl TimerCollection for &'static mut [Timer] {
fn timers(self) -> &'static mut [Timer] {
self
}
}

impl<const N: usize> TimerCollection for &'static mut [Timer; N] {
fn timers(self) -> &'static mut [Timer] {
self.as_mut()
}
}

/// Initialize embassy.
///
/// Call this as soon as possible, before the first timer-related operation.
///
/// The time driver can be one of a number of different options:
///
/// - A timg `Timer` instance
/// - A systimer `Alarm` instance
/// - An `ErasedTimer` instance
/// - A `OneShotTimer` instance
/// - A mutable static slice of `OneShotTimer` instances
/// - A mutable static array of `OneShotTimer` instances
///
/// # Examples
///
/// ```rust, no_run
#[doc = esp_hal::before_snippet!()]
/// use esp_hal::timg::TimerGroup;
///
/// let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks);
/// esp_hal_embassy::init(&clocks, timg0.timer0);
///
/// // ... now you can spawn embassy tasks or use `Timer::after` etc.
/// # }
/// ```
pub fn init(clocks: &Clocks, time_driver: impl TimerCollection) {
EmbassyTimer::init(clocks, time_driver.timers())
}
10 changes: 8 additions & 2 deletions esp-hal/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -680,7 +680,10 @@ unsafe extern "C" fn stack_chk_fail() {
#[macro_export]
macro_rules! before_snippet {
() => {
core::include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/doc-helper/before"))
core::include_str!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/../esp-hal/doc-helper/before"
))
};
}

Expand All @@ -690,6 +693,9 @@ macro_rules! before_snippet {
#[macro_export]
macro_rules! before_snippet {
() => {
core::include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "\\doc-helper\\before"))
core::include_str!(concat!(
env!("CARGO_MANIFEST_DIR"),
"\\..\\esp-hal\\doc-helper\\before"
))
};
}
2 changes: 1 addition & 1 deletion esp-hal/src/timer/timg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ where
}
}

/// Block until the timer has elasped.
/// Block until the timer has elapsed.
pub fn wait(&mut self) {
while !self.has_elapsed() {}
}
Expand Down
2 changes: 2 additions & 0 deletions esp-wifi/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Changed

- Changed `init` to accept timers of multiple types (#1957)

### Fixed

- Increased NPL event queue size to prevent overflow (#1891)
Expand Down
5 changes: 3 additions & 2 deletions esp-wifi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,9 @@ atomic-waker = { version = "1.1.2", default-features = false, features = [
] }

[build-dependencies]
toml-cfg = "0.2.0"
esp-build = { version = "0.1.0", path = "../esp-build" }
toml-cfg = "0.2.0"
esp-build = { version = "0.1.0", path = "../esp-build" }
esp-metadata = { version = "0.2.0", path = "../esp-metadata" }

[features]
default = ["log"]
Expand Down
2 changes: 1 addition & 1 deletion esp-wifi/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Minimum supported Rust compiler version: 1.72.0.0

### Importing

Ensure that the right features are enabled for your chip. See [Examples] for more examples.
Ensure that the right features are enabled for your chip. See [Examples](https://github.com/esp-rs/esp-hal/tree/main/examples#examples) for more examples.

```toml
[dependencies.esp-wifi]
Expand Down
70 changes: 39 additions & 31 deletions esp-wifi/build.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,41 @@
use std::{error::Error, str::FromStr};

use esp_build::assert_unique_used_features;
use esp_metadata::{Chip, Config};

fn main() -> Result<(), String> {
fn main() -> Result<(), Box<dyn Error>> {
// Ensure that only a single chip is specified:
assert_unique_used_features!(
"esp32", "esp32c2", "esp32c3", "esp32c6", "esp32h2", "esp32s2", "esp32s3"
);

// NOTE: update when adding new device support!
// Determine the name of the configured device:
let device_name = if cfg!(feature = "esp32") {
"esp32"
} else if cfg!(feature = "esp32c2") {
"esp32c2"
} else if cfg!(feature = "esp32c3") {
"esp32c3"
} else if cfg!(feature = "esp32c6") {
"esp32c6"
} else if cfg!(feature = "esp32h2") {
"esp32h2"
} else if cfg!(feature = "esp32s2") {
"esp32s2"
} else if cfg!(feature = "esp32s3") {
"esp32s3"
} else {
unreachable!() // We've confirmed exactly one known device was selected
};

// Load the configuration file for the configured device:
let chip = Chip::from_str(device_name)?;
let config = Config::for_chip(&chip);

// Define all necessary configuration symbols for the configured device:
config.define_symbols();

#[cfg(all(feature = "ble", feature = "esp32s2"))]
{
panic!(
Expand Down Expand Up @@ -38,39 +68,17 @@ fn main() -> Result<(), String> {
"#
);
}
match std::env::var("OPT_LEVEL") {
Ok(level) => {
if level != "2" && level != "3" {
let message = format!(
"esp-wifi should be built with optimization level 2 or 3 - yours is {level}.
See https://github.com/esp-rs/esp-wifi",
);
print_warning(message);
}
if let Ok(level) = std::env::var("OPT_LEVEL") {
if level != "2" && level != "3" {
let message = format!(
"esp-wifi should be built with optimization level 2 or 3 - yours is {level}.
See https://github.com/esp-rs/esp-wifi",
);
print_warning(message);
}
Err(_err) => (),
}

#[cfg(feature = "esp32")]
println!("cargo:rustc-cfg=esp32");

#[cfg(feature = "esp32c2")]
println!("cargo:rustc-cfg=esp32c2");

#[cfg(feature = "esp32c3")]
println!("cargo:rustc-cfg=esp32c3");

#[cfg(feature = "esp32c6")]
println!("cargo:rustc-cfg=esp32c6");

#[cfg(feature = "esp32h2")]
println!("cargo:rustc-cfg=esp32h2");

#[cfg(feature = "esp32s2")]
println!("cargo:rustc-cfg=esp32s2");

#[cfg(feature = "esp32s3")]
println!("cargo:rustc-cfg=esp32s3");
println!("cargo:rustc-cfg={}", device_name);

#[cfg(feature = "coex")]
{
Expand Down
Loading