diff --git a/esp-wifi/src/ble/btdm.rs b/esp-wifi/src/ble/btdm.rs index 7e538bb23c4..3aca6832efe 100644 --- a/esp-wifi/src/ble/btdm.rs +++ b/esp-wifi/src/ble/btdm.rs @@ -93,6 +93,9 @@ extern "C" fn notify_host_recv(data: *mut u8, len: u16) -> i32 { let mut queue = BT_RECEIVE_QUEUE.borrow_ref_mut(cs); queue.enqueue(packet).unwrap(); }); + + #[cfg(feature = "async")] + crate::ble::controller::asynch::hci_read_data_available(); } 0 @@ -522,6 +525,14 @@ 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 fn read_hci(data: &mut [u8]) -> usize { unsafe { if BLE_HCI_READ_DATA_LEN == 0 { @@ -529,11 +540,9 @@ pub fn read_hci(data: &mut [u8]) -> usize { let mut queue = BT_RECEIVE_QUEUE.borrow_ref_mut(cs); if let Some(packet) = queue.dequeue() { - for i in 0..(packet.len as usize + 0/*1*/) { - BLE_HCI_READ_DATA[i] = packet.data[i]; - } - - BLE_HCI_READ_DATA_LEN = packet.len as usize + 0 /*1*/; + 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; } }); diff --git a/esp-wifi/src/ble/controller/mod.rs b/esp-wifi/src/ble/controller/mod.rs index b2361f383c4..8fa0398979a 100644 --- a/esp-wifi/src/ble/controller/mod.rs +++ b/esp-wifi/src/ble/controller/mod.rs @@ -67,3 +67,95 @@ impl Write for BleConnector<'_> { Ok(()) } } + +#[cfg(feature = "async")] +pub mod asynch { + use core::task::Poll; + + use crate::ble::ble::have_hci_read_data; + + use super::BleConnectorError; + use super::{read_hci, send_hci}; + use embassy_sync::waitqueue::AtomicWaker; + use embedded_io::asynch; + use embedded_io::Io; + use esp_hal_common::peripheral::{Peripheral, PeripheralRef}; + + static HCI_WAKER: AtomicWaker = AtomicWaker::new(); + + pub(crate) fn hci_read_data_available() { + HCI_WAKER.wake(); + } + + pub struct BleConnector<'d> { + _device: PeripheralRef<'d, esp_hal_common::radio::Bluetooth>, + } + + impl<'d> BleConnector<'d> { + pub fn new( + device: impl Peripheral

+ 'd, + ) -> BleConnector<'d> { + Self { + _device: device.into_ref(), + } + } + } + + impl Io for BleConnector<'_> { + type Error = BleConnectorError; + } + + impl asynch::Read for BleConnector<'_> { + async fn read(&mut self, buf: &mut [u8]) -> Result { + if !have_hci_read_data() { + HciReadyEventFuture.await; + } + + let mut total = 0; + for b in buf { + let mut buffer = [0u8]; + let len = read_hci(&mut buffer); + + if len == 1 { + *b = buffer[0]; + total += 1; + } else { + return Ok(total); + } + } + + Ok(total) + } + } + + impl asynch::Write for BleConnector<'_> { + async fn write(&mut self, buf: &[u8]) -> Result { + send_hci(buf); + Ok(buf.len()) + } + + async fn flush(&mut self) -> Result<(), BleConnectorError> { + // nothing to do + Ok(()) + } + } + + pub(crate) struct HciReadyEventFuture; + + impl core::future::Future for HciReadyEventFuture { + type Output = (); + + fn poll( + self: core::pin::Pin<&mut Self>, + cx: &mut core::task::Context<'_>, + ) -> Poll { + HCI_WAKER.register(cx.waker()); + + if have_hci_read_data() { + Poll::Ready(()) + } else { + Poll::Pending + } + } + } +} diff --git a/esp-wifi/src/ble/npl.rs b/esp-wifi/src/ble/npl.rs index 2510db189b6..dbce8d2cbb3 100644 --- a/esp-wifi/src/ble/npl.rs +++ b/esp-wifi/src/ble/npl.rs @@ -1232,6 +1232,9 @@ unsafe extern "C" fn ble_hs_hci_rx_evt(cmd: *const u8, arg: *const c_void) { }) .unwrap(); }); + + #[cfg(feature = "async")] + crate::ble::controller::asynch::hci_read_data_available(); } unsafe extern "C" fn ble_hs_rx_data(om: *const OsMbuf, arg: *const c_void) { @@ -1255,12 +1258,23 @@ unsafe extern "C" fn ble_hs_rx_data(om: *const OsMbuf, arg: *const c_void) { }) .unwrap(); }); + + #[cfg(feature = "async")] + crate::ble::controller::asynch::hci_read_data_available(); } 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 fn read_hci(data: &mut [u8]) -> usize { unsafe { if BLE_HCI_READ_DATA_LEN == 0 { @@ -1274,7 +1288,6 @@ pub fn read_hci(data: &mut [u8]) -> usize { BLE_HCI_READ_DATA_INDEX = 0; } }); - return 0; } if BLE_HCI_READ_DATA_LEN > 0 { diff --git a/esp-wifi/src/ble/os_adapter_esp32c3.rs b/esp-wifi/src/ble/os_adapter_esp32c3.rs index 79ff3c67002..767009ccc24 100644 --- a/esp-wifi/src/ble/os_adapter_esp32c3.rs +++ b/esp-wifi/src/ble/os_adapter_esp32c3.rs @@ -160,7 +160,7 @@ pub(crate) fn create_ble_config() -> esp_bt_controller_config_t { hci_tl_funcs: core::ptr::null_mut(), txant_dft: 0, rxant_dft: 0, - txpwr_dft: 7, + txpwr_dft: 9, cfg_mask: 1, scan_duplicate_mode: 0, scan_duplicate_type: 0, @@ -179,9 +179,7 @@ pub(crate) fn create_ble_config() -> esp_bt_controller_config_t { pub(crate) unsafe extern "C" fn interrupt_on(intr_num: i32) { trace!("interrupt_on {}", intr_num); - (*esp32c3::INTERRUPT_CORE0::PTR) - .cpu_int_enable - .modify(|r, w| w.bits(r.bits() | 1 << intr_num)); + // NO-OP } pub(crate) unsafe extern "C" fn interrupt_off(_intr_num: i32) { @@ -218,13 +216,10 @@ pub(crate) unsafe extern "C" fn interrupt_set( interrupt_prio ); - ((0x600c2000 + 0x114 + interrupt_no * 4) as *mut u32).write_volatile(interrupt_prio as u32); - /* Set the interrupt type (Edge or Level). */ - // ---- - /* Map the CPU interrupt ID to the peripheral. */ - ((0x600c2000 + intr_source * 4) as *mut u32).write_volatile(interrupt_no as u32); + + // NO-OP } pub(crate) unsafe extern "C" fn interrupt_clear(_interrupt_source: i32, _interrupt_no: i32) { diff --git a/esp-wifi/src/lib.rs b/esp-wifi/src/lib.rs index b29b47cbbff..44b150d50f2 100644 --- a/esp-wifi/src/lib.rs +++ b/esp-wifi/src/lib.rs @@ -1,6 +1,8 @@ #![no_std] #![cfg_attr(target_arch = "xtensa", feature(asm_experimental_arch))] #![feature(c_variadic)] +#![cfg_attr(feature = "async", feature(async_fn_in_trait))] +#![cfg_attr(feature = "async", allow(incomplete_features))] use core::cell::RefCell; use core::mem::MaybeUninit;