Skip to content

Commit d5bed3e

Browse files
MabezDevbjoernQ
authored andcommitted
Feature/radio singletons (esp-rs#141)
* Use RADIO singletons - Uses the RADIO singletons when creating wifi/ble/esp_now - Updates all examples to use the singletons - Simplfy esp_now::ReceiveFuture * Fixup examples * fmt * fix examples
1 parent fd4da26 commit d5bed3e

File tree

6 files changed

+106
-97
lines changed

6 files changed

+106
-97
lines changed

esp-wifi/Cargo.toml

+7-6
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ esp32c3 = { workspace = true, optional = true }
1616
esp32c2 = { workspace = true, optional = true }
1717
esp32c6 = { workspace = true, optional = true }
1818
smoltcp = { workspace = true, optional = true }
19+
esp-hal-common = { workspace = true, optional = true }
1920
critical-section.workspace = true
2021
atomic-polyfill.workspace = true
2122
log.workspace = true
@@ -37,12 +38,12 @@ embassy-net-driver = { workspace = true, optional = true }
3738
default = [ "utils" ]
3839

3940
# chip features
40-
esp32c3 = [ "esp32c3-hal", "dep:esp32c3", "esp-wifi-sys/esp32c3" ]
41-
esp32c2 = [ "esp32c2-hal", "dep:esp32c2", "esp-wifi-sys/esp32c2" ]
42-
esp32c6 = [ "esp32c6-hal", "dep:esp32c6", "esp-wifi-sys/esp32c6" ]
43-
esp32 = [ "esp32-hal", "esp-wifi-sys/esp32" ]
44-
esp32s3 = [ "esp32s3-hal", "esp-wifi-sys/esp32s3" ]
45-
esp32s2 = [ "esp32s2-hal", "esp-wifi-sys/esp32s2" ]
41+
esp32c3 = [ "esp32c3-hal", "dep:esp32c3", "esp-wifi-sys/esp32c3", "esp-hal-common/esp32c3" ]
42+
esp32c2 = [ "esp32c2-hal", "dep:esp32c2", "esp-wifi-sys/esp32c2", "esp-hal-common/esp32c2" ]
43+
esp32c6 = [ "esp32c6-hal", "dep:esp32c6", "esp-wifi-sys/esp32c6", "esp-hal-common/esp32c6" ]
44+
esp32 = [ "esp32-hal", "esp-wifi-sys/esp32", "esp-hal-common/esp32" ]
45+
esp32s3 = [ "esp32s3-hal", "esp-wifi-sys/esp32s3", "esp-hal-common/esp32s3" ]
46+
esp32s2 = [ "esp32s2-hal", "esp-wifi-sys/esp32s2", "esp-hal-common/esp32s2" ]
4647

4748
# async features
4849
esp32c3-async = [ "esp32c3-hal/embassy", "esp32c3-hal/embassy-time-timg0", "async" ]

esp-wifi/src/ble/controller/mod.rs

+17-4
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,23 @@ use embedded_io::{
22
blocking::{Read, Write},
33
Error, Io,
44
};
5+
use esp_hal_common::peripheral::{Peripheral, PeripheralRef};
56

67
use super::{read_hci, send_hci};
78

8-
pub struct BleConnector {}
9+
pub struct BleConnector<'d> {
10+
_device: PeripheralRef<'d, esp_hal_common::radio::Bluetooth>,
11+
}
12+
13+
impl<'d> BleConnector<'d> {
14+
pub fn new(
15+
device: impl Peripheral<P = esp_hal_common::radio::Bluetooth> + 'd,
16+
) -> BleConnector<'d> {
17+
Self {
18+
_device: device.into_ref(),
19+
}
20+
}
21+
}
922

1023
#[derive(Debug)]
1124
pub enum BleConnectorError {
@@ -18,11 +31,11 @@ impl Error for BleConnectorError {
1831
}
1932
}
2033

21-
impl Io for BleConnector {
34+
impl Io for BleConnector<'_> {
2235
type Error = BleConnectorError;
2336
}
2437

