wpan: fully implement initial draft concept

This commit is contained in:
xoviat 2023-07-18 18:28:12 -05:00
parent d040871f7a
commit 890d113b85
6 changed files with 80 additions and 50 deletions

View file

@ -6,11 +6,11 @@ pub struct Error {
} }
pub struct Control<'a> { pub struct Control<'a> {
runner: &'a Runner, runner: &'a Runner<'a>,
} }
impl<'a> Control<'a> { impl<'a> Control<'a> {
pub(crate) fn new(runner: &'a Runner) -> Self { pub(crate) fn new(runner: &'a Runner<'a>) -> Self {
Self { runner: runner } Self { runner: runner }
} }

View file

@ -4,16 +4,20 @@
use core::task::Context; use core::task::Context;
use embassy_net_driver::{Capabilities, LinkState, Medium}; use embassy_net_driver::{Capabilities, LinkState, Medium};
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_sync::channel::Channel;
use super::event::MacEvent;
use crate::mac::event::Event;
use crate::mac::runner::Runner; use crate::mac::runner::Runner;
use crate::mac::MTU; use crate::mac::MTU;
pub struct Driver<'d> { pub struct Driver<'d> {
runner: &'d Runner, runner: &'d Runner<'d>,
} }
impl<'d> Driver<'d> { impl<'d> Driver<'d> {
pub(crate) fn new(runner: &'d Runner) -> Self { pub(crate) fn new(runner: &'d Runner<'d>) -> Self {
Self { runner: runner } Self { runner: runner }
} }
} }
@ -21,34 +25,33 @@ impl<'d> Driver<'d> {
impl<'d> embassy_net_driver::Driver for Driver<'d> { impl<'d> embassy_net_driver::Driver for Driver<'d> {
// type RxToken<'a> = RxToken<'a, 'd> where Self: 'a; // type RxToken<'a> = RxToken<'a, 'd> where Self: 'a;
// type TxToken<'a> = TxToken<'a, 'd> where Self: 'a; // type TxToken<'a> = TxToken<'a, 'd> where Self: 'a;
type RxToken<'a> = RxToken where Self: 'a; type RxToken<'a> = RxToken<'d> where Self: 'a;
type TxToken<'a> = TxToken where Self: 'a; type TxToken<'a> = TxToken<'d> where Self: 'a;
fn receive(&mut self, cx: &mut Context) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> { fn receive(&mut self, cx: &mut Context) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
self.runner.rx_waker.register(cx.waker()); if self.runner.rx_channel.poll_ready_to_receive(cx) && self.runner.tx_channel.poll_ready_to_receive(cx) {
Some((
// WAKER.register(cx.waker()); RxToken {
// if self.rx.available().is_some() && self.tx.available().is_some() { rx: &self.runner.rx_channel,
// Some((RxToken { rx: &mut self.rx }, TxToken { tx: &mut self.tx })) },
// } else { TxToken {
// None tx: &self.runner.tx_channel,
// } },
))
} else {
None None
} }
}
fn transmit(&mut self, cx: &mut Context) -> Option<Self::TxToken<'_>> { fn transmit(&mut self, cx: &mut Context) -> Option<Self::TxToken<'_>> {
self.runner.tx_waker.register(cx.waker()); if self.runner.tx_channel.poll_ready_to_receive(cx) {
Some(TxToken {
// WAKER.register(cx.waker()); tx: &self.runner.tx_channel,
// / if self.tx.available().is_some() { })
// / Some(TxToken { tx: &mut self.tx }) } else {
// / } else {
// / None
// / }
None None
} }
}
fn capabilities(&self) -> Capabilities { fn capabilities(&self) -> Capabilities {
let mut caps = Capabilities::default(); let mut caps = Capabilities::default();
@ -76,30 +79,38 @@ impl<'d> embassy_net_driver::Driver for Driver<'d> {
} }
} }
pub struct RxToken { pub struct RxToken<'d> {
// rx: &'a mut RDesRing<'d>, rx: &'d Channel<CriticalSectionRawMutex, Event, 1>,
} }
impl embassy_net_driver::RxToken for RxToken { impl<'d> embassy_net_driver::RxToken for RxToken<'d> {
fn consume<R, F>(self, f: F) -> R fn consume<R, F>(self, f: F) -> R
where where
F: FnOnce(&mut [u8]) -> R, F: FnOnce(&mut [u8]) -> R,
{ {
// NOTE(unwrap): we checked the queue wasn't full when creating the token. // Only valid data events should be put into the queue
// let pkt = unwrap!(self.rx.available());
let event = self.rx.try_recv().unwrap();
let mac_event = event.mac_event().unwrap();
let data_event = match mac_event {
MacEvent::McpsDataInd(data_event) => data_event,
_ => unreachable!(),
};
let pkt = &mut []; let pkt = &mut [];
let r = f(&mut pkt[0..]); let r = f(&mut pkt[0..]);
// self.rx.pop_packet();
// let r = f(&mut data_event.payload());
r r
} }
} }
pub struct TxToken { pub struct TxToken<'d> {
tx: &'d Channel<CriticalSectionRawMutex, &'d [u8], 1>,
// tx: &'a mut TDesRing<'d>, // tx: &'a mut TDesRing<'d>,
} }
impl embassy_net_driver::TxToken for TxToken { impl<'d> embassy_net_driver::TxToken for TxToken<'d> {
fn consume<R, F>(self, len: usize, f: F) -> R fn consume<R, F>(self, len: usize, f: F) -> R
where where
F: FnOnce(&mut [u8]) -> R, F: FnOnce(&mut [u8]) -> R,

View file

@ -18,7 +18,7 @@ pub use crate::mac::runner::Runner;
const MTU: usize = 127; const MTU: usize = 127;
pub async fn new<'a>(runner: &'a Runner) -> (Control<'a>, Driver<'a>) { pub async fn new<'a>(runner: &'a Runner<'a>) -> (Control<'a>, Driver<'a>) {
(Control::new(runner), Driver::new(runner)) (Control::new(runner), Driver::new(runner))
} }

