Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove EspWifiInitFor & more granular init/deinit per driver #2301

Merged
merged 8 commits into from
Nov 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions esp-hal/src/rng.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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!()]
Expand Down
1 change: 1 addition & 0 deletions esp-wifi/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
1 change: 1 addition & 0 deletions esp-wifi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
Expand Down
17 changes: 17 additions & 0 deletions esp-wifi/MIGRATING-0.10.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
2 changes: 2 additions & 0 deletions esp-wifi/src/ble/btdm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -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]) {
Expand Down
49 changes: 12 additions & 37 deletions esp-wifi/src/ble/controller/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,26 @@ 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
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();
MabezDev marked this conversation as resolved.
Show resolved Hide resolved
}
}

impl<'d> BleConnector<'d> {
pub fn new(
init: &EspWifiInitialization,
_init: &'d EspWifiController<'d>,
jessebraham marked this conversation as resolved.
Show resolved Hide resolved
device: impl Peripheral<P = crate::hal::peripherals::BT> + 'd,
) -> BleConnector<'d> {
if !init.is_ble() {
panic!("Not initialized for BLE use");
}
crate::ble::ble_init();

Self {
_device: device.into_ref(),
Expand Down Expand Up @@ -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::{
Expand All @@ -91,45 +95,16 @@ 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();

pub(crate) fn hci_read_data_available() {
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<'_> {
async fn read(&mut self, buf: &mut [u8]) -> Result<usize, BleConnectorError> {
if !have_hci_read_data() {
Expand Down
2 changes: 1 addition & 1 deletion esp-wifi/src/ble/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))]
Expand Down
3 changes: 3 additions & 0 deletions esp-wifi/src/ble/npl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::*;
Expand Down Expand Up @@ -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() {
Expand All @@ -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)]
Expand Down
3 changes: 2 additions & 1 deletion esp-wifi/src/compat/misc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down Expand Up @@ -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);
Expand Down
43 changes: 34 additions & 9 deletions esp-wifi/src/esp_now/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -113,6 +113,14 @@ pub enum EspNowError {
SendFailed,
/// Attempt to create `EspNow` instance twice.
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.
Expand Down Expand Up @@ -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.
///
Expand Down Expand Up @@ -607,24 +630,24 @@ impl Drop for EspNowRc<'_> {
/// Currently this implementation (when used together with traditional Wi-Fi)
/// ONLY support STA mode.
pub struct EspNow<'d> {
_device: Option<PeripheralRef<'d, crate::hal::peripherals::WIFI>>,
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<P = crate::hal::peripherals::WIFI> + 'd,
) -> Result<EspNow<'d>, EspNowError> {
EspNow::new_internal(inited, Some(device.into_ref()))
}

/// Creates an `EspNow` instance with support for Wi-Fi coexistence.
pub fn new_with_wifi(
inited: &EspWifiInitialization,
inited: &'d EspWifiController<'d>,
_token: EspNowWithWifiCreateToken,
) -> Result<EspNow<'d>, EspNowError> {
EspNow::new_internal(
Expand All @@ -634,23 +657,25 @@ impl<'d> EspNow<'d> {
}

fn new_internal(
inited: &EspWifiInitialization,
inited: &'d EspWifiController<'d>,
device: Option<PeripheralRef<'d, crate::hal::peripherals::WIFI>>,
) -> Result<EspNow<'d>, 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(),
},
sender: EspNowSender {
_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() })?;
Expand Down
Loading