1use cortex_m::peripheral::NVIC;
4
5use crate::{peripherals::ETHERNET_DMA, stm32::Interrupt};
6
7#[cfg(feature = "smoltcp-phy")]
8mod smoltcp_phy;
9#[cfg(feature = "smoltcp-phy")]
10pub use smoltcp_phy::*;
11
12#[cfg(feature = "async-await")]
13use futures::task::AtomicWaker;
14
15#[cfg(any(feature = "ptp", feature = "async-await"))]
16use core::task::Poll;
17
18pub(crate) mod desc;
19
20pub(crate) mod ring;
21
22mod rx;
23pub use rx::{RunningState as RxRunningState, RxError, RxPacket, RxRing, RxRingEntry};
24
25mod tx;
26pub use tx::{RunningState as TxRunningState, TxError, TxPacket, TxRing, TxRingEntry};
27
28#[cfg(feature = "ptp")]
29use crate::ptp::Timestamp;
30
31mod packet_id;
32pub use packet_id::PacketId;
33
34pub(crate) const MTU: usize = 1522;
36
37#[cfg_attr(feature = "defmt", derive(defmt::Format))]
38#[derive(Clone, Copy, Debug, PartialEq)]
39pub struct PacketIdNotFound;
42
43pub struct EthernetDMA<'rx, 'tx> {
45 pub(crate) eth_dma: ETHERNET_DMA,
46 pub(crate) rx_ring: RxRing<'rx>,
47 pub(crate) tx_ring: TxRing<'tx>,
48
49 #[cfg(feature = "ptp")]
50 packet_id_counter: u32,
51}
52
53impl<'rx, 'tx> EthernetDMA<'rx, 'tx> {
54 pub(crate) fn new(
61 eth_dma: ETHERNET_DMA,
62 rx_buffer: &'rx mut [RxRingEntry],
63 tx_buffer: &'tx mut [TxRingEntry],
64 ) -> Self {
65 eth_dma.dmabmr.modify(|_, w| w.sr().set_bit());
67
68 while eth_dma.dmabmr.read().sr().bit_is_set() {}
70
71 eth_dma.dmaomr.modify(|_, w| {
73 w.dtcefd()
75 .set_bit()
76 .rsf()
78 .set_bit()
79 .dfrf()
81 .set_bit()
82 .tsf()
84 .set_bit()
85 .fef()
87 .set_bit()
88 .osf()
90 .set_bit()
91 });
92
93 eth_dma.dmabmr.modify(|_, w| {
95 #[cfg(not(feature = "stm32f1xx-hal"))]
98 let w = w.edfe().set_bit();
99
100 unsafe {
101 w.aab()
103 .set_bit()
104 .fb()
106 .set_bit()
107 .rdp()
109 .bits(32)
110 .pbl()
112 .bits(32)
113 .pm()
115 .bits(0b01)
116 .usp()
118 .set_bit()
119 }
120 });
121
122 let mut dma = EthernetDMA {
123 eth_dma,
124 rx_ring: RxRing::new(rx_buffer),
125 tx_ring: TxRing::new(tx_buffer),
126
127 #[cfg(feature = "ptp")]
128 packet_id_counter: 0,
129 };
130
131 dma.rx_ring.start(&dma.eth_dma);
132 dma.tx_ring.start(&dma.eth_dma);
133
134 dma
135 }
136
137 pub fn split(&mut self) -> (&mut RxRing<'rx>, &mut TxRing<'tx>) {
140 (&mut self.rx_ring, &mut self.tx_ring)
141 }
142
143 #[cfg_attr(
151 feature = "ptp",
152 doc = "If you have PTP enabled, you must also call [`EthernetPTP::interrupt_handler()`] if you wish to make use of the PTP timestamp trigger feature."
153 )]
154 pub fn enable_interrupt(&self) {
155 self.eth_dma.dmaier.modify(|_, w| {
156 w
157 .nise()
159 .set_bit()
160 .rie()
162 .set_bit()
163 .tie()
165 .set_bit()
166 });
167
168 unsafe {
170 NVIC::unmask(Interrupt::ETH);
171 }
172 }
173
174 pub fn interrupt_handler() -> InterruptReasonSummary {
176 let eth_dma = unsafe { &*ETHERNET_DMA::ptr() };
178
179 let status = eth_dma.dmasr.read();
180
181 let status = InterruptReasonSummary {
182 is_rx: status.rs().bit_is_set(),
183 is_tx: status.ts().bit_is_set(),
184 is_error: status.ais().bit_is_set(),
185 };
186
187 eth_dma
188 .dmasr
189 .write(|w| w.nis().set_bit().ts().set_bit().rs().set_bit());
190
191 #[cfg(feature = "async-await")]
192 {
193 if status.is_tx {
194 EthernetDMA::tx_waker().wake();
195 }
196
197 if status.is_rx {
198 EthernetDMA::rx_waker().wake();
199 }
200 }
201
202 status
203 }
204
205 pub fn recv_next(&mut self, packet_id: Option<PacketId>) -> Result<RxPacket, RxError> {
211 self.rx_ring.recv_next(packet_id.map(Into::into))
212 }
213
214 pub fn rx_is_running(&self) -> bool {
219 self.rx_ring.running_state().is_running()
220 }
221
222 pub fn tx_is_running(&self) -> bool {
224 self.tx_ring.is_running()
225 }
226
227 pub fn send<F>(
232 &mut self,
233 length: usize,
234 packet_id: Option<PacketId>,
235 f: F,
236 ) -> Result<(), TxError>
237 where
238 F: FnOnce(&mut [u8]),
239 {
240 let mut tx_packet = self.tx_ring.send_next(length, packet_id)?;
241 f(&mut tx_packet);
242 tx_packet.send();
243 Ok(())
244 }
245
246 pub fn rx_available(&mut self) -> bool {
251 self.rx_ring.next_entry_available()
252 }
253
254 pub fn tx_available(&mut self) -> bool {
259 self.tx_ring.next_entry_available()
260 }
261}
262
263impl Drop for EthernetDMA<'_, '_> {
264 fn drop(&mut self) {
266 self.tx_ring.stop(&self.eth_dma);
267
268 self.rx_ring.stop(&self.eth_dma);
269 }
270}
271
272#[cfg(feature = "async-await")]
273impl<'rx, 'tx> EthernetDMA<'rx, 'tx> {
274 pub(crate) fn rx_waker() -> &'static AtomicWaker {
275 static WAKER: AtomicWaker = AtomicWaker::new();
276 &WAKER
277 }
278
279 pub(crate) fn tx_waker() -> &'static AtomicWaker {
280 static WAKER: AtomicWaker = AtomicWaker::new();
281 &WAKER
282 }
283
284 pub async fn recv(&mut self, packet_id: Option<PacketId>) -> RxPacket {
288 self.rx_ring.recv(packet_id).await
289 }
290
291 pub async fn prepare_packet<'borrow>(
295 &'borrow mut self,
296 length: usize,
297 packet_id: Option<PacketId>,
298 ) -> TxPacket<'borrow, 'tx> {
299 self.tx_ring.prepare_packet(length, packet_id).await
300 }
301
302 pub async fn rx_or_tx(&mut self) {
305 let mut polled_once = false;
306 core::future::poll_fn(|ctx| {
307 if polled_once {
308 Poll::Ready(())
309 } else {
310 polled_once = true;
311 EthernetDMA::rx_waker().register(ctx.waker());
312 EthernetDMA::tx_waker().register(ctx.waker());
313 Poll::Pending
314 }
315 })
316 .await;
317 }
318}
319
320#[cfg(feature = "ptp")]
321impl EthernetDMA<'_, '_> {
322 pub fn poll_timestamp(
327 &self,
328 packet_id: &PacketId,
329 ) -> Poll<Result<Option<Timestamp>, PacketIdNotFound>> {
330 let tx = self.poll_tx_timestamp(packet_id);
332
333 if tx != Poll::Ready(Err(PacketIdNotFound)) {
334 return tx;
335 }
336
337 Poll::Ready(self.rx_timestamp(packet_id))
339 }
340
341 pub fn rx_timestamp(
343 &self,
344 packet_id: &PacketId,
345 ) -> Result<Option<Timestamp>, PacketIdNotFound> {
346 self.rx_ring.timestamp(packet_id)
347 }
348
349 pub fn wait_for_tx_timestamp(
352 &self,
353 packet_id: &PacketId,
354 ) -> Result<Option<Timestamp>, PacketIdNotFound> {
355 self.tx_ring.wait_for_timestamp(packet_id)
356 }
357
358 pub fn poll_tx_timestamp(
361 &self,
362 packet_id: &PacketId,
363 ) -> Poll<Result<Option<Timestamp>, PacketIdNotFound>> {
364 self.tx_ring.poll_timestamp(packet_id)
365 }
366
367 #[cfg(feature = "async-await")]
369 pub async fn tx_timestamp(
370 &mut self,
371 packet_id: &PacketId,
372 ) -> Result<Option<Timestamp>, PacketIdNotFound> {
373 self.tx_ring.timestamp(packet_id).await
374 }
375
376 pub fn next_packet_id(&mut self) -> PacketId {
378 let id = PacketId(self.packet_id_counter);
379 self.packet_id_counter = self.packet_id_counter.wrapping_add(1);
380 id
381 }
382}
383
384#[cfg_attr(feature = "defmt", derive(defmt::Format))]
387#[derive(Debug, Clone, Copy)]
388pub struct InterruptReasonSummary {
389 pub is_rx: bool,
391 pub is_tx: bool,
393 pub is_error: bool,
395}