View file

@ -1,4 +1,6 @@
use embassy_futures::select::{select3, Either3}; use embassy_futures::select::{select3, Either3};
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_sync::channel::Channel;
use embassy_sync::waitqueue::AtomicWaker; use embassy_sync::waitqueue::AtomicWaker;
use crate::mac::event::{Event, MacEvent}; use crate::mac::event::{Event, MacEvent};
@ -44,22 +46,18 @@ impl TxRing {
} }
} }
pub struct Runner { pub struct Runner<'a> {
mac_subsystem: Mac, mac_subsystem: Mac,
pub(crate) rx_ring: Option<Event>, pub(crate) rx_channel: Channel<CriticalSectionRawMutex, Event, 1>,
pub(crate) tx_ring: TxRing, pub(crate) tx_channel: Channel<CriticalSectionRawMutex, &'a [u8], 1>,
pub(crate) rx_waker: AtomicWaker,
pub(crate) tx_waker: AtomicWaker,
} }
impl Runner { impl<'a> Runner<'a> {
pub fn new(mac: Mac) -> Self { pub fn new(mac: Mac) -> Self {
Self { Self {
mac_subsystem: mac, mac_subsystem: mac,
rx_ring: None, rx_channel: Channel::new(),
tx_ring: TxRing::new(), tx_channel: Channel::new(),
rx_waker: AtomicWaker::new(),
tx_waker: AtomicWaker::new(),
} }
} }
@ -73,8 +71,7 @@ impl Runner {
if let Ok(evt) = event.mac_event() { if let Ok(evt) = event.mac_event() {
match evt { match evt {
MacEvent::McpsDataInd(data_ind) => { MacEvent::McpsDataInd(data_ind) => {
// TODO: store mac_event in rx_ring self.rx_channel.try_send(event);
self.rx_waker.wake();
} }
_ => {} _ => {}
} }

View file

@ -335,6 +335,12 @@ impl<T, const N: usize> ChannelState<T, N> {
} }
} }
fn poll_ready_to_receive(&mut self, cx: &mut Context<'_>) -> bool {
self.receiver_waker.register(cx.waker());
!self.queue.is_empty()
}
fn try_send(&mut self, message: T) -> Result<(), TrySendError<T>> { fn try_send(&mut self, message: T) -> Result<(), TrySendError<T>> {
self.try_send_with_context(message, None) self.try_send_with_context(message, None)
} }
@ -353,6 +359,12 @@ impl<T, const N: usize> ChannelState<T, N> {
} }
} }
} }
fn poll_ready_to_send(&mut self, cx: &mut Context<'_>) -> bool {
self.senders_waker.register(cx.waker());
!self.queue.is_full()
}
} }
/// A bounded channel for communicating between asynchronous tasks /// A bounded channel for communicating between asynchronous tasks
@ -401,6 +413,16 @@ where
self.lock(|c| c.try_send_with_context(m, cx)) self.lock(|c| c.try_send_with_context(m, cx))
} }
/// Allows a poll_fn to poll until the channel is ready to receive
pub fn poll_ready_to_receive(&self, cx: &mut Context<'_>) -> bool {
self.lock(|c| c.poll_ready_to_receive(cx))
}
/// Allows a poll_fn to poll until the channel is ready to send
pub fn poll_ready_to_send(&self, cx: &mut Context<'_>) -> bool {
self.lock(|c| c.poll_ready_to_send(cx))
}
/// Get a sender for this channel. /// Get a sender for this channel.
pub fn sender(&self) -> Sender<'_, M, T, N> { pub fn sender(&self) -> Sender<'_, M, T, N> {
Sender { channel: self } Sender { channel: self }

View file

@ -25,7 +25,7 @@ async fn run_mm_queue(memory_manager: mm::MemoryManager) {
} }
#[embassy_executor::task] #[embassy_executor::task]
async fn run_mac(runner: &'static Runner) { async fn run_mac(runner: &'static Runner<'static>) {
runner.run().await; runner.run().await;
} }