Skip to content

Commit

Permalink
Implement try-init feature
Browse files Browse the repository at this point in the history
  • Loading branch information
speelbarrow committed Nov 27, 2024
1 parent cfb83b1 commit 6bfebd8
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 0 deletions.
1 change: 1 addition & 0 deletions esp-hal/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added `esp_hal::psram::psram_raw_parts` (#2546)
- The timer drivers `OneShotTimer` & `PeriodicTimer` have `into_async` and `new_typed` methods (#2586)
- `timer::Timer` trait has three new methods, `wait`, `async_interrupt_handler` and `peripheral_interrupt` (#2586)
- Add `try_init` function behind non-default feature `try-init` (#2618)

### Changed

Expand Down
4 changes: 4 additions & 0 deletions esp-hal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ esp-synopsys-usb-otg = { version = "0.4.2", optional = true, features = ["fs
fugit = "0.3.7"
log = { version = "0.4.22", optional = true }
nb = "1.1.0"
once_cell = { version = "1.20.2", optional = true, default-features = false, features = ["race"] }
paste = "1.0.15"
portable-atomic = { version = "1.9.0", default-features = false }
procmacros = { version = "0.15.0", package = "esp-hal-procmacros", path = "../esp-hal-procmacros" }
Expand Down Expand Up @@ -152,6 +153,9 @@ octal-psram = []
# This feature is intended for testing; you probably don't want to enable it:
ci = ["defmt", "bluetooth"]

# Enable `try_init` -- requires once_cell
try-init = ["once_cell"]

[lints.clippy]
mixed_attributes_style = "allow"

Expand Down
15 changes: 15 additions & 0 deletions esp-hal/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -559,3 +559,18 @@ pub fn init(config: Config) -> Peripherals {

peripherals
}

/// Attempts to initialize the system.
///
/// If [`init`] has already been executed, returns [`None`].
/// (This check is [thread-safe](once_cell::race::OnceBool))
///
/// Otherwise, initializes and returns the [`Peripherals`].
#[cfg(feature = "try-init")]
pub fn try_init(config: Config) -> Option<Peripherals> {
if !Peripherals::initialized() {
Some(init(config))
} else {
None
}
}
19 changes: 19 additions & 0 deletions esp-hal/src/peripheral.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,8 @@ mod peripheral_macros {
),* $(,)?
]
) => {
#[cfg(feature = "try-init")]
use once_cell::race::OnceBool;

/// Contains the generated peripherals which implement [`Peripheral`]
mod peripherals {
Expand Down Expand Up @@ -293,8 +295,25 @@ mod peripheral_macros {
}

impl Peripherals {
#[cfg(feature = "try-init")]
const INITIALIZED: OnceBool = OnceBool::new();

#[cfg(feature = "try-init")]
pub(crate) fn initialized() -> bool {
Self::INITIALIZED.get().is_some()
}

/// Returns all the peripherals *once*
#[inline]
#[cfg(feature = "try-init")]
pub(crate) fn take() -> Self {
if let Ok(_) = Self::INITIALIZED.set(true) {
unsafe { Self::steal() }
} else {
panic!("init called more than once!")
}
}
#[cfg(not(feature = "try-init"))]
pub(crate) fn take() -> Self {
#[no_mangle]
static mut _ESP_HAL_DEVICE_PERIPHERALS: bool = false;
Expand Down
2 changes: 2 additions & 0 deletions hil-test/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,8 @@ integrated-timers = [
"esp-hal-embassy/integrated-timers",
]
octal-psram = ["esp-hal/octal-psram", "esp-alloc"]
# `try-init`:
try-init = ["esp-hal/try-init"]

# https://doc.rust-lang.org/cargo/reference/profiles.html#test
# Test and bench profiles inherit from dev and release respectively.
Expand Down
7 changes: 7 additions & 0 deletions hil-test/tests/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,4 +107,11 @@ mod tests {
let delay = Delay::new();
delay.delay(2000.millis());
}

#[cfg(feature = "try-init")]
#[test]
fn test_try_init() {
assert!(esp_hal::try_init(Config::default()).is_some());
assert!(esp_hal::try_init(Config::default()).is_none());
}
}

0 comments on commit 6bfebd8

Please sign in to comment.