wpan: impl. draft control scheme

This commit is contained in:
xoviat 2023-07-20 20:51:49 -05:00
parent c80c232a72
commit 899a68325c
4 changed files with 109 additions and 12 deletions

View file

@ -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; use crate::mac::runner::Runner;
#[derive(Debug)]
pub struct Error {
pub status: u32,
}
pub struct Control<'a> { pub struct Control<'a> {
#[allow(dead_code)]
runner: &'a Runner<'a>, runner: &'a Runner<'a>,
} }
@ -15,7 +19,73 @@ impl<'a> Control<'a> {
Self { runner: runner } Self { runner: runner }
} }
pub async fn init(&mut self) { pub async fn send_command<T>(&self, cmd: &T) -> Result<(), MacError>
// TODO 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<T>(&self, cmd: &T) -> Result<EventToken<'a>, 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::Output> {
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;
});
} }
} }

View file

@ -144,6 +144,8 @@ impl<'a> MacEvent<'a> {
} }
} }
unsafe impl<'a> Send for MacEvent<'a> {}
impl<'a> Drop for MacEvent<'a> { impl<'a> Drop for MacEvent<'a> {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { mac::Mac::drop_event_packet(ptr::null_mut()) }; unsafe { mac::Mac::drop_event_packet(ptr::null_mut()) };

View file

@ -10,7 +10,7 @@ pub mod responses;
pub mod runner; pub mod runner;
pub mod typedefs; pub mod typedefs;
pub use crate::mac::control::{Control, Error as ControlError}; pub use crate::mac::control::Control;
use crate::mac::driver::Driver; use crate::mac::driver::Driver;
pub use crate::mac::runner::Runner; pub use crate::mac::runner::Runner;

View file

@ -1,6 +1,11 @@
use core::cell::RefCell;
use embassy_futures::join; 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::channel::Channel;
use embassy_sync::mutex::Mutex;
use embassy_sync::signal::Signal;
use crate::mac::commands::DataRequest; use crate::mac::commands::DataRequest;
use crate::mac::event::MacEvent; use crate::mac::event::MacEvent;
@ -9,7 +14,13 @@ use crate::mac::MTU;
use crate::sub::mac::Mac; use crate::sub::mac::Mac;
pub struct Runner<'a> { 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<CriticalSectionRawMutex, RefCell<Option<Signal<NoopRawMutex, MacEvent<'a>>>>>,
pub(crate) read_mutex: Mutex<CriticalSectionRawMutex, ()>,
pub(crate) write_mutex: Mutex<CriticalSectionRawMutex, ()>,
pub(crate) rx_channel: Channel<CriticalSectionRawMutex, MacEvent<'a>, 1>, pub(crate) rx_channel: Channel<CriticalSectionRawMutex, MacEvent<'a>, 1>,
pub(crate) tx_channel: Channel<CriticalSectionRawMutex, (&'a mut [u8; MTU], usize), 5>, pub(crate) tx_channel: Channel<CriticalSectionRawMutex, (&'a mut [u8; MTU], usize), 5>,
pub(crate) tx_buf_channel: Channel<CriticalSectionRawMutex, &'a mut [u8; MTU], 5>, pub(crate) tx_buf_channel: Channel<CriticalSectionRawMutex, &'a mut [u8; MTU], 5>,
@ -19,6 +30,9 @@ impl<'a> Runner<'a> {
pub fn new(mac: Mac, tx_buf_queue: [&'a mut [u8; MTU]; 5]) -> Self { pub fn new(mac: Mac, tx_buf_queue: [&'a mut [u8; MTU]; 5]) -> Self {
let this = Self { let this = Self {
mac_subsystem: mac, 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(), rx_channel: Channel::new(),
tx_channel: Channel::new(), tx_channel: Channel::new(),
tx_buf_channel: Channel::new(), tx_buf_channel: Channel::new(),
@ -40,7 +54,16 @@ impl<'a> Runner<'a> {
MacEvent::McpsDataInd(_) => { MacEvent::McpsDataInd(_) => {
self.rx_channel.send(mac_event).await; 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 { loop {
let (buf, len) = self.tx_channel.recv().await; 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 self.mac_subsystem
.send_command( .send_command(
DataRequest { DataRequest {