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
This commit is contained in:
Scott Mabin 2024-11-04 08:08:19 +00:00 committed by GitHub
parent f9ba299f2e
commit c717f04d4d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
36 changed files with 358 additions and 348 deletions

View File

@ -130,10 +130,7 @@ impl rand_core::RngCore for Rng {
/// the randomness from the hardware RNG and an ADC. This struct provides /// the randomness from the hardware RNG and an ADC. This struct provides
/// methods to generate random numbers and fill buffers with random bytes. /// methods to generate random numbers and fill buffers with random bytes.
/// Due to pulling the entropy source from the ADC, it uses the associated /// 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. /// registers, 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)
/// ///
/// ```rust, no_run /// ```rust, no_run
#[doc = crate::before_snippet!()] #[doc = crate::before_snippet!()]

View File

@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed ### 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) - No need to add `rom_functions.x` manually anymore (#2374)
- esp-now: Data is now private in `ReceivedData` - use `data()`(#2396) - esp-now: Data is now private in `ReceivedData` - use `data()`(#2396)

View File

@ -39,6 +39,7 @@ libm = "0.2.8"
cfg-if = "1.0.0" cfg-if = "1.0.0"
portable-atomic = { version = "1.9.0", default-features = false } portable-atomic = { version = "1.9.0", default-features = false }
portable_atomic_enum = { version = "0.3.1", features = ["portable-atomic"] } portable_atomic_enum = { version = "0.3.1", features = ["portable-atomic"] }
rand_core = "0.6.4"
bt-hci = { version = "0.1.1", optional = true } bt-hci = { version = "0.1.1", optional = true }
esp-config = { version = "0.1.0", path = "../esp-config" } esp-config = { version = "0.1.0", path = "../esp-config" }

View File

@ -1,5 +1,22 @@
# Migration Guide from 0.10.x to v0.11.x # 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 ## No need to include `rom_functions.x` manually
Don't include `rom_functions.x` from esp-wifi Don't include `rom_functions.x` from esp-wifi

View File

@ -442,6 +442,7 @@ pub(crate) fn ble_init() {
API_vhci_host_register_callback(&VHCI_HOST_CALLBACK); API_vhci_host_register_callback(&VHCI_HOST_CALLBACK);
} }
crate::flags::BLE.store(true, Ordering::Release);
} }
pub(crate) fn ble_deinit() { pub(crate) fn ble_deinit() {
@ -453,6 +454,7 @@ pub(crate) fn ble_deinit() {
btdm_controller_deinit(); btdm_controller_deinit();
crate::common_adapter::chip_specific::phy_disable(); crate::common_adapter::chip_specific::phy_disable();
} }
crate::flags::BLE.store(false, Ordering::Release);
} }
pub fn send_hci(data: &[u8]) { pub fn send_hci(data: &[u8]) {

View File

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

View File

@ -9,7 +9,7 @@ pub(crate) mod npl;
use alloc::{boxed::Box, collections::vec_deque::VecDeque, vec::Vec}; use alloc::{boxed::Box, collections::vec_deque::VecDeque, vec::Vec};
use core::{cell::RefCell, mem::MaybeUninit}; 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; use critical_section::Mutex;
#[cfg(any(esp32, esp32c3, esp32s3))] #[cfg(any(esp32, esp32c3, esp32s3))]

View File

@ -2,6 +2,7 @@ use alloc::boxed::Box;
use core::{ use core::{
mem::size_of_val, mem::size_of_val,
ptr::{addr_of, addr_of_mut}, ptr::{addr_of, addr_of_mut},
sync::atomic::Ordering,
}; };
use super::*; use super::*;
@ -1179,6 +1180,7 @@ pub(crate) fn ble_init() {
debug!("The ble_controller_init was initialized"); debug!("The ble_controller_init was initialized");
} }
crate::flags::BLE.store(true, Ordering::Release);
} }
pub(crate) fn ble_deinit() { pub(crate) fn ble_deinit() {
@ -1205,6 +1207,7 @@ pub(crate) fn ble_deinit() {
crate::common_adapter::chip_specific::phy_disable(); crate::common_adapter::chip_specific::phy_disable();
} }
crate::flags::BLE.store(false, Ordering::Release);
} }
#[cfg(esp32c2)] #[cfg(esp32c2)]

View File

