aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/src/eth/v2/mod.rs89
1 files changed, 88 insertions, 1 deletions
diff --git a/embassy-stm32/src/eth/v2/mod.rs b/embassy-stm32/src/eth/v2/mod.rs
index 67d722d15..7debd5a19 100644
--- a/embassy-stm32/src/eth/v2/mod.rs
+++ b/embassy-stm32/src/eth/v2/mod.rs
@@ -1,11 +1,12 @@
1use core::marker::PhantomData; 1use core::marker::PhantomData;
2use core::pin::Pin; 2use core::pin::Pin;
3use core::sync::atomic::{fence, Ordering}; 3use core::sync::atomic::{fence, Ordering};
4use core::task::Waker;
4 5
5use embassy::util::{AtomicWaker, Unborrow}; 6use embassy::util::{AtomicWaker, Unborrow};
6use embassy_extras::peripheral::{PeripheralMutex, PeripheralState}; 7use embassy_extras::peripheral::{PeripheralMutex, PeripheralState};
7use embassy_extras::unborrow; 8use embassy_extras::unborrow;
8use embassy_net::MTU; 9use embassy_net::{Device, DeviceCapabilities, LinkState, PacketBuf, MTU};
9 10
10use crate::gpio::sealed::Pin as __GpioPin; 11use crate::gpio::sealed::Pin as __GpioPin;
11use crate::gpio::AnyPin; 12use crate::gpio::AnyPin;
@@ -26,6 +27,7 @@ pub struct Ethernet<'d, T: Instance, P: PHY, const TX: usize, const RX: usize> {
26 _phy: P, 27 _phy: P,
27 clock_range: u8, 28 clock_range: u8,
28 phy_addr: u8, 29 phy_addr: u8,
30 mac_addr: [u8; 6],
29} 31}
30 32
31impl<'d, T: Instance, P: PHY, const TX: usize, const RX: usize> Ethernet<'d, T, P, TX, RX> { 33impl<'d, T: Instance, P: PHY, const TX: usize, const RX: usize> Ethernet<'d, T, P, TX, RX> {
@@ -140,6 +142,7 @@ impl<'d, T: Instance, P: PHY, const TX: usize, const RX: usize> Ethernet<'d, T,
140 _phy: phy, 142 _phy: phy,
141 clock_range, 143 clock_range,
142 phy_addr, 144 phy_addr,
145 mac_addr,
143 } 146 }
144 } 147 }
145 148
@@ -218,10 +221,94 @@ unsafe impl<'d, T: Instance, P: PHY, const TX: usize, const RX: usize> StationMa
218 } 221 }
219} 222}
220 223
224impl<'d, T: Instance, P: PHY, const TX: usize, const RX: usize> Device
225 for Pin<&mut Ethernet<'d, T, P, TX, RX>>
226{
227 fn is_transmit_ready(&mut self) -> bool {
228 // NOTE(unsafe) We won't move out of self
229 let this = unsafe { self.as_mut().get_unchecked_mut() };
230 let mutex = unsafe { Pin::new_unchecked(&mut this.state) };
231
232 mutex.with(|s, _| s.desc_ring.tx.available())
233 }
234
235 fn transmit(&mut self, pkt: PacketBuf) {
236 // NOTE(unsafe) We won't move out of self
237 let this = unsafe { self.as_mut().get_unchecked_mut() };
238 let mutex = unsafe { Pin::new_unchecked(&mut this.state) };
239
240 mutex.with(|s, _| unwrap!(s.desc_ring.tx.transmit(pkt)));
241 }
242
243 fn receive(&mut self) -> Option<PacketBuf> {
244 // NOTE(unsafe) We won't move out of self
245 let this = unsafe { self.as_mut().get_unchecked_mut() };
246 let mutex = unsafe { Pin::new_unchecked(&mut this.state) };
247
248 mutex.with(|s, _| s.desc_ring.rx.pop_packet())
249 }
250
251 fn register_waker(&mut self, waker: &Waker) {
252 T::state().register(waker);
253 }
254
255 fn capabilities(&mut self) -> DeviceCapabilities {
256 let mut caps = DeviceCapabilities::default();
257 caps.max_transmission_unit = MTU;
258 caps.max_burst_size = Some(TX.min(RX));
259 caps
260 }
261
262 fn link_state(&mut self) -> LinkState {
263 // NOTE(unsafe) We won't move out of self
264 let this = unsafe { self.as_mut().get_unchecked_mut() };
265
266 if P::poll_link(this) {
267 LinkState::Up
268 } else {
269 LinkState::Down
270 }
271 }
272
273 fn ethernet_address(&mut self) -> [u8; 6] {
274 // NOTE(unsafe) We won't move out of self
275 let this = unsafe { self.as_mut().get_unchecked_mut() };
276
277 this.mac_addr
278 }
279}
280
221impl<'d, T: Instance, P: PHY, const TX: usize, const RX: usize> Drop 281impl<'d, T: Instance, P: PHY, const TX: usize, const RX: usize> Drop
222 for Ethernet<'d, T, P, TX, RX> 282 for Ethernet<'d, T, P, TX, RX>
223{ 283{
224 fn drop(&mut self) { 284 fn drop(&mut self) {
285 // NOTE(unsafe) We have `&mut self` and the interrupt doesn't use this registers
286 unsafe {
287 let dma = ETH.ethernet_dma();
288 let mac = ETH.ethernet_mac();
289 let mtl = ETH.ethernet_mtl();
290
291 // Disable the TX DMA and wait for any previous transmissions to be completed
292 dma.dmactx_cr().modify(|w| w.set_st(false));
293 while {
294 let txqueue = mtl.mtltx_qdr().read();
295 txqueue.trcsts() == 0b01 || txqueue.txqsts()
296 } {}
297
298 // Disable MAC transmitter and receiver
299 mac.maccr().modify(|w| {
300 w.set_re(false);
301 w.set_te(false);
302 });
303
304 // Wait for previous receiver transfers to be completed and then disable the RX DMA
305 while {
306 let rxqueue = mtl.mtlrx_qdr().read();
307 rxqueue.rxqsts() != 0b00 || rxqueue.prxq() != 0
308 } {}
309 dma.dmacrx_cr().modify(|w| w.set_sr(false));
310 }
311
225 for pin in self.pins.iter_mut() { 312 for pin in self.pins.iter_mut() {
226 // NOTE(unsafe) Exclusive access to the regs 313 // NOTE(unsafe) Exclusive access to the regs
227 critical_section::with(|_| unsafe { 314 critical_section::with(|_| unsafe {