docs: document public apis of embassy-net-driver-channel
This commit is contained in:
parent
97e919ea64
commit
fc6e70caa5
@ -1,5 +1,6 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
#![doc = include_str!("../README.md")]
|
#![doc = include_str!("../README.md")]
|
||||||
|
#![warn(missing_docs)]
|
||||||
|
|
||||||
// must go first!
|
// must go first!
|
||||||
mod fmt;
|
mod fmt;
|
||||||
@ -15,6 +16,9 @@ use embassy_sync::blocking_mutex::Mutex;
|
|||||||
use embassy_sync::waitqueue::WakerRegistration;
|
use embassy_sync::waitqueue::WakerRegistration;
|
||||||
use embassy_sync::zerocopy_channel;
|
use embassy_sync::zerocopy_channel;
|
||||||
|
|
||||||
|
/// Channel state.
|
||||||
|
///
|
||||||
|
/// Holds a buffer of packets with size MTU, for both TX and RX.
|
||||||
pub struct State<const MTU: usize, const N_RX: usize, const N_TX: usize> {
|
pub struct State<const MTU: usize, const N_RX: usize, const N_TX: usize> {
|
||||||
rx: [PacketBuf<MTU>; N_RX],
|
rx: [PacketBuf<MTU>; N_RX],
|
||||||
tx: [PacketBuf<MTU>; N_TX],
|
tx: [PacketBuf<MTU>; N_TX],
|
||||||
@ -24,6 +28,7 @@ pub struct State<const MTU: usize, const N_RX: usize, const N_TX: usize> {
|
|||||||
impl<const MTU: usize, const N_RX: usize, const N_TX: usize> State<MTU, N_RX, N_TX> {
|
impl<const MTU: usize, const N_RX: usize, const N_TX: usize> State<MTU, N_RX, N_TX> {
|
||||||
const NEW_PACKET: PacketBuf<MTU> = PacketBuf::new();
|
const NEW_PACKET: PacketBuf<MTU> = PacketBuf::new();
|
||||||
|
|
||||||
|
/// Create a new channel state.
|
||||||
pub const fn new() -> Self {
|
pub const fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
rx: [Self::NEW_PACKET; N_RX],
|
rx: [Self::NEW_PACKET; N_RX],
|
||||||
@ -39,33 +44,45 @@ struct StateInner<'d, const MTU: usize> {
|
|||||||
shared: Mutex<NoopRawMutex, RefCell<Shared>>,
|
shared: Mutex<NoopRawMutex, RefCell<Shared>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// State of the LinkState
|
|
||||||
struct Shared {
|
struct Shared {
|
||||||
link_state: LinkState,
|
link_state: LinkState,
|
||||||
waker: WakerRegistration,
|
waker: WakerRegistration,
|
||||||
hardware_address: driver::HardwareAddress,
|
hardware_address: driver::HardwareAddress,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Channel runner.
|
||||||
|
///
|
||||||
|
/// Holds the shared state and the lower end of channels for inbound and outbound packets.
|
||||||
pub struct Runner<'d, const MTU: usize> {
|
pub struct Runner<'d, const MTU: usize> {
|
||||||
tx_chan: zerocopy_channel::Receiver<'d, NoopRawMutex, PacketBuf<MTU>>,
|
tx_chan: zerocopy_channel::Receiver<'d, NoopRawMutex, PacketBuf<MTU>>,
|
||||||
rx_chan: zerocopy_channel::Sender<'d, NoopRawMutex, PacketBuf<MTU>>,
|
rx_chan: zerocopy_channel::Sender<'d, NoopRawMutex, PacketBuf<MTU>>,
|
||||||
shared: &'d Mutex<NoopRawMutex, RefCell<Shared>>,
|
shared: &'d Mutex<NoopRawMutex, RefCell<Shared>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// State runner.
|
||||||
|
///
|
||||||
|
/// Holds the shared state of the channel such as link state.
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct StateRunner<'d> {
|
pub struct StateRunner<'d> {
|
||||||
shared: &'d Mutex<NoopRawMutex, RefCell<Shared>>,
|
shared: &'d Mutex<NoopRawMutex, RefCell<Shared>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// RX runner.
|
||||||
|
///
|
||||||
|
/// Holds the lower end of the channel for passing inbound packets up the stack.
|
||||||
pub struct RxRunner<'d, const MTU: usize> {
|
pub struct RxRunner<'d, const MTU: usize> {
|
||||||
rx_chan: zerocopy_channel::Sender<'d, NoopRawMutex, PacketBuf<MTU>>,
|
rx_chan: zerocopy_channel::Sender<'d, NoopRawMutex, PacketBuf<MTU>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// TX runner.
|
||||||
|
///
|
||||||
|
/// Holds the lower end of the channel for passing outbound packets down the stack.
|
||||||
pub struct TxRunner<'d, const MTU: usize> {
|
pub struct TxRunner<'d, const MTU: usize> {
|
||||||
tx_chan: zerocopy_channel::Receiver<'d, NoopRawMutex, PacketBuf<MTU>>,
|
tx_chan: zerocopy_channel::Receiver<'d, NoopRawMutex, PacketBuf<MTU>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, const MTU: usize> Runner<'d, MTU> {
|
impl<'d, const MTU: usize> Runner<'d, MTU> {
|
||||||
|
/// Split the runner into separate runners for controlling state, rx and tx.
|
||||||
pub fn split(self) -> (StateRunner<'d>, RxRunner<'d, MTU>, TxRunner<'d, MTU>) {
|
pub fn split(self) -> (StateRunner<'d>, RxRunner<'d, MTU>, TxRunner<'d, MTU>) {
|
||||||
(
|
(
|
||||||
StateRunner { shared: self.shared },
|
StateRunner { shared: self.shared },
|
||||||
@ -74,6 +91,7 @@ impl<'d, const MTU: usize> Runner<'d, MTU> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Split the runner into separate runners for controlling state, rx and tx borrowing the underlying state.
|
||||||
pub fn borrow_split(&mut self) -> (StateRunner<'_>, RxRunner<'_, MTU>, TxRunner<'_, MTU>) {
|
pub fn borrow_split(&mut self) -> (StateRunner<'_>, RxRunner<'_, MTU>, TxRunner<'_, MTU>) {
|
||||||
(
|
(
|
||||||
StateRunner { shared: self.shared },
|
StateRunner { shared: self.shared },
|
||||||
@ -86,10 +104,12 @@ impl<'d, const MTU: usize> Runner<'d, MTU> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a state runner sharing the state channel.
|
||||||
pub fn state_runner(&self) -> StateRunner<'d> {
|
pub fn state_runner(&self) -> StateRunner<'d> {
|
||||||
StateRunner { shared: self.shared }
|
StateRunner { shared: self.shared }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the link state.
|
||||||
pub fn set_link_state(&mut self, state: LinkState) {
|
pub fn set_link_state(&mut self, state: LinkState) {
|
||||||
self.shared.lock(|s| {
|
self.shared.lock(|s| {
|
||||||
let s = &mut *s.borrow_mut();
|
let s = &mut *s.borrow_mut();
|
||||||
@ -98,6 +118,7 @@ impl<'d, const MTU: usize> Runner<'d, MTU> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the hardware address.
|
||||||
pub fn set_hardware_address(&mut self, address: driver::HardwareAddress) {
|
pub fn set_hardware_address(&mut self, address: driver::HardwareAddress) {
|
||||||
self.shared.lock(|s| {
|
self.shared.lock(|s| {
|
||||||
let s = &mut *s.borrow_mut();
|
let s = &mut *s.borrow_mut();
|
||||||
@ -106,16 +127,19 @@ impl<'d, const MTU: usize> Runner<'d, MTU> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Wait until there is space for more inbound packets and return a slice they can be copied into.
|
||||||
pub async fn rx_buf(&mut self) -> &mut [u8] {
|
pub async fn rx_buf(&mut self) -> &mut [u8] {
|
||||||
let p = self.rx_chan.send().await;
|
let p = self.rx_chan.send().await;
|
||||||
&mut p.buf
|
&mut p.buf
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check if there is space for more inbound packets right now.
|
||||||
pub fn try_rx_buf(&mut self) -> Option<&mut [u8]> {
|
pub fn try_rx_buf(&mut self) -> Option<&mut [u8]> {
|
||||||
let p = self.rx_chan.try_send()?;
|
let p = self.rx_chan.try_send()?;
|
||||||
Some(&mut p.buf)
|
Some(&mut p.buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Polling the inbound channel if there is space for packets.
|
||||||
pub fn poll_rx_buf(&mut self, cx: &mut Context) -> Poll<&mut [u8]> {
|
pub fn poll_rx_buf(&mut self, cx: &mut Context) -> Poll<&mut [u8]> {
|
||||||
match self.rx_chan.poll_send(cx) {
|
match self.rx_chan.poll_send(cx) {
|
||||||
Poll::Ready(p) => Poll::Ready(&mut p.buf),
|
Poll::Ready(p) => Poll::Ready(&mut p.buf),
|
||||||
@ -123,22 +147,26 @@ impl<'d, const MTU: usize> Runner<'d, MTU> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Mark packet of len bytes as pushed to the inbound channel.
|
||||||
pub fn rx_done(&mut self, len: usize) {
|
pub fn rx_done(&mut self, len: usize) {
|
||||||
let p = self.rx_chan.try_send().unwrap();
|
let p = self.rx_chan.try_send().unwrap();
|
||||||
p.len = len;
|
p.len = len;
|
||||||
self.rx_chan.send_done();
|
self.rx_chan.send_done();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Wait until there is space for more outbound packets and return a slice they can be copied into.
|
||||||
pub async fn tx_buf(&mut self) -> &mut [u8] {
|
pub async fn tx_buf(&mut self) -> &mut [u8] {
|
||||||
let p = self.tx_chan.receive().await;
|
let p = self.tx_chan.receive().await;
|
||||||
&mut p.buf[..p.len]
|
&mut p.buf[..p.len]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check if there is space for more outbound packets right now.
|
||||||
pub fn try_tx_buf(&mut self) -> Option<&mut [u8]> {
|
pub fn try_tx_buf(&mut self) -> Option<&mut [u8]> {
|
||||||
let p = self.tx_chan.try_receive()?;
|
let p = self.tx_chan.try_receive()?;
|
||||||
Some(&mut p.buf[..p.len])
|
Some(&mut p.buf[..p.len])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Polling the outbound channel if there is space for packets.
|
||||||
pub fn poll_tx_buf(&mut self, cx: &mut Context) -> Poll<&mut [u8]> {
|
pub fn poll_tx_buf(&mut self, cx: &mut Context) -> Poll<&mut [u8]> {
|
||||||
match self.tx_chan.poll_receive(cx) {
|
match self.tx_chan.poll_receive(cx) {
|
||||||
Poll::Ready(p) => Poll::Ready(&mut p.buf[..p.len]),
|
Poll::Ready(p) => Poll::Ready(&mut p.buf[..p.len]),
|
||||||
@ -146,12 +174,14 @@ impl<'d, const MTU: usize> Runner<'d, MTU> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Mark outbound packet as copied.
|
||||||
pub fn tx_done(&mut self) {
|
pub fn tx_done(&mut self) {
|
||||||
self.tx_chan.receive_done();
|
self.tx_chan.receive_done();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d> StateRunner<'d> {
|
impl<'d> StateRunner<'d> {
|
||||||
|
/// Set link state.
|
||||||
pub fn set_link_state(&self, state: LinkState) {
|
pub fn set_link_state(&self, state: LinkState) {
|
||||||
self.shared.lock(|s| {
|
self.shared.lock(|s| {
|
||||||
let s = &mut *s.borrow_mut();
|
let s = &mut *s.borrow_mut();
|
||||||
@ -160,6 +190,7 @@ impl<'d> StateRunner<'d> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the hardware address.
|
||||||
pub fn set_hardware_address(&self, address: driver::HardwareAddress) {
|
pub fn set_hardware_address(&self, address: driver::HardwareAddress) {
|
||||||
self.shared.lock(|s| {
|
self.shared.lock(|s| {
|
||||||
let s = &mut *s.borrow_mut();
|
let s = &mut *s.borrow_mut();
|
||||||
@ -170,16 +201,19 @@ impl<'d> StateRunner<'d> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, const MTU: usize> RxRunner<'d, MTU> {
|
impl<'d, const MTU: usize> RxRunner<'d, MTU> {
|
||||||
|
/// Wait until there is space for more inbound packets and return a slice they can be copied into.
|
||||||
pub async fn rx_buf(&mut self) -> &mut [u8] {
|
pub async fn rx_buf(&mut self) -> &mut [u8] {
|
||||||
let p = self.rx_chan.send().await;
|
let p = self.rx_chan.send().await;
|
||||||
&mut p.buf
|
&mut p.buf
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check if there is space for more inbound packets right now.
|
||||||
pub fn try_rx_buf(&mut self) -> Option<&mut [u8]> {
|
pub fn try_rx_buf(&mut self) -> Option<&mut [u8]> {
|
||||||
let p = self.rx_chan.try_send()?;
|
let p = self.rx_chan.try_send()?;
|
||||||
Some(&mut p.buf)
|
Some(&mut p.buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Polling the inbound channel if there is space for packets.
|
||||||
pub fn poll_rx_buf(&mut self, cx: &mut Context) -> Poll<&mut [u8]> {
|
pub fn poll_rx_buf(&mut self, cx: &mut Context) -> Poll<&mut [u8]> {
|
||||||
match self.rx_chan.poll_send(cx) {
|
match self.rx_chan.poll_send(cx) {
|
||||||
Poll::Ready(p) => Poll::Ready(&mut p.buf),
|
Poll::Ready(p) => Poll::Ready(&mut p.buf),
|
||||||
@ -187,6 +221,7 @@ impl<'d, const MTU: usize> RxRunner<'d, MTU> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Mark packet of len bytes as pushed to the inbound channel.
|
||||||
pub fn rx_done(&mut self, len: usize) {
|
pub fn rx_done(&mut self, len: usize) {
|
||||||
let p = self.rx_chan.try_send().unwrap();
|
let p = self.rx_chan.try_send().unwrap();
|
||||||
p.len = len;
|
p.len = len;
|
||||||
@ -195,16 +230,19 @@ impl<'d, const MTU: usize> RxRunner<'d, MTU> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, const MTU: usize> TxRunner<'d, MTU> {
|
impl<'d, const MTU: usize> TxRunner<'d, MTU> {
|
||||||
|
/// Wait until there is space for more outbound packets and return a slice they can be copied into.
|
||||||
pub async fn tx_buf(&mut self) -> &mut [u8] {
|
pub async fn tx_buf(&mut self) -> &mut [u8] {
|
||||||
let p = self.tx_chan.receive().await;
|
let p = self.tx_chan.receive().await;
|
||||||
&mut p.buf[..p.len]
|
&mut p.buf[..p.len]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check if there is space for more outbound packets right now.
|
||||||
pub fn try_tx_buf(&mut self) -> Option<&mut [u8]> {
|
pub fn try_tx_buf(&mut self) -> Option<&mut [u8]> {
|
||||||
let p = self.tx_chan.try_receive()?;
|
let p = self.tx_chan.try_receive()?;
|
||||||
Some(&mut p.buf[..p.len])
|
Some(&mut p.buf[..p.len])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Polling the outbound channel if there is space for packets.
|
||||||
pub fn poll_tx_buf(&mut self, cx: &mut Context) -> Poll<&mut [u8]> {
|
pub fn poll_tx_buf(&mut self, cx: &mut Context) -> Poll<&mut [u8]> {
|
||||||
match self.tx_chan.poll_receive(cx) {
|
match self.tx_chan.poll_receive(cx) {
|
||||||
Poll::Ready(p) => Poll::Ready(&mut p.buf[..p.len]),
|
Poll::Ready(p) => Poll::Ready(&mut p.buf[..p.len]),
|
||||||
@ -212,11 +250,18 @@ impl<'d, const MTU: usize> TxRunner<'d, MTU> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Mark outbound packet as copied.
|
||||||
pub fn tx_done(&mut self) {
|
pub fn tx_done(&mut self) {
|
||||||
self.tx_chan.receive_done();
|
self.tx_chan.receive_done();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a channel.
|
||||||
|
///
|
||||||
|
/// Returns a pair of handles for interfacing with the peripheral and the networking stack.
|
||||||
|
///
|
||||||
|
/// The runner is interfacing with the peripheral at the lower part of the stack.
|
||||||
|
/// The device is interfacing with the networking stack on the layer above.
|
||||||
pub fn new<'d, const MTU: usize, const N_RX: usize, const N_TX: usize>(
|
pub fn new<'d, const MTU: usize, const N_RX: usize, const N_TX: usize>(
|
||||||
state: &'d mut State<MTU, N_RX, N_TX>,
|
state: &'d mut State<MTU, N_RX, N_TX>,
|
||||||
hardware_address: driver::HardwareAddress,
|
hardware_address: driver::HardwareAddress,
|
||||||
@ -257,17 +302,22 @@ pub fn new<'d, const MTU: usize, const N_RX: usize, const N_TX: usize>(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Represents a packet of size MTU.
|
||||||
pub struct PacketBuf<const MTU: usize> {
|
pub struct PacketBuf<const MTU: usize> {
|
||||||
len: usize,
|
len: usize,
|
||||||
buf: [u8; MTU],
|
buf: [u8; MTU],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<const MTU: usize> PacketBuf<MTU> {
|
impl<const MTU: usize> PacketBuf<MTU> {
|
||||||
|
/// Create a new packet buffer.
|
||||||
pub const fn new() -> Self {
|
pub const fn new() -> Self {
|
||||||
Self { len: 0, buf: [0; MTU] }
|
Self { len: 0, buf: [0; MTU] }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Channel device.
|
||||||
|
///
|
||||||
|
/// Holds the shared state and upper end of channels for inbound and outbound packets.
|
||||||
pub struct Device<'d, const MTU: usize> {
|
pub struct Device<'d, const MTU: usize> {
|
||||||
rx: zerocopy_channel::Receiver<'d, NoopRawMutex, PacketBuf<MTU>>,
|
rx: zerocopy_channel::Receiver<'d, NoopRawMutex, PacketBuf<MTU>>,
|
||||||
tx: zerocopy_channel::Sender<'d, NoopRawMutex, PacketBuf<MTU>>,
|
tx: zerocopy_channel::Sender<'d, NoopRawMutex, PacketBuf<MTU>>,
|
||||||
@ -314,6 +364,9 @@ impl<'d, const MTU: usize> embassy_net_driver::Driver for Device<'d, MTU> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A rx token.
|
||||||
|
///
|
||||||
|
/// Holds inbound receive channel and interfaces with embassy-net-driver.
|
||||||
pub struct RxToken<'a, const MTU: usize> {
|
pub struct RxToken<'a, const MTU: usize> {
|
||||||
rx: zerocopy_channel::Receiver<'a, NoopRawMutex, PacketBuf<MTU>>,
|
rx: zerocopy_channel::Receiver<'a, NoopRawMutex, PacketBuf<MTU>>,
|
||||||
}
|
}
|
||||||
@ -331,6 +384,9 @@ impl<'a, const MTU: usize> embassy_net_driver::RxToken for RxToken<'a, MTU> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A tx token.
|
||||||
|
///
|
||||||
|
/// Holds outbound transmit channel and interfaces with embassy-net-driver.
|
||||||
pub struct TxToken<'a, const MTU: usize> {
|
pub struct TxToken<'a, const MTU: usize> {
|
||||||
tx: zerocopy_channel::Sender<'a, NoopRawMutex, PacketBuf<MTU>>,
|
tx: zerocopy_channel::Sender<'a, NoopRawMutex, PacketBuf<MTU>>,
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user