From c717f04d4d1fa9b5ccb22c60fa6a14c506e7ef06 Mon Sep 17 00:00:00 2001 From: Scott Mabin Date: Mon, 4 Nov 2024 08:08:19 +0000 Subject: [PATCH] Remove `EspWifiInitFor` & more granular init/deinit per driver (#2301) * More granular init and deinit per driver - Rework EspWifiInit - No longer require EspWifiInitFor - Add Drop impls for each driver, and add Drop for EspWifiController to fully deinit the stack * unwrap! more stuff * fixup examples and esp-now * unwrap less stuff * review feedback * seal wifi traits, allow rng or trng to init esp-wifi * changelog and migration guide * return wifi error in esp now constructor instead of panic --- esp-hal/src/rng.rs | 5 +- esp-wifi/CHANGELOG.md | 1 + esp-wifi/Cargo.toml | 1 + esp-wifi/MIGRATING-0.10.md | 17 ++ esp-wifi/src/ble/btdm.rs | 2 + esp-wifi/src/ble/controller/mod.rs | 49 +--- esp-wifi/src/ble/mod.rs | 2 +- esp-wifi/src/ble/npl.rs | 3 + esp-wifi/src/compat/misc.rs | 3 +- esp-wifi/src/esp_now/mod.rs | 43 ++- esp-wifi/src/lib.rs | 254 ++++++++---------- esp-wifi/src/timer/mod.rs | 10 +- esp-wifi/src/timer/riscv.rs | 12 +- esp-wifi/src/timer/xtensa.rs | 11 +- esp-wifi/src/wifi/mod.rs | 57 ++-- esp-wifi/src/wifi/utils.rs | 6 +- examples/Cargo.toml | 2 +- examples/src/bin/wifi_80211_tx.rs | 14 +- examples/src/bin/wifi_access_point.rs | 2 - .../src/bin/wifi_access_point_with_sta.rs | 2 - examples/src/bin/wifi_bench.rs | 2 - examples/src/bin/wifi_ble.rs | 3 +- examples/src/bin/wifi_coex.rs | 2 - examples/src/bin/wifi_dhcp.rs | 2 - examples/src/bin/wifi_embassy_access_point.rs | 18 +- .../bin/wifi_embassy_access_point_with_sta.rs | 18 +- examples/src/bin/wifi_embassy_bench.rs | 18 +- examples/src/bin/wifi_embassy_ble.rs | 28 +- examples/src/bin/wifi_embassy_dhcp.rs | 18 +- examples/src/bin/wifi_embassy_esp_now.rs | 28 +- .../src/bin/wifi_embassy_esp_now_duplex.rs | 18 +- examples/src/bin/wifi_embassy_trouble.rs | 30 ++- examples/src/bin/wifi_esp_now.rs | 2 - examples/src/bin/wifi_sniffer.rs | 14 +- examples/src/bin/wifi_static_ip.rs | 2 - hil-test/tests/esp_wifi_floats.rs | 7 +- 36 files changed, 358 insertions(+), 348 deletions(-) diff --git a/esp-hal/src/rng.rs b/esp-hal/src/rng.rs index 406a99808..d0875012a 100644 --- a/esp-hal/src/rng.rs +++ b/esp-hal/src/rng.rs @@ -130,10 +130,7 @@ impl rand_core::RngCore for Rng { /// the randomness from the hardware RNG and an ADC. This struct provides /// methods to generate random numbers and fill buffers with random bytes. /// Due to pulling the entropy source from the ADC, it uses the associated -/// regiters, so to use TRNG we need to "occupy" the ADC peripheral. -/// -/// For now, even after calling `core::mem::drop()` on `TRNG` ADC1 will not be -/// usable (details in esp-hal/#1750) +/// registers, so to use TRNG we need to "occupy" the ADC peripheral. /// /// ```rust, no_run #[doc = crate::before_snippet!()] diff --git a/esp-wifi/CHANGELOG.md b/esp-wifi/CHANGELOG.md index aa932a028..24189dc5a 100644 --- a/esp-wifi/CHANGELOG.md +++ b/esp-wifi/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- `esp_wifi::init` no longer requires `EspWifiInitFor`, and now returns `EspWifiController`, see the migration guide for more details (#2301) - No need to add `rom_functions.x` manually anymore (#2374) - esp-now: Data is now private in `ReceivedData` - use `data()`(#2396) diff --git a/esp-wifi/Cargo.toml b/esp-wifi/Cargo.toml index d6d92be54..0b448583c 100644 --- a/esp-wifi/Cargo.toml +++ b/esp-wifi/Cargo.toml @@ -39,6 +39,7 @@ libm = "0.2.8" cfg-if = "1.0.0" portable-atomic = { version = "1.9.0", default-features = false } portable_atomic_enum = { version = "0.3.1", features = ["portable-atomic"] } +rand_core = "0.6.4" bt-hci = { version = "0.1.1", optional = true } esp-config = { version = "0.1.0", path = "../esp-config" } diff --git a/esp-wifi/MIGRATING-0.10.md b/esp-wifi/MIGRATING-0.10.md index a8c7414dc..0bf1d4c5c 100644 --- a/esp-wifi/MIGRATING-0.10.md +++ b/esp-wifi/MIGRATING-0.10.md @@ -1,5 +1,22 @@ # Migration Guide from 0.10.x to v0.11.x +## Initialization changes + +`EspWifiInitFor` has been removed, individual drivers such as `Wifi` and `BleConnector` handle the initialization and de-initialization of the radio stack. + +`EspWifiInit` has been removed in favour of `EspWifiController`, each radio driver takes reference to this object. If no driver is borrowing `EspWifiController`, +you can safely call `EspWifiController::deinit()` to completely deinit the stack and return the peripherals used in `esp_wifi::init`. + +`esp-wifi::init` now takes all peripherals using the `PeripheralRef` pattern, with the exception of the rng source. + +`esp_wifi::init` now accepts `esp_hal::rng::Rng` or `esp_hal::rng::Trng`. + +The following error enum variants have been removed from `InitializationError`: + +- `Timer(hal::timer::Error)` +- `TimerUnavailable` +- `RadioClockUnavailable` + ## No need to include `rom_functions.x` manually Don't include `rom_functions.x` from esp-wifi diff --git a/esp-wifi/src/ble/btdm.rs b/esp-wifi/src/ble/btdm.rs index aa601f69d..c6ca321db 100644 --- a/esp-wifi/src/ble/btdm.rs +++ b/esp-wifi/src/ble/btdm.rs @@ -442,6 +442,7 @@ pub(crate) fn ble_init() { API_vhci_host_register_callback(&VHCI_HOST_CALLBACK); } + crate::flags::BLE.store(true, Ordering::Release); } pub(crate) fn ble_deinit() { @@ -453,6 +454,7 @@ pub(crate) fn ble_deinit() { btdm_controller_deinit(); crate::common_adapter::chip_specific::phy_disable(); } + crate::flags::BLE.store(false, Ordering::Release); } pub fn send_hci(data: &[u8]) { diff --git a/esp-wifi/src/ble/controller/mod.rs b/esp-wifi/src/ble/controller/mod.rs index de26dfb51..bd2b58c92 100644 --- a/esp-wifi/src/ble/controller/mod.rs +++ b/esp-wifi/src/ble/controller/mod.rs @@ -3,7 +3,7 @@ use embedded_io::{Error, ErrorType, Read, Write}; use super::{read_hci, read_next, send_hci}; use crate::{ hal::peripheral::{Peripheral, PeripheralRef}, - EspWifiInitialization, + EspWifiController, }; /// A blocking HCI connector @@ -11,14 +11,18 @@ pub struct BleConnector<'d> { _device: PeripheralRef<'d, crate::hal::peripherals::BT>, } +impl<'d> Drop for BleConnector<'d> { + fn drop(&mut self) { + crate::ble::ble_deinit(); + } +} + impl<'d> BleConnector<'d> { pub fn new( - init: &EspWifiInitialization, + _init: &'d EspWifiController<'d>, device: impl Peripheral

+ 'd, ) -> BleConnector<'d> { - if !init.is_ble() { - panic!("Not initialized for BLE use"); - } + crate::ble::ble_init(); Self { _device: device.into_ref(), @@ -80,7 +84,7 @@ impl Write for BleConnector<'_> { /// Async Interface #[cfg(feature = "async")] -pub mod asynch { +pub(crate) mod asynch { use core::task::Poll; use bt_hci::{ @@ -91,14 +95,9 @@ pub mod asynch { WriteHci, }; use embassy_sync::waitqueue::AtomicWaker; - use embedded_io::ErrorType; - use super::{read_hci, send_hci, BleConnectorError}; - use crate::{ - ble::have_hci_read_data, - hal::peripheral::{Peripheral, PeripheralRef}, - EspWifiInitialization, - }; + use super::*; + use crate::ble::have_hci_read_data; static HCI_WAKER: AtomicWaker = AtomicWaker::new(); @@ -106,30 +105,6 @@ pub mod asynch { HCI_WAKER.wake(); } - /// Async HCI connector - pub struct BleConnector<'d> { - _device: PeripheralRef<'d, crate::hal::peripherals::BT>, - } - - impl<'d> BleConnector<'d> { - pub fn new( - init: &EspWifiInitialization, - device: impl Peripheral

+ 'd, - ) -> BleConnector<'d> { - if !init.is_ble() { - panic!("Not initialized for BLE use"); - } - - Self { - _device: device.into_ref(), - } - } - } - - impl ErrorType for BleConnector<'_> { - type Error = BleConnectorError; - } - impl embedded_io_async::Read for BleConnector<'_> { async fn read(&mut self, buf: &mut [u8]) -> Result { if !have_hci_read_data() { diff --git a/esp-wifi/src/ble/mod.rs b/esp-wifi/src/ble/mod.rs index 1ea694fde..7246ffbcb 100644 --- a/esp-wifi/src/ble/mod.rs +++ b/esp-wifi/src/ble/mod.rs @@ -9,7 +9,7 @@ pub(crate) mod npl; use alloc::{boxed::Box, collections::vec_deque::VecDeque, vec::Vec}; use core::{cell::RefCell, mem::MaybeUninit}; -pub(crate) use ble::{ble_init, send_hci}; +pub(crate) use ble::{ble_deinit, ble_init, send_hci}; use critical_section::Mutex; #[cfg(any(esp32, esp32c3, esp32s3))] diff --git a/esp-wifi/src/ble/npl.rs b/esp-wifi/src/ble/npl.rs index 6b755ee68..3d8696966 100644 --- a/esp-wifi/src/ble/npl.rs +++ b/esp-wifi/src/ble/npl.rs @@ -2,6 +2,7 @@ use alloc::boxed::Box; use core::{ mem::size_of_val, ptr::{addr_of, addr_of_mut}, + sync::atomic::Ordering, }; use super::*; @@ -1179,6 +1180,7 @@ pub(crate) fn ble_init() { debug!("The ble_controller_init was initialized"); } + crate::flags::BLE.store(true, Ordering::Release); } pub(crate) fn ble_deinit() { @@ -1205,6 +1207,7 @@ pub(crate) fn ble_deinit() { crate::common_adapter::chip_specific::phy_disable(); } + crate::flags::BLE.store(false, Ordering::Release); } #[cfg(esp32c2)] diff --git a/esp-wifi/src/compat/misc.rs b/esp-wifi/src/compat/misc.rs index 91035ffe2..783fd5f59 100644 --- a/esp-wifi/src/compat/misc.rs +++ b/esp-wifi/src/compat/misc.rs @@ -34,6 +34,7 @@ unsafe extern "C" fn strcat(destination: *mut u8, source: *const u8) -> *const u unsafe extern "C" fn strcmp(str1: *const i8, str2: *const i8) -> i32 { trace!("strcmp {:?} {:?}", str1, str2); + // TODO: unwrap!() when defmt supports it let s1 = core::ffi::CStr::from_ptr(str1).to_str().unwrap(); let s2 = core::ffi::CStr::from_ptr(str2).to_str().unwrap(); @@ -146,7 +147,7 @@ unsafe extern "C" fn strdup(str: *const i8) -> *const u8 { unsafe { let s = core::ffi::CStr::from_ptr(str); - let s = s.to_str().unwrap(); + let s = s.to_str().unwrap(); // TODO when defmt supports it let p = malloc(s.len() + 1); core::ptr::copy_nonoverlapping(str, p as *mut i8, s.len() + 1); diff --git a/esp-wifi/src/esp_now/mod.rs b/esp-wifi/src/esp_now/mod.rs index ecdbd6886..febd478bf 100644 --- a/esp-wifi/src/esp_now/mod.rs +++ b/esp-wifi/src/esp_now/mod.rs @@ -19,8 +19,8 @@ use portable_atomic::{AtomicBool, AtomicU8, Ordering}; use crate::{ binary::include::*, hal::peripheral::{Peripheral, PeripheralRef}, - wifi::{Protocol, RxControlInfo}, - EspWifiInitialization, + wifi::{Protocol, RxControlInfo, WifiError}, + EspWifiController, }; const RECEIVE_QUEUE_SIZE: usize = 10; @@ -113,6 +113,14 @@ pub enum EspNowError { SendFailed, /// Attempt to create `EspNow` instance twice. DuplicateInstance, + /// Initialization error + Initialization(WifiError), +} + +impl From for EspNowError { + fn from(f: WifiError) -> Self { + Self::Initialization(f) + } } /// Holds the count of peers in an ESP-NOW communication context. @@ -469,6 +477,21 @@ impl EspNowManager<'_> { } } +impl<'d> Drop for EspNowManager<'d> { + fn drop(&mut self) { + if unwrap!( + crate::flags::WIFI.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| { + Some(x.saturating_sub(1)) + }) + ) == 0 + { + if let Err(e) = crate::wifi::wifi_deinit() { + warn!("Failed to cleanly deinit wifi: {:?}", e); + } + } + } +} + /// This is the sender part of ESP-NOW. You can get this sender by splitting /// a `EspNow` instance. /// @@ -607,16 +630,16 @@ impl Drop for EspNowRc<'_> { /// Currently this implementation (when used together with traditional Wi-Fi) /// ONLY support STA mode. pub struct EspNow<'d> { - _device: Option>, manager: EspNowManager<'d>, sender: EspNowSender<'d>, receiver: EspNowReceiver<'d>, + _phantom: PhantomData<&'d ()>, } impl<'d> EspNow<'d> { /// Creates an `EspNow` instance. pub fn new( - inited: &EspWifiInitialization, + inited: &'d EspWifiController<'d>, device: impl Peripheral

+ 'd, ) -> Result, EspNowError> { EspNow::new_internal(inited, Some(device.into_ref())) @@ -624,7 +647,7 @@ impl<'d> EspNow<'d> { /// Creates an `EspNow` instance with support for Wi-Fi coexistence. pub fn new_with_wifi( - inited: &EspWifiInitialization, + inited: &'d EspWifiController<'d>, _token: EspNowWithWifiCreateToken, ) -> Result, EspNowError> { EspNow::new_internal( @@ -634,16 +657,17 @@ impl<'d> EspNow<'d> { } fn new_internal( - inited: &EspWifiInitialization, + inited: &'d EspWifiController<'d>, device: Option>, ) -> Result, EspNowError> { - if !inited.is_wifi() { - return Err(EspNowError::Error(Error::NotInitialized)); + if !inited.wifi() { + // if wifi isn't already enabled, and we try to coexist - panic + assert!(device.is_some()); + crate::wifi::wifi_init()?; } let espnow_rc = EspNowRc::new()?; let esp_now = EspNow { - _device: device, manager: EspNowManager { _rc: espnow_rc.clone(), }, @@ -651,6 +675,7 @@ impl<'d> EspNow<'d> { _rc: espnow_rc.clone(), }, receiver: EspNowReceiver { _rc: espnow_rc }, + _phantom: PhantomData, }; check_error!({ esp_wifi_set_mode(wifi_mode_t_WIFI_MODE_STA) })?; check_error!({ esp_wifi_start() })?; diff --git a/esp-wifi/src/lib.rs b/esp-wifi/src/lib.rs index 7d4152590..e96f3c417 100644 --- a/esp-wifi/src/lib.rs +++ b/esp-wifi/src/lib.rs @@ -93,25 +93,25 @@ extern crate alloc; // MUST be the first module mod fmt; +use core::marker::PhantomData; + use common_adapter::chip_specific::phy_mem_init; use esp_config::*; use esp_hal as hal; +use esp_hal::peripheral::Peripheral; #[cfg(not(feature = "esp32"))] use esp_hal::timer::systimer::Alarm; use fugit::MegahertzU32; use hal::{ clock::Clocks, + rng::{Rng, Trng}, system::RadioClockController, timer::{timg::Timer as TimgTimer, AnyTimer, PeriodicTimer}, }; -#[cfg(feature = "wifi")] -use num_traits::FromPrimitive; +use portable_atomic::Ordering; #[cfg(feature = "wifi")] -use crate::{ - binary::include::{self, esp_supplicant_deinit, esp_wifi_deinit_internal, esp_wifi_stop}, - wifi::WifiError, -}; +use crate::wifi::WifiError; use crate::{ tasks::init_tasks, timer::{setup_timer_isr, shutdown_timer_isr}, @@ -233,73 +233,53 @@ const _: () = { type TimeBase = PeriodicTimer<'static, AnyTimer>; -#[derive(Debug, PartialEq, PartialOrd)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -#[non_exhaustive] -/// An internal struct designed to make [`EspWifiInitialization`] uncreatable -/// outside of this crate. -pub struct EspWifiInitializationInternal; +pub(crate) mod flags { + use portable_atomic::{AtomicBool, AtomicUsize}; -#[derive(Debug, PartialEq, PartialOrd)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -/// Initialized the driver for WiFi, Bluetooth or both. -pub enum EspWifiInitialization { - #[cfg(feature = "wifi")] - Wifi(EspWifiInitializationInternal), - #[cfg(feature = "ble")] - Ble(EspWifiInitializationInternal), - #[cfg(coex)] - WifiBle(EspWifiInitializationInternal), -} - -impl EspWifiInitialization { - #[allow(unused)] - fn is_wifi(&self) -> bool { - match self { - #[cfg(feature = "ble")] - EspWifiInitialization::Ble(_) => false, - _ => true, - } - } - - #[allow(unused)] - fn is_ble(&self) -> bool { - match self { - #[cfg(feature = "wifi")] - EspWifiInitialization::Wifi(_) => false, - _ => true, - } - } + pub(crate) static ESP_WIFI_INITIALIZED: AtomicBool = AtomicBool::new(false); + pub(crate) static WIFI: AtomicUsize = AtomicUsize::new(0); + pub(crate) static BLE: AtomicBool = AtomicBool::new(false); } #[derive(Debug, PartialEq, PartialOrd)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] -/// Initialize the driver for WiFi, Bluetooth or both. -pub enum EspWifiInitFor { - #[cfg(feature = "wifi")] - Wifi, - #[cfg(feature = "ble")] - Ble, - #[cfg(coex)] - WifiBle, +pub struct EspWifiController<'d> { + _inner: PhantomData<&'d ()>, } -impl EspWifiInitFor { - #[allow(unused)] - fn is_wifi(&self) -> bool { - match self { - #[cfg(feature = "ble")] - EspWifiInitFor::Ble => false, - _ => true, +impl<'d> EspWifiController<'d> { + /// Is the WiFi part of the radio running + pub fn wifi(&self) -> bool { + crate::flags::WIFI.load(Ordering::Acquire) > 0 + } + + /// Is the BLE part of the radio running + pub fn ble(&self) -> bool { + crate::flags::BLE.load(Ordering::Acquire) + } + + /// De-initialize the radio + pub fn deinit(self) -> Result<(), InitializationError> { + if crate::flags::ESP_WIFI_INITIALIZED.load(Ordering::Acquire) { + // safety: no other driver can be using this if this is callable + unsafe { deinit_unchecked() } + } else { + Ok(()) } } - #[allow(unused)] - fn is_ble(&self) -> bool { - match self { - #[cfg(feature = "wifi")] - EspWifiInitFor::Wifi => false, - _ => true, + pub(crate) unsafe fn conjure() -> Self { + Self { + _inner: PhantomData, + } + } +} + +impl<'d> Drop for EspWifiController<'d> { + fn drop(&mut self) { + if crate::flags::ESP_WIFI_INITIALIZED.load(Ordering::Acquire) { + // safety: no other driver can be using this if this is callable + unsafe { deinit_unchecked().ok() }; } } } @@ -308,7 +288,7 @@ impl EspWifiInitFor { /// /// This trait is meant to be used only for the `init` function. /// Calling `timers()` multiple times may panic. -pub trait EspWifiTimerSource { +pub trait EspWifiTimerSource: private::Sealed { /// Returns the timer source. fn timer(self) -> TimeBase; } @@ -338,7 +318,7 @@ impl IntoAnyTimer for AnyTimer {} impl EspWifiTimerSource for T where - T: IntoAnyTimer, + T: IntoAnyTimer + private::Sealed, { fn timer(self) -> TimeBase { TimeBase::new(self.into()).timer() @@ -351,6 +331,29 @@ impl EspWifiTimerSource for TimeBase { } } +impl private::Sealed for TimeBase {} +impl private::Sealed for TimgTimer +where + DM: esp_hal::Mode, + Self: Into, +{ +} +#[cfg(not(feature = "esp32"))] +impl private::Sealed for Alarm<'_, T, DM, COMP, UNIT> +where + DM: esp_hal::Mode, + Self: Into, +{ +} + +/// A marker trait for suitable Rng sources for esp-wifi +pub trait EspWifiRngSource: rand_core::RngCore + private::Sealed {} + +impl EspWifiRngSource for Rng {} +impl private::Sealed for Rng {} +impl EspWifiRngSource for Trng<'_> {} +impl private::Sealed for Trng<'_> {} + /// Initialize for using WiFi and or BLE. /// /// # The `timer` argument @@ -380,12 +383,11 @@ impl EspWifiTimerSource for TimeBase { /// .unwrap(); /// # } /// ``` -pub fn init( - init_for: EspWifiInitFor, - timer: impl EspWifiTimerSource, - _rng: hal::rng::Rng, - _radio_clocks: hal::peripherals::RADIO_CLK, -) -> Result { +pub fn init<'d, T: EspWifiTimerSource>( + timer: impl Peripheral

+ 'd, + _rng: impl EspWifiRngSource, + _radio_clocks: impl Peripheral

+ 'd, +) -> Result, InitializationError> { // A minimum clock of 80MHz is required to operate WiFi module. const MIN_CLOCK: u32 = 80; let clocks = Clocks::get(); @@ -397,7 +399,7 @@ pub fn init( crate::common_adapter::chip_specific::enable_wifi_power_domain(); phy_mem_init(); init_tasks(); - setup_timer_isr(timer.timer())?; + setup_timer_isr(unsafe { timer.clone_unchecked() }.timer()); wifi_set_log_verbose(); init_clocks(); @@ -408,60 +410,23 @@ pub fn init( error => return Err(InitializationError::General(error)), } - #[cfg(feature = "wifi")] - if init_for.is_wifi() { - debug!("wifi init"); - // wifi init - crate::wifi::wifi_init()?; - } + crate::flags::ESP_WIFI_INITIALIZED.store(true, Ordering::Release); - #[cfg(feature = "ble")] - if init_for.is_ble() { - // ble init - // for some reason things don't work when initializing things the other way - // around while the original implementation in NuttX does it like that - debug!("ble init"); - crate::ble::ble_init(); - } - - match init_for { - #[cfg(feature = "wifi")] - EspWifiInitFor::Wifi => Ok(EspWifiInitialization::Wifi(EspWifiInitializationInternal)), - #[cfg(feature = "ble")] - EspWifiInitFor::Ble => Ok(EspWifiInitialization::Ble(EspWifiInitializationInternal)), - #[cfg(coex)] - EspWifiInitFor::WifiBle => Ok(EspWifiInitialization::WifiBle( - EspWifiInitializationInternal, - )), - } + Ok(EspWifiController { + _inner: PhantomData, + }) } -/// Deinitializes WiFi and/or BLE +/// Deinitializes the entire radio stack /// -/// After user calls this function, WiFi and/or BLE (depending on what has been -/// initialized) are fully stopped and deinitialized. After that, they should -/// not be used until they have been reinitialized with the `init` function. -/// -/// The function also disables the corresponding interrupts, deinitializes -/// the timer and radio clock, freeing these resources and returning them. -/// -/// Calling this while still using WiFi/BLE will cause crashes or undefined -/// behavior. +/// This can be useful to shutdown the stack before going to sleep for example. /// /// # Safety -/// Actual implementation assumes that the user takes responsibility for how the -/// function is used. For example, after using this function, user should not -/// use BLE or WiFi stack or controller instances (it is possible to -/// reinitialize communication using the `init` function), not to call -/// `deinit_unsafe` before the first initialization, and so on. Also, there is -/// currently no way to track whether a peripheral has been initialized, -/// so deinitialization is done based on the activated feature (`wifi`, `ble` -/// and/or `coex`). -/// Before deinitializing, chips with NPL bluetooth (esp32c2, esp32c6, esp32h2) -/// users must make sure to stop BLE advertising before. -pub unsafe fn deinit_unchecked( - init: EspWifiInitialization, -) -> Result<(TimeBase, hal::peripherals::RADIO_CLK), InitializationError> { +/// +/// The user must ensure that any use of the radio via the WIFI/BLE/ESP-NOW +/// drivers are complete, else undefined behavour may occur within those +/// drivers. +pub unsafe fn deinit_unchecked() -> Result<(), InitializationError> { // Disable coexistence #[cfg(coex)] { @@ -469,33 +434,35 @@ pub unsafe fn deinit_unchecked( unsafe { crate::wifi::os_adapter::coex_deinit() }; } - // Deinitialize WiFi - #[cfg(feature = "wifi")] - if init.is_wifi() { - esp_wifi_result!(unsafe { esp_wifi_stop() })?; - esp_wifi_result!(unsafe { esp_wifi_deinit_internal() })?; - esp_wifi_result!(esp_supplicant_deinit())?; + let controller = unsafe { EspWifiController::conjure() }; + + // Peripheral drivers should already take care of shutting these down + // we have to check this in the case where a user calls `deinit_unchecked` + // directly. + if controller.wifi() { + #[cfg(feature = "wifi")] + crate::wifi::wifi_deinit()?; + crate::flags::WIFI.store(0, Ordering::Release); } - // Deinitialize BLE - #[cfg(feature = "ble")] - if init.is_ble() { - #[cfg(any(esp32, esp32c3, esp32s3))] - crate::ble::btdm::ble_deinit(); - - #[cfg(any(esp32c2, esp32c6, esp32h2))] - crate::ble::npl::ble_deinit(); + if controller.ble() { + #[cfg(feature = "ble")] + crate::ble::ble_deinit(); + crate::flags::BLE.store(false, Ordering::Release); } - shutdown_timer_isr().unwrap(); + shutdown_timer_isr(); crate::preempt::delete_all_tasks(); - let timer = critical_section::with(|cs| crate::timer::TIMER.borrow_ref_mut(cs).take()) - .ok_or(InitializationError::TimerUnavailable)?; + critical_section::with(|cs| crate::timer::TIMER.borrow_ref_mut(cs).take()); - let radio_clocks = unsafe { esp_hal::peripherals::RADIO_CLK::steal() }; + crate::flags::ESP_WIFI_INITIALIZED.store(false, Ordering::Release); - Ok((timer, radio_clocks)) + Ok(()) +} + +pub(crate) mod private { + pub trait Sealed {} } #[derive(Debug, Clone, Copy)] @@ -506,15 +473,6 @@ pub enum InitializationError { #[cfg(feature = "wifi")] WifiError(WifiError), WrongClockConfig, - Timer(hal::timer::Error), - TimerUnavailable, - RadioClockUnavailable, -} - -impl From for InitializationError { - fn from(value: hal::timer::Error) -> Self { - InitializationError::Timer(value) - } } #[cfg(feature = "wifi")] diff --git a/esp-wifi/src/timer/mod.rs b/esp-wifi/src/timer/mod.rs index f6531158a..d806fd911 100644 --- a/esp-wifi/src/timer/mod.rs +++ b/esp-wifi/src/timer/mod.rs @@ -22,24 +22,22 @@ use crate::TimeBase; pub(crate) static TIMER: Mutex>> = Mutex::new(RefCell::new(None)); -pub(crate) fn setup_timer_isr(timebase: TimeBase) -> Result<(), esp_hal::timer::Error> { +pub(crate) fn setup_timer_isr(timebase: TimeBase) { setup_radio_isr(); - setup_timer(timebase)?; + setup_timer(timebase); setup_multitasking(); yield_task(); - Ok(()) } -pub(crate) fn shutdown_timer_isr() -> Result<(), esp_hal::timer::Error> { +pub(crate) fn shutdown_timer_isr() { shutdown_radio_isr(); - disable_timer()?; + disable_timer(); disable_multitasking(); - Ok(()) } #[allow(unused)] diff --git a/esp-wifi/src/timer/riscv.rs b/esp-wifi/src/timer/riscv.rs index 46eafa162..8cb7c9191 100644 --- a/esp-wifi/src/timer/riscv.rs +++ b/esp-wifi/src/timer/riscv.rs @@ -23,28 +23,24 @@ pub const TICKS_PER_SECOND: u64 = 1_000_000; use super::TIMER; -pub(crate) fn setup_timer(mut alarm0: TimeBase) -> Result<(), esp_hal::timer::Error> { +pub(crate) fn setup_timer(mut alarm0: TimeBase) { // make sure the scheduling won't start before everything is setup riscv::interrupt::disable(); let cb: extern "C" fn() = unsafe { core::mem::transmute(handler as *const ()) }; alarm0.set_interrupt_handler(InterruptHandler::new(cb, interrupt::Priority::Priority1)); - alarm0.start(TIMESLICE_FREQUENCY.into_duration())?; + unwrap!(alarm0.start(TIMESLICE_FREQUENCY.into_duration())); critical_section::with(|cs| { alarm0.enable_interrupt(true); TIMER.borrow_ref_mut(cs).replace(alarm0); }); - - Ok(()) } -pub(crate) fn disable_timer() -> Result<(), esp_hal::timer::Error> { +pub(crate) fn disable_timer() { critical_section::with(|cs| { unwrap!(TIMER.borrow_ref_mut(cs).as_mut()).enable_interrupt(false); - unwrap!(TIMER.borrow_ref_mut(cs).as_mut()).cancel().unwrap(); + unwrap!(unwrap!(TIMER.borrow_ref_mut(cs).as_mut()).cancel()); }); - - Ok(()) } pub(crate) fn setup_multitasking() { diff --git a/esp-wifi/src/timer/xtensa.rs b/esp-wifi/src/timer/xtensa.rs index 6c123edae..dedb61b4a 100644 --- a/esp-wifi/src/timer/xtensa.rs +++ b/esp-wifi/src/timer/xtensa.rs @@ -21,26 +21,23 @@ pub(crate) fn get_systimer_count() -> u64 { esp_hal::time::now().ticks() } -pub(crate) fn setup_timer(mut timer1: TimeBase) -> Result<(), esp_hal::timer::Error> { +pub(crate) fn setup_timer(mut timer1: TimeBase) { timer1.set_interrupt_handler(InterruptHandler::new( unsafe { core::mem::transmute::<*const (), extern "C" fn()>(handler as *const ()) }, interrupt::Priority::Priority2, )); - timer1.start(TIMESLICE_FREQUENCY.into_duration())?; + unwrap!(timer1.start(TIMESLICE_FREQUENCY.into_duration())); critical_section::with(|cs| { timer1.enable_interrupt(true); TIMER.borrow_ref_mut(cs).replace(timer1); }); - Ok(()) } -pub(crate) fn disable_timer() -> Result<(), esp_hal::timer::Error> { +pub(crate) fn disable_timer() { critical_section::with(|cs| { unwrap!(TIMER.borrow_ref_mut(cs).as_mut()).enable_interrupt(false); - unwrap!(TIMER.borrow_ref_mut(cs).as_mut()).cancel().unwrap(); + unwrap!(unwrap!(TIMER.borrow_ref_mut(cs).as_mut()).cancel()); }); - - Ok(()) } pub(crate) fn setup_multitasking() { diff --git a/esp-wifi/src/wifi/mod.rs b/esp-wifi/src/wifi/mod.rs index 3d92900e8..33df1bcef 100644 --- a/esp-wifi/src/wifi/mod.rs +++ b/esp-wifi/src/wifi/mod.rs @@ -69,7 +69,7 @@ use crate::{ macros::ram, peripheral::{Peripheral, PeripheralRef}, }, - EspWifiInitialization, + EspWifiController, }; const ETHERNET_FRAME_HEADER_SIZE: usize = 18; @@ -90,8 +90,10 @@ use crate::binary::{ esp_err_t, esp_interface_t_ESP_IF_WIFI_AP, esp_interface_t_ESP_IF_WIFI_STA, + esp_supplicant_deinit, esp_supplicant_init, esp_wifi_connect, + esp_wifi_deinit_internal, esp_wifi_disconnect, esp_wifi_get_mode, esp_wifi_init_internal, @@ -281,7 +283,7 @@ pub struct AccessPointConfiguration { impl Default for AccessPointConfiguration { fn default() -> Self { Self { - ssid: "iot-device".try_into().unwrap(), + ssid: unwrap!("iot-device".try_into()), ssid_hidden: false, channel: 1, secondary_channel: None, @@ -1587,10 +1589,19 @@ pub(crate) fn wifi_init() -> Result<(), WifiError> { chip_specific::g_misc_nvs = addr_of!(NVS_STRUCT) as u32; } + crate::flags::WIFI.fetch_add(1, Ordering::SeqCst); + Ok(()) } } +pub(crate) fn wifi_deinit() -> Result<(), crate::InitializationError> { + esp_wifi_result!(unsafe { esp_wifi_stop() })?; + esp_wifi_result!(unsafe { esp_wifi_deinit_internal() })?; + esp_wifi_result!(unsafe { esp_supplicant_deinit() })?; + Ok(()) +} + unsafe extern "C" fn recv_cb_sta( buffer: *mut c_types::c_void, len: u16, @@ -1654,11 +1665,11 @@ unsafe extern "C" fn recv_cb_ap( pub(crate) static WIFI_TX_INFLIGHT: AtomicUsize = AtomicUsize::new(0); fn decrement_inflight_counter() { - WIFI_TX_INFLIGHT - .fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| { + unwrap!( + WIFI_TX_INFLIGHT.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| { Some(x.saturating_sub(1)) }) - .unwrap(); + ); } #[ram] @@ -1878,7 +1889,7 @@ pub(crate) fn wifi_start_scan( /// /// If you want to use AP-STA mode, use `[new_ap_sta]`. pub fn new_with_config<'d, MODE: WifiDeviceMode>( - inited: &EspWifiInitialization, + inited: &'d EspWifiController<'d>, device: impl Peripheral

+ 'd, config: MODE::Config, ) -> Result<(WifiDevice<'d, MODE>, WifiController<'d>), WifiError> { @@ -1896,8 +1907,8 @@ pub fn new_with_config<'d, MODE: WifiDeviceMode>( /// This function will panic if the mode is [`WifiMode::ApSta`]. /// If you want to use AP-STA mode, use `[new_ap_sta]`. pub fn new_with_mode<'d, MODE: WifiDeviceMode>( - inited: &EspWifiInitialization, - device: impl crate::hal::peripheral::Peripheral

+ 'd, + inited: &'d EspWifiController<'d>, + device: impl Peripheral

+ 'd, _mode: MODE, ) -> Result<(WifiDevice<'d, MODE>, WifiController<'d>), WifiError> { new_with_config(inited, device, ::Config::default()) @@ -1908,7 +1919,7 @@ pub fn new_with_mode<'d, MODE: WifiDeviceMode>( /// /// Returns a tuple of `(AP device, STA device, controller)`. pub fn new_ap_sta<'d>( - inited: &EspWifiInitialization, + inited: &'d EspWifiController<'d>, device: impl Peripheral

+ 'd, ) -> Result< ( @@ -1925,7 +1936,7 @@ pub fn new_ap_sta<'d>( /// /// Returns a tuple of `(AP device, STA device, controller)`. pub fn new_ap_sta_with_config<'d>( - inited: &EspWifiInitialization, + inited: &'d EspWifiController<'d>, device: impl Peripheral

+ 'd, sta_config: crate::wifi::ClientConfiguration, ap_config: crate::wifi::AccessPointConfiguration, @@ -2448,8 +2459,9 @@ impl Sniffer { pub(crate) fn new() -> Self { // This shouldn't fail, since the way this is created, means that wifi will // always be initialized. - esp_wifi_result!(unsafe { esp_wifi_set_promiscuous_rx_cb(Some(promiscuous_rx_cb)) }) - .unwrap(); + unwrap!(esp_wifi_result!(unsafe { + esp_wifi_set_promiscuous_rx_cb(Some(promiscuous_rx_cb)) + })); Self { promiscuous_mode_enabled: AtomicBool::new(false), } @@ -2493,14 +2505,29 @@ pub struct WifiController<'d> { sniffer_taken: AtomicBool, } +impl<'d> Drop for WifiController<'d> { + fn drop(&mut self) { + if unwrap!( + crate::flags::WIFI.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| { + Some(x.saturating_sub(1)) + }) + ) == 0 + { + if let Err(e) = crate::wifi::wifi_deinit() { + warn!("Failed to cleanly deinit wifi: {:?}", e); + } + } + } +} + impl<'d> WifiController<'d> { pub(crate) fn new_with_config( - inited: &EspWifiInitialization, + inited: &'d EspWifiController<'d>, _device: PeripheralRef<'d, crate::hal::peripherals::WIFI>, config: Configuration, ) -> Result { - if !inited.is_wifi() { - return Err(WifiError::NotInitialized); + if !inited.wifi() { + crate::wifi::wifi_init()?; } // We set up the controller with the default config because we need to call diff --git a/esp-wifi/src/wifi/utils.rs b/esp-wifi/src/wifi/utils.rs index 1eb5da3a2..e48f28f8d 100644 --- a/esp-wifi/src/wifi/utils.rs +++ b/esp-wifi/src/wifi/utils.rs @@ -8,7 +8,7 @@ use smoltcp::{ }; use super::{WifiApDevice, WifiController, WifiDevice, WifiDeviceMode, WifiError, WifiStaDevice}; -use crate::{timestamp, EspWifiInitialization}; +use crate::{timestamp, EspWifiController}; fn setup_iface<'a, MODE: WifiDeviceMode>( device: &mut WifiDevice<'_, MODE>, @@ -38,7 +38,7 @@ fn setup_iface<'a, MODE: WifiDeviceMode>( /// You can use the provided macros to create and pass a suitable backing /// storage. pub fn create_network_interface<'a, 'd, MODE: WifiDeviceMode>( - inited: &EspWifiInitialization, + inited: &'d EspWifiController<'d>, device: impl crate::hal::peripheral::Peripheral

+ 'd, mode: MODE, storage: &'a mut [SocketStorage<'a>], @@ -69,7 +69,7 @@ pub struct ApStaInterface<'a, 'd> { } pub fn create_ap_sta_network_interface<'a, 'd>( - inited: &EspWifiInitialization, + inited: &'d EspWifiController<'d>, device: impl crate::hal::peripheral::Peripheral

+ 'd, ap_storage: &'a mut [SocketStorage<'a>], sta_storage: &'a mut [SocketStorage<'a>], diff --git a/examples/Cargo.toml b/examples/Cargo.toml index d3aeba474..c9af37737 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -30,7 +30,7 @@ esp-hal-embassy = { path = "../esp-hal-embassy", optional = true } esp-ieee802154 = { path = "../esp-ieee802154", optional = true } esp-println = { path = "../esp-println", features = ["log"] } esp-storage = { path = "../esp-storage", optional = true } -esp-wifi = { path = "../esp-wifi", optional = true } +esp-wifi = { path = "../esp-wifi", features = ["log"], optional = true } fugit = "0.3.7" heapless = "0.8.0" hmac = { version = "0.12.1", default-features = false } diff --git a/examples/src/bin/wifi_80211_tx.rs b/examples/src/bin/wifi_80211_tx.rs index 8cc6deb75..c073ce127 100644 --- a/examples/src/bin/wifi_80211_tx.rs +++ b/examples/src/bin/wifi_80211_tx.rs @@ -13,13 +13,8 @@ use core::marker::PhantomData; use esp_alloc as _; use esp_backtrace as _; -use esp_hal::{ - delay::Delay, - prelude::*, - rng::Rng, - timer::{timg::TimerGroup, AnyTimer, PeriodicTimer}, -}; -use esp_wifi::{init, wifi, EspWifiInitFor}; +use esp_hal::{delay::Delay, prelude::*, rng::Rng, timer::timg::TimerGroup}; +use esp_wifi::{init, wifi}; use ieee80211::{ common::{CapabilitiesInformation, FCFFlags}, element_chain, @@ -47,12 +42,9 @@ fn main() -> ! { let delay = Delay::new(); let timg0 = TimerGroup::new(peripherals.TIMG0); - let timer0: AnyTimer = timg0.timer0.into(); - let timer = PeriodicTimer::new(timer0); let init = init( - EspWifiInitFor::Wifi, - timer, + timg0.timer0, Rng::new(peripherals.RNG), peripherals.RADIO_CLK, ) diff --git a/examples/src/bin/wifi_access_point.rs b/examples/src/bin/wifi_access_point.rs index fec2923ff..a4e803285 100644 --- a/examples/src/bin/wifi_access_point.rs +++ b/examples/src/bin/wifi_access_point.rs @@ -33,7 +33,6 @@ use esp_wifi::{ WifiApDevice, }, wifi_interface::WifiStack, - EspWifiInitFor, }; use smoltcp::iface::SocketStorage; @@ -51,7 +50,6 @@ fn main() -> ! { let timg0 = TimerGroup::new(peripherals.TIMG0); let init = init( - EspWifiInitFor::Wifi, timg0.timer0, Rng::new(peripherals.RNG), peripherals.RADIO_CLK, diff --git a/examples/src/bin/wifi_access_point_with_sta.rs b/examples/src/bin/wifi_access_point_with_sta.rs index 03f963c4c..36e175128 100644 --- a/examples/src/bin/wifi_access_point_with_sta.rs +++ b/examples/src/bin/wifi_access_point_with_sta.rs @@ -34,7 +34,6 @@ use esp_wifi::{ Configuration, }, wifi_interface::WifiStack, - EspWifiInitFor, }; use smoltcp::{ iface::SocketStorage, @@ -58,7 +57,6 @@ fn main() -> ! { let timg0 = TimerGroup::new(peripherals.TIMG0); let init = init( - EspWifiInitFor::Wifi, timg0.timer0, Rng::new(peripherals.RNG), peripherals.RADIO_CLK, diff --git a/examples/src/bin/wifi_bench.rs b/examples/src/bin/wifi_bench.rs index 4ab9e4fa1..06a474b8f 100644 --- a/examples/src/bin/wifi_bench.rs +++ b/examples/src/bin/wifi_bench.rs @@ -36,7 +36,6 @@ use esp_wifi::{ WifiStaDevice, }, wifi_interface::WifiStack, - EspWifiInitFor, }; use smoltcp::{ iface::SocketStorage, @@ -71,7 +70,6 @@ fn main() -> ! { let timg0 = TimerGroup::new(peripherals.TIMG0); let init = init( - EspWifiInitFor::Wifi, timg0.timer0, Rng::new(peripherals.RNG), peripherals.RADIO_CLK, diff --git a/examples/src/bin/wifi_ble.rs b/examples/src/bin/wifi_ble.rs index 4ba170f33..26ac4f4be 100644 --- a/examples/src/bin/wifi_ble.rs +++ b/examples/src/bin/wifi_ble.rs @@ -32,7 +32,7 @@ use esp_hal::{ timer::timg::TimerGroup, }; use esp_println::println; -use esp_wifi::{ble::controller::BleConnector, init, EspWifiInitFor}; +use esp_wifi::{ble::controller::BleConnector, init}; #[entry] fn main() -> ! { @@ -48,7 +48,6 @@ fn main() -> ! { let timg0 = TimerGroup::new(peripherals.TIMG0); let init = init( - EspWifiInitFor::Ble, timg0.timer0, Rng::new(peripherals.RNG), peripherals.RADIO_CLK, diff --git a/examples/src/bin/wifi_coex.rs b/examples/src/bin/wifi_coex.rs index ad0e92e81..a8c779d11 100644 --- a/examples/src/bin/wifi_coex.rs +++ b/examples/src/bin/wifi_coex.rs @@ -41,7 +41,6 @@ use esp_wifi::{ init, wifi::{utils::create_network_interface, ClientConfiguration, Configuration, WifiStaDevice}, wifi_interface::WifiStack, - EspWifiInitFor, }; use smoltcp::{ iface::SocketStorage, @@ -83,7 +82,6 @@ fn main() -> ! { let timg0 = TimerGroup::new(peripherals.TIMG0); let init = init( - EspWifiInitFor::WifiBle, timg0.timer0, Rng::new(peripherals.RNG), peripherals.RADIO_CLK, diff --git a/examples/src/bin/wifi_dhcp.rs b/examples/src/bin/wifi_dhcp.rs index c223de675..68f642c3d 100644 --- a/examples/src/bin/wifi_dhcp.rs +++ b/examples/src/bin/wifi_dhcp.rs @@ -35,7 +35,6 @@ use esp_wifi::{ WifiStaDevice, }, wifi_interface::WifiStack, - EspWifiInitFor, }; use smoltcp::{ iface::SocketStorage, @@ -59,7 +58,6 @@ fn main() -> ! { let timg0 = TimerGroup::new(peripherals.TIMG0); let init = init( - EspWifiInitFor::Wifi, timg0.timer0, Rng::new(peripherals.RNG), peripherals.RADIO_CLK, diff --git a/examples/src/bin/wifi_embassy_access_point.rs b/examples/src/bin/wifi_embassy_access_point.rs index d99dd331c..748df8ccb 100644 --- a/examples/src/bin/wifi_embassy_access_point.rs +++ b/examples/src/bin/wifi_embassy_access_point.rs @@ -41,7 +41,7 @@ use esp_wifi::{ WifiEvent, WifiState, }, - EspWifiInitFor, + EspWifiController, }; // When you are okay with using a nightly compiler it's better to use https://docs.rs/static_cell/2.1.0/static_cell/macro.make_static.html @@ -67,13 +67,15 @@ async fn main(spawner: Spawner) -> ! { let timg0 = TimerGroup::new(peripherals.TIMG0); - let init = init( - EspWifiInitFor::Wifi, - timg0.timer0, - Rng::new(peripherals.RNG), - peripherals.RADIO_CLK, - ) - .unwrap(); + let init = &*mk_static!( + EspWifiController<'static>, + init( + timg0.timer0, + Rng::new(peripherals.RNG), + peripherals.RADIO_CLK, + ) + .unwrap() + ); let wifi = peripherals.WIFI; let (wifi_interface, controller) = diff --git a/examples/src/bin/wifi_embassy_access_point_with_sta.rs b/examples/src/bin/wifi_embassy_access_point_with_sta.rs index 8beb0f163..82f748055 100644 --- a/examples/src/bin/wifi_embassy_access_point_with_sta.rs +++ b/examples/src/bin/wifi_embassy_access_point_with_sta.rs @@ -46,7 +46,7 @@ use esp_wifi::{ WifiStaDevice, WifiState, }, - EspWifiInitFor, + EspWifiController, }; const SSID: &str = env!("SSID"); @@ -75,13 +75,15 @@ async fn main(spawner: Spawner) -> ! { let timg0 = TimerGroup::new(peripherals.TIMG0); - let init = init( - EspWifiInitFor::Wifi, - timg0.timer0, - Rng::new(peripherals.RNG), - peripherals.RADIO_CLK, - ) - .unwrap(); + let init = &*mk_static!( + EspWifiController<'static>, + init( + timg0.timer0, + Rng::new(peripherals.RNG), + peripherals.RADIO_CLK, + ) + .unwrap() + ); let wifi = peripherals.WIFI; let (wifi_ap_interface, wifi_sta_interface, mut controller) = diff --git a/examples/src/bin/wifi_embassy_bench.rs b/examples/src/bin/wifi_embassy_bench.rs index 6659ed604..80334b862 100644 --- a/examples/src/bin/wifi_embassy_bench.rs +++ b/examples/src/bin/wifi_embassy_bench.rs @@ -36,7 +36,7 @@ use esp_wifi::{ WifiStaDevice, WifiState, }, - EspWifiInitFor, + EspWifiController, }; // When you are okay with using a nightly compiler it's better to use https://docs.rs/static_cell/2.1.0/static_cell/macro.make_static.html @@ -98,13 +98,15 @@ async fn main(spawner: Spawner) -> ! { let timg0 = TimerGroup::new(peripherals.TIMG0); - let init = init( - EspWifiInitFor::Wifi, - timg0.timer0, - Rng::new(peripherals.RNG), - peripherals.RADIO_CLK, - ) - .unwrap(); + let init = &*mk_static!( + EspWifiController<'static>, + init( + timg0.timer0, + Rng::new(peripherals.RNG), + peripherals.RADIO_CLK, + ) + .unwrap() + ); let wifi = peripherals.WIFI; let (wifi_interface, controller) = diff --git a/examples/src/bin/wifi_embassy_ble.rs b/examples/src/bin/wifi_embassy_ble.rs index f9ab2b322..3fb6d0dd1 100644 --- a/examples/src/bin/wifi_embassy_ble.rs +++ b/examples/src/bin/wifi_embassy_ble.rs @@ -35,7 +35,17 @@ use esp_hal::{ timer::timg::TimerGroup, }; use esp_println::println; -use esp_wifi::{ble::controller::asynch::BleConnector, init, EspWifiInitFor}; +use esp_wifi::{ble::controller::BleConnector, init, EspWifiController}; + +// When you are okay with using a nightly compiler it's better to use https://docs.rs/static_cell/2.1.0/static_cell/macro.make_static.html +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 + }}; +} #[esp_hal_embassy::main] async fn main(_spawner: Spawner) -> ! { @@ -50,13 +60,15 @@ async fn main(_spawner: Spawner) -> ! { let timg0 = TimerGroup::new(peripherals.TIMG0); - let init = init( - EspWifiInitFor::Ble, - timg0.timer0, - Rng::new(peripherals.RNG), - peripherals.RADIO_CLK, - ) - .unwrap(); + let init = &*mk_static!( + EspWifiController<'static>, + init( + timg0.timer0, + Rng::new(peripherals.RNG), + peripherals.RADIO_CLK, + ) + .unwrap() + ); let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); cfg_if::cfg_if! { diff --git a/examples/src/bin/wifi_embassy_dhcp.rs b/examples/src/bin/wifi_embassy_dhcp.rs index 65f4443ce..5ee5bb322 100644 --- a/examples/src/bin/wifi_embassy_dhcp.rs +++ b/examples/src/bin/wifi_embassy_dhcp.rs @@ -32,7 +32,7 @@ use esp_wifi::{ WifiStaDevice, WifiState, }, - EspWifiInitFor, + EspWifiController, }; // When you are okay with using a nightly compiler it's better to use https://docs.rs/static_cell/2.1.0/static_cell/macro.make_static.html @@ -61,13 +61,15 @@ async fn main(spawner: Spawner) -> ! { let timg0 = TimerGroup::new(peripherals.TIMG0); - let init = init( - EspWifiInitFor::Wifi, - timg0.timer0, - Rng::new(peripherals.RNG), - peripherals.RADIO_CLK, - ) - .unwrap(); + let init = &*mk_static!( + EspWifiController<'static>, + init( + timg0.timer0, + Rng::new(peripherals.RNG), + peripherals.RADIO_CLK, + ) + .unwrap() + ); let wifi = peripherals.WIFI; let (wifi_interface, controller) = diff --git a/examples/src/bin/wifi_embassy_esp_now.rs b/examples/src/bin/wifi_embassy_esp_now.rs index ada751521..3b7aecd43 100644 --- a/examples/src/bin/wifi_embassy_esp_now.rs +++ b/examples/src/bin/wifi_embassy_esp_now.rs @@ -20,9 +20,19 @@ use esp_println::println; use esp_wifi::{ esp_now::{PeerInfo, BROADCAST_ADDRESS}, init, - EspWifiInitFor, + EspWifiController, }; +// When you are okay with using a nightly compiler it's better to use https://docs.rs/static_cell/2.1.0/static_cell/macro.make_static.html +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 + }}; +} + #[esp_hal_embassy::main] async fn main(_spawner: Spawner) -> ! { esp_println::logger::init_logger_from_env(); @@ -36,13 +46,15 @@ async fn main(_spawner: Spawner) -> ! { let timg0 = TimerGroup::new(peripherals.TIMG0); - let init = init( - EspWifiInitFor::Wifi, - timg0.timer0, - Rng::new(peripherals.RNG), - peripherals.RADIO_CLK, - ) - .unwrap(); + let init = &*mk_static!( + EspWifiController<'static>, + init( + timg0.timer0, + Rng::new(peripherals.RNG), + peripherals.RADIO_CLK, + ) + .unwrap() + ); let wifi = peripherals.WIFI; let mut esp_now = esp_wifi::esp_now::EspNow::new(&init, wifi).unwrap(); diff --git a/examples/src/bin/wifi_embassy_esp_now_duplex.rs b/examples/src/bin/wifi_embassy_esp_now_duplex.rs index 270a68a7a..1eeec3a88 100644 --- a/examples/src/bin/wifi_embassy_esp_now_duplex.rs +++ b/examples/src/bin/wifi_embassy_esp_now_duplex.rs @@ -20,7 +20,7 @@ use esp_println::println; use esp_wifi::{ esp_now::{EspNowManager, EspNowReceiver, EspNowSender, PeerInfo, BROADCAST_ADDRESS}, init, - EspWifiInitFor, + EspWifiController, }; // When you are okay with using a nightly compiler it's better to use https://docs.rs/static_cell/2.1.0/static_cell/macro.make_static.html @@ -46,13 +46,15 @@ async fn main(spawner: Spawner) -> ! { let timg0 = TimerGroup::new(peripherals.TIMG0); - let init = init( - EspWifiInitFor::Wifi, - timg0.timer0, - Rng::new(peripherals.RNG), - peripherals.RADIO_CLK, - ) - .unwrap(); + let init = &*mk_static!( + EspWifiController<'static>, + init( + timg0.timer0, + Rng::new(peripherals.RNG), + peripherals.RADIO_CLK, + ) + .unwrap() + ); let wifi = peripherals.WIFI; let esp_now = esp_wifi::esp_now::EspNow::new(&init, wifi).unwrap(); diff --git a/examples/src/bin/wifi_embassy_trouble.rs b/examples/src/bin/wifi_embassy_trouble.rs index 2e3d66724..45253463a 100644 --- a/examples/src/bin/wifi_embassy_trouble.rs +++ b/examples/src/bin/wifi_embassy_trouble.rs @@ -18,8 +18,8 @@ use embassy_sync::blocking_mutex::raw::NoopRawMutex; use embassy_time::{Duration, Timer}; use esp_alloc as _; use esp_backtrace as _; -use esp_hal::{prelude::*, timer::timg::TimerGroup}; -use esp_wifi::ble::controller::asynch::BleConnector; +use esp_hal::{prelude::*, rng::Rng, timer::timg::TimerGroup}; +use esp_wifi::{ble::controller::BleConnector, init, EspWifiController}; use log::*; use static_cell::StaticCell; use trouble_host::{ @@ -31,6 +31,16 @@ use trouble_host::{ PacketQos, }; +// When you are okay with using a nightly compiler it's better to use https://docs.rs/static_cell/2.1.0/static_cell/macro.make_static.html +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 + }}; +} + #[esp_hal_embassy::main] async fn main(_s: Spawner) { esp_println::logger::init_logger_from_env(); @@ -44,13 +54,15 @@ async fn main(_s: Spawner) { let timg0 = TimerGroup::new(peripherals.TIMG0); - let init = esp_wifi::init( - esp_wifi::EspWifiInitFor::Ble, - timg0.timer0, - esp_hal::rng::Rng::new(peripherals.RNG), - peripherals.RADIO_CLK, - ) - .unwrap(); + let init = &*mk_static!( + EspWifiController<'static>, + init( + timg0.timer0, + Rng::new(peripherals.RNG), + peripherals.RADIO_CLK, + ) + .unwrap() + ); #[cfg(feature = "esp32")] { diff --git a/examples/src/bin/wifi_esp_now.rs b/examples/src/bin/wifi_esp_now.rs index 294bddc1e..0b3a268db 100644 --- a/examples/src/bin/wifi_esp_now.rs +++ b/examples/src/bin/wifi_esp_now.rs @@ -20,7 +20,6 @@ use esp_println::println; use esp_wifi::{ esp_now::{PeerInfo, BROADCAST_ADDRESS}, init, - EspWifiInitFor, }; #[entry] @@ -37,7 +36,6 @@ fn main() -> ! { let timg0 = TimerGroup::new(peripherals.TIMG0); let init = init( - EspWifiInitFor::Wifi, timg0.timer0, Rng::new(peripherals.RNG), peripherals.RADIO_CLK, diff --git a/examples/src/bin/wifi_sniffer.rs b/examples/src/bin/wifi_sniffer.rs index 2e82c66f5..4e56d6338 100644 --- a/examples/src/bin/wifi_sniffer.rs +++ b/examples/src/bin/wifi_sniffer.rs @@ -19,13 +19,9 @@ use core::cell::RefCell; use critical_section::Mutex; use esp_backtrace as _; -use esp_hal::{ - prelude::*, - rng::Rng, - timer::{timg::TimerGroup, AnyTimer, PeriodicTimer}, -}; +use esp_hal::{prelude::*, rng::Rng, timer::timg::TimerGroup}; use esp_println::println; -use esp_wifi::{init, wifi, EspWifiInitFor}; +use esp_wifi::{init, wifi}; use ieee80211::{match_frames, mgmt_frame::BeaconFrame}; static KNOWN_SSIDS: Mutex>> = Mutex::new(RefCell::new(BTreeSet::new())); @@ -42,12 +38,8 @@ fn main() -> ! { esp_alloc::heap_allocator!(72 * 1024); let timg0 = TimerGroup::new(peripherals.TIMG0); - let timer0: AnyTimer = timg0.timer0.into(); - let timer = PeriodicTimer::new(timer0); - let init = init( - EspWifiInitFor::Wifi, - timer, + timg0.timer0, Rng::new(peripherals.RNG), peripherals.RADIO_CLK, ) diff --git a/examples/src/bin/wifi_static_ip.rs b/examples/src/bin/wifi_static_ip.rs index 4e0742e30..e9a91fe1f 100644 --- a/examples/src/bin/wifi_static_ip.rs +++ b/examples/src/bin/wifi_static_ip.rs @@ -34,7 +34,6 @@ use esp_wifi::{ WifiStaDevice, }, wifi_interface::WifiStack, - EspWifiInitFor, }; use smoltcp::iface::SocketStorage; @@ -57,7 +56,6 @@ fn main() -> ! { let timg0 = TimerGroup::new(peripherals.TIMG0); let init = init( - EspWifiInitFor::Wifi, timg0.timer0, Rng::new(peripherals.RNG), peripherals.RADIO_CLK, diff --git a/hil-test/tests/esp_wifi_floats.rs b/hil-test/tests/esp_wifi_floats.rs index 0b9a82c8a..f04fe7283 100644 --- a/hil-test/tests/esp_wifi_floats.rs +++ b/hil-test/tests/esp_wifi_floats.rs @@ -17,7 +17,6 @@ use esp_hal::{ rng::Rng, timer::timg::TimerGroup, }; -use esp_wifi::{init, EspWifiInitFor}; use hil_test as _; #[inline(never)] @@ -101,8 +100,7 @@ mod tests { #[timeout(3)] fn fpu_stays_enabled_with_wifi(peripherals: Peripherals) { let timg0 = TimerGroup::new(peripherals.TIMG0); - let _init = init( - EspWifiInitFor::Wifi, + let _init = esp_wifi::init( timg0.timer1, Rng::new(peripherals.RNG), peripherals.RADIO_CLK, @@ -138,8 +136,7 @@ mod tests { unsafe { &mut *core::ptr::addr_of_mut!(APP_CORE_STACK) }, move || { let timg0 = TimerGroup::new(peripherals.TIMG0); - let _init = init( - EspWifiInitFor::Wifi, + let _init = esp_wifi::init( timg0.timer1, Rng::new(peripherals.RNG), peripherals.RADIO_CLK,