mirror of
https://github.com/esp-rs/esp-hal.git
synced 2025-10-02 06:40:47 +00:00
Replace some esp-wifi critical sections with locks (#2554)
* Replace some esp-wifi critical sections with locks * Remove critical section from event handlers * Fix doc warnings and accidentally hard-coded esp32s3 * Use Lock in wifi_int_disable/restore * Replace critical_section in ConcurrentQueue * Deduplicate wifi_int_disable
This commit is contained in:
parent
aed0fac0eb
commit
eec75c8f82
@ -12,6 +12,7 @@ use esp_wifi_sys::include::malloc;
|
||||
use super::malloc::free;
|
||||
use crate::{
|
||||
binary::c_types::{c_int, c_void},
|
||||
hal::sync::Locked,
|
||||
memory_fence::memory_fence,
|
||||
preempt::current_task,
|
||||
timer::yield_task,
|
||||
@ -27,36 +28,34 @@ struct Mutex {
|
||||
}
|
||||
|
||||
pub(crate) struct ConcurrentQueue {
|
||||
raw_queue: critical_section::Mutex<RefCell<RawQueue>>,
|
||||
raw_queue: Locked<RawQueue>,
|
||||
}
|
||||
|
||||
impl ConcurrentQueue {
|
||||
pub(crate) fn new(count: usize, item_size: usize) -> Self {
|
||||
Self {
|
||||
raw_queue: critical_section::Mutex::new(RefCell::new(RawQueue::new(count, item_size))),
|
||||
raw_queue: Locked::new(RawQueue::new(count, item_size)),
|
||||
}
|
||||
}
|
||||
|
||||
fn release_storage(&mut self) {
|
||||
critical_section::with(|cs| unsafe {
|
||||
self.raw_queue.borrow_ref_mut(cs).release_storage();
|
||||
})
|
||||
self.raw_queue.with(|q| unsafe { q.release_storage() })
|
||||
}
|
||||
|
||||
pub(crate) fn enqueue(&mut self, item: *mut c_void) -> i32 {
|
||||
critical_section::with(|cs| unsafe { self.raw_queue.borrow_ref_mut(cs).enqueue(item) })
|
||||
self.raw_queue.with(|q| unsafe { q.enqueue(item) })
|
||||
}
|
||||
|
||||
pub(crate) fn try_dequeue(&mut self, item: *mut c_void) -> bool {
|
||||
critical_section::with(|cs| unsafe { self.raw_queue.borrow_ref_mut(cs).try_dequeue(item) })
|
||||
self.raw_queue.with(|q| unsafe { q.try_dequeue(item) })
|
||||
}
|
||||
|
||||
pub(crate) fn remove(&mut self, item: *mut c_void) {
|
||||
critical_section::with(|cs| unsafe { self.raw_queue.borrow_ref_mut(cs).remove(item) });
|
||||
self.raw_queue.with(|q| unsafe { q.remove(item) })
|
||||
}
|
||||
|
||||
pub(crate) fn count(&self) -> usize {
|
||||
critical_section::with(|cs| unsafe { self.raw_queue.borrow_ref(cs).count() })
|
||||
self.raw_queue.with(|q| unsafe { q.count() })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
use alloc::boxed::Box;
|
||||
use core::cell::RefCell;
|
||||
|
||||
use critical_section::Mutex;
|
||||
use esp_hal::sync::Locked;
|
||||
|
||||
use crate::binary::{
|
||||
c_types,
|
||||
@ -138,7 +137,7 @@ impl TimerQueue {
|
||||
|
||||
unsafe impl Send for TimerQueue {}
|
||||
|
||||
pub(crate) static TIMERS: Mutex<RefCell<TimerQueue>> = Mutex::new(RefCell::new(TimerQueue::new()));
|
||||
pub(crate) static TIMERS: Locked<TimerQueue> = Locked::new(TimerQueue::new());
|
||||
|
||||
pub(crate) fn compat_timer_arm(ets_timer: *mut ets_timer, tmout: u32, repeat: bool) {
|
||||
compat_timer_arm_us(ets_timer, tmout * 1000, repeat);
|
||||
@ -156,8 +155,8 @@ pub(crate) fn compat_timer_arm_us(ets_timer: *mut ets_timer, us: u32, repeat: bo
|
||||
repeat
|
||||
);
|
||||
|
||||
critical_section::with(|cs| {
|
||||
if let Some(timer) = TIMERS.borrow_ref_mut(cs).find(ets_timer) {
|
||||
TIMERS.with(|timers| {
|
||||
if let Some(timer) = timers.find(ets_timer) {
|
||||
timer.started = systick;
|
||||
timer.timeout = ticks;
|
||||
timer.active = true;
|
||||
@ -170,8 +169,8 @@ pub(crate) fn compat_timer_arm_us(ets_timer: *mut ets_timer, us: u32, repeat: bo
|
||||
|
||||
pub fn compat_timer_disarm(ets_timer: *mut ets_timer) {
|
||||
trace!("timer disarm");
|
||||
critical_section::with(|cs| {
|
||||
if let Some(timer) = TIMERS.borrow_ref_mut(cs).find(ets_timer) {
|
||||
TIMERS.with(|timers| {
|
||||
if let Some(timer) = timers.find(ets_timer) {
|
||||
trace!("timer_disarm {:x}", timer.id());
|
||||
timer.active = false;
|
||||
} else {
|
||||
@ -182,8 +181,7 @@ pub fn compat_timer_disarm(ets_timer: *mut ets_timer) {
|
||||
|
||||
pub fn compat_timer_done(ets_timer: *mut ets_timer) {
|
||||
trace!("timer done");
|
||||
critical_section::with(|cs| {
|
||||
let mut timers = TIMERS.borrow_ref_mut(cs);
|
||||
TIMERS.with(|timers| {
|
||||
if let Some(timer) = timers.find(ets_timer) {
|
||||
trace!("timer_done {:x}", timer.id());
|
||||
timer.active = false;
|
||||
@ -211,8 +209,7 @@ pub(crate) fn compat_timer_setfn(
|
||||
pfunction,
|
||||
parg
|
||||
);
|
||||
let set = critical_section::with(|cs| unsafe {
|
||||
let mut timers = TIMERS.borrow_ref_mut(cs);
|
||||
let set = TIMERS.with(|timers| unsafe {
|
||||
if let Some(timer) = timers.find(ets_timer) {
|
||||
timer.callback = TimerCallback::new(pfunction, parg);
|
||||
timer.active = false;
|
||||
|
@ -22,16 +22,15 @@
|
||||
//! ```toml
|
||||
//! [dependencies.esp-wifi]
|
||||
//! # A supported chip needs to be specified, as well as specific use-case features
|
||||
//! features = ["esp32s3", "wifi", "esp-now"]
|
||||
#![doc = concat!(r#"features = [""#, esp_hal::chip!(), r#"", "wifi", "esp-now"]"#)]
|
||||
//! ```
|
||||
//!
|
||||
//!
|
||||
//! ### Optimization Level
|
||||
//!
|
||||
//! It is necessary to build with optimization level 2 or 3 since otherwise, it
|
||||
//! might not even be able to connect or advertise.
|
||||
//!
|
||||
//! To make it work also for your debug builds add this to your `Cargo.toml`
|
||||
//!
|
||||
//! ```toml
|
||||
//! [profile.dev.package.esp-wifi]
|
||||
//! opt-level = 3
|
||||
@ -419,7 +418,7 @@ pub unsafe fn deinit_unchecked() -> Result<(), InitializationError> {
|
||||
shutdown_timer_isr();
|
||||
crate::preempt::delete_all_tasks();
|
||||
|
||||
critical_section::with(|cs| crate::timer::TIMER.borrow_ref_mut(cs).take());
|
||||
crate::timer::TIMER.with(|timer| timer.take());
|
||||
|
||||
crate::flags::ESP_WIFI_INITIALIZED.store(false, Ordering::Release);
|
||||
|
||||
|
@ -2,10 +2,10 @@
|
||||
#[cfg_attr(target_arch = "xtensa", path = "preempt_xtensa.rs")]
|
||||
pub mod arch_specific;
|
||||
|
||||
use core::{cell::RefCell, mem::size_of};
|
||||
use core::mem::size_of;
|
||||
|
||||
use arch_specific::*;
|
||||
use critical_section::Mutex;
|
||||
use esp_hal::sync::Locked;
|
||||
use esp_wifi_sys::include::malloc;
|
||||
|
||||
use crate::{compat::malloc::free, hal::trapframe::TrapFrame, memory_fence::memory_fence};
|
||||
@ -15,14 +15,12 @@ struct ContextWrapper(*mut Context);
|
||||
|
||||
unsafe impl Send for ContextWrapper {}
|
||||
|
||||
static CTX_NOW: Mutex<RefCell<ContextWrapper>> =
|
||||
Mutex::new(RefCell::new(ContextWrapper(core::ptr::null_mut())));
|
||||
static CTX_NOW: Locked<ContextWrapper> = Locked::new(ContextWrapper(core::ptr::null_mut()));
|
||||
|
||||
static mut SCHEDULED_TASK_TO_DELETE: *mut Context = core::ptr::null_mut();
|
||||
|
||||
pub(crate) fn allocate_main_task() -> *mut Context {
|
||||
critical_section::with(|cs| unsafe {
|
||||
let mut ctx_now = CTX_NOW.borrow_ref_mut(cs);
|
||||
CTX_NOW.with(|ctx_now| unsafe {
|
||||
if !ctx_now.0.is_null() {
|
||||
panic!("Tried to allocate main task multiple times");
|
||||
}
|
||||
@ -36,8 +34,7 @@ pub(crate) fn allocate_main_task() -> *mut Context {
|
||||
}
|
||||
|
||||
fn allocate_task() -> *mut Context {
|
||||
critical_section::with(|cs| unsafe {
|
||||
let mut ctx_now = CTX_NOW.borrow_ref_mut(cs);
|
||||
CTX_NOW.with(|ctx_now| unsafe {
|
||||
if ctx_now.0.is_null() {
|
||||
panic!("Called `allocate_task` before allocating main task");
|
||||
}
|
||||
@ -51,8 +48,7 @@ fn allocate_task() -> *mut Context {
|
||||
}
|
||||
|
||||
fn next_task() {
|
||||
critical_section::with(|cs| unsafe {
|
||||
let mut ctx_now = CTX_NOW.borrow_ref_mut(cs);
|
||||
CTX_NOW.with(|ctx_now| unsafe {
|
||||
ctx_now.0 = (*ctx_now.0).next;
|
||||
});
|
||||
}
|
||||
@ -61,8 +57,8 @@ fn next_task() {
|
||||
///
|
||||
/// This will also free the memory (stack and context) allocated for it.
|
||||
pub(crate) fn delete_task(task: *mut Context) {
|
||||
critical_section::with(|cs| unsafe {
|
||||
let mut ptr = CTX_NOW.borrow_ref_mut(cs).0;
|
||||
CTX_NOW.with(|ctx_now| unsafe {
|
||||
let mut ptr = ctx_now.0;
|
||||
let initial = ptr;
|
||||
loop {
|
||||
if (*ptr).next == task {
|
||||
@ -85,9 +81,8 @@ pub(crate) fn delete_task(task: *mut Context) {
|
||||
}
|
||||
|
||||
pub(crate) fn delete_all_tasks() {
|
||||
critical_section::with(|cs| unsafe {
|
||||
let mut ctx_now_ref = CTX_NOW.borrow_ref_mut(cs);
|
||||
let current_task = ctx_now_ref.0;
|
||||
CTX_NOW.with(|ctx_now| unsafe {
|
||||
let current_task = ctx_now.0;
|
||||
|
||||
if current_task.is_null() {
|
||||
return;
|
||||
@ -108,14 +103,14 @@ pub(crate) fn delete_all_tasks() {
|
||||
task_to_delete = next_task;
|
||||
}
|
||||
|
||||
ctx_now_ref.0 = core::ptr::null_mut();
|
||||
ctx_now.0 = core::ptr::null_mut();
|
||||
|
||||
memory_fence();
|
||||
});
|
||||
}
|
||||
|
||||
pub(crate) fn current_task() -> *mut Context {
|
||||
critical_section::with(|cs| CTX_NOW.borrow_ref(cs).0)
|
||||
CTX_NOW.with(|ctx_now| ctx_now.0)
|
||||
}
|
||||
|
||||
pub(crate) fn schedule_task_deletion(task: *mut Context) {
|
||||
|
@ -18,21 +18,16 @@ pub(crate) fn init_tasks() {
|
||||
pub(crate) extern "C" fn timer_task(_param: *mut esp_wifi_sys::c_types::c_void) {
|
||||
loop {
|
||||
let current_timestamp = systimer_count();
|
||||
let to_run = critical_section::with(|cs| unsafe {
|
||||
let mut timers = TIMERS.borrow_ref_mut(cs);
|
||||
let to_run = timers.find_next_due(current_timestamp);
|
||||
let to_run = TIMERS.with(|timers| {
|
||||
let to_run = unsafe { timers.find_next_due(current_timestamp) }?;
|
||||
|
||||
if let Some(to_run) = to_run {
|
||||
to_run.active = to_run.periodic;
|
||||
to_run.active = to_run.periodic;
|
||||
|
||||
if to_run.periodic {
|
||||
to_run.started = current_timestamp;
|
||||
}
|
||||
|
||||
Some(to_run.callback)
|
||||
} else {
|
||||
None
|
||||
if to_run.periodic {
|
||||
to_run.started = current_timestamp;
|
||||
}
|
||||
|
||||
Some(to_run.callback)
|
||||
});
|
||||
|
||||
// run the due timer callback NOT in an interrupt free context
|
||||
|
@ -1,6 +1,4 @@
|
||||
use core::cell::RefCell;
|
||||
|
||||
use critical_section::Mutex;
|
||||
use esp_hal::sync::Locked;
|
||||
|
||||
#[cfg_attr(esp32, path = "timer_esp32.rs")]
|
||||
#[cfg_attr(esp32c2, path = "timer_esp32c2.rs")]
|
||||
@ -20,7 +18,7 @@ pub(crate) use chip_specific::*;
|
||||
|
||||
use crate::TimeBase;
|
||||
|
||||
pub(crate) static TIMER: Mutex<RefCell<Option<TimeBase>>> = Mutex::new(RefCell::new(None));
|
||||
pub(crate) static TIMER: Locked<Option<TimeBase>> = Locked::new(None);
|
||||
|
||||
pub(crate) fn setup_timer_isr(timebase: TimeBase) {
|
||||
setup_radio_isr();
|
||||
|
@ -30,16 +30,17 @@ pub(crate) fn setup_timer(mut alarm0: TimeBase) {
|
||||
let cb: extern "C" fn() = unsafe { core::mem::transmute(handler as *const ()) };
|
||||
alarm0.set_interrupt_handler(InterruptHandler::new(cb, interrupt::Priority::Priority1));
|
||||
unwrap!(alarm0.start(TIMESLICE_FREQUENCY.into_duration()));
|
||||
critical_section::with(|cs| {
|
||||
TIMER.with(|timer| {
|
||||
alarm0.enable_interrupt(true);
|
||||
TIMER.borrow_ref_mut(cs).replace(alarm0);
|
||||
timer.replace(alarm0);
|
||||
});
|
||||
}
|
||||
|
||||
pub(crate) fn disable_timer() {
|
||||
critical_section::with(|cs| {
|
||||
unwrap!(TIMER.borrow_ref_mut(cs).as_mut()).enable_interrupt(false);
|
||||
unwrap!(unwrap!(TIMER.borrow_ref_mut(cs).as_mut()).cancel());
|
||||
TIMER.with(|timer| {
|
||||
let timer = unwrap!(timer.as_mut());
|
||||
timer.enable_interrupt(false);
|
||||
unwrap!(timer.cancel());
|
||||
});
|
||||
}
|
||||
|
||||
@ -60,8 +61,8 @@ pub(crate) fn disable_multitasking() {
|
||||
|
||||
extern "C" fn handler(trap_frame: &mut TrapFrame) {
|
||||
// clear the systimer intr
|
||||
critical_section::with(|cs| {
|
||||
unwrap!(TIMER.borrow_ref_mut(cs).as_mut()).clear_interrupt();
|
||||
TIMER.with(|timer| {
|
||||
unwrap!(timer.as_mut()).clear_interrupt();
|
||||
});
|
||||
|
||||
task_switch(trap_frame);
|
||||
@ -76,8 +77,7 @@ extern "C" fn FROM_CPU_INTR3(trap_frame: &mut TrapFrame) {
|
||||
.modify(|_, w| w.cpu_intr_from_cpu_3().clear_bit());
|
||||
}
|
||||
|
||||
critical_section::with(|cs| {
|
||||
let mut alarm0 = TIMER.borrow_ref_mut(cs);
|
||||
TIMER.with(|alarm0| {
|
||||
let alarm0 = unwrap!(alarm0.as_mut());
|
||||
alarm0.clear_interrupt();
|
||||
});
|
||||
|
@ -27,16 +27,17 @@ pub(crate) fn setup_timer(mut timer1: TimeBase) {
|
||||
interrupt::Priority::Priority2,
|
||||
));
|
||||
unwrap!(timer1.start(TIMESLICE_FREQUENCY.into_duration()));
|
||||
critical_section::with(|cs| {
|
||||
TIMER.with(|timer| {
|
||||
timer1.enable_interrupt(true);
|
||||
TIMER.borrow_ref_mut(cs).replace(timer1);
|
||||
timer.replace(timer1);
|
||||
});
|
||||
}
|
||||
|
||||
pub(crate) fn disable_timer() {
|
||||
critical_section::with(|cs| {
|
||||
unwrap!(TIMER.borrow_ref_mut(cs).as_mut()).enable_interrupt(false);
|
||||
unwrap!(unwrap!(TIMER.borrow_ref_mut(cs).as_mut()).cancel());
|
||||
TIMER.with(|timer| {
|
||||
let timer = unwrap!(timer.as_mut());
|
||||
timer.enable_interrupt(false);
|
||||
unwrap!(timer.cancel());
|
||||
});
|
||||
}
|
||||
|
||||
@ -58,8 +59,7 @@ pub(crate) fn disable_multitasking() {
|
||||
}
|
||||
|
||||
fn do_task_switch(context: &mut TrapFrame) {
|
||||
critical_section::with(|cs| {
|
||||
let mut timer = TIMER.borrow_ref_mut(cs);
|
||||
TIMER.with(|timer| {
|
||||
let timer = unwrap!(timer.as_mut());
|
||||
timer.clear_interrupt();
|
||||
});
|
||||
|
@ -1,7 +1,6 @@
|
||||
use alloc::boxed::Box;
|
||||
use core::cell::RefCell;
|
||||
|
||||
use critical_section::Mutex;
|
||||
use esp_hal::sync::Locked;
|
||||
|
||||
use super::WifiEvent;
|
||||
|
||||
@ -10,17 +9,17 @@ pub(crate) mod sealed {
|
||||
|
||||
pub trait Event {
|
||||
/// Get the static reference to the handler for this event.
|
||||
fn handler() -> &'static Mutex<RefCell<Option<Box<Handler<Self>>>>>;
|
||||
fn handler() -> &'static Locked<Option<Box<Handler<Self>>>>;
|
||||
/// # Safety
|
||||
/// `ptr` must be a valid for casting to this event's inner event data.
|
||||
unsafe fn from_raw_event_data(ptr: *mut crate::binary::c_types::c_void) -> Self;
|
||||
}
|
||||
}
|
||||
/// The type of handlers of events.
|
||||
pub type Handler<T> = dyn FnMut(critical_section::CriticalSection<'_>, &T) + Sync + Send;
|
||||
pub type Handler<T> = dyn FnMut(&T) + Sync + Send;
|
||||
|
||||
fn default_handler<Event: 'static>() -> Box<Handler<Event>> {
|
||||
fn drop_ref<T>(_: critical_section::CriticalSection<'_>, _: &T) {}
|
||||
fn drop_ref<T>(_: &T) {}
|
||||
// perf: `drop_ref` is a ZST [function item](https://doc.rust-lang.org/reference/types/function-item.html)
|
||||
// so this doesn't actually allocate.
|
||||
Box::new(drop_ref)
|
||||
@ -29,9 +28,10 @@ fn default_handler<Event: 'static>() -> Box<Handler<Event>> {
|
||||
/// Extension trait for setting handlers for an event.
|
||||
///
|
||||
/// Register a new event handler like:
|
||||
/// ```
|
||||
///
|
||||
/// ```rust, no_run
|
||||
/// # use esp_wifi::wifi::event::{self, *};
|
||||
/// # fn new_handler(_: critical_section::CriticalSection<'_>, _: &ApStaconnected) {}
|
||||
/// # fn new_handler(_: &ApStaconnected) {}
|
||||
/// event::ApStaconnected::update_handler(|_cs, event| {
|
||||
/// new_handler(event);
|
||||
/// })
|
||||
@ -43,46 +43,28 @@ fn default_handler<Event: 'static>() -> Box<Handler<Event>> {
|
||||
pub trait EventExt: sealed::Event + Sized + 'static {
|
||||
/// Get the handler for this event, replacing it with the default handler.
|
||||
fn take_handler() -> Box<Handler<Self>> {
|
||||
critical_section::with(|cs| {
|
||||
Self::handler()
|
||||
.borrow_ref_mut(cs)
|
||||
.take()
|
||||
.unwrap_or_else(default_handler::<Self>)
|
||||
})
|
||||
Self::handler().with(|handler| handler.take().unwrap_or_else(default_handler::<Self>))
|
||||
}
|
||||
/// Set the handler for this event, returning the old handler.
|
||||
fn replace_handler<
|
||||
F: FnMut(critical_section::CriticalSection<'_>, &Self) + Sync + Send + 'static,
|
||||
>(
|
||||
f: F,
|
||||
) -> Box<Handler<Self>> {
|
||||
critical_section::with(|cs| {
|
||||
Self::handler()
|
||||
.borrow_ref_mut(cs)
|
||||
fn replace_handler<F: FnMut(&Self) + Sync + Send + 'static>(f: F) -> Box<Handler<Self>> {
|
||||
Self::handler().with(|handler| {
|
||||
handler
|
||||
.replace(Box::new(f))
|
||||
.unwrap_or_else(default_handler::<Self>)
|
||||
})
|
||||
}
|
||||
/// Atomic combination of [`take_handler`] and [`replace_handler`]. Use this
|
||||
/// to add a new handler which runs after the previously registered
|
||||
/// handlers.
|
||||
fn update_handler<
|
||||
F: FnMut(critical_section::CriticalSection<'_>, &Self) + Sync + Send + 'static,
|
||||
>(
|
||||
mut f: F,
|
||||
) {
|
||||
critical_section::with(move |cs| {
|
||||
let mut handler: Box<Handler<Self>> = Self::handler()
|
||||
.borrow_ref_mut(cs)
|
||||
.take()
|
||||
.unwrap_or_else(default_handler::<Self>);
|
||||
Self::handler().borrow_ref_mut(cs).replace(Box::new(
|
||||
move |cs: critical_section::CriticalSection<'_>, event| {
|
||||
handler(cs, event);
|
||||
f(cs, event)
|
||||
},
|
||||
));
|
||||
});
|
||||
/// Atomic combination of [`Self::take_handler`] and
|
||||
/// [`Self::replace_handler`]. Use this to add a new handler which runs
|
||||
/// after the previously registered handlers.
|
||||
fn update_handler<F: FnMut(&Self) + Sync + Send + 'static>(mut f: F) {
|
||||
Self::handler().with(|handler| {
|
||||
let mut prev: Box<Handler<Self>> =
|
||||
handler.take().unwrap_or_else(default_handler::<Self>);
|
||||
handler.replace(Box::new(move |event| {
|
||||
prev(event);
|
||||
f(event)
|
||||
}));
|
||||
})
|
||||
}
|
||||
}
|
||||
impl<T: sealed::Event + 'static> EventExt for T {}
|
||||
@ -97,9 +79,8 @@ macro_rules! impl_wifi_event {
|
||||
unsafe fn from_raw_event_data(_: *mut crate::binary::c_types::c_void) -> Self {
|
||||
Self
|
||||
}
|
||||
fn handler() -> &'static Mutex<RefCell<Option<Box<Handler<Self>>>>> {
|
||||
static HANDLE: Mutex<RefCell<Option<Box<Handler<$newtype>>>>> =
|
||||
Mutex::new(RefCell::new(None));
|
||||
fn handler() -> &'static Locked<Option<Box<Handler<Self>>>> {
|
||||
static HANDLE: Locked<Option<Box<Handler<$newtype>>>> = Locked::new(None);
|
||||
&HANDLE
|
||||
}
|
||||
}
|
||||
@ -114,9 +95,8 @@ macro_rules! impl_wifi_event {
|
||||
unsafe fn from_raw_event_data(ptr: *mut crate::binary::c_types::c_void) -> Self {
|
||||
Self(unsafe { *ptr.cast() })
|
||||
}
|
||||
fn handler() -> &'static Mutex<RefCell<Option<Box<Handler<Self>>>>> {
|
||||
static HANDLE: Mutex<RefCell<Option<Box<Handler<$newtype>>>>> =
|
||||
Mutex::new(RefCell::new(None));
|
||||
fn handler() -> &'static Locked<Option<Box<Handler<Self>>>> {
|
||||
static HANDLE: Locked<Option<Box<Handler<$newtype>>>> = Locked::new(None);
|
||||
&HANDLE
|
||||
}
|
||||
}
|
||||
@ -170,23 +150,21 @@ impl_wifi_event!(HomeChannelChange, wifi_event_home_channel_change_t);
|
||||
impl_wifi_event!(StaNeighborRep, wifi_event_neighbor_report_t);
|
||||
|
||||
/// Handle the given event using the registered event handlers.
|
||||
pub fn handle<Event: EventExt>(
|
||||
cs: critical_section::CriticalSection<'_>,
|
||||
event_data: &Event,
|
||||
) -> bool {
|
||||
if let Some(handler) = &mut *Event::handler().borrow_ref_mut(cs) {
|
||||
handler(cs, event_data);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
pub fn handle<Event: EventExt>(event_data: &Event) -> bool {
|
||||
Event::handler().with(|handler| {
|
||||
if let Some(handler) = handler {
|
||||
handler(event_data);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Handle an event given the raw pointers.
|
||||
/// # Safety
|
||||
/// The pointer should be valid to cast to `Event`'s inner type (if it has one)
|
||||
pub(crate) unsafe fn handle_raw<Event: EventExt>(
|
||||
cs: critical_section::CriticalSection<'_>,
|
||||
event_data: *mut crate::binary::c_types::c_void,
|
||||
event_data_size: usize,
|
||||
) -> bool {
|
||||
@ -195,7 +173,7 @@ pub(crate) unsafe fn handle_raw<Event: EventExt>(
|
||||
core::mem::size_of::<Event>(),
|
||||
"wrong size event data"
|
||||
);
|
||||
handle::<Event>(cs, unsafe { &Event::from_raw_event_data(event_data) })
|
||||
handle::<Event>(unsafe { &Event::from_raw_event_data(event_data) })
|
||||
}
|
||||
|
||||
/// Handle event regardless of its type.
|
||||
@ -203,146 +181,145 @@ pub(crate) unsafe fn handle_raw<Event: EventExt>(
|
||||
/// Arguments should be self-consistent.
|
||||
#[rustfmt::skip]
|
||||
pub(crate) unsafe fn dispatch_event_handler(
|
||||
cs: critical_section::CriticalSection<'_>,
|
||||
event: WifiEvent,
|
||||
event_data: *mut crate::binary::c_types::c_void,
|
||||
event_data_size: usize,
|
||||
) -> bool {
|
||||
match event {
|
||||
WifiEvent::WifiReady => {
|
||||
handle_raw::<WifiReady>(cs, event_data, event_data_size)
|
||||
handle_raw::<WifiReady>(event_data, event_data_size)
|
||||
}
|
||||
WifiEvent::ScanDone => {
|
||||
handle_raw::<ScanDone>(cs, event_data, event_data_size)
|
||||
handle_raw::<ScanDone>(event_data, event_data_size)
|
||||
}
|
||||
WifiEvent::StaStart => {
|
||||
handle_raw::<StaStart>(cs, event_data, event_data_size)
|
||||
handle_raw::<StaStart>(event_data, event_data_size)
|
||||
}
|
||||
WifiEvent::StaStop => {
|
||||
handle_raw::<StaStop>(cs, event_data, event_data_size)
|
||||
handle_raw::<StaStop>(event_data, event_data_size)
|
||||
}
|
||||
WifiEvent::StaConnected => {
|
||||
handle_raw::<StaConnected>(cs, event_data, event_data_size)
|
||||
handle_raw::<StaConnected>(event_data, event_data_size)
|
||||
}
|
||||
WifiEvent::StaDisconnected => {
|
||||
handle_raw::<StaDisconnected>(cs, event_data, event_data_size)
|
||||
handle_raw::<StaDisconnected>(event_data, event_data_size)
|
||||
}
|
||||
WifiEvent::StaAuthmodeChange => {
|
||||
handle_raw::<StaAuthmodeChange>(cs, event_data, event_data_size)
|
||||
handle_raw::<StaAuthmodeChange>(event_data, event_data_size)
|
||||
}
|
||||
WifiEvent::StaWpsErSuccess => {
|
||||
handle_raw::<StaWpsErSuccess>(cs, event_data, event_data_size)
|
||||
handle_raw::<StaWpsErSuccess>(event_data, event_data_size)
|
||||
}
|
||||
WifiEvent::StaWpsErFailed => {
|
||||
handle_raw::<StaWpsErFailed>(cs, event_data, event_data_size)
|
||||
handle_raw::<StaWpsErFailed>(event_data, event_data_size)
|
||||
}
|
||||
WifiEvent::StaWpsErTimeout => {
|
||||
handle_raw::<StaWpsErTimeout>(cs, event_data, event_data_size)
|
||||
handle_raw::<StaWpsErTimeout>(event_data, event_data_size)
|
||||
}
|
||||
WifiEvent::StaWpsErPin => {
|
||||
handle_raw::<StaWpsErPin>(cs, event_data, event_data_size)
|
||||
handle_raw::<StaWpsErPin>(event_data, event_data_size)
|
||||
}
|
||||
WifiEvent::StaWpsErPbcOverlap => {
|
||||
handle_raw::<StaWpsErPbcOverlap>(cs, event_data, event_data_size)
|
||||
handle_raw::<StaWpsErPbcOverlap>(event_data, event_data_size)
|
||||
}
|
||||
WifiEvent::ApStart => {
|
||||
handle_raw::<ApStart>(cs, event_data, event_data_size)
|
||||
handle_raw::<ApStart>(event_data, event_data_size)
|
||||
}
|
||||
WifiEvent::ApStop => {
|
||||
handle_raw::<ApStop>(cs, event_data, event_data_size)
|
||||
handle_raw::<ApStop>(event_data, event_data_size)
|
||||
}
|
||||
WifiEvent::ApStaconnected => {
|
||||
handle_raw::<ApStaconnected>(cs, event_data, event_data_size)
|
||||
handle_raw::<ApStaconnected>(event_data, event_data_size)
|
||||
}
|
||||
WifiEvent::ApStadisconnected => {
|
||||
handle_raw::<ApStadisconnected>(cs, event_data, event_data_size)
|
||||
handle_raw::<ApStadisconnected>(event_data, event_data_size)
|
||||
}
|
||||
WifiEvent::ApProbereqrecved => {
|
||||
handle_raw::<ApProbereqrecved>(cs, event_data, event_data_size)
|
||||
handle_raw::<ApProbereqrecved>(event_data, event_data_size)
|
||||
}
|
||||
WifiEvent::FtmReport => {
|
||||
handle_raw::<FtmReport>(cs, event_data, event_data_size)
|
||||
handle_raw::<FtmReport>(event_data, event_data_size)
|
||||
}
|
||||
WifiEvent::StaBssRssiLow => {
|
||||
handle_raw::<StaBssRssiLow>(cs, event_data, event_data_size)
|
||||
handle_raw::<StaBssRssiLow>(event_data, event_data_size)
|
||||
}
|
||||
WifiEvent::ActionTxStatus => {
|
||||
handle_raw::<ActionTxStatus>(cs, event_data, event_data_size)
|
||||
handle_raw::<ActionTxStatus>(event_data, event_data_size)
|
||||
}
|
||||
WifiEvent::RocDone => {
|
||||
handle_raw::<RocDone>(cs, event_data, event_data_size)
|
||||
handle_raw::<RocDone>(event_data, event_data_size)
|
||||
}
|
||||
WifiEvent::StaBeaconTimeout => {
|
||||
handle_raw::<StaBeaconTimeout>(cs, event_data, event_data_size)
|
||||
handle_raw::<StaBeaconTimeout>(event_data, event_data_size)
|
||||
}
|
||||
WifiEvent::ConnectionlessModuleWakeIntervalStart => {
|
||||
handle_raw::<ConnectionlessModuleWakeIntervalStart>(cs, event_data, event_data_size)
|
||||
handle_raw::<ConnectionlessModuleWakeIntervalStart>(event_data, event_data_size)
|
||||
}
|
||||
WifiEvent::ApWpsRgSuccess => {
|
||||
handle_raw::<ApWpsRgSuccess>(cs, event_data, event_data_size)
|
||||
handle_raw::<ApWpsRgSuccess>(event_data, event_data_size)
|
||||
}
|
||||
WifiEvent::ApWpsRgFailed => {
|
||||
handle_raw::<ApWpsRgFailed>(cs, event_data, event_data_size)
|
||||
handle_raw::<ApWpsRgFailed>(event_data, event_data_size)
|
||||
}
|
||||
WifiEvent::ApWpsRgTimeout => {
|
||||
handle_raw::<ApWpsRgTimeout>(cs, event_data, event_data_size)
|
||||
handle_raw::<ApWpsRgTimeout>(event_data, event_data_size)
|
||||
}
|
||||
WifiEvent::ApWpsRgPin => {
|
||||
handle_raw::<ApWpsRgPin>(cs, event_data, event_data_size)
|
||||
handle_raw::<ApWpsRgPin>(event_data, event_data_size)
|
||||
}
|
||||
WifiEvent::ApWpsRgPbcOverlap => {
|
||||
handle_raw::<ApWpsRgPbcOverlap>(cs, event_data, event_data_size)
|
||||
handle_raw::<ApWpsRgPbcOverlap>(event_data, event_data_size)
|
||||
}
|
||||
WifiEvent::ItwtSetup => {
|
||||
handle_raw::<ItwtSetup>(cs, event_data, event_data_size)
|
||||
handle_raw::<ItwtSetup>(event_data, event_data_size)
|
||||
}
|
||||
WifiEvent::ItwtTeardown => {
|
||||
handle_raw::<ItwtTeardown>(cs, event_data, event_data_size)
|
||||
handle_raw::<ItwtTeardown>(event_data, event_data_size)
|
||||
}
|
||||
WifiEvent::ItwtProbe => {
|
||||
handle_raw::<ItwtProbe>(cs, event_data, event_data_size)
|
||||
handle_raw::<ItwtProbe>(event_data, event_data_size)
|
||||
}
|
||||
WifiEvent::ItwtSuspend => {
|
||||
handle_raw::<ItwtSuspend>(cs, event_data, event_data_size)
|
||||
handle_raw::<ItwtSuspend>(event_data, event_data_size)
|
||||
}
|
||||
WifiEvent::TwtWakeup => {
|
||||
handle_raw::<TwtWakeup>(cs, event_data, event_data_size)
|
||||
handle_raw::<TwtWakeup>(event_data, event_data_size)
|
||||
}
|
||||
WifiEvent::BtwtSetup => {
|
||||
handle_raw::<BtwtSetup>(cs, event_data, event_data_size)
|
||||
handle_raw::<BtwtSetup>(event_data, event_data_size)
|
||||
}
|
||||
WifiEvent::BtwtTeardown => {
|
||||
handle_raw::<BtwtTeardown>(cs, event_data, event_data_size)
|
||||
handle_raw::<BtwtTeardown>(event_data, event_data_size)
|
||||
}
|
||||
WifiEvent::NanStarted => {
|
||||
handle_raw::<NanStarted>(cs, event_data, event_data_size)
|
||||
handle_raw::<NanStarted>(event_data, event_data_size)
|
||||
}
|
||||
WifiEvent::NanStopped => {
|
||||
handle_raw::<NanStopped>(cs, event_data, event_data_size)
|
||||
handle_raw::<NanStopped>(event_data, event_data_size)
|
||||
}
|
||||
WifiEvent::NanSvcMatch => {
|
||||
handle_raw::<NanSvcMatch>(cs, event_data, event_data_size)
|
||||
handle_raw::<NanSvcMatch>(event_data, event_data_size)
|
||||
}
|
||||
WifiEvent::NanReplied => {
|
||||
handle_raw::<NanReplied>(cs, event_data, event_data_size)
|
||||
handle_raw::<NanReplied>(event_data, event_data_size)
|
||||
}
|
||||
WifiEvent::NanReceive => {
|
||||
handle_raw::<NanReceive>(cs, event_data, event_data_size)
|
||||
handle_raw::<NanReceive>(event_data, event_data_size)
|
||||
}
|
||||
WifiEvent::NdpIndication => {
|
||||
handle_raw::<NdpIndication>(cs, event_data, event_data_size)
|
||||
handle_raw::<NdpIndication>(event_data, event_data_size)
|
||||
}
|
||||
WifiEvent::NdpConfirm => {
|
||||
handle_raw::<NdpConfirm>(cs, event_data, event_data_size)
|
||||
handle_raw::<NdpConfirm>(event_data, event_data_size)
|
||||
}
|
||||
WifiEvent::NdpTerminated => {
|
||||
handle_raw::<NdpTerminated>(cs, event_data, event_data_size)
|
||||
handle_raw::<NdpTerminated>(event_data, event_data_size)
|
||||
}
|
||||
WifiEvent::HomeChannelChange => {
|
||||
handle_raw::<HomeChannelChange>(cs, event_data, event_data_size)
|
||||
handle_raw::<HomeChannelChange>(event_data, event_data_size)
|
||||
}
|
||||
WifiEvent::StaNeighborRep => {
|
||||
handle_raw::<StaNeighborRep>(cs, event_data, event_data_size)
|
||||
handle_raw::<StaNeighborRep>(event_data, event_data_size)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,15 +6,14 @@ pub(crate) mod state;
|
||||
|
||||
use alloc::collections::vec_deque::VecDeque;
|
||||
use core::{
|
||||
cell::{RefCell, RefMut},
|
||||
fmt::Debug,
|
||||
mem::{self, MaybeUninit},
|
||||
ptr::addr_of,
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use critical_section::{CriticalSection, Mutex};
|
||||
use enumset::{EnumSet, EnumSetType};
|
||||
use esp_hal::sync::Locked;
|
||||
use esp_wifi_sys::include::{
|
||||
esp_eap_client_clear_ca_cert,
|
||||
esp_eap_client_clear_certificate_and_key,
|
||||
@ -952,11 +951,11 @@ const DATA_FRAME_SIZE: usize = MTU + ETHERNET_FRAME_HEADER_SIZE;
|
||||
const RX_QUEUE_SIZE: usize = crate::CONFIG.rx_queue_size;
|
||||
const TX_QUEUE_SIZE: usize = crate::CONFIG.tx_queue_size;
|
||||
|
||||
pub(crate) static DATA_QUEUE_RX_AP: Mutex<RefCell<VecDeque<EspWifiPacketBuffer>>> =
|
||||
Mutex::new(RefCell::new(VecDeque::new()));
|
||||
pub(crate) static DATA_QUEUE_RX_AP: Locked<VecDeque<EspWifiPacketBuffer>> =
|
||||
Locked::new(VecDeque::new());
|
||||
|
||||
pub(crate) static DATA_QUEUE_RX_STA: Mutex<RefCell<VecDeque<EspWifiPacketBuffer>>> =
|
||||
Mutex::new(RefCell::new(VecDeque::new()));
|
||||
pub(crate) static DATA_QUEUE_RX_STA: Locked<VecDeque<EspWifiPacketBuffer>> =
|
||||
Locked::new(VecDeque::new());
|
||||
|
||||
/// Common errors.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
@ -1529,14 +1528,13 @@ unsafe extern "C" fn recv_cb_sta(
|
||||
eb: *mut c_types::c_void,
|
||||
) -> esp_err_t {
|
||||
let packet = EspWifiPacketBuffer { buffer, len, eb };
|
||||
// We must handle the result outside of the critical section because
|
||||
// We must handle the result outside of the lock because
|
||||
// EspWifiPacketBuffer::drop must not be called in a critical section.
|
||||
// Dropping an EspWifiPacketBuffer will call `esp_wifi_internal_free_rx_buffer`
|
||||
// which will try to lock an internal mutex. If the mutex is already taken,
|
||||
// the function will try to trigger a context switch, which will fail if we
|
||||
// are in a critical section.
|
||||
if critical_section::with(|cs| {
|
||||
let mut queue = DATA_QUEUE_RX_STA.borrow_ref_mut(cs);
|
||||
// are in an interrupt-free context.
|
||||
if DATA_QUEUE_RX_STA.with(|queue| {
|
||||
if queue.len() < RX_QUEUE_SIZE {
|
||||
queue.push_back(packet);
|
||||
true
|
||||
@ -1563,9 +1561,8 @@ unsafe extern "C" fn recv_cb_ap(
|
||||
// Dropping an EspWifiPacketBuffer will call `esp_wifi_internal_free_rx_buffer`
|
||||
// which will try to lock an internal mutex. If the mutex is already taken,
|
||||
// the function will try to trigger a context switch, which will fail if we
|
||||
// are in a critical section.
|
||||
if critical_section::with(|cs| {
|
||||
let mut queue = DATA_QUEUE_RX_AP.borrow_ref_mut(cs);
|
||||
// are in an interrupt-free context.
|
||||
if DATA_QUEUE_RX_AP.with(|queue| {
|
||||
if queue.len() < RX_QUEUE_SIZE {
|
||||
queue.push_back(packet);
|
||||
true
|
||||
@ -1905,7 +1902,7 @@ mod sealed {
|
||||
|
||||
fn wrap_config(config: Self::Config) -> Configuration;
|
||||
|
||||
fn data_queue_rx(self, cs: CriticalSection) -> RefMut<'_, VecDeque<EspWifiPacketBuffer>>;
|
||||
fn data_queue_rx(self) -> &'static Locked<VecDeque<EspWifiPacketBuffer>>;
|
||||
|
||||
fn can_send(self) -> bool {
|
||||
WIFI_TX_INFLIGHT.load(Ordering::SeqCst) < TX_QUEUE_SIZE
|
||||
@ -1928,13 +1925,12 @@ mod sealed {
|
||||
}
|
||||
|
||||
fn rx_token(self) -> Option<(WifiRxToken<Self>, WifiTxToken<Self>)> {
|
||||
let is_empty = critical_section::with(|cs| self.data_queue_rx(cs).is_empty());
|
||||
let is_empty = self.data_queue_rx().with(|q| q.is_empty());
|
||||
if is_empty || !self.can_send() {
|
||||
crate::timer::yield_task();
|
||||
}
|
||||
|
||||
let is_empty =
|
||||
is_empty && critical_section::with(|cs| self.data_queue_rx(cs).is_empty());
|
||||
let is_empty = is_empty && self.data_queue_rx().with(|q| q.is_empty());
|
||||
|
||||
if !is_empty {
|
||||
self.tx_token().map(|tx| (WifiRxToken { mode: self }, tx))
|
||||
@ -1967,8 +1963,8 @@ mod sealed {
|
||||
Configuration::Client(config)
|
||||
}
|
||||
|
||||
fn data_queue_rx(self, cs: CriticalSection) -> RefMut<'_, VecDeque<EspWifiPacketBuffer>> {
|
||||
DATA_QUEUE_RX_STA.borrow_ref_mut(cs)
|
||||
fn data_queue_rx(self) -> &'static Locked<VecDeque<EspWifiPacketBuffer>> {
|
||||
&DATA_QUEUE_RX_STA
|
||||
}
|
||||
|
||||
fn interface(self) -> wifi_interface_t {
|
||||
@ -2003,8 +1999,8 @@ mod sealed {
|
||||
Configuration::AccessPoint(config)
|
||||
}
|
||||
|
||||
fn data_queue_rx(self, cs: CriticalSection) -> RefMut<'_, VecDeque<EspWifiPacketBuffer>> {
|
||||
DATA_QUEUE_RX_AP.borrow_ref_mut(cs)
|
||||
fn data_queue_rx(self) -> &'static Locked<VecDeque<EspWifiPacketBuffer>> {
|
||||
&DATA_QUEUE_RX_AP
|
||||
}
|
||||
|
||||
fn interface(self) -> wifi_interface_t {
|
||||
@ -2321,7 +2317,7 @@ impl PromiscuousPkt<'_> {
|
||||
frame_type,
|
||||
len,
|
||||
data: core::slice::from_raw_parts(
|
||||
(buf as *const u8).add(size_of::<wifi_pkt_rx_ctrl_t>()),
|
||||
(buf as *const u8).add(core::mem::size_of::<wifi_pkt_rx_ctrl_t>()),
|
||||
len,
|
||||
),
|
||||
}
|
||||
@ -2329,18 +2325,14 @@ impl PromiscuousPkt<'_> {
|
||||
}
|
||||
|
||||
#[cfg(feature = "sniffer")]
|
||||
#[allow(clippy::type_complexity)]
|
||||
static SNIFFER_CB: Mutex<RefCell<Option<fn(PromiscuousPkt)>>> = Mutex::new(RefCell::new(None));
|
||||
static SNIFFER_CB: Locked<Option<fn(PromiscuousPkt)>> = Locked::new(None);
|
||||
|
||||
#[cfg(feature = "sniffer")]
|
||||
unsafe extern "C" fn promiscuous_rx_cb(buf: *mut core::ffi::c_void, frame_type: u32) {
|
||||
critical_section::with(|cs| {
|
||||
let Some(sniffer_callback) = *SNIFFER_CB.borrow_ref(cs) else {
|
||||
return;
|
||||
};
|
||||
if let Some(sniffer_callback) = SNIFFER_CB.with(|callback| *callback) {
|
||||
let promiscuous_pkt = PromiscuousPkt::from_raw(buf as *const _, frame_type);
|
||||
sniffer_callback(promiscuous_pkt);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "sniffer")]
|
||||
@ -2385,9 +2377,7 @@ impl Sniffer {
|
||||
}
|
||||
/// Set the callback for receiving a packet.
|
||||
pub fn set_receive_cb(&mut self, cb: fn(PromiscuousPkt)) {
|
||||
critical_section::with(|cs| {
|
||||
*SNIFFER_CB.borrow_ref_mut(cs) = Some(cb);
|
||||
});
|
||||
SNIFFER_CB.with(|callback| *callback = Some(cb));
|
||||
}
|
||||
}
|
||||
|
||||
@ -2675,21 +2665,19 @@ impl<MODE: Sealed> WifiRxToken<MODE> {
|
||||
where
|
||||
F: FnOnce(&mut [u8]) -> R,
|
||||
{
|
||||
let mut data = critical_section::with(|cs| {
|
||||
let mut queue = self.mode.data_queue_rx(cs);
|
||||
|
||||
let mut data = self.mode.data_queue_rx().with(|queue| {
|
||||
unwrap!(
|
||||
queue.pop_front(),
|
||||
"unreachable: transmit()/receive() ensures there is a packet to process"
|
||||
)
|
||||
});
|
||||
|
||||
// We handle the received data outside of the critical section because
|
||||
// We handle the received data outside of the lock because
|
||||
// EspWifiPacketBuffer::drop must not be called in a critical section.
|
||||
// Dropping an EspWifiPacketBuffer will call `esp_wifi_internal_free_rx_buffer`
|
||||
// which will try to lock an internal mutex. If the mutex is already
|
||||
// taken, the function will try to trigger a context switch, which will
|
||||
// fail if we are in a critical section.
|
||||
// fail if we are in an interrupt-free context.
|
||||
let buffer = data.as_slice_mut();
|
||||
dump_packet_info(buffer);
|
||||
|
||||
@ -3321,7 +3309,7 @@ mod asynch {
|
||||
}
|
||||
|
||||
fn clear_events(events: impl Into<EnumSet<WifiEvent>>) {
|
||||
critical_section::with(|cs| WIFI_EVENTS.borrow_ref_mut(cs).remove_all(events.into()));
|
||||
WIFI_EVENTS.with(|evts| evts.get_mut().remove_all(events.into()));
|
||||
}
|
||||
|
||||
/// Wait for one [`WifiEvent`].
|
||||
@ -3390,7 +3378,7 @@ mod asynch {
|
||||
cx: &mut core::task::Context<'_>,
|
||||
) -> Poll<Self::Output> {
|
||||
self.event.waker().register(cx.waker());
|
||||
if critical_section::with(|cs| WIFI_EVENTS.borrow_ref_mut(cs).remove(self.event)) {
|
||||
if WIFI_EVENTS.with(|events| events.get_mut().remove(self.event)) {
|
||||
Poll::Ready(())
|
||||
} else {
|
||||
Poll::Pending
|
||||
@ -3417,8 +3405,8 @@ mod asynch {
|
||||
self: core::pin::Pin<&mut Self>,
|
||||
cx: &mut core::task::Context<'_>,
|
||||
) -> Poll<Self::Output> {
|
||||
let output = critical_section::with(|cs| {
|
||||
let mut events = WIFI_EVENTS.borrow_ref_mut(cs);
|
||||
let output = WIFI_EVENTS.with(|events| {
|
||||
let events = events.get_mut();
|
||||
let active = events.intersection(self.event);
|
||||
events.remove_all(active);
|
||||
active
|
||||
|
@ -9,8 +9,8 @@ pub(crate) mod os_adapter_chip_specific;
|
||||
|
||||
use core::{cell::RefCell, ptr::addr_of_mut};
|
||||
|
||||
use critical_section::Mutex;
|
||||
use enumset::EnumSet;
|
||||
use esp_hal::sync::{Lock, Locked};
|
||||
|
||||
use super::WifiEvent;
|
||||
use crate::{
|
||||
@ -35,12 +35,14 @@ use crate::{
|
||||
timer::yield_task,
|
||||
};
|
||||
|
||||
static WIFI_LOCK: Lock = Lock::new();
|
||||
|
||||
static mut QUEUE_HANDLE: *mut ConcurrentQueue = core::ptr::null_mut();
|
||||
|
||||
// useful for waiting for events - clear and wait for the event bit to be set
|
||||
// again
|
||||
pub(crate) static WIFI_EVENTS: Mutex<RefCell<EnumSet<WifiEvent>>> =
|
||||
Mutex::new(RefCell::new(enumset::enum_set!()));
|
||||
pub(crate) static WIFI_EVENTS: Locked<RefCell<EnumSet<WifiEvent>>> =
|
||||
Locked::new(RefCell::new(enumset::enum_set!()));
|
||||
|
||||
/// **************************************************************************
|
||||
/// Name: wifi_env_is_chip
|
||||
@ -214,10 +216,11 @@ pub unsafe extern "C" fn spin_lock_delete(lock: *mut crate::binary::c_types::c_v
|
||||
///
|
||||
/// *************************************************************************
|
||||
pub unsafe extern "C" fn wifi_int_disable(
|
||||
wifi_int_mux: *mut crate::binary::c_types::c_void,
|
||||
_wifi_int_mux: *mut crate::binary::c_types::c_void,
|
||||
) -> u32 {
|
||||
trace!("wifi_int_disable");
|
||||
crate::wifi::os_adapter::os_adapter_chip_specific::wifi_int_disable(wifi_int_mux)
|
||||
// TODO: can we use wifi_int_mux?
|
||||
unsafe { WIFI_LOCK.acquire() as _ }
|
||||
}
|
||||
|
||||
/// **************************************************************************
|
||||
@ -236,11 +239,12 @@ pub unsafe extern "C" fn wifi_int_disable(
|
||||
///
|
||||
/// *************************************************************************
|
||||
pub unsafe extern "C" fn wifi_int_restore(
|
||||
wifi_int_mux: *mut crate::binary::c_types::c_void,
|
||||
_wifi_int_mux: *mut crate::binary::c_types::c_void,
|
||||
tmp: u32,
|
||||
) {
|
||||
trace!("wifi_int_restore");
|
||||
crate::wifi::os_adapter::os_adapter_chip_specific::wifi_int_restore(wifi_int_mux, tmp)
|
||||
let token = tmp as critical_section::RawRestoreState;
|
||||
unsafe { WIFI_LOCK.release(token) }
|
||||
}
|
||||
|
||||
/// **************************************************************************
|
||||
@ -867,11 +871,8 @@ pub unsafe extern "C" fn event_post(
|
||||
let event = unwrap!(WifiEvent::from_i32(event_id));
|
||||
trace!("EVENT: {:?}", event);
|
||||
|
||||
let mut handled = false;
|
||||
critical_section::with(|cs| {
|
||||
WIFI_EVENTS.borrow_ref_mut(cs).insert(event);
|
||||
handled = super::event::dispatch_event_handler(cs, event, event_data, event_data_size);
|
||||
});
|
||||
WIFI_EVENTS.with(|events| events.borrow_mut().insert(event));
|
||||
let handled = super::event::dispatch_event_handler(event, event_data, event_data_size);
|
||||
|
||||
super::state::update_state(event, handled);
|
||||
|
||||
|
@ -1,11 +1,5 @@
|
||||
#![allow(unused_variables)]
|
||||
#![allow(dead_code)]
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
use crate::hal::{interrupt, peripherals};
|
||||
|
||||
const DPORT_WIFI_CLK_WIFI_EN_M: u32 = 0x406;
|
||||
|
||||
pub(crate) fn chip_ints_on(mask: u32) {
|
||||
unsafe { crate::hal::xtensa_lx::interrupt::enable_mask(mask) };
|
||||
}
|
||||
@ -14,21 +8,6 @@ pub(crate) fn chip_ints_off(mask: u32) {
|
||||
crate::hal::xtensa_lx::interrupt::disable_mask(mask);
|
||||
}
|
||||
|
||||
pub(crate) unsafe extern "C" fn wifi_int_disable(
|
||||
wifi_int_mux: *mut crate::binary::c_types::c_void,
|
||||
) -> u32 {
|
||||
core::mem::transmute(critical_section::acquire())
|
||||
}
|
||||
|
||||
pub(crate) unsafe extern "C" fn wifi_int_restore(
|
||||
wifi_int_mux: *mut crate::binary::c_types::c_void,
|
||||
tmp: u32,
|
||||
) {
|
||||
critical_section::release(core::mem::transmute::<u32, critical_section::RestoreState>(
|
||||
tmp,
|
||||
))
|
||||
}
|
||||
|
||||
pub(crate) unsafe extern "C" fn phy_common_clock_disable() {
|
||||
crate::common_adapter::chip_specific::phy_disable_clock();
|
||||
}
|
||||
@ -50,24 +29,6 @@ pub(crate) unsafe extern "C" fn set_intr(
|
||||
intr_matrix_set(0, intr_source, intr_num);
|
||||
}
|
||||
|
||||
pub(crate) unsafe extern "C" fn wifi_clock_enable() {
|
||||
let dport = &*crate::hal::peripherals::SYSTEM::ptr();
|
||||
dport.wifi_clk_en().modify(|r, w| {
|
||||
let old = r.bits();
|
||||
let new_bits = old | DPORT_WIFI_CLK_WIFI_EN_M;
|
||||
w.bits(new_bits)
|
||||
});
|
||||
}
|
||||
|
||||
pub(crate) unsafe extern "C" fn wifi_clock_disable() {
|
||||
let dport = &*crate::hal::peripherals::SYSTEM::ptr();
|
||||
dport.wifi_clk_en().modify(|r, w| {
|
||||
let old = r.bits();
|
||||
let new_bits = old & !DPORT_WIFI_CLK_WIFI_EN_M;
|
||||
w.bits(new_bits)
|
||||
});
|
||||
}
|
||||
|
||||
/// **************************************************************************
|
||||
/// Name: esp_set_isr
|
||||
///
|
||||
|
@ -1,8 +1,4 @@
|
||||
use crate::hal::{
|
||||
interrupt,
|
||||
peripherals::{self, Interrupt},
|
||||
riscv,
|
||||
};
|
||||
use crate::hal::{interrupt, peripherals};
|
||||
|
||||
pub(crate) fn chip_ints_on(mask: u32) {
|
||||
unsafe {
|
||||
@ -20,40 +16,6 @@ pub(crate) fn chip_ints_off(mask: u32) {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) unsafe extern "C" fn wifi_int_disable(
|
||||
wifi_int_mux: *mut crate::binary::c_types::c_void,
|
||||
) -> u32 {
|
||||
let res = if riscv::register::mstatus::read().mie() {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
};
|
||||
riscv::interrupt::disable();
|
||||
|
||||
trace!(
|
||||
"wifi_int_disable wifi_int_mux {:?} - return {}",
|
||||
wifi_int_mux,
|
||||
res,
|
||||
);
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
pub(crate) unsafe extern "C" fn wifi_int_restore(
|
||||
wifi_int_mux: *mut crate::binary::c_types::c_void,
|
||||
tmp: u32,
|
||||
) {
|
||||
trace!(
|
||||
"wifi_int_restore wifi_int_mux {:?} tmp {}",
|
||||
wifi_int_mux,
|
||||
tmp
|
||||
);
|
||||
|
||||
if tmp == 1 {
|
||||
riscv::interrupt::enable();
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) unsafe extern "C" fn set_intr(
|
||||
_cpu_no: i32,
|
||||
_intr_source: u32,
|
||||
@ -103,11 +65,11 @@ pub unsafe extern "C" fn set_isr(
|
||||
#[cfg(feature = "wifi")]
|
||||
{
|
||||
unwrap!(interrupt::enable(
|
||||
Interrupt::WIFI_MAC,
|
||||
peripherals::Interrupt::WIFI_MAC,
|
||||
interrupt::Priority::Priority1
|
||||
));
|
||||
unwrap!(interrupt::enable(
|
||||
Interrupt::WIFI_PWR,
|
||||
peripherals::Interrupt::WIFI_PWR,
|
||||
interrupt::Priority::Priority1
|
||||
));
|
||||
}
|
||||
|
@ -1,8 +1,4 @@
|
||||
use crate::hal::{
|
||||
interrupt,
|
||||
peripherals::{self, Interrupt},
|
||||
riscv,
|
||||
};
|
||||
use crate::hal::{interrupt, peripherals};
|
||||
|
||||
pub(crate) fn chip_ints_on(mask: u32) {
|
||||
unsafe {
|
||||
@ -20,40 +16,6 @@ pub(crate) fn chip_ints_off(mask: u32) {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) unsafe extern "C" fn wifi_int_disable(
|
||||
wifi_int_mux: *mut crate::binary::c_types::c_void,
|
||||
) -> u32 {
|
||||
let res = if riscv::register::mstatus::read().mie() {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
};
|
||||
riscv::interrupt::disable();
|
||||
|
||||
trace!(
|
||||
"wifi_int_disable wifi_int_mux {:?} - return {}",
|
||||
wifi_int_mux,
|
||||
res,
|
||||
);
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
pub(crate) unsafe extern "C" fn wifi_int_restore(
|
||||
wifi_int_mux: *mut crate::binary::c_types::c_void,
|
||||
tmp: u32,
|
||||
) {
|
||||
trace!(
|
||||
"wifi_int_restore wifi_int_mux {:?} tmp {}",
|
||||
wifi_int_mux,
|
||||
tmp
|
||||
);
|
||||
|
||||
if tmp == 1 {
|
||||
riscv::interrupt::enable();
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) unsafe extern "C" fn set_intr(
|
||||
_cpu_no: i32,
|
||||
_intr_source: u32,
|
||||
@ -104,11 +66,11 @@ pub unsafe extern "C" fn set_isr(
|
||||
#[cfg(feature = "wifi")]
|
||||
{
|
||||
unwrap!(interrupt::enable(
|
||||
Interrupt::WIFI_MAC,
|
||||
peripherals::Interrupt::WIFI_MAC,
|
||||
interrupt::Priority::Priority1
|
||||
));
|
||||
unwrap!(interrupt::enable(
|
||||
Interrupt::WIFI_PWR,
|
||||
peripherals::Interrupt::WIFI_PWR,
|
||||
interrupt::Priority::Priority1
|
||||
));
|
||||
}
|
||||
|
@ -1,8 +1,4 @@
|
||||
use crate::hal::{
|
||||
interrupt,
|
||||
peripherals::{self, Interrupt},
|
||||
riscv,
|
||||
};
|
||||
use crate::hal::{interrupt, peripherals};
|
||||
|
||||
pub(crate) fn chip_ints_on(mask: u32) {
|
||||
unsafe {
|
||||
@ -20,40 +16,6 @@ pub(crate) fn chip_ints_off(mask: u32) {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) unsafe extern "C" fn wifi_int_disable(
|
||||
wifi_int_mux: *mut crate::binary::c_types::c_void,
|
||||
) -> u32 {
|
||||
let res = if riscv::register::mstatus::read().mie() {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
};
|
||||
riscv::interrupt::disable();
|
||||
|
||||
trace!(
|
||||
"wifi_int_disable wifi_int_mux {:?} - return {}",
|
||||
wifi_int_mux,
|
||||
res,
|
||||
);
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
pub(crate) unsafe extern "C" fn wifi_int_restore(
|
||||
wifi_int_mux: *mut crate::binary::c_types::c_void,
|
||||
tmp: u32,
|
||||
) {
|
||||
trace!(
|
||||
"wifi_int_restore wifi_int_mux {:?} tmp {}",
|
||||
wifi_int_mux,
|
||||
tmp
|
||||
);
|
||||
|
||||
if tmp == 1 {
|
||||
riscv::interrupt::enable();
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) unsafe extern "C" fn set_intr(
|
||||
_cpu_no: i32,
|
||||
_intr_source: u32,
|
||||
@ -117,11 +79,11 @@ pub unsafe extern "C" fn set_isr(
|
||||
#[cfg(feature = "wifi")]
|
||||
{
|
||||
unwrap!(interrupt::enable(
|
||||
Interrupt::WIFI_MAC,
|
||||
peripherals::Interrupt::WIFI_MAC,
|
||||
interrupt::Priority::Priority1
|
||||
));
|
||||
unwrap!(interrupt::enable(
|
||||
Interrupt::WIFI_PWR,
|
||||
peripherals::Interrupt::WIFI_PWR,
|
||||
interrupt::Priority::Priority1
|
||||
));
|
||||
}
|
||||
|
@ -1,8 +1,4 @@
|
||||
use crate::hal::{
|
||||
interrupt,
|
||||
peripherals::{self, Interrupt},
|
||||
riscv,
|
||||
};
|
||||
use crate::hal::{interrupt, peripherals};
|
||||
|
||||
pub(crate) fn chip_ints_on(mask: u32) {
|
||||
unsafe {
|
||||
@ -20,40 +16,6 @@ pub(crate) fn chip_ints_off(mask: u32) {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) unsafe extern "C" fn wifi_int_disable(
|
||||
wifi_int_mux: *mut crate::binary::c_types::c_void,
|
||||
) -> u32 {
|
||||
let res = if riscv::register::mstatus::read().mie() {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
};
|
||||
riscv::interrupt::disable();
|
||||
|
||||
trace!(
|
||||
"wifi_int_disable wifi_int_mux {:?} - return {}",
|
||||
wifi_int_mux,
|
||||
res,
|
||||
);
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
pub(crate) unsafe extern "C" fn wifi_int_restore(
|
||||
wifi_int_mux: *mut crate::binary::c_types::c_void,
|
||||
tmp: u32,
|
||||
) {
|
||||
trace!(
|
||||
"wifi_int_restore wifi_int_mux {:?} tmp {}",
|
||||
wifi_int_mux,
|
||||
tmp
|
||||
);
|
||||
|
||||
if tmp == 1 {
|
||||
riscv::interrupt::enable();
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) unsafe extern "C" fn set_intr(
|
||||
_cpu_no: i32,
|
||||
_intr_source: u32,
|
||||
|
@ -1,7 +1,3 @@
|
||||
#![allow(unused_variables)]
|
||||
#![allow(dead_code)]
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
use crate::hal::{interrupt, peripherals};
|
||||
|
||||
pub(crate) fn chip_ints_on(mask: u32) {
|
||||
@ -12,21 +8,6 @@ pub(crate) fn chip_ints_off(mask: u32) {
|
||||
crate::hal::xtensa_lx::interrupt::disable_mask(mask);
|
||||
}
|
||||
|
||||
pub(crate) unsafe extern "C" fn wifi_int_disable(
|
||||
wifi_int_mux: *mut crate::binary::c_types::c_void,
|
||||
) -> u32 {
|
||||
core::mem::transmute(critical_section::acquire())
|
||||
}
|
||||
|
||||
pub(crate) unsafe extern "C" fn wifi_int_restore(
|
||||
wifi_int_mux: *mut crate::binary::c_types::c_void,
|
||||
tmp: u32,
|
||||
) {
|
||||
critical_section::release(core::mem::transmute::<u32, critical_section::RestoreState>(
|
||||
tmp,
|
||||
))
|
||||
}
|
||||
|
||||
pub(crate) unsafe extern "C" fn set_intr(
|
||||
_cpu_no: i32,
|
||||
intr_source: u32,
|
||||
|
@ -1,7 +1,3 @@
|
||||
#![allow(unused_variables)]
|
||||
#![allow(dead_code)]
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
use crate::hal::{interrupt, peripherals};
|
||||
|
||||
pub(crate) fn chip_ints_on(mask: u32) {
|
||||
@ -12,21 +8,6 @@ pub(crate) fn chip_ints_off(mask: u32) {
|
||||
crate::hal::xtensa_lx::interrupt::disable_mask(mask);
|
||||
}
|
||||
|
||||
pub(crate) unsafe extern "C" fn wifi_int_disable(
|
||||
wifi_int_mux: *mut crate::binary::c_types::c_void,
|
||||
) -> u32 {
|
||||
core::mem::transmute(critical_section::acquire())
|
||||
}
|
||||
|
||||
pub(crate) unsafe extern "C" fn wifi_int_restore(
|
||||
wifi_int_mux: *mut crate::binary::c_types::c_void,
|
||||
tmp: u32,
|
||||
) {
|
||||
critical_section::release(core::mem::transmute::<u32, critical_section::RestoreState>(
|
||||
tmp,
|
||||
))
|
||||
}
|
||||
|
||||
pub(crate) unsafe extern "C" fn set_intr(
|
||||
_cpu_no: i32,
|
||||
intr_source: u32,
|
||||
|
@ -52,15 +52,15 @@ fn main() -> ! {
|
||||
|
||||
// Set event handlers for wifi before init to avoid missing any.
|
||||
let mut connections = 0u32;
|
||||
_ = event::ApStart::replace_handler(|_, _| esp_println::println!("ap start event"));
|
||||
event::ApStaconnected::update_handler(move |_, event| {
|
||||
_ = event::ApStart::replace_handler(|_| esp_println::println!("ap start event"));
|
||||
event::ApStaconnected::update_handler(move |event| {
|
||||
connections += 1;
|
||||
esp_println::println!("connected {}, mac: {:?}", connections, event.0.mac);
|
||||
});
|
||||
event::ApStaconnected::update_handler(|_, event| {
|
||||
event::ApStaconnected::update_handler(|event| {
|
||||
esp_println::println!("connected aid: {}", event.0.aid);
|
||||
});
|
||||
event::ApStadisconnected::update_handler(|_, event| {
|
||||
event::ApStadisconnected::update_handler(|event| {
|
||||
esp_println::println!(
|
||||
"disconnected mac: {:?}, reason: {:?}",
|
||||
event.0.mac,
|
||||
|
@ -9,7 +9,7 @@
|
||||
//! Because of the huge task-arena size configured this won't work on ESP32-S2
|
||||
//!
|
||||
|
||||
//% FEATURES: embassy embassy-generic-timers esp-wifi esp-wifi/wifi esp-wifi/utils
|
||||
//% FEATURES: embassy embassy-generic-timers esp-wifi esp-wifi/wifi esp-wifi/utils esp-wifi/sniffer
|
||||
//% CHIPS: esp32 esp32s2 esp32s3 esp32c2 esp32c3 esp32c6
|
||||
|
||||
#![no_std]
|
||||
|
Loading…
x
Reference in New Issue
Block a user