diff --git a/embassy-stm32-wpan/src/mac/control.rs b/embassy-stm32-wpan/src/mac/control.rs index c45f6407..fd8c22b2 100644 --- a/embassy-stm32-wpan/src/mac/control.rs +++ b/embassy-stm32-wpan/src/mac/control.rs @@ -1,12 +1,16 @@ +use core::future::Future; +use core::task; + +use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; +use embassy_sync::mutex::MutexGuard; +use embassy_sync::signal::Signal; +use futures::FutureExt; + +use super::commands::MacCommand; +use super::typedefs::MacError; use crate::mac::runner::Runner; -#[derive(Debug)] -pub struct Error { - pub status: u32, -} - pub struct Control<'a> { - #[allow(dead_code)] runner: &'a Runner<'a>, } @@ -15,7 +19,73 @@ impl<'a> Control<'a> { Self { runner: runner } } - pub async fn init(&mut self) { - // TODO + pub async fn send_command(&self, cmd: &T) -> Result<(), MacError> + where + T: MacCommand, + { + let _wm = self.runner.write_mutex.lock().await; + + self.runner.mac_subsystem.send_command(cmd).await + } + + pub async fn send_command_and_get_response(&self, cmd: &T) -> Result, MacError> + where + T: MacCommand, + { + let _wm = self.runner.write_mutex.lock().await; + let rm = self.runner.read_mutex.lock().await; + let token = EventToken::new(self.runner, rm); + + self.runner.mac_subsystem.send_command(cmd).await?; + + Ok(token) + } +} + +pub struct EventToken<'a> { + runner: &'a Runner<'a>, + _mutex_guard: MutexGuard<'a, CriticalSectionRawMutex, ()>, +} + +impl<'a> EventToken<'a> { + pub(crate) fn new(runner: &'a Runner<'a>, mutex_guard: MutexGuard<'a, CriticalSectionRawMutex, ()>) -> Self { + // Enable event receiving + runner.rx_event_channel.lock(|s| { + *s.borrow_mut() = Some(Signal::new()); + }); + + Self { + runner: runner, + _mutex_guard: mutex_guard, + } + } +} + +impl<'a> Future for EventToken<'a> { + // TODO: output something + type Output = (); + + fn poll(self: core::pin::Pin<&mut Self>, cx: &mut task::Context<'_>) -> task::Poll { + self.get_mut().runner.rx_event_channel.lock(|s| { + let signal = s.borrow_mut(); + let signal = match &*signal { + Some(s) => s, + _ => unreachable!(), + }; + + let _ = signal.wait().poll_unpin(cx); + }); + + todo!() + } +} + +impl<'a> Drop for EventToken<'a> { + fn drop(&mut self) { + // Disable event receiving + // This will also drop the contained event, if it exists, and will free up receiving the next event + self.runner.rx_event_channel.lock(|s| { + *s.borrow_mut() = None; + }); } } diff --git a/embassy-stm32-wpan/src/mac/event.rs b/embassy-stm32-wpan/src/mac/event.rs index 8415bc11..9ca4f5a2 100644 --- a/embassy-stm32-wpan/src/mac/event.rs +++ b/embassy-stm32-wpan/src/mac/event.rs @@ -144,6 +144,8 @@ impl<'a> MacEvent<'a> { } } +unsafe impl<'a> Send for MacEvent<'a> {} + impl<'a> Drop for MacEvent<'a> { fn drop(&mut self) { unsafe { mac::Mac::drop_event_packet(ptr::null_mut()) }; diff --git a/embassy-stm32-wpan/src/mac/mod.rs b/embassy-stm32-wpan/src/mac/mod.rs index a93f7a69..c847a5cc 100644 --- a/embassy-stm32-wpan/src/mac/mod.rs +++ b/embassy-stm32-wpan/src/mac/mod.rs @@ -10,7 +10,7 @@ pub mod responses; pub mod runner; pub mod typedefs; -pub use crate::mac::control::{Control, Error as ControlError}; +pub use crate::mac::control::Control; use crate::mac::driver::Driver; pub use crate::mac::runner::Runner; diff --git a/embassy-stm32-wpan/src/mac/runner.rs b/embassy-stm32-wpan/src/mac/runner.rs index 007544c6..f964d6b3 100644 --- a/embassy-stm32-wpan/src/mac/runner.rs +++ b/embassy-stm32-wpan/src/mac/runner.rs @@ -1,6 +1,11 @@ +use core::cell::RefCell; + use embassy_futures::join; -use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; +use embassy_sync::blocking_mutex; +use embassy_sync::blocking_mutex::raw::{CriticalSectionRawMutex, NoopRawMutex}; use embassy_sync::channel::Channel; +use embassy_sync::mutex::Mutex; +use embassy_sync::signal::Signal; use crate::mac::commands::DataRequest; use crate::mac::event::MacEvent; @@ -9,7 +14,13 @@ use crate::mac::MTU; use crate::sub::mac::Mac; pub struct Runner<'a> { - mac_subsystem: Mac, + pub(crate) mac_subsystem: Mac, + + // rx event backpressure is already provided through the MacEvent drop mechanism + pub(crate) rx_event_channel: + blocking_mutex::Mutex>>>>, + pub(crate) read_mutex: Mutex, + pub(crate) write_mutex: Mutex, pub(crate) rx_channel: Channel, 1>, pub(crate) tx_channel: Channel, pub(crate) tx_buf_channel: Channel, @@ -19,6 +30,9 @@ impl<'a> Runner<'a> { pub fn new(mac: Mac, tx_buf_queue: [&'a mut [u8; MTU]; 5]) -> Self { let this = Self { mac_subsystem: mac, + rx_event_channel: blocking_mutex::Mutex::new(RefCell::new(None)), + read_mutex: Mutex::new(()), + write_mutex: Mutex::new(()), rx_channel: Channel::new(), tx_channel: Channel::new(), tx_buf_channel: Channel::new(), @@ -40,7 +54,16 @@ impl<'a> Runner<'a> { MacEvent::McpsDataInd(_) => { self.rx_channel.send(mac_event).await; } - _ => {} + _ => { + self.rx_event_channel.lock(|s| { + match &*s.borrow() { + Some(signal) => { + signal.signal(mac_event); + } + None => {} + }; + }); + } } } } @@ -50,7 +73,9 @@ impl<'a> Runner<'a> { loop { let (buf, len) = self.tx_channel.recv().await; + let _wm = self.write_mutex.lock().await; + // The mutex should be dropped on the next loop iteration self.mac_subsystem .send_command( DataRequest {