diff --git a/esp-wifi/CHANGELOG.md b/esp-wifi/CHANGELOG.md index 5597d41884c..aa932a0287a 100644 --- a/esp-wifi/CHANGELOG.md +++ b/esp-wifi/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - No need to add `rom_functions.x` manually anymore (#2374) +- esp-now: Data is now private in `ReceivedData` - use `data()`(#2396) ### Fixed diff --git a/esp-wifi/MIGRATING-0.10.md b/esp-wifi/MIGRATING-0.10.md index 6bfc390fd6b..a8c7414dce1 100644 --- a/esp-wifi/MIGRATING-0.10.md +++ b/esp-wifi/MIGRATING-0.10.md @@ -10,3 +10,9 @@ rustflags = [ - "-C", "link-arg=-Trom_functions.x", ] ``` + +## ESP-NOW: Use `data` to access the received payload + +Previously `data` and `len` were public - use the previously already existing `data()` function. + +Accessing `data` or `len` was never encouraged. diff --git a/esp-wifi/src/ble/btdm.rs b/esp-wifi/src/ble/btdm.rs index 3c8a90d43cd..ba84cf1a54c 100644 --- a/esp-wifi/src/ble/btdm.rs +++ b/esp-wifi/src/ble/btdm.rs @@ -1,8 +1,10 @@ -use core::{cell::RefCell, ptr::addr_of}; +use alloc::boxed::Box; +use core::ptr::{addr_of, addr_of_mut}; -use critical_section::Mutex; +use esp_wifi_sys::c_types::c_void; use portable_atomic::{AtomicBool, Ordering}; +use super::ReceivedPacket; use crate::{ binary::include::*, ble::{ @@ -10,10 +12,8 @@ use crate::{ HciOutCollector, HCI_OUT_COLLECTOR, }, - compat::{common::str_from_c, queue::SimpleQueue}, + compat::common::{self, str_from_c, ConcurrentQueue}, hal::macros::ram, - memory_fence::memory_fence, - timer::yield_task, }; #[cfg_attr(esp32c3, path = "os_adapter_esp32c3.rs")] @@ -21,23 +21,10 @@ use crate::{ #[cfg_attr(esp32, path = "os_adapter_esp32.rs")] pub(crate) mod ble_os_adapter_chip_specific; -static BT_RECEIVE_QUEUE: Mutex>> = - Mutex::new(RefCell::new(SimpleQueue::new())); - -#[derive(Debug, Clone, Copy)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub struct ReceivedPacket { - pub len: u8, - pub data: [u8; 256], -} - -static BT_INTERNAL_QUEUE: Mutex>> = - Mutex::new(RefCell::new(SimpleQueue::new())); - static PACKET_SENT: AtomicBool = AtomicBool::new(true); #[repr(C)] -struct vhci_host_callback_s { +struct VhciHostCallbacks { notify_host_send_available: extern "C" fn(), /* callback used to notify that the host can * send packet to controller */ notify_host_recv: extern "C" fn(*mut u8, u16) -> i32, /* callback used to notify that the @@ -62,10 +49,10 @@ extern "C" { fn API_vhci_host_check_send_available() -> bool; fn API_vhci_host_send_packet(data: *const u8, len: u16); - fn API_vhci_host_register_callback(vhci_host_callbac: *const vhci_host_callback_s) -> i32; + fn API_vhci_host_register_callback(vhci_host_callbac: *const VhciHostCallbacks) -> i32; } -static VHCI_HOST_CALLBACK: vhci_host_callback_s = vhci_host_callback_s { +static VHCI_HOST_CALLBACK: VhciHostCallbacks = VhciHostCallbacks { notify_host_send_available, notify_host_recv, }; @@ -79,27 +66,21 @@ extern "C" fn notify_host_send_available() { extern "C" fn notify_host_recv(data: *mut u8, len: u16) -> i32 { trace!("notify_host_recv {:?} {}", data, len); - unsafe { - let mut buf = [0u8; 256]; - buf[..len as usize].copy_from_slice(core::slice::from_raw_parts(data, len as usize)); - - let packet = ReceivedPacket { - len: len as u8, - data: buf, - }; - - critical_section::with(|cs| { - let mut queue = BT_RECEIVE_QUEUE.borrow_ref_mut(cs); - if queue.enqueue(packet).is_err() { - warn!("Dropping BLE packet"); - } - }); + let data = unsafe { core::slice::from_raw_parts(data, len as usize) }; + + let packet = ReceivedPacket { + data: Box::from(data), + }; - dump_packet_info(core::slice::from_raw_parts(data as *const u8, len as usize)); + critical_section::with(|cs| { + let mut queue = super::BT_RECEIVE_QUEUE.borrow_ref_mut(cs); + queue.push_back(packet); + }); - #[cfg(feature = "async")] - crate::ble::controller::asynch::hci_read_data_available(); - } + super::dump_packet_info(data); + + #[cfg(feature = "async")] + crate::ble::controller::asynch::hci_read_data_available(); 0 } @@ -178,38 +159,21 @@ unsafe extern "C" fn mutex_unlock(_mutex: *const ()) -> i32 { } unsafe extern "C" fn queue_create(len: u32, item_size: u32) -> *const () { - if len != 5 && item_size != 8 { - panic!("Unexpected queue spec {} {}", len, item_size); - } - &BT_INTERNAL_QUEUE as *const _ as *const () + let ptr = common::create_queue(len as i32, item_size as i32); + ptr.cast() } unsafe extern "C" fn queue_delete(queue: *const ()) { - trace!("Unimplemented queue_delete {:?}", queue); + common::delete_queue(queue as *mut ConcurrentQueue) } #[ram] -unsafe extern "C" fn queue_send(queue: *const (), item: *const (), _block_time_ms: u32) -> i32 { - if queue == &BT_INTERNAL_QUEUE as *const _ as *const () { - critical_section::with(|_| { - // assume the size is 8 - shouldn't rely on that - let message = item as *const u8; - let mut data = [0u8; 8]; - for (i, data) in data.iter_mut().enumerate() { - *data = *message.add(i); - } - trace!("queue posting {:?}", data); - - critical_section::with(|cs| { - let mut queue = BT_INTERNAL_QUEUE.borrow_ref_mut(cs); - unwrap!(queue.enqueue(data)); - }); - memory_fence(); - }); - } else { - panic!("Unknown queue"); - } - 1 +unsafe extern "C" fn queue_send(queue: *const (), item: *const (), block_time_ms: u32) -> i32 { + common::send_queued( + queue as *mut ConcurrentQueue, + item as *mut c_void, + block_time_ms, + ) } #[ram] @@ -225,53 +189,11 @@ unsafe extern "C" fn queue_send_from_isr( } unsafe extern "C" fn queue_recv(queue: *const (), item: *const (), block_time_ms: u32) -> i32 { - trace!( - "queue_recv {:?} item {:?} block_time_tick {}", - queue, - item, - block_time_ms - ); - - let forever = block_time_ms == crate::compat::common::OSI_FUNCS_TIME_BLOCKING; - let start = crate::timer::get_systimer_count(); - let block_ticks = crate::timer::millis_to_ticks(block_time_ms as u64); - - // handle the BT_QUEUE - if queue == &BT_INTERNAL_QUEUE as *const _ as *const () { - loop { - let res = critical_section::with(|_| { - memory_fence(); - - critical_section::with(|cs| { - let mut queue = BT_INTERNAL_QUEUE.borrow_ref_mut(cs); - if let Some(message) = queue.dequeue() { - let item = item as *mut u8; - for i in 0..8 { - item.offset(i).write_volatile(message[i as usize]); - } - trace!("received {:?}", message); - 1 - } else { - 0 - } - }) - }); - - if res == 1 { - trace!("queue_recv returns"); - return res; - } - - if !forever && crate::timer::elapsed_time_since(start) > block_ticks { - trace!("queue_recv returns with timeout"); - return -1; - } - - yield_task(); - } - } else { - panic!("Unknown queue to handle in queue_recv"); - } + common::receive_queued( + queue as *mut ConcurrentQueue, + item as *mut c_void, + block_time_ms, + ) } #[ram] @@ -444,7 +366,7 @@ unsafe extern "C" fn custom_queue_create( pub(crate) fn ble_init() { unsafe { - *(HCI_OUT_COLLECTOR.as_mut_ptr()) = HciOutCollector::new(); + (*addr_of_mut!(HCI_OUT_COLLECTOR)).write(HciOutCollector::new()); // turn on logging #[cfg(feature = "sys-logs")] { @@ -532,67 +454,8 @@ pub(crate) fn ble_deinit() { } } -static mut BLE_HCI_READ_DATA: [u8; 256] = [0u8; 256]; -static mut BLE_HCI_READ_DATA_INDEX: usize = 0; -static mut BLE_HCI_READ_DATA_LEN: usize = 0; - -#[cfg(feature = "async")] -pub(crate) fn have_hci_read_data() -> bool { - critical_section::with(|cs| { - let queue = BT_RECEIVE_QUEUE.borrow_ref_mut(cs); - !queue.is_empty() - || unsafe { - BLE_HCI_READ_DATA_LEN > 0 && (BLE_HCI_READ_DATA_LEN >= BLE_HCI_READ_DATA_INDEX) - } - }) -} - -pub(crate) fn read_next(data: &mut [u8]) -> usize { - critical_section::with(|cs| { - let mut queue = BT_RECEIVE_QUEUE.borrow_ref_mut(cs); - - match queue.dequeue() { - Some(packet) => { - data[..packet.len as usize].copy_from_slice(&packet.data[..packet.len as usize]); - packet.len as usize - } - None => 0, - } - }) -} - -pub(crate) fn read_hci(data: &mut [u8]) -> usize { - unsafe { - if BLE_HCI_READ_DATA_LEN == 0 { - critical_section::with(|cs| { - let mut queue = BT_RECEIVE_QUEUE.borrow_ref_mut(cs); - - if let Some(packet) = queue.dequeue() { - BLE_HCI_READ_DATA[..packet.len as usize] - .copy_from_slice(&packet.data[..packet.len as usize]); - BLE_HCI_READ_DATA_LEN = packet.len as usize; - BLE_HCI_READ_DATA_INDEX = 0; - } - }); - } - - if BLE_HCI_READ_DATA_LEN > 0 { - data[0] = BLE_HCI_READ_DATA[BLE_HCI_READ_DATA_INDEX]; - BLE_HCI_READ_DATA_INDEX += 1; - - if BLE_HCI_READ_DATA_INDEX >= BLE_HCI_READ_DATA_LEN { - BLE_HCI_READ_DATA_LEN = 0; - BLE_HCI_READ_DATA_INDEX = 0; - } - return 1; - } - } - - 0 -} - -pub(crate) fn send_hci(data: &[u8]) { - let hci_out = unsafe { &mut *HCI_OUT_COLLECTOR.as_mut_ptr() }; +pub fn send_hci(data: &[u8]) { + let hci_out = unsafe { (*addr_of_mut!(HCI_OUT_COLLECTOR)).assume_init_mut() }; hci_out.push(data); if hci_out.is_ready() { @@ -611,7 +474,7 @@ pub(crate) fn send_hci(data: &[u8]) { API_vhci_host_send_packet(packet.as_ptr(), packet.len() as u16); trace!("sent vhci host packet"); - dump_packet_info(packet); + super::dump_packet_info(packet); break; } @@ -623,13 +486,3 @@ pub(crate) fn send_hci(data: &[u8]) { hci_out.reset(); } } - -#[allow(unreachable_code, unused_variables)] -fn dump_packet_info(buffer: &[u8]) { - #[cfg(not(feature = "dump-packets"))] - return; - - critical_section::with(|cs| { - info!("@HCIFRAME {:?}", buffer); - }); -} diff --git a/esp-wifi/src/ble/controller/mod.rs b/esp-wifi/src/ble/controller/mod.rs index 9ca3cc76177..1d639b469e0 100644 --- a/esp-wifi/src/ble/controller/mod.rs +++ b/esp-wifi/src/ble/controller/mod.rs @@ -95,7 +95,7 @@ pub mod asynch { use super::{read_hci, send_hci, BleConnectorError}; use crate::{ - ble::ble::have_hci_read_data, + ble::have_hci_read_data, hal::peripheral::{Peripheral, PeripheralRef}, EspWifiInitialization, }; diff --git a/esp-wifi/src/ble/mod.rs b/esp-wifi/src/ble/mod.rs index bf26fc3d913..1ea694fde5d 100644 --- a/esp-wifi/src/ble/mod.rs +++ b/esp-wifi/src/ble/mod.rs @@ -6,9 +6,11 @@ pub(crate) mod btdm; #[cfg(any(esp32c2, esp32c6, esp32h2))] pub(crate) mod npl; -use core::mem::MaybeUninit; +use alloc::{boxed::Box, collections::vec_deque::VecDeque, vec::Vec}; +use core::{cell::RefCell, mem::MaybeUninit}; -pub(crate) use ble::{ble_init, read_hci, read_next, send_hci}; +pub(crate) use ble::{ble_init, send_hci}; +use critical_section::Mutex; #[cfg(any(esp32, esp32c3, esp32s3))] use self::btdm as ble; @@ -30,6 +32,10 @@ pub(crate) unsafe extern "C" fn free(ptr: *mut crate::binary::c_types::c_void) { crate::compat::malloc::free(ptr.cast()) } +// Stores received packets until the the BLE stack dequeues them +static BT_RECEIVE_QUEUE: Mutex>> = + Mutex::new(RefCell::new(VecDeque::new())); + static mut HCI_OUT_COLLECTOR: MaybeUninit = MaybeUninit::uninit(); #[derive(PartialEq, Debug)] @@ -96,3 +102,66 @@ impl HciOutCollector { &self.data[0..self.index] } } + +static BLE_HCI_READ_DATA: Mutex>> = Mutex::new(RefCell::new(Vec::new())); + +#[derive(Debug, Clone)] +pub struct ReceivedPacket { + pub data: Box<[u8]>, +} + +#[cfg(feature = "defmt")] +impl defmt::Format for ReceivedPacket { + fn format(&self, fmt: defmt::Formatter) { + defmt::write!(fmt, "ReceivedPacket {}", &self.data[..]) + } +} + +#[cfg(feature = "async")] +pub fn have_hci_read_data() -> bool { + critical_section::with(|cs| { + let queue = BT_RECEIVE_QUEUE.borrow_ref_mut(cs); + let hci_read_data = BLE_HCI_READ_DATA.borrow_ref(cs); + !queue.is_empty() || !hci_read_data.is_empty() + }) +} + +pub(crate) fn read_next(data: &mut [u8]) -> usize { + critical_section::with(|cs| { + let mut queue = BT_RECEIVE_QUEUE.borrow_ref_mut(cs); + + match queue.pop_front() { + Some(packet) => { + data[..packet.data.len()].copy_from_slice(&packet.data[..packet.data.len()]); + packet.data.len() + } + None => 0, + } + }) +} + +pub fn read_hci(data: &mut [u8]) -> usize { + critical_section::with(|cs| { + let mut hci_read_data = BLE_HCI_READ_DATA.borrow_ref_mut(cs); + + if hci_read_data.is_empty() { + let mut queue = BT_RECEIVE_QUEUE.borrow_ref_mut(cs); + + if let Some(packet) = queue.pop_front() { + hci_read_data.extend_from_slice(&packet.data); + } + } + + let l = usize::min(hci_read_data.len(), data.len()); + data[..l].copy_from_slice(&hci_read_data[..l]); + hci_read_data.drain(..l); + l + }) +} + +fn dump_packet_info(_buffer: &[u8]) { + #[cfg(feature = "dump-packets")] + critical_section::with(|_cs| { + info!("@HCIFRAME {:?}", _buffer); + }); +} diff --git a/esp-wifi/src/ble/npl.rs b/esp-wifi/src/ble/npl.rs index 8deaadc5bc3..a7d34884f6d 100644 --- a/esp-wifi/src/ble/npl.rs +++ b/esp-wifi/src/ble/npl.rs @@ -1,18 +1,19 @@ +use alloc::boxed::Box; use core::{ - cell::RefCell, + mem::size_of_val, ptr::{addr_of, addr_of_mut}, }; -use critical_section::Mutex; - use super::*; use crate::{ binary::{ c_types::{c_char, c_void}, include::*, }, - compat, - compat::{common::str_from_c, queue::SimpleQueue}, + compat::{ + self, + common::{str_from_c, ConcurrentQueue}, + }, timer::yield_task, }; @@ -21,6 +22,8 @@ use crate::{ #[cfg_attr(esp32h2, path = "os_adapter_esp32h2.rs")] pub(crate) mod ble_os_adapter_chip_specific; +const EVENT_QUEUE_SIZE: usize = 16; + const TIME_FOREVER: u32 = crate::compat::common::OSI_FUNCS_TIME_BLOCKING; #[cfg(esp32c2)] @@ -41,41 +44,25 @@ const BLE_HCI_TRANS_BUF_CMD: i32 = 3; // ACL_DATA_MBUF_LEADINGSPCAE: The leadingspace in user info header for ACL data const ACL_DATA_MBUF_LEADINGSPACE: usize = 4; +#[repr(C)] #[derive(Copy, Clone)] struct Callout { - _callout: *const ble_npl_callout, eventq: *const ble_npl_eventq, timer_handle: ets_timer, events: ble_npl_event, } -static mut CALLOUTS: [Option; 18] = [None; 18]; - +#[repr(C)] #[derive(Copy, Clone)] struct Event { - event: *const ble_npl_event, event_fn_ptr: *const ble_npl_event_fn, ev_arg_ptr: *const c_void, queued: bool, } -static mut EVENTS: [Option; 95] = [None; 95]; - -static mut EVENT_QUEUE: SimpleQueue = SimpleQueue::new(); - -static BT_RECEIVE_QUEUE: Mutex>> = - Mutex::new(RefCell::new(SimpleQueue::new())); - #[cfg(esp32c2)] type OsMembufT = u32; -#[derive(Debug, Clone, Copy)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub struct ReceivedPacket { - pub len: u8, - pub data: [u8; 256], -} - /// Memory pool #[repr(C)] pub(crate) struct OsMempool { @@ -711,14 +698,12 @@ unsafe extern "C" fn ble_npl_callout_deinit(callout: *const ble_npl_callout) { unsafe extern "C" fn ble_npl_callout_stop(callout: *const ble_npl_callout) { trace!("ble_npl_callout_stop {:?}", callout); - if (*callout).dummy == 0 { - panic!("Trying to stop an uninitialzed callout"); - } + assert!((*callout).dummy != 0); - let co = unwrap!(CALLOUTS[((*callout).dummy - 1) as usize].as_mut()); + let co = (*callout).dummy as *mut Callout; // stop timer - compat::timer_compat::compat_timer_disarm(addr_of_mut!(co.timer_handle)); + compat::timer_compat::compat_timer_disarm(addr_of_mut!((*co).timer_handle)); } unsafe extern "C" fn ble_npl_callout_reset( @@ -727,10 +712,10 @@ unsafe extern "C" fn ble_npl_callout_reset( ) -> ble_npl_error_t { trace!("ble_npl_callout_reset {:?} {}", callout, time); - let co = unwrap!(CALLOUTS[((*callout).dummy - 1) as usize].as_mut()); + let co = (*callout).dummy as *mut Callout; // start timer - compat::timer_compat::compat_timer_arm(addr_of_mut!(co.timer_handle), time, false); + compat::timer_compat::compat_timer_arm(addr_of_mut!((*co).timer_handle), time, false); 0 } @@ -775,20 +760,20 @@ unsafe extern "C" fn ble_npl_mutex_deinit(_mutex: *const ble_npl_mutex) -> ble_n unsafe extern "C" fn ble_npl_event_set_arg(event: *const ble_npl_event, arg: *const c_void) { trace!("ble_npl_event_set_arg {:?} {:?}", event, arg); - if (*event).dummy == 0 { - panic!("Call set_arg on uninitialized event"); - } - unwrap!(EVENTS[((*event).dummy - 1) as usize].as_mut()).ev_arg_ptr = arg; + let evt = (*event).dummy as *mut Event; + assert!(!evt.is_null()); + + (*evt).ev_arg_ptr = arg; } unsafe extern "C" fn ble_npl_event_get_arg(event: *const ble_npl_event) -> *const c_void { trace!("ble_npl_event_get_arg {:?}", event); - if (*event).dummy == 0 { - panic!("Call get_arg on uninitialized event"); - } - let arg_ptr = unwrap!(EVENTS[((*event).dummy - 1) as usize].as_mut()).ev_arg_ptr; + let evt = (*event).dummy as *mut Event; + assert!(!evt.is_null()); + + let arg_ptr = (*evt).ev_arg_ptr; trace!("returning arg {:x}", arg_ptr as usize); @@ -797,36 +782,31 @@ unsafe extern "C" fn ble_npl_event_get_arg(event: *const ble_npl_event) -> *cons unsafe extern "C" fn ble_npl_event_is_queued(event: *const ble_npl_event) -> bool { trace!("ble_npl_event_is_queued {:?}", event); - if (*event).dummy == 0 { - panic!("Call is_queued on uninitialized event"); - } - unwrap!(EVENTS[((*event).dummy - 1) as usize].as_mut()).queued + let evt = (*event).dummy as *mut Event; + assert!(!evt.is_null()); + + (*evt).queued } unsafe extern "C" fn ble_npl_event_reset(event: *const ble_npl_event) { trace!("ble_npl_event_reset {:?}", event); - let event = event as *mut ble_npl_event; - if (*event).dummy == 0 { - panic!("Trying to reset an uninitialized event"); - } else { - unwrap!(EVENTS[((*event).dummy - 1) as usize].as_mut()).queued = false; - } + let evt = (*event).dummy as *mut Event; + assert!(!evt.is_null()); + + (*evt).queued = false } unsafe extern "C" fn ble_npl_event_deinit(event: *const ble_npl_event) { trace!("ble_npl_event_deinit {:?}", event); - let event = event.cast_mut(); + let event = event as *mut ble_npl_event; + let evt = (*event).dummy as *mut Event; + assert!(!evt.is_null()); - if (*event).dummy == 0 { - panic!("Trying to deinitialize an uninitialized event"); - } else { - let idx = ((*event).dummy - 1) as usize; - EVENTS[idx] = None; - (*event).dummy = 0; - } + crate::compat::malloc::free(evt.cast()); + (*event).dummy = 0; } unsafe extern "C" fn ble_npl_event_init( @@ -837,41 +817,34 @@ unsafe extern "C" fn ble_npl_event_init( trace!("ble_npl_event_init {:?} {:?} {:?}", event, func, arg); if (*event).dummy == 0 { - let idx = unwrap!(EVENTS.iter().position(|item| item.is_none())); - EVENTS[idx] = Some(Event { - event, - event_fn_ptr: func, - ev_arg_ptr: arg, - queued: false, - }); + let evt = crate::compat::malloc::calloc(1, core::mem::size_of::()) as *mut Event; + + (*evt).event_fn_ptr = func; + (*evt).ev_arg_ptr = arg; + (*evt).queued = false; let event = event.cast_mut(); - (*event).dummy = (idx + 1) as i32; + (*event).dummy = evt as i32; } } unsafe extern "C" fn ble_npl_eventq_is_empty(queue: *const ble_npl_eventq) -> bool { trace!("ble_npl_eventq_is_empty {:?}", queue); - if (*queue).dummy == 0 { - panic!("Try to use uninitialized queue"); - } - - critical_section::with(|_| EVENT_QUEUE.is_empty()) + let queue = (*queue).dummy as *mut ConcurrentQueue; + assert!(!queue.is_null()); + (*queue).count() == 0 } unsafe extern "C" fn ble_npl_event_run(event: *const ble_npl_event) { trace!("ble_npl_event_run {:?}", event); - let event = event as *mut ble_npl_event; - if (*event).dummy == 0 { - panic!("Trying to run an uninitialized event"); - } else { - let ev = unwrap!(EVENTS[((*event).dummy - 1) as usize].as_mut()); - trace!("info {:?} with arg {:x}", ev.event_fn_ptr, event as u32); - let func: unsafe extern "C" fn(u32) = core::mem::transmute(ev.event_fn_ptr); - func(event as u32); - } + let evt = (*event).dummy as *mut Event; + assert!(!evt.is_null()); + + trace!("info {:?} with arg {:x}", (*evt).event_fn_ptr, event as u32); + let func: unsafe extern "C" fn(u32) = core::mem::transmute((*evt).event_fn_ptr); + func(event as u32); trace!("ble_npl_event_run done"); } @@ -880,36 +853,35 @@ unsafe extern "C" fn ble_npl_eventq_remove( queue: *const ble_npl_eventq, event: *const ble_npl_event, ) { - trace!("ble_npl_eventq_remove {:?} {:?}", queue, event); + info!("ble_npl_eventq_remove {:?} {:?}", queue, event); - if (*queue).dummy == 0 { - panic!("Try to use uninitialized queue"); - } + assert!((*queue).dummy != 0); + let evt = (*event).dummy as *mut Event; + assert!(!evt.is_null()); - if (*event).dummy == 0 { - panic!("Try to use uninitialized event"); + if !(*evt).queued { + return; } - critical_section::with(|_| { - unwrap!(EVENTS[((*event).dummy - 1) as usize].as_mut()).queued = false; - }); + let queue = (*queue).dummy as *mut ConcurrentQueue; + (*queue).remove(addr_of!(event) as *mut _); + + (*evt).queued = false; } unsafe extern "C" fn ble_npl_eventq_put(queue: *const ble_npl_eventq, event: *const ble_npl_event) { trace!("ble_npl_eventq_put {:?} {:?}", queue, event); - if (*queue).dummy == 0 { - panic!("Try to use uninitialized queue"); - } + assert!((*queue).dummy != 0); - if (*event).dummy == 0 { - panic!("Try to use uninitialized event"); - } + let evt = (*event).dummy as *mut Event; + assert!(!evt.is_null()); - critical_section::with(|_| { - unwrap!(EVENTS[((*event).dummy - 1) as usize].as_mut()).queued = true; - unwrap!(EVENT_QUEUE.enqueue((*event).dummy as usize)); - }); + (*evt).queued = true; + + let queue = (*queue).dummy as *mut ConcurrentQueue; + let mut event = event as usize; + (*queue).enqueue(addr_of_mut!(event).cast()); } unsafe extern "C" fn ble_npl_eventq_get( @@ -918,16 +890,18 @@ unsafe extern "C" fn ble_npl_eventq_get( ) -> *const ble_npl_event { trace!("ble_npl_eventq_get {:?} {}", queue, time); + let queue = (*queue).dummy as *mut ConcurrentQueue; + + let mut event: usize = 0; if time == TIME_FOREVER { loop { - let dequeued = critical_section::with(|_| EVENT_QUEUE.dequeue()); - - if let Some(event_idx) = dequeued { - let evt = unwrap!(EVENTS[event_idx - 1].as_mut()); - if evt.queued { - trace!("got {:x}", evt.event as usize); - evt.queued = false; - return evt.event; + if (*queue).try_dequeue(addr_of_mut!(event).cast()) { + let event = event as *mut ble_npl_event; + let evt = (*event).dummy as *mut Event; + if (*evt).queued { + trace!("got {:x}", evt as usize); + (*evt).queued = false; + return event as *const ble_npl_event; } } @@ -942,19 +916,13 @@ unsafe extern "C" fn ble_npl_eventq_deinit(queue: *const ble_npl_eventq) { trace!("ble_npl_eventq_deinit {:?}", queue); let queue = queue.cast_mut(); - if (*queue).dummy == 0 { - panic!("Trying to deinitialize an uninitialized queue"); - } else { - critical_section::with(|_| { - while let Some(event_idx) = EVENT_QUEUE.dequeue() { - if let Some(event) = EVENTS[event_idx - 1].as_mut() { - event.queued = false; - } - } - }); + assert!((*queue).dummy != 0); - (*queue).dummy = 0; + let real_queue = (*queue).dummy as *mut ConcurrentQueue; + unsafe { + core::ptr::drop_in_place(real_queue); } + (*queue).dummy = 0; } unsafe extern "C" fn ble_npl_callout_init( @@ -973,58 +941,46 @@ unsafe extern "C" fn ble_npl_callout_init( if (*callout).dummy == 0 { let callout = callout.cast_mut(); - let idx = unwrap!(CALLOUTS.iter().position(|item| item.is_none())); - - let new_callout = CALLOUTS[idx].insert(Callout { - _callout: callout, - eventq, - timer_handle: ets_timer { - next: core::ptr::null_mut(), - expire: 0, - period: 0, - func: None, - priv_: core::ptr::null_mut(), - }, - events: ble_npl_event { dummy: 0 }, - }); - ble_npl_event_init(addr_of_mut!(new_callout.events), func, args); + let new_callout = + crate::compat::malloc::calloc(1, core::mem::size_of::()) as *mut Callout; + ble_npl_event_init(addr_of_mut!((*new_callout).events), func, args); + (*callout).dummy = new_callout as i32; crate::compat::timer_compat::compat_timer_setfn( - addr_of_mut!(new_callout.timer_handle), + addr_of_mut!((*new_callout).timer_handle), callout_timer_callback_wrapper, - idx as *mut c_void, + callout as *mut c_void, ); - - (*callout).dummy = (idx + 1) as i32; } 0 } unsafe extern "C" fn callout_timer_callback_wrapper(arg: *mut c_void) { - info!("callout_timer_callback_wrapper {:?}", arg); - let co = unwrap!(CALLOUTS[arg as usize].as_mut()); + trace!("callout_timer_callback_wrapper {:?}", arg); + let co = (*(arg as *mut ble_npl_callout)).dummy as *mut Callout; - if co.eventq.is_null() { - ble_npl_eventq_put(addr_of!(co.events).cast(), addr_of!(co.events)); + if !(*co).eventq.is_null() { + ble_npl_eventq_put(addr_of!((*co).eventq).cast(), addr_of!((*co).events)); } else { - ble_npl_event_run(addr_of!(co.events)); + ble_npl_event_run(addr_of!((*co).events)); } } unsafe extern "C" fn ble_npl_eventq_init(queue: *const ble_npl_eventq) { trace!("ble_npl_eventq_init {:?}", queue); - critical_section::with(|_cs| { - let queue = queue as *mut ble_npl_eventq; + let queue = queue as *mut ble_npl_eventq; - if (*queue).dummy == 0 { - (*queue).dummy = 1; - } else { - panic!("Only one emulated queue supported"); - } - }); + let raw_queue = ConcurrentQueue::new(EVENT_QUEUE_SIZE, 4); + let ptr = + unsafe { crate::compat::malloc::malloc(size_of_val(&raw_queue)) as *mut ConcurrentQueue }; + unsafe { + ptr.write(raw_queue); + } + + (*queue).dummy = ptr as i32; } unsafe extern "C" fn ble_npl_mutex_init(_mutex: *const ble_npl_mutex) -> u32 { @@ -1050,7 +1006,7 @@ pub struct BleNplCountInfoT { pub(crate) fn ble_init() { unsafe { - *(HCI_OUT_COLLECTOR.as_mut_ptr()) = HciOutCollector::new(); + (*addr_of_mut!(HCI_OUT_COLLECTOR)).write(HciOutCollector::new()); // turn on logging #[cfg(all(feature = "sys-logs", esp32c2))] @@ -1247,10 +1203,6 @@ pub(crate) fn ble_deinit() { npl::esp_unregister_ext_funcs(); crate::common_adapter::chip_specific::phy_disable(); - - CALLOUTS.iter_mut().for_each(|item| { - item.take(); - }); } } @@ -1325,7 +1277,7 @@ unsafe extern "C" fn ble_hs_hci_rx_evt(cmd: *const u8, arg: *const c_void) -> i3 trace!("$ pld = {:?}", payload); critical_section::with(|cs| { - let mut queue = BT_RECEIVE_QUEUE.borrow_ref_mut(cs); + let mut queue = super::BT_RECEIVE_QUEUE.borrow_ref_mut(cs); let mut data = [0u8; 256]; data[0] = 0x04; // this is an event @@ -1333,15 +1285,9 @@ unsafe extern "C" fn ble_hs_hci_rx_evt(cmd: *const u8, arg: *const c_void) -> i3 data[2] = len as u8; data[3..][..len].copy_from_slice(payload); - if queue - .enqueue(ReceivedPacket { - len: (len + 3) as u8, - data, - }) - .is_err() - { - warn!("Dropping BLE packet"); - } + queue.push_back(ReceivedPacket { + data: Box::from(&data[..len + 3]), + }); dump_packet_info(&data[..(len + 3)]); }); @@ -1362,23 +1308,17 @@ unsafe extern "C" fn ble_hs_rx_data(om: *const OsMbuf, arg: *const c_void) -> i3 let data_slice = core::slice::from_raw_parts(data_ptr, len as usize); critical_section::with(|cs| { - let mut queue = BT_RECEIVE_QUEUE.borrow_ref_mut(cs); + let mut queue = super::BT_RECEIVE_QUEUE.borrow_ref_mut(cs); let mut data = [0u8; 256]; data[0] = 0x02; // ACL data[1..][..data_slice.len()].copy_from_slice(data_slice); - if queue - .enqueue(ReceivedPacket { - len: (len + 1) as u8, - data, - }) - .is_err() - { - warn!("Dropping BLE packet"); - } + queue.push_back(ReceivedPacket { + data: Box::from(&data[..data_slice.len() + 1]), + }); - dump_packet_info(&data[..(len + 1) as usize]); + super::dump_packet_info(&data[..(len + 1) as usize]); }); r_os_mbuf_free_chain(om as *mut _); @@ -1389,67 +1329,8 @@ unsafe extern "C" fn ble_hs_rx_data(om: *const OsMbuf, arg: *const c_void) -> i3 0 } -static mut BLE_HCI_READ_DATA: [u8; 256] = [0u8; 256]; -static mut BLE_HCI_READ_DATA_INDEX: usize = 0; -static mut BLE_HCI_READ_DATA_LEN: usize = 0; - -#[cfg(feature = "async")] -pub fn have_hci_read_data() -> bool { - critical_section::with(|cs| { - let queue = BT_RECEIVE_QUEUE.borrow_ref_mut(cs); - !queue.is_empty() - || unsafe { - BLE_HCI_READ_DATA_LEN > 0 && (BLE_HCI_READ_DATA_LEN >= BLE_HCI_READ_DATA_INDEX) - } - }) -} - -pub(crate) fn read_next(data: &mut [u8]) -> usize { - critical_section::with(|cs| { - let mut queue = BT_RECEIVE_QUEUE.borrow_ref_mut(cs); - - match queue.dequeue() { - Some(packet) => { - data[..packet.len as usize].copy_from_slice(&packet.data[..packet.len as usize]); - packet.len as usize - } - None => 0, - } - }) -} - -pub fn read_hci(data: &mut [u8]) -> usize { - unsafe { - if BLE_HCI_READ_DATA_LEN == 0 { - critical_section::with(|cs| { - let mut queue = BT_RECEIVE_QUEUE.borrow_ref_mut(cs); - - if let Some(packet) = queue.dequeue() { - BLE_HCI_READ_DATA[..packet.len as usize] - .copy_from_slice(&packet.data[..packet.len as usize]); - BLE_HCI_READ_DATA_LEN = packet.len as usize; - BLE_HCI_READ_DATA_INDEX = 0; - } - }); - } - - if BLE_HCI_READ_DATA_LEN > 0 { - data[0] = BLE_HCI_READ_DATA[BLE_HCI_READ_DATA_INDEX]; - BLE_HCI_READ_DATA_INDEX += 1; - - if BLE_HCI_READ_DATA_INDEX >= BLE_HCI_READ_DATA_LEN { - BLE_HCI_READ_DATA_LEN = 0; - BLE_HCI_READ_DATA_INDEX = 0; - } - return 1; - } - } - - 0 -} - pub fn send_hci(data: &[u8]) { - let hci_out = unsafe { &mut *HCI_OUT_COLLECTOR.as_mut_ptr() }; + let hci_out = unsafe { (*addr_of_mut!(HCI_OUT_COLLECTOR)).assume_init_mut() }; hci_out.push(data); if hci_out.is_ready() { @@ -1503,13 +1384,3 @@ pub fn send_hci(data: &[u8]) { hci_out.reset(); } } - -#[allow(unreachable_code, unused_variables)] -fn dump_packet_info(buffer: &[u8]) { - #[cfg(not(feature = "dump-packets"))] - return; - - critical_section::with(|cs| { - info!("@HCIFRAME {:?}", buffer); - }); -} diff --git a/esp-wifi/src/ble/os_adapter_esp32c2.rs b/esp-wifi/src/ble/os_adapter_esp32c2.rs index 06307c58ac3..8a24212b7b1 100644 --- a/esp-wifi/src/ble/os_adapter_esp32c2.rs +++ b/esp-wifi/src/ble/os_adapter_esp32c2.rs @@ -1,8 +1,4 @@ -use crate::{ - binary::include::esp_bt_controller_config_t, - common_adapter::RADIO_CLOCKS, - hal::system::RadioClockController, -}; +use crate::{binary::include::esp_bt_controller_config_t, hal::system::RadioClockController}; pub(crate) static mut ISR_INTERRUPT_4: ( *mut crate::binary::c_types::c_void, @@ -103,14 +99,16 @@ pub(super) unsafe extern "C" fn esp_intr_alloc( } pub(super) fn ble_rtc_clk_init() { - unsafe { - unwrap!(RADIO_CLOCKS.as_mut()).ble_rtc_clk_init(); - } + // stealing RADIO_CLK is safe since it is passed (as mutable reference or by + // value) into `init` + let mut radio_clocks = unsafe { esp_hal::peripherals::RADIO_CLK::steal() }; + radio_clocks.ble_rtc_clk_init(); } pub(super) unsafe extern "C" fn esp_reset_rpa_moudle() { trace!("esp_reset_rpa_moudle"); - unsafe { - unwrap!(RADIO_CLOCKS.as_mut()).reset_rpa(); - } + // stealing RADIO_CLK is safe since it is passed (as mutable reference or by + // value) into `init` + let mut radio_clocks = unsafe { esp_hal::peripherals::RADIO_CLK::steal() }; + radio_clocks.reset_rpa(); } diff --git a/esp-wifi/src/ble/os_adapter_esp32c6.rs b/esp-wifi/src/ble/os_adapter_esp32c6.rs index 50b1127e058..49cc0c033cd 100644 --- a/esp-wifi/src/ble/os_adapter_esp32c6.rs +++ b/esp-wifi/src/ble/os_adapter_esp32c6.rs @@ -1,6 +1,5 @@ use crate::{ binary::include::esp_bt_controller_config_t, - common_adapter::RADIO_CLOCKS, hal::system::{RadioClockController, RadioPeripherals}, }; @@ -66,9 +65,10 @@ pub(crate) static BLE_CONFIG: esp_bt_controller_config_t = esp_bt_controller_con }; pub(crate) fn bt_periph_module_enable() { - unsafe { - unwrap!(RADIO_CLOCKS.as_mut()).enable(RadioPeripherals::Bt); - } + // stealing RADIO_CLK is safe since it is passed (as mutable reference or by + // value) into `init` + let mut radio_clocks = unsafe { esp_hal::peripherals::RADIO_CLK::steal() }; + radio_clocks.enable(RadioPeripherals::Bt); } pub(crate) fn disable_sleep_mode() { @@ -101,16 +101,18 @@ pub(super) unsafe extern "C" fn esp_intr_alloc( } pub(super) fn ble_rtc_clk_init() { - unsafe { - unwrap!(RADIO_CLOCKS.as_mut()).ble_rtc_clk_init(); - } + // stealing RADIO_CLK is safe since it is passed (as mutable reference or by + // value) into `init` + let mut radio_clocks = unsafe { esp_hal::peripherals::RADIO_CLK::steal() }; + radio_clocks.ble_rtc_clk_init(); } pub(super) unsafe extern "C" fn esp_reset_rpa_moudle() { trace!("esp_reset_rpa_moudle"); - unsafe { - unwrap!(RADIO_CLOCKS.as_mut()).reset_rpa(); - } + // stealing RADIO_CLK is safe since it is passed (as mutable reference or by + // value) into `init` + let mut radio_clocks = unsafe { esp_hal::peripherals::RADIO_CLK::steal() }; + radio_clocks.reset_rpa(); } #[allow(improper_ctypes_definitions)] diff --git a/esp-wifi/src/ble/os_adapter_esp32h2.rs b/esp-wifi/src/ble/os_adapter_esp32h2.rs index f0f8d49b1f1..5c310927023 100644 --- a/esp-wifi/src/ble/os_adapter_esp32h2.rs +++ b/esp-wifi/src/ble/os_adapter_esp32h2.rs @@ -1,6 +1,5 @@ use crate::{ binary::include::esp_bt_controller_config_t, - common_adapter::RADIO_CLOCKS, hal::system::{RadioClockController, RadioPeripherals}, }; @@ -66,9 +65,10 @@ pub(crate) static BLE_CONFIG: esp_bt_controller_config_t = esp_bt_controller_con }; pub(crate) fn bt_periph_module_enable() { - unsafe { - unwrap!(RADIO_CLOCKS.as_mut()).enable(RadioPeripherals::Bt); - } + // stealing RADIO_CLK is safe since it is passed (as mutable reference or by + // value) into `init` + let mut radio_clocks = unsafe { esp_hal::peripherals::RADIO_CLK::steal() }; + radio_clocks.enable(RadioPeripherals::Bt); } pub(crate) fn disable_sleep_mode() { @@ -101,16 +101,18 @@ pub(super) unsafe extern "C" fn esp_intr_alloc( } pub(super) fn ble_rtc_clk_init() { - unsafe { - unwrap!(RADIO_CLOCKS.as_mut()).ble_rtc_clk_init(); - } + // stealing RADIO_CLK is safe since it is passed (as reference or by value) into + // `init` + let mut radio_clocks = unsafe { esp_hal::peripherals::RADIO_CLK::steal() }; + radio_clocks.ble_rtc_clk_init(); } pub(super) unsafe extern "C" fn esp_reset_rpa_moudle() { trace!("esp_reset_rpa_moudle"); - unsafe { - unwrap!(RADIO_CLOCKS.as_mut()).reset_rpa(); - } + // stealing RADIO_CLK is safe since it is passed (as mutable reference or by + // value) into `init` + let mut radio_clocks = unsafe { esp_hal::peripherals::RADIO_CLK::steal() }; + radio_clocks.reset_rpa(); } #[allow(improper_ctypes_definitions)] diff --git a/esp-wifi/src/common_adapter/common_adapter_esp32.rs b/esp-wifi/src/common_adapter/common_adapter_esp32.rs index cdc16fa0434..26a05931a95 100644 --- a/esp-wifi/src/common_adapter/common_adapter_esp32.rs +++ b/esp-wifi/src/common_adapter/common_adapter_esp32.rs @@ -3,7 +3,6 @@ use portable_atomic::{AtomicU32, Ordering}; use super::phy_init_data::PHY_INIT_DATA_DEFAULT; use crate::{ binary::include::*, - common_adapter::RADIO_CLOCKS, hal::{ prelude::ram, system::{RadioClockController, RadioPeripherals}, @@ -16,8 +15,8 @@ static mut SOC_PHY_DIG_REGS_MEM: [u8; SOC_PHY_DIG_REGS_MEM_SIZE] = [0u8; SOC_PHY static mut G_IS_PHY_CALIBRATED: bool = false; static mut G_PHY_DIGITAL_REGS_MEM: *mut u32 = core::ptr::null_mut(); static mut S_IS_PHY_REG_STORED: bool = false; -static mut PHY_ACCESS_REF: AtomicU32 = AtomicU32::new(0); -static mut PHY_CLOCK_ENABLE_REF: AtomicU32 = AtomicU32::new(0); +static PHY_ACCESS_REF: AtomicU32 = AtomicU32::new(0); +static PHY_CLOCK_ENABLE_REF: AtomicU32 = AtomicU32::new(0); pub(crate) fn enable_wifi_power_domain() { unsafe { @@ -35,7 +34,7 @@ pub(crate) fn enable_wifi_power_domain() { pub(crate) fn phy_mem_init() { unsafe { - G_PHY_DIGITAL_REGS_MEM = SOC_PHY_DIG_REGS_MEM.as_ptr() as *mut u32; + G_PHY_DIGITAL_REGS_MEM = core::ptr::addr_of_mut!(SOC_PHY_DIG_REGS_MEM).cast(); } } @@ -123,9 +122,10 @@ pub(crate) unsafe fn phy_enable_clock() { let count = PHY_CLOCK_ENABLE_REF.fetch_add(1, Ordering::SeqCst); if count == 0 { - critical_section::with(|_| { - unwrap!(RADIO_CLOCKS.as_mut()).enable(RadioPeripherals::Phy); - }); + // stealing RADIO_CLK is safe since it is passed (as mutable reference or by + // value) into `init` + let mut radio_clocks = unsafe { esp_hal::peripherals::RADIO_CLK::steal() }; + radio_clocks.enable(RadioPeripherals::Phy); } } @@ -135,9 +135,10 @@ pub(crate) unsafe fn phy_disable_clock() { let count = PHY_CLOCK_ENABLE_REF.fetch_sub(1, Ordering::SeqCst); if count == 1 { - critical_section::with(|_| { - unwrap!(RADIO_CLOCKS.as_mut()).disable(RadioPeripherals::Phy); - }); + // stealing RADIO_CLK is safe since it is passed (as mutable reference or by + // value) into `init` + let mut radio_clocks = unsafe { esp_hal::peripherals::RADIO_CLK::steal() }; + radio_clocks.disable(RadioPeripherals::Phy); } } diff --git a/esp-wifi/src/common_adapter/common_adapter_esp32c2.rs b/esp-wifi/src/common_adapter/common_adapter_esp32c2.rs index 53265bb42a2..99a8f74da20 100644 --- a/esp-wifi/src/common_adapter/common_adapter_esp32c2.rs +++ b/esp-wifi/src/common_adapter/common_adapter_esp32c2.rs @@ -3,7 +3,6 @@ use portable_atomic::{AtomicU32, Ordering}; use super::phy_init_data::PHY_INIT_DATA_DEFAULT; use crate::{ binary::include::*, - common_adapter::RADIO_CLOCKS, compat::common::str_from_c, hal::system::{RadioClockController, RadioPeripherals}, }; @@ -14,7 +13,7 @@ static mut SOC_PHY_DIG_REGS_MEM: [u8; SOC_PHY_DIG_REGS_MEM_SIZE] = [0u8; SOC_PHY static mut G_IS_PHY_CALIBRATED: bool = false; static mut G_PHY_DIGITAL_REGS_MEM: *mut u32 = core::ptr::null_mut(); static mut S_IS_PHY_REG_STORED: bool = false; -static mut PHY_ACCESS_REF: AtomicU32 = AtomicU32::new(0); +static PHY_ACCESS_REF: AtomicU32 = AtomicU32::new(0); pub(crate) fn enable_wifi_power_domain() { // In esp-idf, neither SOC_PM_SUPPORT_MODEM_PD or SOC_PM_SUPPORT_WIFI_PD are @@ -23,7 +22,7 @@ pub(crate) fn enable_wifi_power_domain() { pub(crate) fn phy_mem_init() { unsafe { - G_PHY_DIGITAL_REGS_MEM = SOC_PHY_DIG_REGS_MEM.as_ptr() as *mut u32; + G_PHY_DIGITAL_REGS_MEM = core::ptr::addr_of_mut!(SOC_PHY_DIG_REGS_MEM).cast(); } } @@ -114,9 +113,10 @@ fn phy_digital_regs_store() { pub(crate) unsafe fn phy_enable_clock() { trace!("phy_enable_clock"); - critical_section::with(|_| { - unwrap!(RADIO_CLOCKS.as_mut()).enable(RadioPeripherals::Phy); - }); + // stealing RADIO_CLK is safe since it is passed (as mutable reference or by + // value) into `init` + let mut radio_clocks = unsafe { esp_hal::peripherals::RADIO_CLK::steal() }; + radio_clocks.enable(RadioPeripherals::Phy); trace!("phy_enable_clock done!"); } @@ -124,9 +124,10 @@ pub(crate) unsafe fn phy_enable_clock() { #[allow(unused)] pub(crate) unsafe fn phy_disable_clock() { trace!("phy_disable_clock"); - critical_section::with(|_| { - unwrap!(RADIO_CLOCKS.as_mut()).disable(RadioPeripherals::Phy); - }); + // stealing RADIO_CLK is safe since it is passed (as mutable reference or by + // value) into `init` + let mut radio_clocks = unsafe { esp_hal::peripherals::RADIO_CLK::steal() }; + radio_clocks.disable(RadioPeripherals::Phy); trace!("phy_disable_clock done!"); } diff --git a/esp-wifi/src/common_adapter/common_adapter_esp32c3.rs b/esp-wifi/src/common_adapter/common_adapter_esp32c3.rs index b901b3423b0..8a4bf0ab044 100644 --- a/esp-wifi/src/common_adapter/common_adapter_esp32c3.rs +++ b/esp-wifi/src/common_adapter/common_adapter_esp32c3.rs @@ -3,7 +3,6 @@ use portable_atomic::{AtomicU32, Ordering}; use super::phy_init_data::PHY_INIT_DATA_DEFAULT; use crate::{ binary::include::*, - common_adapter::RADIO_CLOCKS, compat::common::str_from_c, hal::system::{RadioClockController, RadioPeripherals}, }; @@ -14,7 +13,7 @@ static mut SOC_PHY_DIG_REGS_MEM: [u8; SOC_PHY_DIG_REGS_MEM_SIZE] = [0u8; SOC_PHY static mut G_IS_PHY_CALIBRATED: bool = false; static mut G_PHY_DIGITAL_REGS_MEM: *mut u32 = core::ptr::null_mut(); static mut S_IS_PHY_REG_STORED: bool = false; -static mut PHY_ACCESS_REF: AtomicU32 = AtomicU32::new(0); +static PHY_ACCESS_REF: AtomicU32 = AtomicU32::new(0); pub(crate) fn enable_wifi_power_domain() { const SYSTEM_WIFIBB_RST: u32 = 1 << 0; @@ -58,7 +57,7 @@ pub(crate) fn enable_wifi_power_domain() { pub(crate) fn phy_mem_init() { unsafe { - G_PHY_DIGITAL_REGS_MEM = SOC_PHY_DIG_REGS_MEM.as_ptr() as *mut u32; + G_PHY_DIGITAL_REGS_MEM = core::ptr::addr_of_mut!(SOC_PHY_DIG_REGS_MEM).cast(); } } @@ -156,19 +155,20 @@ fn phy_digital_regs_store() { pub(crate) unsafe fn phy_enable_clock() { trace!("phy_enable_clock"); - critical_section::with(|_| { - unwrap!(RADIO_CLOCKS.as_mut()).enable(RadioPeripherals::Phy); - }); + // stealing RADIO_CLK is safe since it is passed (as mutable reference or by + // value) into `init` + let mut radio_clocks = unsafe { esp_hal::peripherals::RADIO_CLK::steal() }; + radio_clocks.enable(RadioPeripherals::Phy); trace!("phy_enable_clock done!"); } #[allow(unused)] pub(crate) unsafe fn phy_disable_clock() { trace!("phy_disable_clock"); - const SYSTEM_WIFI_CLK_EN_REG: u32 = 0x60026000 + 0x014; - critical_section::with(|_| { - unwrap!(RADIO_CLOCKS.as_mut()).disable(RadioPeripherals::Phy); - }); + // stealing RADIO_CLK is safe since it is passed (as mutable reference or by + // value) into `init` + let mut radio_clocks = unsafe { esp_hal::peripherals::RADIO_CLK::steal() }; + radio_clocks.disable(RadioPeripherals::Phy); trace!("phy_disable_clock done!"); } diff --git a/esp-wifi/src/common_adapter/common_adapter_esp32c6.rs b/esp-wifi/src/common_adapter/common_adapter_esp32c6.rs index 215879d7f6c..74f3d76cecd 100644 --- a/esp-wifi/src/common_adapter/common_adapter_esp32c6.rs +++ b/esp-wifi/src/common_adapter/common_adapter_esp32c6.rs @@ -3,7 +3,6 @@ use portable_atomic::{AtomicU32, Ordering}; use super::phy_init_data::PHY_INIT_DATA_DEFAULT; use crate::{ binary::include::*, - common_adapter::RADIO_CLOCKS, compat::common::str_from_c, hal::system::{RadioClockController, RadioPeripherals}, }; @@ -14,7 +13,7 @@ static mut SOC_PHY_DIG_REGS_MEM: [u8; SOC_PHY_DIG_REGS_MEM_SIZE] = [0u8; SOC_PHY static mut G_IS_PHY_CALIBRATED: bool = false; static mut G_PHY_DIGITAL_REGS_MEM: *mut u32 = core::ptr::null_mut(); static mut S_IS_PHY_REG_STORED: bool = false; -static mut PHY_ACCESS_REF: AtomicU32 = AtomicU32::new(0); +static PHY_ACCESS_REF: AtomicU32 = AtomicU32::new(0); pub(crate) fn enable_wifi_power_domain() { // In esp-idf, SOC_PMU_SUPPORTED is set which makes @@ -23,7 +22,7 @@ pub(crate) fn enable_wifi_power_domain() { pub(crate) fn phy_mem_init() { unsafe { - G_PHY_DIGITAL_REGS_MEM = SOC_PHY_DIG_REGS_MEM.as_ptr() as *mut u32; + G_PHY_DIGITAL_REGS_MEM = core::ptr::addr_of_mut!(SOC_PHY_DIG_REGS_MEM).cast(); } } @@ -120,13 +119,19 @@ fn phy_digital_regs_store() { pub(crate) unsafe fn phy_enable_clock() { trace!("phy_enable_clock"); - unwrap!(RADIO_CLOCKS.as_mut()).enable(RadioPeripherals::Phy); + // stealing RADIO_CLK is safe since it is passed (as mutable reference or by + // value) into `init` + let mut radio_clocks = unsafe { esp_hal::peripherals::RADIO_CLK::steal() }; + radio_clocks.enable(RadioPeripherals::Phy); trace!("phy_enable_clock done!"); } #[allow(unused)] pub(crate) unsafe fn phy_disable_clock() { trace!("phy_disable_clock"); - unwrap!(RADIO_CLOCKS.as_mut()).disable(RadioPeripherals::Phy); + // stealing RADIO_CLK is safe since it is passed (as mutable reference or by + // value) into `init` + let mut radio_clocks = unsafe { esp_hal::peripherals::RADIO_CLK::steal() }; + radio_clocks.disable(RadioPeripherals::Phy); trace!("phy_disable_clock done!"); } diff --git a/esp-wifi/src/common_adapter/common_adapter_esp32h2.rs b/esp-wifi/src/common_adapter/common_adapter_esp32h2.rs index 8b2e4646d90..1cb0b537589 100644 --- a/esp-wifi/src/common_adapter/common_adapter_esp32h2.rs +++ b/esp-wifi/src/common_adapter/common_adapter_esp32h2.rs @@ -4,7 +4,6 @@ use portable_atomic::{AtomicU32, Ordering}; use super::phy_init_data::PHY_INIT_DATA_DEFAULT; use crate::{ binary::include::*, - common_adapter::RADIO_CLOCKS, compat::common::str_from_c, hal::system::{RadioClockController, RadioPeripherals}, }; @@ -15,7 +14,7 @@ static mut SOC_PHY_DIG_REGS_MEM: [u8; SOC_PHY_DIG_REGS_MEM_SIZE] = [0u8; SOC_PHY static mut G_IS_PHY_CALIBRATED: bool = false; static mut G_PHY_DIGITAL_REGS_MEM: *mut u32 = core::ptr::null_mut(); static mut S_IS_PHY_REG_STORED: bool = false; -static mut PHY_ACCESS_REF: AtomicU32 = AtomicU32::new(0); +static PHY_ACCESS_REF: AtomicU32 = AtomicU32::new(0); pub(crate) fn enable_wifi_power_domain() { // In esp-idf, SOC_PMU_SUPPORTED is set which makes @@ -24,7 +23,7 @@ pub(crate) fn enable_wifi_power_domain() { pub(crate) fn phy_mem_init() { unsafe { - G_PHY_DIGITAL_REGS_MEM = SOC_PHY_DIG_REGS_MEM.as_ptr() as *mut u32; + G_PHY_DIGITAL_REGS_MEM = core::ptr::addr_of_mut!(SOC_PHY_DIG_REGS_MEM).cast(); } } @@ -123,13 +122,19 @@ fn phy_digital_regs_store() { pub(crate) unsafe fn phy_enable_clock() { trace!("phy_enable_clock"); - unwrap!(RADIO_CLOCKS.as_mut()).enable(RadioPeripherals::Phy); + // stealing RADIO_CLK is safe since it is passed (as mutable reference or by + // value) into `init` + let mut radio_clocks = unsafe { esp_hal::peripherals::RADIO_CLK::steal() }; + radio_clocks.enable(RadioPeripherals::Phy); trace!("phy_enable_clock done!"); } #[allow(unused)] pub(crate) unsafe fn phy_disable_clock() { trace!("phy_disable_clock"); - unwrap!(RADIO_CLOCKS.as_mut()).disable(RadioPeripherals::Phy); + // stealing RADIO_CLK is safe since it is passed (as mutable reference or by + // value) into `init` + let mut radio_clocks = unsafe { esp_hal::peripherals::RADIO_CLK::steal() }; + radio_clocks.disable(RadioPeripherals::Phy); trace!("phy_disable_clock done!"); } diff --git a/esp-wifi/src/common_adapter/common_adapter_esp32s2.rs b/esp-wifi/src/common_adapter/common_adapter_esp32s2.rs index a48a28870f6..b87536dbf75 100644 --- a/esp-wifi/src/common_adapter/common_adapter_esp32s2.rs +++ b/esp-wifi/src/common_adapter/common_adapter_esp32s2.rs @@ -3,7 +3,6 @@ use portable_atomic::{AtomicU32, Ordering}; use super::phy_init_data::PHY_INIT_DATA_DEFAULT; use crate::{ binary::include::*, - common_adapter::RADIO_CLOCKS, hal::{ prelude::ram, system::{RadioClockController, RadioPeripherals}, @@ -16,8 +15,8 @@ static mut SOC_PHY_DIG_REGS_MEM: [u8; SOC_PHY_DIG_REGS_MEM_SIZE] = [0u8; SOC_PHY static mut G_IS_PHY_CALIBRATED: bool = false; static mut G_PHY_DIGITAL_REGS_MEM: *mut u32 = core::ptr::null_mut(); static mut S_IS_PHY_REG_STORED: bool = false; -static mut PHY_ACCESS_REF: AtomicU32 = AtomicU32::new(0); -static mut PHY_CLOCK_ENABLE_REF: AtomicU32 = AtomicU32::new(0); +static PHY_ACCESS_REF: AtomicU32 = AtomicU32::new(0); +static PHY_CLOCK_ENABLE_REF: AtomicU32 = AtomicU32::new(0); pub(crate) fn enable_wifi_power_domain() { const DPORT_WIFIBB_RST: u32 = 1 << 0; @@ -58,7 +57,7 @@ pub(crate) fn enable_wifi_power_domain() { pub(crate) fn phy_mem_init() { unsafe { - G_PHY_DIGITAL_REGS_MEM = SOC_PHY_DIG_REGS_MEM.as_ptr() as *mut u32; + G_PHY_DIGITAL_REGS_MEM = core::ptr::addr_of_mut!(SOC_PHY_DIG_REGS_MEM).cast(); } } @@ -137,10 +136,10 @@ fn phy_digital_regs_store() { pub(crate) unsafe fn phy_enable_clock() { let count = PHY_CLOCK_ENABLE_REF.fetch_add(1, Ordering::SeqCst); if count == 0 { - critical_section::with(|_| { - unwrap!(RADIO_CLOCKS.as_mut()).enable(RadioPeripherals::Phy); - }); - + // stealing RADIO_CLK is safe since it is passed (as mutable reference or by + // value) into `init` + let mut radio_clocks = unsafe { esp_hal::peripherals::RADIO_CLK::steal() }; + radio_clocks.enable(RadioPeripherals::Phy); trace!("phy_enable_clock done!"); } } @@ -149,10 +148,10 @@ pub(crate) unsafe fn phy_enable_clock() { pub(crate) unsafe fn phy_disable_clock() { let count = PHY_CLOCK_ENABLE_REF.fetch_sub(1, Ordering::SeqCst); if count == 1 { - critical_section::with(|_| { - unwrap!(RADIO_CLOCKS.as_mut()).disable(RadioPeripherals::Phy); - }); - + // stealing RADIO_CLK is safe since it is passed (as mutable reference or by + // value) into `init` + let mut radio_clocks = unsafe { esp_hal::peripherals::RADIO_CLK::steal() }; + radio_clocks.disable(RadioPeripherals::Phy); trace!("phy_disable_clock done!"); } } diff --git a/esp-wifi/src/common_adapter/common_adapter_esp32s3.rs b/esp-wifi/src/common_adapter/common_adapter_esp32s3.rs index 49b9aabc52f..249370caa1f 100644 --- a/esp-wifi/src/common_adapter/common_adapter_esp32s3.rs +++ b/esp-wifi/src/common_adapter/common_adapter_esp32s3.rs @@ -3,7 +3,6 @@ use portable_atomic::{AtomicU32, Ordering}; use super::phy_init_data::PHY_INIT_DATA_DEFAULT; use crate::{ binary::include::*, - common_adapter::RADIO_CLOCKS, hal::system::{RadioClockController, RadioPeripherals}, }; @@ -13,11 +12,11 @@ static mut SOC_PHY_DIG_REGS_MEM: [u8; SOC_PHY_DIG_REGS_MEM_SIZE] = [0u8; SOC_PHY static mut G_IS_PHY_CALIBRATED: bool = false; static mut G_PHY_DIGITAL_REGS_MEM: *mut u32 = core::ptr::null_mut(); static mut S_IS_PHY_REG_STORED: bool = false; -static mut PHY_ACCESS_REF: AtomicU32 = AtomicU32::new(0); +static PHY_ACCESS_REF: AtomicU32 = AtomicU32::new(0); pub(crate) fn phy_mem_init() { unsafe { - G_PHY_DIGITAL_REGS_MEM = SOC_PHY_DIG_REGS_MEM.as_ptr() as *mut u32; + G_PHY_DIGITAL_REGS_MEM = core::ptr::addr_of_mut!(SOC_PHY_DIG_REGS_MEM).cast(); } } @@ -148,20 +147,20 @@ fn phy_digital_regs_store() { pub(crate) unsafe fn phy_enable_clock() { trace!("phy_enable_clock"); - critical_section::with(|_| { - unwrap!(RADIO_CLOCKS.as_mut()).enable(RadioPeripherals::Phy); - }); - + // stealing RADIO_CLK is safe since it is passed (as mutable reference or by + // value) into `init` + let mut radio_clocks = unsafe { esp_hal::peripherals::RADIO_CLK::steal() }; + radio_clocks.enable(RadioPeripherals::Phy); trace!("phy_enable_clock done!"); } #[allow(unused)] pub(crate) unsafe fn phy_disable_clock() { trace!("phy_disable_clock"); - critical_section::with(|_| { - unwrap!(RADIO_CLOCKS.as_mut()).disable(RadioPeripherals::Phy); - }); - + // stealing RADIO_CLK is safe since it is passed (as mutable reference or by + // value) into `init` + let mut radio_clocks = unsafe { esp_hal::peripherals::RADIO_CLK::steal() }; + radio_clocks.disable(RadioPeripherals::Phy); trace!("phy_disable_clock done!"); } diff --git a/esp-wifi/src/common_adapter/mod.rs b/esp-wifi/src/common_adapter/mod.rs index be2b5d52422..e41dc17ec9f 100644 --- a/esp-wifi/src/common_adapter/mod.rs +++ b/esp-wifi/src/common_adapter/mod.rs @@ -1,7 +1,7 @@ use core::ptr::addr_of; use esp_wifi_sys::include::timeval; -use hal::{macros::ram, rng::Rng}; +use hal::macros::ram; use crate::{ binary::include::{esp_event_base_t, esp_timer_get_time}, @@ -27,22 +27,6 @@ pub(crate) mod chip_specific; #[cfg_attr(esp32s2, path = "phy_init_data_esp32s2.rs")] pub(crate) mod phy_init_data; -pub(crate) static mut RANDOM_GENERATOR: Option = None; - -pub(crate) static mut RADIO_CLOCKS: Option = None; - -pub(crate) fn init_rng(rng: Rng) { - unsafe { RANDOM_GENERATOR = Some(rng) }; -} - -pub(crate) fn init_radio_clock_control(rcc: hal::peripherals::RADIO_CLK) { - unsafe { RADIO_CLOCKS = Some(rcc) }; -} - -pub(crate) fn deinit_radio_clock_control() -> Option { - unsafe { RADIO_CLOCKS.take() } -} - /// ************************************************************************** /// Name: esp_semphr_create /// @@ -131,11 +115,9 @@ pub unsafe extern "C" fn semphr_give(semphr: *mut crate::binary::c_types::c_void pub unsafe extern "C" fn random() -> crate::binary::c_types::c_ulong { trace!("random"); - if let Some(ref mut rng) = RANDOM_GENERATOR { - rng.random() - } else { - 0 - } + // stealing RNG is safe since we own it (passed into `init`) + let mut rng = esp_hal::rng::Rng::new(unsafe { esp_hal::peripherals::RNG::steal() }); + rng.random() } /// ************************************************************************** @@ -308,11 +290,11 @@ pub unsafe extern "C" fn esp_fill_random(dst: *mut u8, len: u32) { trace!("esp_fill_random"); let dst = core::slice::from_raw_parts_mut(dst, len as usize); - if let Some(ref mut rng) = RANDOM_GENERATOR { - for chunk in dst.chunks_mut(4) { - let bytes = rng.random().to_le_bytes(); - chunk.copy_from_slice(&bytes[..chunk.len()]); - } + // stealing RNG is safe since we own it (passed into `init`) + let mut rng = esp_hal::rng::Rng::new(unsafe { esp_hal::peripherals::RNG::steal() }); + for chunk in dst.chunks_mut(4) { + let bytes = rng.random().to_le_bytes(); + chunk.copy_from_slice(&bytes[..chunk.len()]); } } diff --git a/esp-wifi/src/compat/common.rs b/esp-wifi/src/compat/common.rs index d8d29aa2245..946650f75c2 100644 --- a/esp-wifi/src/compat/common.rs +++ b/esp-wifi/src/compat/common.rs @@ -1,9 +1,10 @@ #![allow(unused)] use core::{ + cell::RefCell, fmt::Write, mem::size_of_val, - ptr::{addr_of, addr_of_mut}, + ptr::{self, addr_of, addr_of_mut}, }; use esp_wifi_sys::include::malloc; @@ -25,10 +26,52 @@ struct Mutex { recursive: bool, } +pub(crate) struct ConcurrentQueue { + raw_queue: critical_section::Mutex>, +} + +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))), + } + } + + fn release_storage(&mut self) { + critical_section::with(|cs| unsafe { + self.raw_queue.borrow_ref_mut(cs).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) }) + } + + 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) }) + } + + pub(crate) fn remove(&mut self, item: *mut c_void) { + critical_section::with(|cs| unsafe { self.raw_queue.borrow_ref_mut(cs).remove(item) }); + } + + pub(crate) fn count(&self) -> usize { + critical_section::with(|cs| unsafe { self.raw_queue.borrow_ref(cs).count() }) + } +} + +impl Drop for ConcurrentQueue { + fn drop(&mut self) { + self.release_storage(); + } +} + /// A naive and pretty much unsafe queue to back the queues used in drivers and -/// supplicant code -struct RawQueue { - count: usize, +/// supplicant code. +/// +/// The [ConcurrentQueue] wrapper should be used. +pub struct RawQueue { + capacity: usize, item_size: usize, current_read: usize, current_write: usize, @@ -36,10 +79,13 @@ struct RawQueue { } impl RawQueue { - fn new(count: usize, item_size: usize) -> Self { - let storage = unsafe { malloc((count * item_size) as u32) as *mut u8 }; + /// This allocates underlying storage. See [release_storage] + pub fn new(capacity: usize, item_size: usize) -> Self { + let storage = unsafe { malloc((capacity * item_size) as u32) as *mut u8 }; + assert!(!storage.is_null()); + Self { - count, + capacity, item_size, current_read: 0, current_write: 0, @@ -47,19 +93,20 @@ impl RawQueue { } } - fn free_storage(&mut self) { + /// Call `release_storage` to deallocate the underlying storage + unsafe fn release_storage(&mut self) { unsafe { free(self.storage); } self.storage = core::ptr::null_mut(); } - fn enqueue(&mut self, item: *mut c_void) -> i32 { - if self.count() < self.count { + unsafe fn enqueue(&mut self, item: *mut c_void) -> i32 { + if self.count() < self.capacity { unsafe { let p = self.storage.byte_add(self.item_size * self.current_write); p.copy_from(item as *mut u8, self.item_size); - self.current_write = (self.current_write + 1) % self.count; + self.current_write = (self.current_write + 1) % self.capacity; } 1 @@ -68,12 +115,12 @@ impl RawQueue { } } - fn try_dequeue(&mut self, item: *mut c_void) -> bool { + unsafe fn try_dequeue(&mut self, item: *mut c_void) -> bool { if self.count() > 0 { unsafe { let p = self.storage.byte_add(self.item_size * self.current_read) as *const c_void; item.copy_from(p, self.item_size); - self.current_read = (self.current_read + 1) % self.count; + self.current_read = (self.current_read + 1) % self.capacity; } true } else { @@ -81,11 +128,40 @@ impl RawQueue { } } - fn count(&self) -> usize { + unsafe fn remove(&mut self, item: *mut c_void) { + // do what the ESP-IDF implementations does ... + // just remove all elements and add them back except the one we need to remove - + // good enough for now + let item_slice = core::slice::from_raw_parts_mut(item as *mut u8, self.item_size); + let count = self.count(); + + if count == 0 { + return; + } + + let tmp_item = crate::compat::malloc::malloc(self.item_size); + + if tmp_item.is_null() { + panic!("Out of memory"); + } + + for _ in 0..count { + if self.try_dequeue(tmp_item as *mut c_void) { + let tmp_slice = core::slice::from_raw_parts_mut(tmp_item, self.item_size); + if tmp_slice != item_slice { + self.enqueue(tmp_item as *mut c_void); + } + } + } + + crate::compat::malloc::free(tmp_item); + } + + unsafe fn count(&self) -> usize { if self.current_write >= self.current_read { self.current_write - self.current_read } else { - self.count - self.current_read + self.current_write + self.capacity - self.current_read + self.current_write } } } @@ -248,31 +324,34 @@ pub(crate) fn unlock_mutex(mutex: *mut c_void) -> i32 { }) } -pub(crate) fn create_queue(queue_len: c_int, item_size: c_int) -> *mut c_void { +pub(crate) fn create_queue(queue_len: c_int, item_size: c_int) -> *mut ConcurrentQueue { trace!("wifi_create_queue len={} size={}", queue_len, item_size,); - let queue = RawQueue::new(queue_len as usize, item_size as usize); - let ptr = unsafe { malloc(size_of_val(&queue) as u32) as *mut RawQueue }; + let queue = ConcurrentQueue::new(queue_len as usize, item_size as usize); + let ptr = unsafe { malloc(size_of_val(&queue) as u32) as *mut ConcurrentQueue }; unsafe { ptr.write(queue); } trace!("created queue @{:?}", ptr); - ptr.cast() + ptr } -pub(crate) fn delete_queue(queue: *mut c_void) { +pub(crate) fn delete_queue(queue: *mut ConcurrentQueue) { trace!("delete_queue {:?}", queue); - let queue: *mut RawQueue = queue.cast(); unsafe { - (*queue).free_storage(); - free(queue.cast()); + ptr::drop_in_place(queue); + crate::compat::malloc::free(queue.cast()); } } -pub(crate) fn send_queued(queue: *mut c_void, item: *mut c_void, block_time_tick: u32) -> i32 { +pub(crate) fn send_queued( + queue: *mut ConcurrentQueue, + item: *mut c_void, + block_time_tick: u32, +) -> i32 { trace!( "queue_send queue {:?} item {:x} block_time_tick {}", queue, @@ -280,11 +359,15 @@ pub(crate) fn send_queued(queue: *mut c_void, item: *mut c_void, block_time_tick block_time_tick ); - let queue: *mut RawQueue = queue.cast(); - critical_section::with(|_| unsafe { (*queue).enqueue(item) }) + let queue: *mut ConcurrentQueue = queue.cast(); + unsafe { (*queue).enqueue(item) } } -pub(crate) fn receive_queued(queue: *mut c_void, item: *mut c_void, block_time_tick: u32) -> i32 { +pub(crate) fn receive_queued( + queue: *mut ConcurrentQueue, + item: *mut c_void, + block_time_tick: u32, +) -> i32 { trace!( "queue_recv {:?} item {:?} block_time_tick {}", queue, @@ -296,10 +379,8 @@ pub(crate) fn receive_queued(queue: *mut c_void, item: *mut c_void, block_time_t let timeout = block_time_tick as u64; let start = crate::timer::get_systimer_count(); - let queue: *mut RawQueue = queue.cast(); - loop { - if critical_section::with(|_| unsafe { (*queue).try_dequeue(item) }) { + if unsafe { (*queue).try_dequeue(item) } { trace!("received"); return 1; } @@ -313,11 +394,11 @@ pub(crate) fn receive_queued(queue: *mut c_void, item: *mut c_void, block_time_t } } -pub(crate) fn number_of_messages_in_queue(queue: *const c_void) -> u32 { +pub(crate) fn number_of_messages_in_queue(queue: *const ConcurrentQueue) -> u32 { trace!("queue_msg_waiting {:?}", queue); - let queue: *const RawQueue = queue.cast(); - critical_section::with(|_| unsafe { (*queue).count() as u32 }) + let queue: *const ConcurrentQueue = queue.cast(); + unsafe { (*queue).count() as u32 } } /// Implementation of sleep() from newlib in esp-idf. diff --git a/esp-wifi/src/compat/mod.rs b/esp-wifi/src/compat/mod.rs index 25e6d6a1ccb..dc68d68e125 100644 --- a/esp-wifi/src/compat/mod.rs +++ b/esp-wifi/src/compat/mod.rs @@ -3,16 +3,13 @@ pub mod malloc; pub mod misc; pub mod timer_compat; -pub mod queue { - pub use heapless::spsc::Queue as SimpleQueue; -} - #[no_mangle] unsafe extern "C" fn _putchar(c: u8) { static mut BUFFER: [u8; 256] = [0u8; 256]; static mut IDX: usize = 0; - if c == 0 || c == b'\n' || IDX == BUFFER.len() - 1 { + let buffer = core::ptr::addr_of_mut!(BUFFER); + if c == 0 || c == b'\n' || IDX == (*buffer).len() - 1 { if c != 0 { BUFFER[IDX] = c; } else { diff --git a/esp-wifi/src/compat/timer_compat.rs b/esp-wifi/src/compat/timer_compat.rs index b44cade7625..c7f67ea4778 100644 --- a/esp-wifi/src/compat/timer_compat.rs +++ b/esp-wifi/src/compat/timer_compat.rs @@ -1,3 +1,8 @@ +use alloc::boxed::Box; +use core::cell::RefCell; + +use critical_section::Mutex; + use crate::binary::{ c_types, include::{esp_timer_create_args_t, ets_timer}, @@ -25,7 +30,8 @@ impl From<&esp_timer_create_args_t> for TimerCallback { } } -#[derive(Debug, Clone, Copy)] +#[repr(C)] +#[derive(Debug, Clone)] pub(crate) struct Timer { pub ets_timer: *mut ets_timer, pub started: u64, @@ -33,6 +39,8 @@ pub(crate) struct Timer { pub active: bool, pub periodic: bool, pub callback: TimerCallback, + + next: Option>, } impl Timer { @@ -40,10 +48,97 @@ impl Timer { self.ets_timer as usize } } -#[cfg(coex)] -pub(crate) static mut TIMERS: heapless::Vec = heapless::Vec::new(); -#[cfg(not(coex))] -pub(crate) static mut TIMERS: heapless::Vec = heapless::Vec::new(); + +pub(crate) struct TimerQueue { + head: Option>, +} + +impl TimerQueue { + const fn new() -> Self { + Self { head: None } + } + + fn find(&mut self, ets_timer: *mut ets_timer) -> Option<&mut Box> { + let mut current = self.head.as_mut(); + while let Some(timer) = current { + if timer.ets_timer == ets_timer { + return Some(timer); + } + current = timer.next.as_mut(); + } + + None + } + + pub(crate) unsafe fn find_next_due( + &mut self, + current_timestamp: u64, + ) -> Option<&mut Box> { + let mut current = self.head.as_mut(); + while let Some(timer) = current { + if timer.active + && crate::timer::time_diff(timer.started, current_timestamp) >= timer.timeout + { + return Some(timer); + } + current = timer.next.as_mut(); + } + + None + } + + fn remove(&mut self, ets_timer: *mut ets_timer) { + if let Some(head) = self.head.as_mut() { + if head.ets_timer == ets_timer { + self.head = head.next.take(); + return; + } + } + + let timer = self.find(ets_timer); + if let Some(to_remove) = timer { + let tail = to_remove.next.take(); + + let mut current = self.head.as_mut(); + let before = { + let mut found = None; + while let Some(before) = current { + if before.next.as_mut().unwrap().ets_timer == ets_timer { + found = Some(before); + break; + } + current = before.next.as_mut(); + } + found + }; + + if let Some(before) = before { + before.next = tail; + } + } + } + + fn push(&mut self, to_add: Box) -> Result<(), ()> { + if self.head.is_none() { + self.head = Some(to_add); + return Ok(()); + } + + let mut current = self.head.as_mut(); + while let Some(timer) = current { + if timer.next.is_none() { + timer.next = Some(to_add); + break; + } + current = timer.next.as_mut(); + } + Ok(()) + } +} + +unsafe impl Send for TimerQueue {} + +pub(crate) static TIMERS: Mutex> = Mutex::new(RefCell::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); @@ -61,8 +156,8 @@ pub(crate) fn compat_timer_arm_us(ets_timer: *mut ets_timer, us: u32, repeat: bo repeat ); - critical_section::with(|_| unsafe { - if let Some(timer) = TIMERS.iter_mut().find(|t| t.ets_timer == ets_timer) { + critical_section::with(|cs| { + if let Some(timer) = TIMERS.borrow_ref_mut(cs).find(ets_timer) { timer.started = systick; timer.timeout = ticks; timer.active = true; @@ -73,9 +168,10 @@ pub(crate) fn compat_timer_arm_us(ets_timer: *mut ets_timer, us: u32, repeat: bo }) } -pub(crate) fn compat_timer_disarm(ets_timer: *mut ets_timer) { - critical_section::with(|_| unsafe { - if let Some(timer) = TIMERS.iter_mut().find(|t| t.ets_timer == ets_timer) { +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) { trace!("timer_disarm {:x}", timer.id()); timer.active = false; } else { @@ -84,20 +180,20 @@ pub(crate) fn compat_timer_disarm(ets_timer: *mut ets_timer) { }) } -pub(crate) fn compat_timer_done(ets_timer: *mut ets_timer) { - critical_section::with(|_| unsafe { - if let Some((idx, timer)) = TIMERS - .iter_mut() - .enumerate() - .find(|(_, t)| t.ets_timer == 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); + if let Some(timer) = timers.find(ets_timer) { trace!("timer_done {:x}", timer.id()); timer.active = false; - (*ets_timer).priv_ = core::ptr::null_mut(); - (*ets_timer).expire = 0; + unsafe { + (*ets_timer).priv_ = core::ptr::null_mut(); + (*ets_timer).expire = 0; + } - TIMERS.swap_remove(idx); + timers.remove(ets_timer); } else { trace!("timer_done {:x} not found", ets_timer as usize); } @@ -115,9 +211,9 @@ pub(crate) fn compat_timer_setfn( pfunction, parg ); - - let set = critical_section::with(|_| unsafe { - if let Some(timer) = TIMERS.iter_mut().find(|t| t.ets_timer == ets_timer) { + let set = critical_section::with(|cs| unsafe { + let mut timers = TIMERS.borrow_ref_mut(cs); + if let Some(timer) = timers.find(ets_timer) { timer.callback = TimerCallback::new(pfunction, parg); timer.active = false; @@ -129,16 +225,18 @@ pub(crate) fn compat_timer_setfn( (*ets_timer).period = 0; (*ets_timer).func = None; (*ets_timer).priv_ = core::ptr::null_mut(); - TIMERS - .push(Timer { - ets_timer, - started: 0, - timeout: 0, - active: false, - periodic: false, - callback: TimerCallback::new(pfunction, parg), - }) - .is_ok() + + let timer = + crate::compat::malloc::calloc(1, core::mem::size_of::()) as *mut Timer; + (*timer).next = None; + (*timer).ets_timer = ets_timer; + (*timer).started = 0; + (*timer).timeout = 0; + (*timer).active = false; + (*timer).periodic = false; + (*timer).callback = TimerCallback::new(pfunction, parg); + + timers.push(Box::from_raw(timer)).is_ok() } }); diff --git a/esp-wifi/src/esp_now/mod.rs b/esp-wifi/src/esp_now/mod.rs index 5099fe78cd4..ecdbd6886a5 100644 --- a/esp-wifi/src/esp_now/mod.rs +++ b/esp-wifi/src/esp_now/mod.rs @@ -9,6 +9,7 @@ //! //! For more information see https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/network/esp_now.html +use alloc::{boxed::Box, collections::vec_deque::VecDeque}; use core::{cell::RefCell, fmt::Debug, marker::PhantomData}; use critical_section::Mutex; @@ -17,20 +18,23 @@ use portable_atomic::{AtomicBool, AtomicU8, Ordering}; use crate::{ binary::include::*, - compat::queue::SimpleQueue, hal::peripheral::{Peripheral, PeripheralRef}, wifi::{Protocol, RxControlInfo}, EspWifiInitialization, }; +const RECEIVE_QUEUE_SIZE: usize = 10; + /// Maximum payload length pub const ESP_NOW_MAX_DATA_LEN: usize = 250; /// Broadcast address pub const BROADCAST_ADDRESS: [u8; 6] = [0xffu8, 0xffu8, 0xffu8, 0xffu8, 0xffu8, 0xffu8]; -static RECEIVE_QUEUE: Mutex>> = - Mutex::new(RefCell::new(SimpleQueue::new())); +// Stores received packets until dequeued by the user +static RECEIVE_QUEUE: Mutex>> = + Mutex::new(RefCell::new(VecDeque::new())); + /// This atomic behaves like a guard, so we need strict memory ordering when /// operating it. /// @@ -231,30 +235,30 @@ pub struct ReceiveInfo { /// Stores information about the received data, including the packet content and /// associated information. -#[derive(Clone, Copy)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Clone)] pub struct ReceivedData { - /// The length of the received data. - pub len: u8, - - /// The buffer containing the received data. - pub data: [u8; 256], - - /// Information about a received packet. + data: Box<[u8]>, pub info: ReceiveInfo, } impl ReceivedData { /// Returns the received payload. - pub fn get_data(&self) -> &[u8] { - &self.data[..self.len as usize] + pub fn data(&self) -> &[u8] { + &self.data + } +} + +#[cfg(feature = "defmt")] +impl defmt::Format for ReceivedData { + fn format(&self, fmt: defmt::Formatter) { + defmt::write!(fmt, "ReceivedData {}, Info {}", &self.data[..], &self.info,) } } impl Debug for ReceivedData { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { f.debug_struct("ReceivedData") - .field("data", &self.get_data()) + .field("data", &self.data()) .field("info", &self.info) .finish() } @@ -277,7 +281,7 @@ pub struct EspNowManager<'d> { _rc: EspNowRc<'d>, } -impl<'d> EspNowManager<'d> { +impl EspNowManager<'_> { /// Set the wifi protocol. /// /// This will set the wifi protocol to the desired protocol @@ -476,7 +480,7 @@ pub struct EspNowSender<'d> { _rc: EspNowRc<'d>, } -impl<'d> EspNowSender<'d> { +impl EspNowSender<'_> { /// Send data to peer /// /// The peer needs to be added to the peer list first. @@ -506,7 +510,7 @@ impl<'d> EspNowSender<'d> { #[must_use] pub struct SendWaiter<'s>(PhantomData<&'s mut EspNowSender<'s>>); -impl<'s> SendWaiter<'s> { +impl SendWaiter<'_> { /// Wait for the previous sending to complete, i.e. the send callback is /// invoked with status of the sending. pub fn wait(self) -> Result<(), EspNowError> { @@ -523,7 +527,7 @@ impl<'s> SendWaiter<'s> { } } -impl<'s> Drop for SendWaiter<'s> { +impl Drop for SendWaiter<'_> { /// wait for the send to complete to prevent the lock on `EspNowSender` get /// unlocked before a callback is invoked. fn drop(&mut self) { @@ -537,12 +541,12 @@ pub struct EspNowReceiver<'d> { _rc: EspNowRc<'d>, } -impl<'d> EspNowReceiver<'d> { +impl EspNowReceiver<'_> { /// Receives data from the ESP-NOW queue. pub fn receive(&self) -> Option { critical_section::with(|cs| { let mut queue = RECEIVE_QUEUE.borrow_ref_mut(cs); - queue.dequeue() + queue.pop_front() }) } } @@ -554,7 +558,7 @@ struct EspNowRc<'d> { inner: PhantomData>, } -impl<'d> EspNowRc<'d> { +impl EspNowRc<'_> { fn new() -> Result { static ESP_NOW_RC: AtomicU8 = AtomicU8::new(0); // The reference counter is not 0, which means there is another instance of @@ -570,7 +574,7 @@ impl<'d> EspNowRc<'d> { } } -impl<'d> Clone for EspNowRc<'d> { +impl Clone for EspNowRc<'_> { fn clone(&self) -> Self { self.rc.fetch_add(1, Ordering::Release); Self { @@ -580,7 +584,7 @@ impl<'d> Clone for EspNowRc<'d> { } } -impl<'d> Drop for EspNowRc<'d> { +impl Drop for EspNowRc<'_> { fn drop(&mut self) { if self.rc.fetch_sub(1, Ordering::AcqRel) == 1 { unsafe { @@ -834,18 +838,13 @@ unsafe extern "C" fn rcv_cb( let slice = core::slice::from_raw_parts(data, data_len as usize); critical_section::with(|cs| { let mut queue = RECEIVE_QUEUE.borrow_ref_mut(cs); - let mut data = [0u8; 256]; - data[..slice.len()].copy_from_slice(slice); + let data = Box::from(slice); - if queue.is_full() { - queue.dequeue(); + if queue.len() >= RECEIVE_QUEUE_SIZE { + queue.pop_front(); } - unwrap!(queue.enqueue(ReceivedData { - len: slice.len() as u8, - data, - info, - })); + queue.push_back(ReceivedData { data, info }); #[cfg(feature = "async")] asynch::ESP_NOW_RX_WAKER.wake(); @@ -866,7 +865,7 @@ mod asynch { pub(super) static ESP_NOW_TX_WAKER: AtomicWaker = AtomicWaker::new(); pub(super) static ESP_NOW_RX_WAKER: AtomicWaker = AtomicWaker::new(); - impl<'d> EspNowReceiver<'d> { + impl EspNowReceiver<'_> { /// This function takes mutable reference to self because the /// implementation of `ReceiveFuture` is not logically thread /// safe. @@ -875,7 +874,7 @@ mod asynch { } } - impl<'d> EspNowSender<'d> { + impl EspNowSender<'_> { /// Sends data asynchronously to a peer (using its MAC) using ESP-NOW. pub fn send_async<'s, 'r>( &'s mut self, @@ -891,7 +890,7 @@ mod asynch { } } - impl<'d> EspNow<'d> { + impl EspNow<'_> { /// This function takes mutable reference to self because the /// implementation of `ReceiveFuture` is not logically thread /// safe. @@ -920,7 +919,7 @@ mod asynch { sent: bool, } - impl<'s, 'r> core::future::Future for SendFuture<'s, 'r> { + impl core::future::Future for SendFuture<'_, '_> { type Output = Result<(), EspNowError>; fn poll(mut self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { @@ -953,7 +952,7 @@ mod asynch { #[must_use = "futures do nothing unless you `.await` or poll them"] pub struct ReceiveFuture<'r>(PhantomData<&'r mut EspNowReceiver<'r>>); - impl<'r> core::future::Future for ReceiveFuture<'r> { + impl core::future::Future for ReceiveFuture<'_> { type Output = ReceivedData; fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { @@ -961,7 +960,7 @@ mod asynch { if let Some(data) = critical_section::with(|cs| { let mut queue = RECEIVE_QUEUE.borrow_ref_mut(cs); - queue.dequeue() + queue.pop_front() }) { Poll::Ready(data) } else { diff --git a/esp-wifi/src/lib.rs b/esp-wifi/src/lib.rs index 55d60a9c3fa..7d415259004 100644 --- a/esp-wifi/src/lib.rs +++ b/esp-wifi/src/lib.rs @@ -93,12 +93,7 @@ extern crate alloc; // MUST be the first module mod fmt; -use common_adapter::{ - chip_specific::phy_mem_init, - deinit_radio_clock_control, - init_radio_clock_control, - RADIO_CLOCKS, -}; +use common_adapter::chip_specific::phy_mem_init; use esp_config::*; use esp_hal as hal; #[cfg(not(feature = "esp32"))] @@ -118,7 +113,6 @@ use crate::{ wifi::WifiError, }; use crate::{ - common_adapter::init_rng, tasks::init_tasks, timer::{setup_timer_isr, shutdown_timer_isr}, }; @@ -389,8 +383,8 @@ impl EspWifiTimerSource for TimeBase { pub fn init( init_for: EspWifiInitFor, timer: impl EspWifiTimerSource, - rng: hal::rng::Rng, - radio_clocks: hal::peripherals::RADIO_CLK, + _rng: hal::rng::Rng, + _radio_clocks: hal::peripherals::RADIO_CLK, ) -> Result { // A minimum clock of 80MHz is required to operate WiFi module. const MIN_CLOCK: u32 = 80; @@ -402,8 +396,6 @@ pub fn init( info!("esp-wifi configuration {:?}", crate::CONFIG); crate::common_adapter::chip_specific::enable_wifi_power_domain(); phy_mem_init(); - init_radio_clock_control(radio_clocks); - init_rng(rng); init_tasks(); setup_timer_isr(timer.timer())?; @@ -501,8 +493,7 @@ pub unsafe fn deinit_unchecked( let timer = critical_section::with(|cs| crate::timer::TIMER.borrow_ref_mut(cs).take()) .ok_or(InitializationError::TimerUnavailable)?; - let radio_clocks = - deinit_radio_clock_control().ok_or(InitializationError::RadioClockUnavailable)?; + let radio_clocks = unsafe { esp_hal::peripherals::RADIO_CLK::steal() }; Ok((timer, radio_clocks)) } @@ -548,7 +539,6 @@ pub fn wifi_set_log_verbose() { } fn init_clocks() { - unsafe { - unwrap!(RADIO_CLOCKS.as_mut()).init_clocks(); - } + let mut radio_clocks = unsafe { esp_hal::peripherals::RADIO_CLK::steal() }; + radio_clocks.init_clocks(); } diff --git a/esp-wifi/src/preempt/mod.rs b/esp-wifi/src/preempt/mod.rs index edf76b6caae..18e2ffe7e68 100644 --- a/esp-wifi/src/preempt/mod.rs +++ b/esp-wifi/src/preempt/mod.rs @@ -10,21 +10,27 @@ use esp_wifi_sys::include::malloc; use crate::{compat::malloc::free, hal::trapframe::TrapFrame, memory_fence::memory_fence}; -static mut CTX_NOW: Mutex> = Mutex::new(RefCell::new(core::ptr::null_mut())); +#[repr(transparent)] +struct ContextWrapper(*mut Context); + +unsafe impl Send for ContextWrapper {} + +static CTX_NOW: Mutex> = + Mutex::new(RefCell::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); - if !(*ctx_now).is_null() { + if !ctx_now.0.is_null() { panic!("Tried to allocate main task multiple times"); } let ptr = malloc(size_of::() as u32) as *mut Context; core::ptr::write(ptr, Context::new()); (*ptr).next = ptr; - *ctx_now = ptr; + ctx_now.0 = ptr; ptr }) } @@ -32,14 +38,14 @@ 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); - if (*ctx_now).is_null() { + if ctx_now.0.is_null() { panic!("Called `allocate_task` before allocating main task"); } let ptr = malloc(size_of::() as u32) as *mut Context; core::ptr::write(ptr, Context::new()); - (*ptr).next = (**ctx_now).next; - (**ctx_now).next = ptr; + (*ptr).next = (*ctx_now.0).next; + (*ctx_now.0).next = ptr; ptr }) } @@ -47,7 +53,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 = (**ctx_now).next; + ctx_now.0 = (*ctx_now.0).next; }); } @@ -56,7 +62,7 @@ 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); + let mut ptr = CTX_NOW.borrow_ref_mut(cs).0; let initial = ptr; loop { if (*ptr).next == task { @@ -81,7 +87,7 @@ 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; + let current_task = ctx_now_ref.0; if current_task.is_null() { return; @@ -102,14 +108,14 @@ pub(crate) fn delete_all_tasks() { task_to_delete = next_task; } - *ctx_now_ref = core::ptr::null_mut(); + ctx_now_ref.0 = core::ptr::null_mut(); memory_fence(); }); } pub(crate) fn current_task() -> *mut Context { - critical_section::with(|cs| unsafe { *CTX_NOW.borrow_ref(cs) }) + critical_section::with(|cs| CTX_NOW.borrow_ref(cs).0) } pub(crate) fn schedule_task_deletion(task: *mut Context) { diff --git a/esp-wifi/src/tasks.rs b/esp-wifi/src/tasks.rs index 18040173f79..21df825955d 100644 --- a/esp-wifi/src/tasks.rs +++ b/esp-wifi/src/tasks.rs @@ -1,6 +1,5 @@ use crate::{ - compat::{queue::SimpleQueue, timer_compat::TIMERS}, - memory_fence::memory_fence, + compat::timer_compat::TIMERS, preempt::arch_specific::task_create, timer::{get_systimer_count, yield_task}, }; @@ -18,34 +17,31 @@ pub(crate) fn init_tasks() { /// events. pub(crate) extern "C" fn timer_task(_param: *mut esp_wifi_sys::c_types::c_void) { loop { - let mut to_run = SimpleQueue::<_, 20>::new(); - let current_timestamp = get_systimer_count(); - critical_section::with(|_| unsafe { - memory_fence(); - for timer in TIMERS.iter_mut() { - if timer.active - && crate::timer::time_diff(timer.started, current_timestamp) >= timer.timeout - { - trace!("timer is due.... {:x}", timer.id()); + 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); + + if let Some(to_run) = to_run { + to_run.active = to_run.periodic; - if to_run.enqueue(timer.callback).is_err() { - break; - } + if to_run.periodic { + to_run.started = current_timestamp; + } - timer.active = timer.periodic; - }; + Some(to_run.callback) + } else { + None } - memory_fence(); }); - // run the due timer callbacks NOT in an interrupt free context - while let Some(callback) = to_run.dequeue() { + // run the due timer callback NOT in an interrupt free context + if let Some(to_run) = to_run { trace!("trigger timer...."); - callback.call(); + to_run.call(); trace!("timer callback called"); + } else { + yield_task(); } - - yield_task(); } } diff --git a/esp-wifi/src/wifi/mod.rs b/esp-wifi/src/wifi/mod.rs index 16d92c0d2bb..c307f6c61bd 100644 --- a/esp-wifi/src/wifi/mod.rs +++ b/esp-wifi/src/wifi/mod.rs @@ -3,6 +3,7 @@ pub(crate) mod os_adapter; pub(crate) mod state; +use alloc::collections::vec_deque::VecDeque; use core::{ cell::{RefCell, RefMut}, fmt::Debug, @@ -81,65 +82,62 @@ pub mod utils; #[cfg(coex)] use include::{coex_adapter_funcs_t, coex_pre_init, esp_coex_adapter_register}; -use crate::{ - binary::{ - c_types, - include::{ - self, - __BindgenBitfieldUnit, - esp_err_t, - esp_interface_t_ESP_IF_WIFI_AP, - esp_interface_t_ESP_IF_WIFI_STA, - esp_supplicant_init, - esp_wifi_connect, - esp_wifi_disconnect, - esp_wifi_get_mode, - esp_wifi_init_internal, - esp_wifi_internal_free_rx_buffer, - esp_wifi_internal_reg_rxcb, - esp_wifi_internal_tx, - esp_wifi_scan_start, - esp_wifi_set_config, - esp_wifi_set_country, - esp_wifi_set_mode, - esp_wifi_set_protocol, - esp_wifi_set_ps, - esp_wifi_set_tx_done_cb, - esp_wifi_start, - esp_wifi_stop, - g_wifi_default_wpa_crypto_funcs, - wifi_active_scan_time_t, - wifi_ap_config_t, - wifi_auth_mode_t, - wifi_cipher_type_t_WIFI_CIPHER_TYPE_CCMP, - wifi_config_t, - wifi_country_policy_t_WIFI_COUNTRY_POLICY_MANUAL, - wifi_country_t, - wifi_init_config_t, - wifi_interface_t, - wifi_interface_t_WIFI_IF_AP, - wifi_interface_t_WIFI_IF_STA, - wifi_mode_t, - wifi_mode_t_WIFI_MODE_AP, - wifi_mode_t_WIFI_MODE_APSTA, - wifi_mode_t_WIFI_MODE_NULL, - wifi_mode_t_WIFI_MODE_STA, - wifi_osi_funcs_t, - wifi_pmf_config_t, - wifi_scan_config_t, - wifi_scan_threshold_t, - wifi_scan_time_t, - wifi_scan_type_t_WIFI_SCAN_TYPE_ACTIVE, - wifi_scan_type_t_WIFI_SCAN_TYPE_PASSIVE, - wifi_sort_method_t_WIFI_CONNECT_AP_BY_SIGNAL, - wifi_sta_config_t, - wpa_crypto_funcs_t, - ESP_WIFI_OS_ADAPTER_MAGIC, - ESP_WIFI_OS_ADAPTER_VERSION, - WIFI_INIT_CONFIG_MAGIC, - }, +use crate::binary::{ + c_types, + include::{ + self, + __BindgenBitfieldUnit, + esp_err_t, + esp_interface_t_ESP_IF_WIFI_AP, + esp_interface_t_ESP_IF_WIFI_STA, + esp_supplicant_init, + esp_wifi_connect, + esp_wifi_disconnect, + esp_wifi_get_mode, + esp_wifi_init_internal, + esp_wifi_internal_free_rx_buffer, + esp_wifi_internal_reg_rxcb, + esp_wifi_internal_tx, + esp_wifi_scan_start, + esp_wifi_set_config, + esp_wifi_set_country, + esp_wifi_set_mode, + esp_wifi_set_protocol, + esp_wifi_set_ps, + esp_wifi_set_tx_done_cb, + esp_wifi_start, + esp_wifi_stop, + g_wifi_default_wpa_crypto_funcs, + wifi_active_scan_time_t, + wifi_ap_config_t, + wifi_auth_mode_t, + wifi_cipher_type_t_WIFI_CIPHER_TYPE_CCMP, + wifi_config_t, + wifi_country_policy_t_WIFI_COUNTRY_POLICY_MANUAL, + wifi_country_t, + wifi_init_config_t, + wifi_interface_t, + wifi_interface_t_WIFI_IF_AP, + wifi_interface_t_WIFI_IF_STA, + wifi_mode_t, + wifi_mode_t_WIFI_MODE_AP, + wifi_mode_t_WIFI_MODE_APSTA, + wifi_mode_t_WIFI_MODE_NULL, + wifi_mode_t_WIFI_MODE_STA, + wifi_osi_funcs_t, + wifi_pmf_config_t, + wifi_scan_config_t, + wifi_scan_threshold_t, + wifi_scan_time_t, + wifi_scan_type_t_WIFI_SCAN_TYPE_ACTIVE, + wifi_scan_type_t_WIFI_SCAN_TYPE_PASSIVE, + wifi_sort_method_t_WIFI_CONNECT_AP_BY_SIGNAL, + wifi_sta_config_t, + wpa_crypto_funcs_t, + ESP_WIFI_OS_ADAPTER_MAGIC, + ESP_WIFI_OS_ADAPTER_VERSION, + WIFI_INIT_CONFIG_MAGIC, }, - compat::queue::SimpleQueue, }; /// Supported Wi-Fi authentication methods. @@ -1031,13 +1029,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>, -> = Mutex::new(RefCell::new(SimpleQueue::new())); +pub(crate) static DATA_QUEUE_RX_AP: Mutex>> = + Mutex::new(RefCell::new(VecDeque::new())); -pub(crate) static DATA_QUEUE_RX_STA: Mutex< - RefCell>, -> = Mutex::new(RefCell::new(SimpleQueue::new())); +pub(crate) static DATA_QUEUE_RX_STA: Mutex>> = + Mutex::new(RefCell::new(VecDeque::new())); /// Common errors. #[derive(Debug, Clone, Copy)] @@ -1607,16 +1603,21 @@ unsafe extern "C" fn recv_cb_sta( // 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. - match critical_section::with(|cs| DATA_QUEUE_RX_STA.borrow_ref_mut(cs).enqueue(packet)) { - Ok(_) => { - #[cfg(feature = "embassy-net")] - embassy::STA_RECEIVE_WAKER.wake(); - include::ESP_OK as esp_err_t - } - Err(_) => { - debug!("RX QUEUE FULL"); - include::ESP_ERR_NO_MEM as esp_err_t + if critical_section::with(|cs| { + let mut queue = DATA_QUEUE_RX_STA.borrow_ref_mut(cs); + if queue.len() < RX_QUEUE_SIZE { + queue.push_back(packet); + true + } else { + false } + }) { + #[cfg(feature = "embassy-net")] + embassy::STA_RECEIVE_WAKER.wake(); + include::ESP_OK as esp_err_t + } else { + debug!("RX QUEUE FULL"); + include::ESP_ERR_NO_MEM as esp_err_t } } @@ -1632,16 +1633,21 @@ unsafe extern "C" fn recv_cb_ap( // 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. - match critical_section::with(|cs| DATA_QUEUE_RX_AP.borrow_ref_mut(cs).enqueue(packet)) { - Ok(_) => { - #[cfg(feature = "embassy-net")] - embassy::AP_RECEIVE_WAKER.wake(); - include::ESP_OK as esp_err_t - } - Err(_) => { - debug!("RX QUEUE FULL"); - include::ESP_ERR_NO_MEM as esp_err_t + if critical_section::with(|cs| { + let mut queue = DATA_QUEUE_RX_AP.borrow_ref_mut(cs); + if queue.len() < RX_QUEUE_SIZE { + queue.push_back(packet); + true + } else { + false } + }) { + #[cfg(feature = "embassy-net")] + embassy::AP_RECEIVE_WAKER.wake(); + include::ESP_OK as esp_err_t + } else { + debug!("RX QUEUE FULL"); + include::ESP_ERR_NO_MEM as esp_err_t } } @@ -1984,10 +1990,7 @@ mod sealed { fn wrap_config(config: Self::Config) -> Configuration; - fn data_queue_rx( - self, - cs: CriticalSection, - ) -> RefMut<'_, SimpleQueue>; + fn data_queue_rx(self, cs: CriticalSection) -> RefMut<'_, VecDeque>; fn can_send(self) -> bool { WIFI_TX_INFLIGHT.load(Ordering::SeqCst) < TX_QUEUE_SIZE @@ -2053,10 +2056,7 @@ mod sealed { Configuration::Client(config) } - fn data_queue_rx( - self, - cs: CriticalSection, - ) -> RefMut<'_, SimpleQueue> { + fn data_queue_rx(self, cs: CriticalSection) -> RefMut<'_, VecDeque> { DATA_QUEUE_RX_STA.borrow_ref_mut(cs) } @@ -2095,10 +2095,7 @@ mod sealed { Configuration::AccessPoint(config) } - fn data_queue_rx( - self, - cs: CriticalSection, - ) -> RefMut<'_, SimpleQueue> { + fn data_queue_rx(self, cs: CriticalSection) -> RefMut<'_, VecDeque> { DATA_QUEUE_RX_AP.borrow_ref_mut(cs) } @@ -2714,7 +2711,7 @@ impl WifiRxToken { let mut queue = self.mode.data_queue_rx(cs); unwrap!( - queue.dequeue(), + queue.pop_front(), "unreachable: transmit()/receive() ensures there is a packet to process" ) }); diff --git a/esp-wifi/src/wifi/os_adapter.rs b/esp-wifi/src/wifi/os_adapter.rs index cbed1db74cb..c059c8c1a5f 100644 --- a/esp-wifi/src/wifi/os_adapter.rs +++ b/esp-wifi/src/wifi/os_adapter.rs @@ -14,7 +14,6 @@ use enumset::EnumSet; use super::WifiEvent; use crate::{ - common_adapter::RADIO_CLOCKS, compat::{ common::{ create_queue, @@ -27,6 +26,7 @@ use crate::{ str_from_c, thread_sem_get, unlock_mutex, + ConcurrentQueue, }, malloc::calloc, }, @@ -35,7 +35,7 @@ use crate::{ timer::yield_task, }; -static mut QUEUE_HANDLE: *mut crate::binary::c_types::c_void = core::ptr::null_mut(); +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 @@ -391,7 +391,7 @@ pub unsafe extern "C" fn queue_create( (3, 8) }; - create_queue(queue_len as i32, item_size as i32) + create_queue(queue_len as i32, item_size as i32).cast() } /// ************************************************************************** @@ -408,7 +408,7 @@ pub unsafe extern "C" fn queue_create( /// /// ************************************************************************* pub unsafe extern "C" fn queue_delete(queue: *mut crate::binary::c_types::c_void) { - delete_queue(queue); + delete_queue(queue.cast()); } /// ************************************************************************** @@ -431,7 +431,7 @@ pub unsafe extern "C" fn queue_send( item: *mut crate::binary::c_types::c_void, block_time_tick: u32, ) -> i32 { - send_queued(queue, item, block_time_tick) + send_queued(queue.cast(), item, block_time_tick) } /// ************************************************************************** @@ -526,7 +526,7 @@ pub unsafe extern "C" fn queue_recv( item: *mut crate::binary::c_types::c_void, block_time_tick: u32, ) -> i32 { - receive_queued(queue, item, block_time_tick) + receive_queued(queue.cast(), item, block_time_tick) } /// ************************************************************************** @@ -543,7 +543,7 @@ pub unsafe extern "C" fn queue_recv( /// /// ************************************************************************* pub unsafe extern "C" fn queue_msg_waiting(queue: *mut crate::binary::c_types::c_void) -> u32 { - number_of_messages_in_queue(queue) + number_of_messages_in_queue(queue.cast()) } /// ************************************************************************** @@ -1040,7 +1040,10 @@ pub unsafe extern "C" fn phy_update_country_info( /// ************************************************************************* pub unsafe extern "C" fn wifi_reset_mac() { trace!("wifi_reset_mac"); - unwrap!(RADIO_CLOCKS.as_mut()).reset_mac(); + // stealing RADIO_CLK is safe since it is passed (as mutable reference or by + // value) into `init` + let mut radio_clocks = unsafe { esp_hal::peripherals::RADIO_CLK::steal() }; + radio_clocks.reset_mac(); } /// ************************************************************************** @@ -1058,7 +1061,10 @@ pub unsafe extern "C" fn wifi_reset_mac() { /// ************************************************************************* pub unsafe extern "C" fn wifi_clock_enable() { trace!("wifi_clock_enable"); - unwrap!(RADIO_CLOCKS.as_mut()).enable(RadioPeripherals::Wifi); + // stealing RADIO_CLK is safe since it is passed (as mutable reference or by + // value) into `init` + let mut radio_clocks = unsafe { esp_hal::peripherals::RADIO_CLK::steal() }; + radio_clocks.enable(RadioPeripherals::Wifi); } /// ************************************************************************** @@ -1076,7 +1082,10 @@ pub unsafe extern "C" fn wifi_clock_enable() { /// ************************************************************************* pub unsafe extern "C" fn wifi_clock_disable() { trace!("wifi_clock_disable"); - unwrap!(RADIO_CLOCKS.as_mut()).disable(RadioPeripherals::Wifi); + // stealing RADIO_CLK is safe since it is passed (as mutable reference or by + // value) into `init` + let mut radio_clocks = unsafe { esp_hal::peripherals::RADIO_CLK::steal() }; + radio_clocks.disable(RadioPeripherals::Wifi); } /// ************************************************************************** @@ -1394,18 +1403,8 @@ pub unsafe extern "C" fn nvs_erase_key( /// ************************************************************************* pub unsafe extern "C" fn get_random(buf: *mut u8, len: usize) -> crate::binary::c_types::c_int { trace!("get_random"); - if let Some(ref mut rng) = crate::common_adapter::RANDOM_GENERATOR { - let buffer = unsafe { core::slice::from_raw_parts_mut(buf, len) }; - - for chunk in buffer.chunks_mut(4) { - let bytes = rng.random().to_le_bytes(); - chunk.copy_from_slice(&bytes[..chunk.len()]); - } - - 0 - } else { - -1 - } + crate::common_adapter::esp_fill_random(buf, len as u32); + 0 } /// ************************************************************************** diff --git a/examples/src/bin/wifi_embassy_esp_now_duplex.rs b/examples/src/bin/wifi_embassy_esp_now_duplex.rs index c8bf8e4e078..270a68a7a66 100644 --- a/examples/src/bin/wifi_embassy_esp_now_duplex.rs +++ b/examples/src/bin/wifi_embassy_esp_now_duplex.rs @@ -117,7 +117,7 @@ async fn broadcaster(sender: &'static Mutex> async fn listener(manager: &'static EspNowManager<'static>, mut receiver: EspNowReceiver<'static>) { loop { let r = receiver.receive_async().await; - println!("Received {:?}", r.get_data()); + println!("Received {:?}", r.data()); if r.info.dst_address == BROADCAST_ADDRESS { if !manager.peer_exists(&r.info.src_address) { manager