25-
impl Read for BleConnector {
38+
impl Read for BleConnector<'_> {
2639
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
2740
let mut total = 0;
2841
for b in buf {
@@ -41,7 +54,7 @@ impl Read for BleConnector {
4154
}
4255
}
4356

44-
impl Write for BleConnector {
57+
impl Write for BleConnector<'_> {
4558
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
4659
for b in buf {
4760
send_hci(&[*b]);

esp-wifi/src/esp_now/mod.rs

+28-56
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use core::{cell::RefCell, fmt::Debug};
1010

1111
use critical_section::Mutex;
12+
use esp_hal_common::peripheral::{Peripheral, PeripheralRef};
1213

1314
use crate::compat::queue::SimpleQueue;
1415

@@ -20,10 +21,6 @@ pub const ESP_NOW_MAX_DATA_LEN: usize = 250;
2021
/// Broadcast address
2122
pub const BROADCAST_ADDRESS: [u8; 6] = [0xffu8, 0xffu8, 0xffu8, 0xffu8, 0xffu8, 0xffu8];
2223

23-
static ESP_NOW: Mutex<RefCell<EspNowHolder>> = Mutex::new(RefCell::new(EspNowHolder {
24-
esp_now: Some(EspNowCreator { _private: () }),
25-
}));
26-
2724
static RECEIVE_QUEUE: Mutex<RefCell<SimpleQueue<ReceivedData, 10>>> =
2825
Mutex::new(RefCell::new(SimpleQueue::new()));
2926

@@ -236,17 +233,17 @@ impl Debug for ReceivedData {
236233
}
237234
}
238235

239-
pub struct EspNowCreator {
240-
_private: (),
236+
pub struct EspNow<'d> {
237+
_device: PeripheralRef<'d, esp_hal_common::radio::Wifi>,
241238
}
242239

243-
impl EspNowCreator {
244-
/// Initialize esp-now
245-
///
246-
/// Must be called after initializing esp-wifi.
247-
/// After this the broadcast address is already added as a peer.
248-
pub fn initialize(self) -> Result<EspNow, EspNowError> {
249-
let mut esp_now = EspNow { _private: () };
240+
impl<'d> EspNow<'d> {
241+
pub fn new(
242+
device: impl Peripheral<P = esp_hal_common::radio::Wifi> + 'd,
243+
) -> Result<EspNow<'d>, EspNowError> {
244+
let mut esp_now = EspNow {
245+
_device: device.into_ref(),
246+
};
250247
check_error!({ esp_wifi_set_mode(wifi_mode_t_WIFI_MODE_STA) });
251248
check_error!({ esp_wifi_start() });
252249
check_error!({ esp_now_init() });
@@ -261,34 +258,6 @@ impl EspNowCreator {
261258

262259
Ok(esp_now)
263260
}
264-
}
265-
266-
struct EspNowHolder {
267-
esp_now: Option<EspNowCreator>,
268-
}
269-
270-
pub fn esp_now() -> EspNowCreator {
271-
critical_section::with(|cs| ESP_NOW.borrow_ref_mut(cs).esp_now.take().unwrap())
272-
}
273-
274-
pub struct EspNow {
275-
_private: (),
276-
}
277-
278-
impl EspNow {
279-
/// Deinit
280-
pub fn free(self) {
281-
unsafe {
282-
esp_now_unregister_recv_cb();
283-
esp_now_deinit();
284-
critical_section::with(|cs| {
285-
ESP_NOW
286-
.borrow_ref_mut(cs)
287-
.esp_now
288-
.replace(EspNowCreator { _private: () });
289-
})
290-
}
291-
}
292261

293262
/// Get the version of ESPNOW
294263
pub fn get_version(&self) -> Result<u32, EspNowError> {
@@ -454,6 +423,15 @@ impl EspNow {
454423
}
455424
}
456425

426+
impl Drop for EspNow<'_> {
427+
fn drop(&mut self) {
428+
unsafe {
429+
esp_now_unregister_recv_cb();
430+
esp_now_deinit();
431+
}
432+
}
433+
}
434+
457435
unsafe extern "C" fn rcv_cb(
458436
esp_now_info: *const esp_now_recv_info_t,
459437
data: *const u8,
@@ -555,36 +533,30 @@ unsafe extern "C" fn rcv_cb(
555533

556534
#[cfg(feature = "async")]
557535
mod asynch {
536+
use super::*;
558537
use core::task::{Context, Poll};
559538
use embassy_sync::waitqueue::AtomicWaker;
560539

561-
use super::{EspNow, ReceivedData};
562-
563540
pub(super) static ESP_NOW_WAKER: AtomicWaker = AtomicWaker::new();
564541

565-
impl EspNow {
542+
impl<'d> EspNow<'d> {
566543
pub async fn receive_async(&mut self) -> ReceivedData {
567-
ReceiveFuture::new(self).await
544+
ReceiveFuture.await
568545
}
569546
}
570547

571-
struct ReceiveFuture<'a> {
572-
esp_now: &'a mut EspNow,
573-
}
574-
575-
impl<'a> ReceiveFuture<'a> {
576-
fn new(esp_now: &'a mut EspNow) -> Self {
577-
Self { esp_now }
578-
}
579-
}
548+
struct ReceiveFuture;
580549

581-
impl<'a> core::future::Future for ReceiveFuture<'a> {
550+
impl core::future::Future for ReceiveFuture {
582551
type Output = ReceivedData;
583552

584553
fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
585554
ESP_NOW_WAKER.register(cx.waker());
586555

587-
if let Some(data) = self.esp_now.receive() {
556+
if let Some(data) = critical_section::with(|cs| {
557+
let mut queue = RECEIVE_QUEUE.borrow_ref_mut(cs);
558+
queue.dequeue()
559+
}) {
588560
Poll::Ready(data)
589561
} else {
590562
Poll::Pending

esp-wifi/src/wifi/mod.rs

+48-26
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ use critical_section::Mutex;
1010
use embedded_svc::wifi::{AccessPointInfo, AuthMethod, SecondaryChannel};
1111
use enumset::EnumSet;
1212
use enumset::EnumSetType;
13+
use esp_hal_common::peripheral::Peripheral;
14+
use esp_hal_common::peripheral::PeripheralRef;
1315
use esp_wifi_sys::include::esp_interface_t_ESP_IF_WIFI_AP;
1416
use esp_wifi_sys::include::esp_wifi_disconnect;
1517
use esp_wifi_sys::include::esp_wifi_get_mode;
@@ -682,52 +684,72 @@ pub fn wifi_start_scan(block: bool) -> i32 {
682684
unsafe { esp_wifi_scan_start(&scan_config, block) }
683685
}
684686

685-
pub fn new_with_config(config: embedded_svc::wifi::Configuration) -> (WifiDevice, WifiController) {
687+
pub fn new_with_config<'d>(
688+
device: impl Peripheral<P = esp_hal_common::radio::Wifi> + 'd,
689+
config: embedded_svc::wifi::Configuration,
690+
) -> (WifiDevice<'d>, WifiController<'d>) {
691+
esp_hal_common::into_ref!(device);
686692
let mode = match config {
687693
embedded_svc::wifi::Configuration::None => panic!(),
688694
embedded_svc::wifi::Configuration::Client(_) => WifiMode::Sta,
689695
embedded_svc::wifi::Configuration::AccessPoint(_) => WifiMode::Ap,
690696
embedded_svc::wifi::Configuration::Mixed(_, _) => panic!(),
691697
};
692698
(
693-
WifiDevice::new(mode),
694-
WifiController::new_with_config(config),
699+
WifiDevice::new(unsafe { device.clone_unchecked() }, mode),
700+
WifiController::new_with_config(device, config),
701+
)
702+
}
703+
704+
pub fn new_with_mode<'d>(
705+
device: impl Peripheral<P = esp_hal_common::radio::Wifi> + 'd,
706+
mode: WifiMode,
707+
) -> (WifiDevice<'d>, WifiController<'d>) {
708+
new_with_config(
709+
device,
710+
match mode {
711+
WifiMode::Sta => embedded_svc::wifi::Configuration::Client(Default::default()),
712+
WifiMode::Ap => embedded_svc::wifi::Configuration::AccessPoint(Default::default()),
713+
},
695714
)
696715
}
697716

698-
pub fn new(mode: WifiMode) -> (WifiDevice, WifiController) {
699-
(WifiDevice::new(mode), WifiController::new())
717+
pub fn new<'d>(
718+
device: impl Peripheral<P = esp_hal_common::radio::Wifi> + 'd,
719+
) -> (WifiDevice<'d>, WifiController<'d>) {
720+
new_with_config(device, Default::default())
700721
}
701722

702723
/// A wifi device implementing smoltcp's Device trait.
703-
pub struct WifiDevice {
704-
_private: (),
724+
pub struct WifiDevice<'d> {
725+
_device: PeripheralRef<'d, esp_hal_common::radio::Wifi>,
705726

706727
// only used by embassy-net
707728
#[allow(unused)]
708729
mode: WifiMode,
709730
}
710731

711-
impl WifiDevice {
712-
pub(crate) fn new(mode: WifiMode) -> WifiDevice {
713-
Self { _private: (), mode }
732+
impl<'d> WifiDevice<'d> {
733+
pub(crate) fn new(
734+
_device: PeripheralRef<'d, esp_hal_common::radio::Wifi>,
735+
mode: WifiMode,
736+
) -> WifiDevice {
737+
Self { _device, mode }
714738
}
715739
}
716740

717741
/// A wifi controller implementing embedded_svc::Wifi traits
718-
pub struct WifiController {
742+
pub struct WifiController<'d> {
743+
_device: PeripheralRef<'d, esp_hal_common::radio::Wifi>,
719744
config: embedded_svc::wifi::Configuration,
720745
}
721746

722-
impl WifiController {
723-
pub(crate) fn new_with_config(config: embedded_svc::wifi::Configuration) -> Self {
724-
Self { config }
725-
}
726-
727-
pub(crate) fn new() -> Self {
728-
Self {
729-
config: Default::default(),
730-
}
747+
impl<'d> WifiController<'d> {
748+
pub(crate) fn new_with_config(
749+
_device: PeripheralRef<'d, esp_hal_common::radio::Wifi>,
750+
config: embedded_svc::wifi::Configuration,
751+
) -> Self {
752+
Self { _device, config }
731753
}
732754

733755
fn is_sta_enabled(&self) -> Result<bool, WifiError> {
@@ -864,9 +886,9 @@ impl WifiController {
864886
}
865887

866888
// see https://docs.rs/smoltcp/0.7.1/smoltcp/phy/index.html
867-
impl Device for WifiDevice {
868-
type RxToken<'a> = WifiRxToken;
869-
type TxToken<'a> = WifiTxToken;
889+
impl<'d> Device for WifiDevice<'d> {
890+
type RxToken<'a> = WifiRxToken where Self: 'a;
891+
type TxToken<'a> = WifiTxToken where Self: 'a;
870892

871893
fn receive(
872894
&mut self,
@@ -989,7 +1011,7 @@ pub fn send_data_if_needed() {
9891011
});
9901012
}
9911013

992-
impl embedded_svc::wifi::Wifi for WifiController {
1014+
impl embedded_svc::wifi::Wifi for WifiController<'_> {
9931015
type Error = WifiError;
9941016

9951017
/// This currently only supports the `Client` and `AccessPoint` capability.
@@ -1290,7 +1312,7 @@ pub(crate) mod embassy {
12901312
}
12911313
}
12921314

1293-
impl Driver for WifiDevice {
1315+
impl Driver for WifiDevice<'_> {
12941316
type RxToken<'a> = WifiRxToken
12951317
where
12961318
Self: 'a;
@@ -1381,7 +1403,7 @@ mod asynch {
13811403
use super::*;
13821404

13831405
// TODO assumes STA mode only
1384-
impl WifiController {
1406+
impl<'d> WifiController<'d> {
13851407
/// Async version of [`embedded_svc::wifi::Wifi`]'s `scan_n` method
13861408
pub async fn scan_n<const N: usize>(
13871409
&mut self,

esp-wifi/src/wifi/utils.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,11 @@ use super::{WifiController, WifiDevice, WifiMode};
1212

1313
/// Convenient way to create an `smoltcp` ethernet interface
1414
/// You can use the provided macros to create and pass a suitable backing storage.
15-
pub fn create_network_interface<'a>(
15+
pub fn create_network_interface<'a, 'd>(
16+
device: impl esp_hal_common::peripheral::Peripheral<P = esp_hal_common::radio::Wifi> + 'd,
1617
mode: WifiMode,
1718
storage: &'a mut [SocketStorage<'a>],
18-
) -> (Interface, WifiDevice, WifiController, SocketSet<'a>) {
19+
) -> (Interface, WifiDevice<'d>, WifiController<'d>, SocketSet<'a>) {
1920
let socket_set_entries = storage;
2021

2122
let mut mac = [0u8; 6];
@@ -25,7 +26,7 @@ pub fn create_network_interface<'a>(
2526
}
2627
let hw_address = EthernetAddress::from_bytes(&mac);
2728

28-
let (mut device, controller) = crate::wifi::new(mode);
29+
let (mut device, controller) = crate::wifi::new_with_mode(device, mode);
2930

3031
let mut config = Config::new();
3132

0 commit comments

Comments
 (0)