stm32_eth/dma/
smoltcp_phy.rs1use crate::dma::RxError;
2
3use super::rx::RxRing;
4use super::tx::TxRing;
5use super::EthernetDMA;
6
7#[cfg(feature = "ptp")]
8use super::PacketId;
9
10use smoltcp::phy::{ChecksumCapabilities, Device, DeviceCapabilities, RxToken, TxToken};
11use smoltcp::time::Instant;
12
13impl<'a, 'rx, 'tx> Device for &'a mut EthernetDMA<'rx, 'tx> {
15 type RxToken<'token>
16 = EthRxToken<'token, 'rx>
17 where
18 Self: 'token;
19 type TxToken<'token>
20 = EthTxToken<'token, 'tx>
21 where
22 Self: 'token;
23
24 fn capabilities(&self) -> DeviceCapabilities {
25 let mut caps = DeviceCapabilities::default();
26 caps.max_transmission_unit = crate::dma::MTU;
27 caps.max_burst_size = Some(1);
28 caps.checksum = ChecksumCapabilities::ignored();
29 caps
30 }
31
32 fn receive(&mut self, _timestamp: Instant) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
33 if self.tx_available() && self.rx_available() {
34 #[cfg(feature = "ptp")]
35 let rx_packet_id = self.next_packet_id();
36
37 let EthernetDMA {
38 rx_ring, tx_ring, ..
39 } = self;
40
41 let rx = EthRxToken {
42 rx_ring,
43 #[cfg(feature = "ptp")]
44 meta: rx_packet_id,
45 };
46
47 let tx = EthTxToken {
48 tx_ring,
49 #[cfg(feature = "ptp")]
50 meta: None,
51 };
52 Some((rx, tx))
53 } else {
54 None
55 }
56 }
57
58 fn transmit(&mut self, _timestamp: Instant) -> Option<Self::TxToken<'_>> {
59 if self.tx_available() {
60 let EthernetDMA { tx_ring, .. } = self;
61 Some(EthTxToken {
62 tx_ring,
63 #[cfg(feature = "ptp")]
64 meta: None,
65 })
66 } else {
67 None
68 }
69 }
70}
71
72pub struct EthRxToken<'a, 'rx> {
75 rx_ring: &'a mut RxRing<'rx>,
76 #[cfg(feature = "ptp")]
77 meta: PacketId,
78}
79
80impl<'dma, 'rx> RxToken for EthRxToken<'dma, 'rx> {
81 fn consume<R, F>(self, f: F) -> R
82 where
83 F: FnOnce(&[u8]) -> R,
84 {
85 #[cfg(feature = "ptp")]
86 let meta = Some(self.meta.into());
87
88 #[cfg(not(feature = "ptp"))]
89 let meta = None;
90
91 match self.rx_ring.recv_next(meta) {
92 Ok(v) => {
93 let result = f(&v);
94 v.free();
95 result
96 }
97 Err(RxError::WouldBlock) => {
98 #[cfg(feature = "defmt")]
99 defmt::error!("EthRxToken: RX would block");
100 f(&[])
101 }
102 Err(_e) => {
103 #[cfg(feature = "defmt")]
104 defmt::debug!("Failed to receive packet: {}", _e);
105 f(&[])
106 }
107 }
108 }
109
110 #[cfg(feature = "ptp")]
111 fn meta(&self) -> smoltcp::phy::PacketMeta {
112 self.meta.clone().into()
113 }
114}
115
116pub struct EthTxToken<'a, 'tx> {
119 tx_ring: &'a mut TxRing<'tx>,
120 #[cfg(feature = "ptp")]
121 meta: Option<PacketId>,
122}
123
124impl<'dma, 'tx> TxToken for EthTxToken<'dma, 'tx> {
125 fn consume<R, F>(self, len: usize, f: F) -> R
126 where
127 F: FnOnce(&mut [u8]) -> R,
128 {
129 #[cfg(feature = "ptp")]
130 let meta = self.meta.map(Into::into);
131 #[cfg(not(feature = "ptp"))]
132 let meta = None;
133
134 let mut tx_packet = self.tx_ring.send_next(len, meta).ok().unwrap();
137 let res = f(&mut tx_packet);
138 tx_packet.send();
139 res
140 }
141
142 #[cfg(feature = "ptp")]
143 fn set_meta(&mut self, meta: smoltcp::phy::PacketMeta) {
144 self.meta = Some(meta.into());
145 }
146}