wpan: fully implement initial draft concept
This commit is contained in:
parent
d040871f7a
commit
890d113b85
@ -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 }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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();
|
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
@ -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 }
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user