1pub(crate) use self::descriptor::RxDescriptor;
2
3use self::descriptor::RxDescriptorError;
4pub use self::descriptor::RxRingEntry;
5
6use super::PacketId;
7use crate::peripherals::ETHERNET_DMA;
8
9mod descriptor;
10
11#[cfg(feature = "ptp")]
12use crate::{dma::PacketIdNotFound, ptp::Timestamp};
13
14#[cfg(feature = "async-await")]
15use core::task::Poll;
16
17#[cfg_attr(feature = "defmt", derive(defmt::Format))]
19#[derive(Debug, PartialEq)]
20pub enum RxError {
21 Truncated,
23 DmaError,
25 WouldBlock,
27}
28
29impl From<RxDescriptorError> for RxError {
30 fn from(value: RxDescriptorError) -> Self {
31 match value {
32 RxDescriptorError::Truncated => Self::Truncated,
33 RxDescriptorError::DmaError => Self::DmaError,
34 }
35 }
36}
37
38pub struct RxRing<'a> {
40 entries: &'a mut [RxRingEntry],
41 next_entry: usize,
42}
43
44impl<'a> RxRing<'a> {
45 pub(crate) fn new(entries: &'a mut [RxRingEntry]) -> Self {
47 RxRing {
48 entries,
49 next_entry: 0,
50 }
51 }
52
53 pub(crate) fn start(&mut self, eth_dma: ÐERNET_DMA) {
55 {
57 let mut previous: Option<&mut RxRingEntry> = None;
58 for entry in self.entries.iter_mut() {
59 if let Some(prev_entry) = &mut previous {
60 prev_entry.setup(Some(entry));
61 }
62 previous = Some(entry);
63 }
64 if let Some(entry) = &mut previous {
65 entry.setup(None);
66 }
67 }
68 self.next_entry = 0;
69 let ring_ptr = self.entries[0].desc() as *const RxDescriptor;
70
71 eth_dma
73 .dmardlar
74 .write(|w| unsafe { w.srl().bits(ring_ptr as u32) });
75
76 eth_dma.dmaomr.modify(|_, w| w.sr().set_bit());
80
81 self.demand_poll();
82 }
83
84 pub(crate) fn stop(&self, eth_dma: ÐERNET_DMA) {
86 eth_dma.dmaomr.modify(|_, w| w.sr().clear_bit());
87
88 while self.running_state().is_running() {}
92 }
93
94 fn demand_poll(&self) {
97 let eth_dma = unsafe { &*ETHERNET_DMA::ptr() };
99 eth_dma.dmarpdr.write(|w| unsafe { w.rpd().bits(1) });
100 }
101
102 pub fn running_state(&self) -> RunningState {
104 let eth_dma = unsafe { &*ETHERNET_DMA::ptr() };
106 match eth_dma.dmasr.read().rps().bits() {
107 0b000 => RunningState::Stopped,
109 0b001 => RunningState::Running,
111 0b011 => RunningState::Running,
113 0b100 => RunningState::Stopped,
115 0b101 => RunningState::Running,
117 0b111 => RunningState::Running,
119 _ => RunningState::Unknown,
120 }
121 }
122
123 pub fn next_entry_available(&self) -> bool {
125 if !self.running_state().is_running() {
126 self.demand_poll();
127 }
128
129 self.entries[self.next_entry].is_available()
130 }
131
132 fn recv_next_impl(
138 &mut self,
139 #[allow(unused_variables)] packet_id: Option<PacketId>,
141 ) -> Result<(usize, usize), RxError> {
142 if !self.running_state().is_running() {
143 self.demand_poll();
144 }
145
146 let entries_len = self.entries.len();
147 let entry_num = self.next_entry;
148 let entry = &mut self.entries[entry_num];
149
150 if entry.is_available() {
151 let length = entry.recv(packet_id)?;
152
153 self.next_entry = (self.next_entry + 1) % entries_len;
154
155 Ok((entry_num, length))
156 } else {
157 Err(RxError::WouldBlock)
158 }
159 }
160
161 pub fn recv_next(&mut self, packet_id: Option<PacketId>) -> Result<RxPacket, RxError> {
164 let (entry, length) = self.recv_next_impl(packet_id.map(|p| p.into()))?;
165 Ok(RxPacket {
166 entry: &mut self.entries[entry],
167 length,
168 })
169 }
170
171 #[cfg(feature = "async-await")]
176 pub async fn recv(&mut self, packet_id: Option<PacketId>) -> RxPacket {
177 let (entry, length) = core::future::poll_fn(|ctx| {
178 let res = self.recv_next_impl(packet_id.clone());
179
180 match res {
181 Ok(value) => Poll::Ready(value),
182 Err(_) => {
183 crate::dma::EthernetDMA::rx_waker().register(ctx.waker());
184 Poll::Pending
185 }
186 }
187 })
188 .await;
189
190 RxPacket {
191 entry: &mut self.entries[entry],
192 length,
193 }
194 }
195}
196
197#[cfg(feature = "ptp")]
198impl<'a> RxRing<'a> {
199 pub fn timestamp(&self, id: &PacketId) -> Result<Option<Timestamp>, PacketIdNotFound> {
201 let entry = self.entries.iter().find(|e| e.has_packet_id(id));
202
203 let entry = entry.ok_or(PacketIdNotFound)?;
204
205 Ok(entry.read_timestamp())
206 }
207}
208
209#[derive(PartialEq, Eq, Debug)]
211pub enum RunningState {
212 Unknown,
214 Stopped,
216 Running,
218}
219
220impl RunningState {
221 pub fn is_running(&self) -> bool {
223 *self == RunningState::Running
224 }
225}
226
227pub struct RxPacket<'a> {
232 entry: &'a mut RxRingEntry,
233 length: usize,
234}
235
236impl<'a> core::ops::Deref for RxPacket<'a> {
237 type Target = [u8];
238
239 fn deref(&self) -> &Self::Target {
240 &self.entry.as_slice()[0..self.length]
241 }
242}
243
244impl<'a> core::ops::DerefMut for RxPacket<'a> {
245 fn deref_mut(&mut self) -> &mut Self::Target {
246 &mut self.entry.as_mut_slice()[0..self.length]
247 }
248}
249
250impl<'a> Drop for RxPacket<'a> {
251 fn drop(&mut self) {
252 self.entry.desc_mut().set_owned();
253 }
254}
255
256impl<'a> RxPacket<'a> {
257 pub fn free(self) {
259 drop(self)
260 }
261
262 #[cfg(feature = "ptp")]
264 pub fn timestamp(&self) -> Option<Timestamp> {
265 self.entry.read_timestamp()
266 }
267}