Skip to content

Commit

Permalink
Esp wifi/more dynamic allocations (#2396)
Browse files Browse the repository at this point in the history
* Dynamic allocation of timers

* Replace statically allocated NPL events

* Remove NPL CALLOUTS

* Remove NPL EventQueue

* Use `Vec` instead of `heapless::spsc::Queue` internally in NPL

* Use `alloc` since we have it in NPL

* Refactor

* Fix

* More `Vec`

* Fix

* Fix nightly-warnings

* Limit RX_STA queue

* Revert unintentional change

* esp-now: Make data private

* CHANGELOG.md

* Clippy

* MSRV

* Move locking into RawQueue

* Remove unused import

* Simplify `queue_recv`

* Address TODO

* Clippy

* Review I

* Review II

* Clarify

* Review III

* Review IV

* Review V

* Fix

* `steal` RNG and RADIO_CLOCKS

* `drop_in_place`

* De-duplicate

* Use `VecDeque`

* Revert unintentional changes

* Fix

* Update esp-wifi/MIGRATING-0.10.md

Co-authored-by: Dániel Buga <[email protected]>

* assert

* Fix

* Expect `*mut ConcurrentQueue` where applicable

* Comment why stealing is fine

* Fix

---------

Co-authored-by: Dániel Buga <[email protected]>
  • Loading branch information
bjoernQ and bugadani authored Oct 31, 2024
1 parent 6fa2823 commit e5b923b
Show file tree
Hide file tree
Showing 27 changed files with 787 additions and 830 deletions.
1 change: 1 addition & 0 deletions esp-wifi/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
6 changes: 6 additions & 0 deletions esp-wifi/MIGRATING-0.10.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
225 changes: 39 additions & 186 deletions esp-wifi/src/ble/btdm.rs
Original file line number Diff line number Diff line change
@@ -1,43 +1,30 @@
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::{
btdm::ble_os_adapter_chip_specific::{osi_funcs_s, G_OSI_FUNCS},
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")]
#[cfg_attr(esp32s3, path = "os_adapter_esp32s3.rs")]
#[cfg_attr(esp32, path = "os_adapter_esp32.rs")]
pub(crate) mod ble_os_adapter_chip_specific;

static BT_RECEIVE_QUEUE: Mutex<RefCell<SimpleQueue<ReceivedPacket, 10>>> =
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<RefCell<SimpleQueue<[u8; 8], 10>>> =
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
Expand All @@ -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,
};
Expand All @@ -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
}
Expand Down Expand Up @@ -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]
Expand All @@ -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]
Expand Down Expand Up @@ -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")]
{
Expand Down Expand Up @@ -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() {
Expand All @@ -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;
}
Expand All @@ -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);
});
}
2 changes: 1 addition & 1 deletion esp-wifi/src/ble/controller/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Expand Down
Loading

0 comments on commit e5b923b

Please sign in to comment.