@ -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 { unsafe extern "C" fn strcmp(str1: *const i8, str2: *const i8) -> i32 {
trace!("strcmp {:?} {:?}", str1, str2); trace!("strcmp {:?} {:?}", str1, str2);
// TODO: unwrap!() when defmt supports it
let s1 = core::ffi::CStr::from_ptr(str1).to_str().unwrap(); let s1 = core::ffi::CStr::from_ptr(str1).to_str().unwrap();
let s2 = core::ffi::CStr::from_ptr(str2).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 { unsafe {
let s = core::ffi::CStr::from_ptr(str); 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); let p = malloc(s.len() + 1);
core::ptr::copy_nonoverlapping(str, p as *mut i8, s.len() + 1); core::ptr::copy_nonoverlapping(str, p as *mut i8, s.len() + 1);

View File

@ -19,8 +19,8 @@ use portable_atomic::{AtomicBool, AtomicU8, Ordering};
use crate::{ use crate::{
binary::include::*, binary::include::*,
hal::peripheral::{Peripheral, PeripheralRef}, hal::peripheral::{Peripheral, PeripheralRef},
wifi::{Protocol, RxControlInfo}, wifi::{Protocol, RxControlInfo, WifiError},
EspWifiInitialization, EspWifiController,
}; };
const RECEIVE_QUEUE_SIZE: usize = 10; const RECEIVE_QUEUE_SIZE: usize = 10;
@ -113,6 +113,14 @@ pub enum EspNowError {
SendFailed, SendFailed,
/// Attempt to create `EspNow` instance twice. /// Attempt to create `EspNow` instance twice.
DuplicateInstance, DuplicateInstance,
/// Initialization error
Initialization(WifiError),
}
impl From<WifiError> for EspNowError {
fn from(f: WifiError) -> Self {
Self::Initialization(f)
}
} }
/// Holds the count of peers in an ESP-NOW communication context. /// 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 /// This is the sender part of ESP-NOW. You can get this sender by splitting
/// a `EspNow` instance. /// a `EspNow` instance.
/// ///
@ -607,16 +630,16 @@ impl Drop for EspNowRc<'_> {
/// Currently this implementation (when used together with traditional Wi-Fi) /// Currently this implementation (when used together with traditional Wi-Fi)
/// ONLY support STA mode. /// ONLY support STA mode.
pub struct EspNow<'d> { pub struct EspNow<'d> {
_device: Option<PeripheralRef<'d, crate::hal::peripherals::WIFI>>,
manager: EspNowManager<'d>, manager: EspNowManager<'d>,
sender: EspNowSender<'d>, sender: EspNowSender<'d>,
receiver: EspNowReceiver<'d>, receiver: EspNowReceiver<'d>,
_phantom: PhantomData<&'d ()>,
} }
impl<'d> EspNow<'d> { impl<'d> EspNow<'d> {
/// Creates an `EspNow` instance. /// Creates an `EspNow` instance.
pub fn new( pub fn new(
inited: &EspWifiInitialization, inited: &'d EspWifiController<'d>,
device: impl Peripheral<P = crate::hal::peripherals::WIFI> + 'd, device: impl Peripheral<P = crate::hal::peripherals::WIFI> + 'd,
) -> Result<EspNow<'d>, EspNowError> { ) -> Result<EspNow<'d>, EspNowError> {
EspNow::new_internal(inited, Some(device.into_ref())) 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. /// Creates an `EspNow` instance with support for Wi-Fi coexistence.
pub fn new_with_wifi( pub fn new_with_wifi(
inited: &EspWifiInitialization, inited: &'d EspWifiController<'d>,
_token: EspNowWithWifiCreateToken, _token: EspNowWithWifiCreateToken,
) -> Result<EspNow<'d>, EspNowError> { ) -> Result<EspNow<'d>, EspNowError> {
EspNow::new_internal( EspNow::new_internal(
@ -634,16 +657,17 @@ impl<'d> EspNow<'d> {
} }
fn new_internal( fn new_internal(
inited: &EspWifiInitialization, inited: &'d EspWifiController<'d>,
device: Option<PeripheralRef<'d, crate::hal::peripherals::WIFI>>, device: Option<PeripheralRef<'d, crate::hal::peripherals::WIFI>>,
) -> Result<EspNow<'d>, EspNowError> { ) -> Result<EspNow<'d>, EspNowError> {
if !inited.is_wifi() { if !inited.wifi() {
return Err(EspNowError::Error(Error::NotInitialized)); // 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 espnow_rc = EspNowRc::new()?;
let esp_now = EspNow { let esp_now = EspNow {
_device: device,
manager: EspNowManager { manager: EspNowManager {
_rc: espnow_rc.clone(), _rc: espnow_rc.clone(),
}, },
@ -651,6 +675,7 @@ impl<'d> EspNow<'d> {
_rc: espnow_rc.clone(), _rc: espnow_rc.clone(),
}, },
receiver: EspNowReceiver { _rc: espnow_rc }, receiver: EspNowReceiver { _rc: espnow_rc },
_phantom: PhantomData,
}; };
check_error!({ esp_wifi_set_mode(wifi_mode_t_WIFI_MODE_STA) })?; check_error!({ esp_wifi_set_mode(wifi_mode_t_WIFI_MODE_STA) })?;
check_error!({ esp_wifi_start() })?; check_error!({ esp_wifi_start() })?;

View File

@ -93,25 +93,25 @@ extern crate alloc;
// MUST be the first module // MUST be the first module
mod fmt; mod fmt;
use core::marker::PhantomData;
use common_adapter::chip_specific::phy_mem_init; use common_adapter::chip_specific::phy_mem_init;
use esp_config::*; use esp_config::*;
use esp_hal as hal; use esp_hal as hal;
use esp_hal::peripheral::Peripheral;
#[cfg(not(feature = "esp32"))] #[cfg(not(feature = "esp32"))]
use esp_hal::timer::systimer::Alarm; use esp_hal::timer::systimer::Alarm;
use fugit::MegahertzU32; use fugit::MegahertzU32;
use hal::{ use hal::{
clock::Clocks, clock::Clocks,
rng::{Rng, Trng},
system::RadioClockController, system::RadioClockController,
timer::{timg::Timer as TimgTimer, AnyTimer, PeriodicTimer}, timer::{timg::Timer as TimgTimer, AnyTimer, PeriodicTimer},
}; };
#[cfg(feature = "wifi")] use portable_atomic::Ordering;
use num_traits::FromPrimitive;
#[cfg(feature = "wifi")] #[cfg(feature = "wifi")]
use crate::{ use crate::wifi::WifiError;
binary::include::{self, esp_supplicant_deinit, esp_wifi_deinit_internal, esp_wifi_stop},
wifi::WifiError,
};
use crate::{ use crate::{
tasks::init_tasks, tasks::init_tasks,
timer::{setup_timer_isr, shutdown_timer_isr}, timer::{setup_timer_isr, shutdown_timer_isr},
@ -233,73 +233,53 @@ const _: () = {
type TimeBase = PeriodicTimer<'static, AnyTimer>; type TimeBase = PeriodicTimer<'static, AnyTimer>;
#[derive(Debug, PartialEq, PartialOrd)] pub(crate) mod flags {
#[cfg_attr(feature = "defmt", derive(defmt::Format))] use portable_atomic::{AtomicBool, AtomicUsize};
#[non_exhaustive]
/// An internal struct designed to make [`EspWifiInitialization`] uncreatable
/// outside of this crate.
pub struct EspWifiInitializationInternal;
#[derive(Debug, PartialEq, PartialOrd)] pub(crate) static ESP_WIFI_INITIALIZED: AtomicBool = AtomicBool::new(false);
#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub(crate) static WIFI: AtomicUsize = AtomicUsize::new(0);
/// Initialized the driver for WiFi, Bluetooth or both. pub(crate) static BLE: AtomicBool = AtomicBool::new(false);
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,
}
}
} }
#[derive(Debug, PartialEq, PartialOrd)] #[derive(Debug, PartialEq, PartialOrd)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
/// Initialize the driver for WiFi, Bluetooth or both. pub struct EspWifiController<'d> {
pub enum EspWifiInitFor { _inner: PhantomData<&'d ()>,
#[cfg(feature = "wifi")]
Wifi,
#[cfg(feature = "ble")]
Ble,
#[cfg(coex)]
WifiBle,
} }
impl EspWifiInitFor { impl<'d> EspWifiController<'d> {
#[allow(unused)] /// Is the WiFi part of the radio running
fn is_wifi(&self) -> bool { pub fn wifi(&self) -> bool {
match self { crate::flags::WIFI.load(Ordering::Acquire) > 0
#[cfg(feature = "ble")] }
EspWifiInitFor::Ble => false,
_ => true, /// 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)] pub(crate) unsafe fn conjure() -> Self {
fn is_ble(&self) -> bool { Self {
match self { _inner: PhantomData,
#[cfg(feature = "wifi")] }
EspWifiInitFor::Wifi => false, }
_ => true, }
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. /// This trait is meant to be used only for the `init` function.
/// Calling `timers()` multiple times may panic. /// Calling `timers()` multiple times may panic.
pub trait EspWifiTimerSource { pub trait EspWifiTimerSource: private::Sealed {
/// Returns the timer source. /// Returns the timer source.
fn timer(self) -> TimeBase; fn timer(self) -> TimeBase;
} }
@ -338,7 +318,7 @@ impl IntoAnyTimer for AnyTimer {}
impl<T> EspWifiTimerSource for T impl<T> EspWifiTimerSource for T
where where
T: IntoAnyTimer, T: IntoAnyTimer + private::Sealed,
{ {
fn timer(self) -> TimeBase { fn timer(self) -> TimeBase {
TimeBase::new(self.into()).timer() TimeBase::new(self.into()).timer()
@ -351,6 +331,29 @@ impl EspWifiTimerSource for TimeBase {
} }
} }
impl private::Sealed for TimeBase {}
impl<T, DM> private::Sealed for TimgTimer<T, DM>
where
DM: esp_hal::Mode,
Self: Into<AnyTimer>,
{
}
#[cfg(not(feature = "esp32"))]
impl<T, DM, COMP, UNIT> private::Sealed for Alarm<'_, T, DM, COMP, UNIT>
where
DM: esp_hal::Mode,
Self: Into<AnyTimer>,
{
}
/// 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. /// Initialize for using WiFi and or BLE.
/// ///
/// # The `timer` argument /// # The `timer` argument
@ -380,12 +383,11 @@ impl EspWifiTimerSource for TimeBase {
/// .unwrap(); /// .unwrap();
/// # } /// # }
/// ``` /// ```
pub fn init( pub fn init<'d, T: EspWifiTimerSource>(
init_for: EspWifiInitFor, timer: impl Peripheral<P = T> + 'd,
timer: impl EspWifiTimerSource, _rng: impl EspWifiRngSource,
_rng: hal::rng::Rng, _radio_clocks: impl Peripheral<P = hal::peripherals::RADIO_CLK> + 'd,
_radio_clocks: hal::peripherals::RADIO_CLK, ) -> Result<EspWifiController<'d>, InitializationError> {
) -> Result<EspWifiInitialization, InitializationError> {
// A minimum clock of 80MHz is required to operate WiFi module. // A minimum clock of 80MHz is required to operate WiFi module.
const MIN_CLOCK: u32 = 80; const MIN_CLOCK: u32 = 80;
let clocks = Clocks::get(); let clocks = Clocks::get();
@ -397,7 +399,7 @@ pub fn init(
crate::common_adapter::chip_specific::enable_wifi_power_domain(); crate::common_adapter::chip_specific::enable_wifi_power_domain();
phy_mem_init(); phy_mem_init();
init_tasks(); init_tasks();
setup_timer_isr(timer.timer())?; setup_timer_isr(unsafe { timer.clone_unchecked() }.timer());
wifi_set_log_verbose(); wifi_set_log_verbose();
init_clocks(); init_clocks();
@ -408,60 +410,23 @@ pub fn init(
error => return Err(InitializationError::General(error)), error => return Err(InitializationError::General(error)),
} }
#[cfg(feature = "wifi")] crate::flags::ESP_WIFI_INITIALIZED.store(true, Ordering::Release);
if init_for.is_wifi() {
debug!("wifi init");
// wifi init
crate::wifi::wifi_init()?;
}
#[cfg(feature = "ble")] Ok(EspWifiController {
if init_for.is_ble() { _inner: PhantomData,
// 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,
)),
}
} }
/// Deinitializes WiFi and/or BLE /// Deinitializes the entire radio stack
/// ///
/// After user calls this function, WiFi and/or BLE (depending on what has been /// This can be useful to shutdown the stack before going to sleep for example.
/// 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.
/// ///
/// # Safety /// # Safety
/// Actual implementation assumes that the user takes responsibility for how the ///
/// function is used. For example, after using this function, user should not /// The user must ensure that any use of the radio via the WIFI/BLE/ESP-NOW
/// use BLE or WiFi stack or controller instances (it is possible to /// drivers are complete, else undefined behavour may occur within those
/// reinitialize communication using the `init` function), not to call /// drivers.
/// `deinit_unsafe` before the first initialization, and so on. Also, there is pub unsafe fn deinit_unchecked() -> Result<(), InitializationError> {
/// 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> {
// Disable coexistence // Disable coexistence
#[cfg(coex)] #[cfg(coex)]
{ {
@ -469,33 +434,35 @@ pub unsafe fn deinit_unchecked(
unsafe { crate::wifi::os_adapter::coex_deinit() }; unsafe { crate::wifi::os_adapter::coex_deinit() };
} }
// Deinitialize WiFi let controller = unsafe { EspWifiController::conjure() };
#[cfg(feature = "wifi")]
if init.is_wifi() { // Peripheral drivers should already take care of shutting these down
esp_wifi_result!(unsafe { esp_wifi_stop() })?; // we have to check this in the case where a user calls `deinit_unchecked`
esp_wifi_result!(unsafe { esp_wifi_deinit_internal() })?; // directly.
esp_wifi_result!(esp_supplicant_deinit())?; if controller.wifi() {
#[cfg(feature = "wifi")]
crate::wifi::wifi_deinit()?;
crate::flags::WIFI.store(0, Ordering::Release);
} }
// Deinitialize BLE if controller.ble() {
#[cfg(feature = "ble")] #[cfg(feature = "ble")]
if init.is_ble() { crate::ble::ble_deinit();
#[cfg(any(esp32, esp32c3, esp32s3))] crate::flags::BLE.store(false, Ordering::Release);
crate::ble::btdm::ble_deinit();
#[cfg(any(esp32c2, esp32c6, esp32h2))]
crate::ble::npl::ble_deinit();
} }
shutdown_timer_isr().unwrap(); shutdown_timer_isr();
crate::preempt::delete_all_tasks(); crate::preempt::delete_all_tasks();
let timer = critical_section::with(|cs| crate::timer::TIMER.borrow_ref_mut(cs).take()) critical_section::with(|cs| crate::timer::TIMER.borrow_ref_mut(cs).take());
.ok_or(InitializationError::TimerUnavailable)?;
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)] #[derive(Debug, Clone, Copy)]
@ -506,15 +473,6 @@ pub enum InitializationError {
#[cfg(feature = "wifi")] #[cfg(feature = "wifi")]
WifiError(WifiError), WifiError(WifiError),
WrongClockConfig, WrongClockConfig,
Timer(hal::timer::Error),
TimerUnavailable,
RadioClockUnavailable,
}
impl From<hal::timer::Error> for InitializationError {
fn from(value: hal::timer::Error) -> Self {
InitializationError::Timer(value)
}
} }
#[cfg(feature = "wifi")] #[cfg(feature = "wifi")]

View File

@ -22,24 +22,22 @@ use crate::TimeBase;
pub(crate) static TIMER: Mutex<RefCell<Option<TimeBase>>> = Mutex::new(RefCell::new(None)); pub(crate) static TIMER: Mutex<RefCell<Option<TimeBase>>> = 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_radio_isr();
setup_timer(timebase)?; setup_timer(timebase);
setup_multitasking(); setup_multitasking();
yield_task(); yield_task();
Ok(())
} }
pub(crate) fn shutdown_timer_isr() -> Result<(), esp_hal::timer::Error> { pub(crate) fn shutdown_timer_isr() {
shutdown_radio_isr(); shutdown_radio_isr();
disable_timer()?; disable_timer();
disable_multitasking(); disable_multitasking();
Ok(())
} }
#[allow(unused)] #[allow(unused)]

View File

@ -23,28 +23,24 @@ pub const TICKS_PER_SECOND: u64 = 1_000_000;
use super::TIMER; 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 // make sure the scheduling won't start before everything is setup
riscv::interrupt::disable(); riscv::interrupt::disable();
let cb: extern "C" fn() = unsafe { core::mem::transmute(handler as *const ()) }; let cb: extern "C" fn() = unsafe { core::mem::transmute(handler as *const ()) };
alarm0.set_interrupt_handler(InterruptHandler::new(cb, interrupt::Priority::Priority1)); 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| { critical_section::with(|cs| {
alarm0.enable_interrupt(true); alarm0.enable_interrupt(true);
TIMER.borrow_ref_mut(cs).replace(alarm0); 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| { critical_section::with(|cs| {
unwrap!(TIMER.borrow_ref_mut(cs).as_mut()).enable_interrupt(false); 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() { pub(crate) fn setup_multitasking() {

View File

@ -21,26 +21,23 @@ pub(crate) fn get_systimer_count() -> u64 {
esp_hal::time::now().ticks() 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( timer1.set_interrupt_handler(InterruptHandler::new(
unsafe { core::mem::transmute::<*const (), extern "C" fn()>(handler as *const ()) }, unsafe { core::mem::transmute::<*const (), extern "C" fn()>(handler as *const ()) },
interrupt::Priority::Priority2, interrupt::Priority::Priority2,
)); ));
timer1.start(TIMESLICE_FREQUENCY.into_duration())?; unwrap!(timer1.start(TIMESLICE_FREQUENCY.into_duration()));
critical_section::with(|cs| { critical_section::with(|cs| {
timer1.enable_interrupt(true); timer1.enable_interrupt(true);
TIMER.borrow_ref_mut(cs).replace(timer1); 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| { critical_section::with(|cs| {
unwrap!(TIMER.borrow_ref_mut(cs).as_mut()).enable_interrupt(false); 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() { pub(crate) fn setup_multitasking() {

View File

@ -69,7 +69,7 @@ use crate::{
macros::ram, macros::ram,
peripheral::{Peripheral, PeripheralRef}, peripheral::{Peripheral, PeripheralRef},
}, },
EspWifiInitialization, EspWifiController,
}; };
const ETHERNET_FRAME_HEADER_SIZE: usize = 18; const ETHERNET_FRAME_HEADER_SIZE: usize = 18;
@ -90,8 +90,10 @@ use crate::binary::{
esp_err_t, esp_err_t,
esp_interface_t_ESP_IF_WIFI_AP, esp_interface_t_ESP_IF_WIFI_AP,
esp_interface_t_ESP_IF_WIFI_STA, esp_interface_t_ESP_IF_WIFI_STA,
esp_supplicant_deinit,
esp_supplicant_init, esp_supplicant_init,
esp_wifi_connect, esp_wifi_connect,
esp_wifi_deinit_internal,
esp_wifi_disconnect, esp_wifi_disconnect,
esp_wifi_get_mode, esp_wifi_get_mode,
esp_wifi_init_internal, esp_wifi_init_internal,
@ -281,7 +283,7 @@ pub struct AccessPointConfiguration {
impl Default for AccessPointConfiguration { impl Default for AccessPointConfiguration {
fn default() -> Self { fn default() -> Self {
Self { Self {
ssid: "iot-device".try_into().unwrap(), ssid: unwrap!("iot-device".try_into()),
ssid_hidden: false, ssid_hidden: false,
channel: 1, channel: 1,
secondary_channel: None, 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; chip_specific::g_misc_nvs = addr_of!(NVS_STRUCT) as u32;
} }
crate::flags::WIFI.fetch_add(1, Ordering::SeqCst);
Ok(()) 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( unsafe extern "C" fn recv_cb_sta(
buffer: *mut c_types::c_void, buffer: *mut c_types::c_void,
len: u16, len: u16,
@ -1654,11 +1665,11 @@ unsafe extern "C" fn recv_cb_ap(
pub(crate) static WIFI_TX_INFLIGHT: AtomicUsize = AtomicUsize::new(0); pub(crate) static WIFI_TX_INFLIGHT: AtomicUsize = AtomicUsize::new(0);
fn decrement_inflight_counter() { fn decrement_inflight_counter() {
WIFI_TX_INFLIGHT unwrap!(
.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| { WIFI_TX_INFLIGHT.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| {
Some(x.saturating_sub(1)) Some(x.saturating_sub(1))
}) })
.unwrap(); );
} }
#[ram] #[ram]
@ -1878,7 +1889,7 @@ pub(crate) fn wifi_start_scan(
/// ///
/// If you want to use AP-STA mode, use `[new_ap_sta]`. /// If you want to use AP-STA mode, use `[new_ap_sta]`.
pub fn new_with_config<'d, MODE: WifiDeviceMode>( pub fn new_with_config<'d, MODE: WifiDeviceMode>(
inited: &EspWifiInitialization, inited: &'d EspWifiController<'d>,
device: impl Peripheral<P = crate::hal::peripherals::WIFI> + 'd, device: impl Peripheral<P = crate::hal::peripherals::WIFI> + 'd,
config: MODE::Config, config: MODE::Config,
) -> Result<(WifiDevice<'d, MODE>, WifiController<'d>), WifiError> { ) -> 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`]. /// This function will panic if the mode is [`WifiMode::ApSta`].
/// If you want to use AP-STA mode, use `[new_ap_sta]`. /// If you want to use AP-STA mode, use `[new_ap_sta]`.
pub fn new_with_mode<'d, MODE: WifiDeviceMode>( pub fn new_with_mode<'d, MODE: WifiDeviceMode>(
inited: &EspWifiInitialization, inited: &'d EspWifiController<'d>,
device: impl crate::hal::peripheral::Peripheral<P = crate::hal::peripherals::WIFI> + 'd, device: impl Peripheral<P = crate::hal::peripherals::WIFI> + 'd,
_mode: MODE, _mode: MODE,
) -> Result<(WifiDevice<'d, MODE>, WifiController<'d>), WifiError> { ) -> Result<(WifiDevice<'d, MODE>, WifiController<'d>), WifiError> {
new_with_config(inited, device, <MODE as Sealed>::Config::default()) new_with_config(inited, device, <MODE as Sealed>::Config::default())
@ -1908,7 +1919,7 @@ pub fn new_with_mode<'d, MODE: WifiDeviceMode>(
/// ///
/// Returns a tuple of `(AP device, STA device, controller)`. /// Returns a tuple of `(AP device, STA device, controller)`.
pub fn new_ap_sta<'d>( pub fn new_ap_sta<'d>(
inited: &EspWifiInitialization, inited: &'d EspWifiController<'d>,
device: impl Peripheral<P = crate::hal::peripherals::WIFI> + 'd, device: impl Peripheral<P = crate::hal::peripherals::WIFI> + 'd,
) -> Result< ) -> Result<
( (
@ -1925,7 +1936,7 @@ pub fn new_ap_sta<'d>(
/// ///
/// Returns a tuple of `(AP device, STA device, controller)`. /// Returns a tuple of `(AP device, STA device, controller)`.
pub fn new_ap_sta_with_config<'d>( pub fn new_ap_sta_with_config<'d>(
inited: &EspWifiInitialization, inited: &'d EspWifiController<'d>,
device: impl Peripheral<P = crate::hal::peripherals::WIFI> + 'd, device: impl Peripheral<P = crate::hal::peripherals::WIFI> + 'd,
sta_config: crate::wifi::ClientConfiguration, sta_config: crate::wifi::ClientConfiguration,
ap_config: crate::wifi::AccessPointConfiguration, ap_config: crate::wifi::AccessPointConfiguration,
@ -2448,8 +2459,9 @@ impl Sniffer {
pub(crate) fn new() -> Self { pub(crate) fn new() -> Self {
// This shouldn't fail, since the way this is created, means that wifi will // This shouldn't fail, since the way this is created, means that wifi will
// always be initialized. // always be initialized.
esp_wifi_result!(unsafe { esp_wifi_set_promiscuous_rx_cb(Some(promiscuous_rx_cb)) }) unwrap!(esp_wifi_result!(unsafe {
.unwrap(); esp_wifi_set_promiscuous_rx_cb(Some(promiscuous_rx_cb))
}));
Self { Self {
promiscuous_mode_enabled: AtomicBool::new(false), promiscuous_mode_enabled: AtomicBool::new(false),
} }
@ -2493,14 +2505,29 @@ pub struct WifiController<'d> {
sniffer_taken: AtomicBool, 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> { impl<'d> WifiController<'d> {
pub(crate) fn new_with_config( pub(crate) fn new_with_config(
inited: &EspWifiInitialization, inited: &'d EspWifiController<'d>,
_device: PeripheralRef<'d, crate::hal::peripherals::WIFI>, _device: PeripheralRef<'d, crate::hal::peripherals::WIFI>,
config: Configuration, config: Configuration,
) -> Result<Self, WifiError> { ) -> Result<Self, WifiError> {
if !inited.is_wifi() { if !inited.wifi() {
return Err(WifiError::NotInitialized); crate::wifi::wifi_init()?;
} }
// We set up the controller with the default config because we need to call // We set up the controller with the default config because we need to call

View File

@ -8,7 +8,7 @@ use smoltcp::{
}; };
use super::{WifiApDevice, WifiController, WifiDevice, WifiDeviceMode, WifiError, WifiStaDevice}; use super::{WifiApDevice, WifiController, WifiDevice, WifiDeviceMode, WifiError, WifiStaDevice};
use crate::{timestamp, EspWifiInitialization}; use crate::{timestamp, EspWifiController};
fn setup_iface<'a, MODE: WifiDeviceMode>( fn setup_iface<'a, MODE: WifiDeviceMode>(
device: &mut WifiDevice<'_, MODE>, 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 /// You can use the provided macros to create and pass a suitable backing
/// storage. /// storage.
pub fn create_network_interface<'a, 'd, MODE: WifiDeviceMode>( pub fn create_network_interface<'a, 'd, MODE: WifiDeviceMode>(
inited: &EspWifiInitialization, inited: &'d EspWifiController<'d>,
device: impl crate::hal::peripheral::Peripheral<P = crate::hal::peripherals::WIFI> + 'd, device: impl crate::hal::peripheral::Peripheral<P = crate::hal::peripherals::WIFI> + 'd,
mode: MODE, mode: MODE,
storage: &'a mut [SocketStorage<'a>], storage: &'a mut [SocketStorage<'a>],
@ -69,7 +69,7 @@ pub struct ApStaInterface<'a, 'd> {
} }
pub fn create_ap_sta_network_interface<'a, 'd>( pub fn create_ap_sta_network_interface<'a, 'd>(
inited: &EspWifiInitialization, inited: &'d EspWifiController<'d>,
device: impl crate::hal::peripheral::Peripheral<P = crate::hal::peripherals::WIFI> + 'd, device: impl crate::hal::peripheral::Peripheral<P = crate::hal::peripherals::WIFI> + 'd,
ap_storage: &'a mut [SocketStorage<'a>], ap_storage: &'a mut [SocketStorage<'a>],
sta_storage: &'a mut [SocketStorage<'a>], sta_storage: &'a mut [SocketStorage<'a>],

View File

@ -30,7 +30,7 @@ esp-hal-embassy = { path = "../esp-hal-embassy", optional = true }
esp-ieee802154 = { path = "../esp-ieee802154", optional = true } esp-ieee802154 = { path = "../esp-ieee802154", optional = true }
esp-println = { path = "../esp-println", features = ["log"] } esp-println = { path = "../esp-println", features = ["log"] }
esp-storage = { path = "../esp-storage", optional = true } 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" fugit = "0.3.7"
heapless = "0.8.0" heapless = "0.8.0"
hmac = { version = "0.12.1", default-features = false } hmac = { version = "0.12.1", default-features = false }

View File

@ -13,13 +13,8 @@ use core::marker::PhantomData;
use esp_alloc as _; use esp_alloc as _;
use esp_backtrace as _; use esp_backtrace as _;
use esp_hal::{ use esp_hal::{delay::Delay, prelude::*, rng::Rng, timer::timg::TimerGroup};
delay::Delay, use esp_wifi::{init, wifi};
prelude::*,
rng::Rng,
timer::{timg::TimerGroup, AnyTimer, PeriodicTimer},
};
use esp_wifi::{init, wifi, EspWifiInitFor};
use ieee80211::{ use ieee80211::{
common::{CapabilitiesInformation, FCFFlags}, common::{CapabilitiesInformation, FCFFlags},
element_chain, element_chain,
@ -47,12 +42,9 @@ fn main() -> ! {
let delay = Delay::new(); let delay = Delay::new();
let timg0 = TimerGroup::new(peripherals.TIMG0); let timg0 = TimerGroup::new(peripherals.TIMG0);
let timer0: AnyTimer = timg0.timer0.into();
let timer = PeriodicTimer::new(timer0);
let init = init( let init = init(
EspWifiInitFor::Wifi, timg0.timer0,
timer,
Rng::new(peripherals.RNG), Rng::new(peripherals.RNG),
peripherals.RADIO_CLK, peripherals.RADIO_CLK,
) )

View File

@ -33,7 +33,6 @@ use esp_wifi::{
WifiApDevice, WifiApDevice,
}, },
wifi_interface::WifiStack, wifi_interface::WifiStack,
EspWifiInitFor,
}; };
use smoltcp::iface::SocketStorage; use smoltcp::iface::SocketStorage;
@ -51,7 +50,6 @@ fn main() -> ! {
let timg0 = TimerGroup::new(peripherals.TIMG0); let timg0 = TimerGroup::new(peripherals.TIMG0);
let init = init( let init = init(
EspWifiInitFor::Wifi,
timg0.timer0, timg0.timer0,
Rng::new(peripherals.RNG), Rng::new(peripherals.RNG),
peripherals.RADIO_CLK, peripherals.RADIO_CLK,

View File

@ -34,7 +34,6 @@ use esp_wifi::{
Configuration, Configuration,
}, },
wifi_interface::WifiStack, wifi_interface::WifiStack,
EspWifiInitFor,
}; };
use smoltcp::{ use smoltcp::{
iface::SocketStorage, iface::SocketStorage,
@ -58,7 +57,6 @@ fn main() -> ! {
let timg0 = TimerGroup::new(peripherals.TIMG0); let timg0 = TimerGroup::new(peripherals.TIMG0);
let init = init( let init = init(
EspWifiInitFor::Wifi,
timg0.timer0, timg0.timer0,
Rng::new(peripherals.RNG), Rng::new(peripherals.RNG),
peripherals.RADIO_CLK, peripherals.RADIO_CLK,

View File

@ -36,7 +36,6 @@ use esp_wifi::{
WifiStaDevice, WifiStaDevice,
}, },
wifi_interface::WifiStack, wifi_interface::WifiStack,
EspWifiInitFor,
}; };
use smoltcp::{ use smoltcp::{
iface::SocketStorage, iface::SocketStorage,
@ -71,7 +70,6 @@ fn main() -> ! {
let timg0 = TimerGroup::new(peripherals.TIMG0); let timg0 = TimerGroup::new(peripherals.TIMG0);
let init = init( let init = init(
EspWifiInitFor::Wifi,
timg0.timer0, timg0.timer0,
Rng::new(peripherals.RNG), Rng::new(peripherals.RNG),
peripherals.RADIO_CLK, peripherals.RADIO_CLK,

View File

@ -32,7 +32,7 @@ use esp_hal::{
timer::timg::TimerGroup, timer::timg::TimerGroup,
}; };
use esp_println::println; use esp_println::println;
use esp_wifi::{ble::controller::BleConnector, init, EspWifiInitFor}; use esp_wifi::{ble::controller::BleConnector, init};
#[entry] #[entry]
fn main() -> ! { fn main() -> ! {
@ -48,7 +48,6 @@ fn main() -> ! {
let timg0 = TimerGroup::new(peripherals.TIMG0); let timg0 = TimerGroup::new(peripherals.TIMG0);
let init = init( let init = init(
EspWifiInitFor::Ble,
timg0.timer0, timg0.timer0,
Rng::new(peripherals.RNG), Rng::new(peripherals.RNG),
peripherals.RADIO_CLK, peripherals.RADIO_CLK,

View File

@ -41,7 +41,6 @@ use esp_wifi::{
init, init,
wifi::{utils::create_network_interface, ClientConfiguration, Configuration, WifiStaDevice}, wifi::{utils::create_network_interface, ClientConfiguration, Configuration, WifiStaDevice},
wifi_interface::WifiStack, wifi_interface::WifiStack,
EspWifiInitFor,
}; };
use smoltcp::{ use smoltcp::{
iface::SocketStorage, iface::SocketStorage,
@ -83,7 +82,6 @@ fn main() -> ! {
let timg0 = TimerGroup::new(peripherals.TIMG0); let timg0 = TimerGroup::new(peripherals.TIMG0);
let init = init( let init = init(
EspWifiInitFor::WifiBle,
timg0.timer0, timg0.timer0,
Rng::new(peripherals.RNG), Rng::new(peripherals.RNG),
peripherals.RADIO_CLK, peripherals.RADIO_CLK,

View File

@ -35,7 +35,6 @@ use esp_wifi::{
WifiStaDevice, WifiStaDevice,
}, },
wifi_interface::WifiStack, wifi_interface::WifiStack,
EspWifiInitFor,
}; };
use smoltcp::{ use smoltcp::{
iface::SocketStorage, iface::SocketStorage,
@ -59,7 +58,6 @@ fn main() -> ! {
let timg0 = TimerGroup::new(peripherals.TIMG0); let timg0 = TimerGroup::new(peripherals.TIMG0);
let init = init( let init = init(
EspWifiInitFor::Wifi,
timg0.timer0, timg0.timer0,
Rng::new(peripherals.RNG), Rng::new(peripherals.RNG),
peripherals.RADIO_CLK, peripherals.RADIO_CLK,

View File

@ -41,7 +41,7 @@ use esp_wifi::{
WifiEvent, WifiEvent,
WifiState, 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 // 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 timg0 = TimerGroup::new(peripherals.TIMG0);
let init = init( let init = &*mk_static!(
EspWifiInitFor::Wifi, EspWifiController<'static>,
timg0.timer0, init(
Rng::new(peripherals.RNG), timg0.timer0,
peripherals.RADIO_CLK, Rng::new(peripherals.RNG),
) peripherals.RADIO_CLK,
.unwrap(); )
.unwrap()
);
let wifi = peripherals.WIFI; let wifi = peripherals.WIFI;
let (wifi_interface, controller) = let (wifi_interface, controller) =

View File

@ -46,7 +46,7 @@ use esp_wifi::{
WifiStaDevice, WifiStaDevice,
WifiState, WifiState,
}, },
EspWifiInitFor, EspWifiController,
}; };
const SSID: &str = env!("SSID"); const SSID: &str = env!("SSID");
@ -75,13 +75,15 @@ async fn main(spawner: Spawner) -> ! {
let timg0 = TimerGroup::new(peripherals.TIMG0); let timg0 = TimerGroup::new(peripherals.TIMG0);
let init = init( let init = &*mk_static!(
EspWifiInitFor::Wifi, EspWifiController<'static>,
timg0.timer0, init(
Rng::new(peripherals.RNG), timg0.timer0,
peripherals.RADIO_CLK, Rng::new(peripherals.RNG),
) peripherals.RADIO_CLK,
.unwrap(); )
.unwrap()
);
let wifi = peripherals.WIFI; let wifi = peripherals.WIFI;
let (wifi_ap_interface, wifi_sta_interface, mut controller) = let (wifi_ap_interface, wifi_sta_interface, mut controller) =

View File

@ -36,7 +36,7 @@ use esp_wifi::{
WifiStaDevice, WifiStaDevice,
WifiState, 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 // 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 timg0 = TimerGroup::new(peripherals.TIMG0);
let init = init( let init = &*mk_static!(
EspWifiInitFor::Wifi, EspWifiController<'static>,
timg0.timer0, init(
Rng::new(peripherals.RNG), timg0.timer0,
peripherals.RADIO_CLK, Rng::new(peripherals.RNG),
) peripherals.RADIO_CLK,
.unwrap(); )
.unwrap()
);
let wifi = peripherals.WIFI; let wifi = peripherals.WIFI;
let (wifi_interface, controller) = let (wifi_interface, controller) =

View File

@ -35,7 +35,17 @@ use esp_hal::{
timer::timg::TimerGroup, timer::timg::TimerGroup,
}; };
use esp_println::println; 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] #[esp_hal_embassy::main]
async fn main(_spawner: Spawner) -> ! { async fn main(_spawner: Spawner) -> ! {
@ -50,13 +60,15 @@ async fn main(_spawner: Spawner) -> ! {
let timg0 = TimerGroup::new(peripherals.TIMG0); let timg0 = TimerGroup::new(peripherals.TIMG0);
let init = init( let init = &*mk_static!(
EspWifiInitFor::Ble, EspWifiController<'static>,
timg0.timer0, init(
Rng::new(peripherals.RNG), timg0.timer0,
peripherals.RADIO_CLK, Rng::new(peripherals.RNG),
) peripherals.RADIO_CLK,
.unwrap(); )
.unwrap()
);
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
cfg_if::cfg_if! { cfg_if::cfg_if! {

View File

@ -32,7 +32,7 @@ use esp_wifi::{
WifiStaDevice, WifiStaDevice,
WifiState, 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 // 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 timg0 = TimerGroup::new(peripherals.TIMG0);
let init = init( let init = &*mk_static!(
EspWifiInitFor::Wifi, EspWifiController<'static>,
timg0.timer0, init(
Rng::new(peripherals.RNG), timg0.timer0,
peripherals.RADIO_CLK, Rng::new(peripherals.RNG),
) peripherals.RADIO_CLK,
.unwrap(); )
.unwrap()
);
let wifi = peripherals.WIFI; let wifi = peripherals.WIFI;
let (wifi_interface, controller) = let (wifi_interface, controller) =

View File

@ -20,9 +20,19 @@ use esp_println::println;
use esp_wifi::{ use esp_wifi::{
esp_now::{PeerInfo, BROADCAST_ADDRESS}, esp_now::{PeerInfo, BROADCAST_ADDRESS},
init, 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] #[esp_hal_embassy::main]
async fn main(_spawner: Spawner) -> ! { async fn main(_spawner: Spawner) -> ! {
esp_println::logger::init_logger_from_env(); esp_println::logger::init_logger_from_env();
@ -36,13 +46,15 @@ async fn main(_spawner: Spawner) -> ! {
let timg0 = TimerGroup::new(peripherals.TIMG0); let timg0 = TimerGroup::new(peripherals.TIMG0);
let init = init( let init = &*mk_static!(
EspWifiInitFor::Wifi, EspWifiController<'static>,
timg0.timer0, init(
Rng::new(peripherals.RNG), timg0.timer0,
peripherals.RADIO_CLK, Rng::new(peripherals.RNG),
) peripherals.RADIO_CLK,
.unwrap(); )
.unwrap()
);
let wifi = peripherals.WIFI; let wifi = peripherals.WIFI;
let mut esp_now = esp_wifi::esp_now::EspNow::new(&init, wifi).unwrap(); let mut esp_now = esp_wifi::esp_now::EspNow::new(&init, wifi).unwrap();

View File

@ -20,7 +20,7 @@ use esp_println::println;
use esp_wifi::{ use esp_wifi::{
esp_now::{EspNowManager, EspNowReceiver, EspNowSender, PeerInfo, BROADCAST_ADDRESS}, esp_now::{EspNowManager, EspNowReceiver, EspNowSender, PeerInfo, BROADCAST_ADDRESS},
init, 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 // 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 timg0 = TimerGroup::new(peripherals.TIMG0);
let init = init( let init = &*mk_static!(
EspWifiInitFor::Wifi, EspWifiController<'static>,
timg0.timer0, init(
Rng::new(peripherals.RNG), timg0.timer0,
peripherals.RADIO_CLK, Rng::new(peripherals.RNG),
) peripherals.RADIO_CLK,
.unwrap(); )
.unwrap()
);
let wifi = peripherals.WIFI; let wifi = peripherals.WIFI;
let esp_now = esp_wifi::esp_now::EspNow::new(&init, wifi).unwrap(); let esp_now = esp_wifi::esp_now::EspNow::new(&init, wifi).unwrap();

View File

@ -18,8 +18,8 @@ use embassy_sync::blocking_mutex::raw::NoopRawMutex;
use embassy_time::{Duration, Timer}; use embassy_time::{Duration, Timer};
use esp_alloc as _; use esp_alloc as _;
use esp_backtrace as _; use esp_backtrace as _;
use esp_hal::{prelude::*, timer::timg::TimerGroup}; use esp_hal::{prelude::*, rng::Rng, timer::timg::TimerGroup};
use esp_wifi::ble::controller::asynch::BleConnector; use esp_wifi::{ble::controller::BleConnector, init, EspWifiController};
use log::*; use log::*;
use static_cell::StaticCell; use static_cell::StaticCell;
use trouble_host::{ use trouble_host::{
@ -31,6 +31,16 @@ use trouble_host::{
PacketQos, 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] #[esp_hal_embassy::main]
async fn main(_s: Spawner) { async fn main(_s: Spawner) {
esp_println::logger::init_logger_from_env(); esp_println::logger::init_logger_from_env();
@ -44,13 +54,15 @@ async fn main(_s: Spawner) {
let timg0 = TimerGroup::new(peripherals.TIMG0); let timg0 = TimerGroup::new(peripherals.TIMG0);
let init = esp_wifi::init( let init = &*mk_static!(
esp_wifi::EspWifiInitFor::Ble, EspWifiController<'static>,
timg0.timer0, init(
esp_hal::rng::Rng::new(peripherals.RNG), timg0.timer0,
peripherals.RADIO_CLK, Rng::new(peripherals.RNG),
) peripherals.RADIO_CLK,
.unwrap(); )
.unwrap()
);
#[cfg(feature = "esp32")] #[cfg(feature = "esp32")]
{ {

View File

@ -20,7 +20,6 @@ use esp_println::println;
use esp_wifi::{ use esp_wifi::{
esp_now::{PeerInfo, BROADCAST_ADDRESS}, esp_now::{PeerInfo, BROADCAST_ADDRESS},
init, init,
EspWifiInitFor,
}; };
#[entry] #[entry]
@ -37,7 +36,6 @@ fn main() -> ! {
let timg0 = TimerGroup::new(peripherals.TIMG0); let timg0 = TimerGroup::new(peripherals.TIMG0);
let init = init( let init = init(
EspWifiInitFor::Wifi,
timg0.timer0, timg0.timer0,
Rng::new(peripherals.RNG), Rng::new(peripherals.RNG),
peripherals.RADIO_CLK, peripherals.RADIO_CLK,

View File

@ -19,13 +19,9 @@ use core::cell::RefCell;
use critical_section::Mutex; use critical_section::Mutex;
use esp_backtrace as _; use esp_backtrace as _;
use esp_hal::{ use esp_hal::{prelude::*, rng::Rng, timer::timg::TimerGroup};
prelude::*,
rng::Rng,
timer::{timg::TimerGroup, AnyTimer, PeriodicTimer},
};
use esp_println::println; use esp_println::println;
use esp_wifi::{init, wifi, EspWifiInitFor}; use esp_wifi::{init, wifi};
use ieee80211::{match_frames, mgmt_frame::BeaconFrame}; use ieee80211::{match_frames, mgmt_frame::BeaconFrame};
static KNOWN_SSIDS: Mutex<RefCell<BTreeSet<String>>> = Mutex::new(RefCell::new(BTreeSet::new())); static KNOWN_SSIDS: Mutex<RefCell<BTreeSet<String>>> = Mutex::new(RefCell::new(BTreeSet::new()));
@ -42,12 +38,8 @@ fn main() -> ! {
esp_alloc::heap_allocator!(72 * 1024); esp_alloc::heap_allocator!(72 * 1024);
let timg0 = TimerGroup::new(peripherals.TIMG0); let timg0 = TimerGroup::new(peripherals.TIMG0);
let timer0: AnyTimer = timg0.timer0.into();
let timer = PeriodicTimer::new(timer0);
let init = init( let init = init(
EspWifiInitFor::Wifi, timg0.timer0,
timer,
Rng::new(peripherals.RNG), Rng::new(peripherals.RNG),
peripherals.RADIO_CLK, peripherals.RADIO_CLK,
) )

View File

@ -34,7 +34,6 @@ use esp_wifi::{
WifiStaDevice, WifiStaDevice,
}, },
wifi_interface::WifiStack, wifi_interface::WifiStack,
EspWifiInitFor,
}; };
use smoltcp::iface::SocketStorage; use smoltcp::iface::SocketStorage;
@ -57,7 +56,6 @@ fn main() -> ! {
let timg0 = TimerGroup::new(peripherals.TIMG0); let timg0 = TimerGroup::new(peripherals.TIMG0);
let init = init( let init = init(
EspWifiInitFor::Wifi,
timg0.timer0, timg0.timer0,
Rng::new(peripherals.RNG), Rng::new(peripherals.RNG),
peripherals.RADIO_CLK, peripherals.RADIO_CLK,

View File

@ -17,7 +17,6 @@ use esp_hal::{
rng::Rng, rng::Rng,
timer::timg::TimerGroup, timer::timg::TimerGroup,
}; };
use esp_wifi::{init, EspWifiInitFor};
use hil_test as _; use hil_test as _;
#[inline(never)] #[inline(never)]
@ -101,8 +100,7 @@ mod tests {
#[timeout(3)] #[timeout(3)]
fn fpu_stays_enabled_with_wifi(peripherals: Peripherals) { fn fpu_stays_enabled_with_wifi(peripherals: Peripherals) {
let timg0 = TimerGroup::new(peripherals.TIMG0); let timg0 = TimerGroup::new(peripherals.TIMG0);
let _init = init( let _init = esp_wifi::init(
EspWifiInitFor::Wifi,
timg0.timer1, timg0.timer1,
Rng::new(peripherals.RNG), Rng::new(peripherals.RNG),
peripherals.RADIO_CLK, peripherals.RADIO_CLK,
@ -138,8 +136,7 @@ mod tests {
unsafe { &mut *core::ptr::addr_of_mut!(APP_CORE_STACK) }, unsafe { &mut *core::ptr::addr_of_mut!(APP_CORE_STACK) },
move || { move || {
let timg0 = TimerGroup::new(peripherals.TIMG0); let timg0 = TimerGroup::new(peripherals.TIMG0);
let _init = init( let _init = esp_wifi::init(
EspWifiInitFor::Wifi,
timg0.timer1, timg0.timer1,
Rng::new(peripherals.RNG), Rng::new(peripherals.RNG),
peripherals.RADIO_CLK, peripherals.RADIO_CLK,