1#![macro_use]
3
4#[cfg_attr(any(eth_v1a, eth_v1b, eth_v1c), path = "v1/mod.rs")]
5#[cfg_attr(eth_v2, path = "v2/mod.rs")]
6mod _version;
7mod generic_phy;
8
9use core::mem::MaybeUninit;
10use core::task::Context;
11
12use embassy_hal_internal::PeripheralType;
13use embassy_net_driver::{Capabilities, HardwareAddress, LinkState};
14use embassy_sync::waitqueue::AtomicWaker;
15
16pub use self::_version::{InterruptHandler, *};
17pub use self::generic_phy::*;
18use crate::rcc::RccPeripheral;
19
20#[allow(unused)]
21const MTU: usize = 1514;
22const TX_BUFFER_SIZE: usize = 1514;
23const RX_BUFFER_SIZE: usize = 1536;
24
25#[repr(C, align(8))]
26#[derive(Copy, Clone)]
27pub(crate) struct Packet<const N: usize>([u8; N]);
28
29pub struct PacketQueue<const TX: usize, const RX: usize> {
38 tx_desc: [TDes; TX],
39 rx_desc: [RDes; RX],
40 tx_buf: [Packet<TX_BUFFER_SIZE>; TX],
41 rx_buf: [Packet<RX_BUFFER_SIZE>; RX],
42}
43
44impl<const TX: usize, const RX: usize> PacketQueue<TX, RX> {
45 pub const fn new() -> Self {
47 Self {
48 tx_desc: [const { TDes::new() }; TX],
49 rx_desc: [const { RDes::new() }; RX],
50 tx_buf: [Packet([0; TX_BUFFER_SIZE]); TX],
51 rx_buf: [Packet([0; RX_BUFFER_SIZE]); RX],
52 }
53 }
54
55 pub fn init(this: &mut MaybeUninit<Self>) {
68 unsafe {
69 this.as_mut_ptr().write_bytes(0u8, 1);
70 }
71 }
72}
73
74static WAKER: AtomicWaker = AtomicWaker::new();
75
76impl<'d, T: Instance, P: Phy> embassy_net_driver::Driver for Ethernet<'d, T, P> {
77 type RxToken<'a>
78 = RxToken<'a, 'd>
79 where
80 Self: 'a;
81 type TxToken<'a>
82 = TxToken<'a, 'd>
83 where
84 Self: 'a;
85
86 fn receive(&mut self, cx: &mut Context) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
87 WAKER.register(cx.waker());
88 if self.rx.available().is_some() && self.tx.available().is_some() {
89 Some((RxToken { rx: &mut self.rx }, TxToken { tx: &mut self.tx }))
90 } else {
91 None
92 }
93 }
94
95 fn transmit(&mut self, cx: &mut Context) -> Option<Self::TxToken<'_>> {
96 WAKER.register(cx.waker());
97 if self.tx.available().is_some() {
98 Some(TxToken { tx: &mut self.tx })
99 } else {
100 None
101 }
102 }
103
104 fn capabilities(&self) -> Capabilities {
105 let mut caps = Capabilities::default();
106 caps.max_transmission_unit = MTU;
107 caps.max_burst_size = Some(self.tx.len());
108 caps
109 }
110
111 fn link_state(&mut self, cx: &mut Context) -> LinkState {
112 if self.phy.poll_link(&mut self.station_management, cx) {
113 LinkState::Up
114 } else {
115 LinkState::Down
116 }
117 }
118
119 fn hardware_address(&self) -> HardwareAddress {
120 HardwareAddress::Ethernet(self.mac_addr)
121 }
122}
123
124pub struct RxToken<'a, 'd> {
126 rx: &'a mut RDesRing<'d>,
127}
128
129impl<'a, 'd> embassy_net_driver::RxToken for RxToken<'a, 'd> {
130 fn consume<R, F>(self, f: F) -> R
131 where
132 F: FnOnce(&mut [u8]) -> R,
133 {
134 let pkt = unwrap!(self.rx.available());
136 let r = f(pkt);
137 self.rx.pop_packet();
138 r
139 }
140}
141
142pub struct TxToken<'a, 'd> {
144 tx: &'a mut TDesRing<'d>,
145}
146
147impl<'a, 'd> embassy_net_driver::TxToken for TxToken<'a, 'd> {
148 fn consume<R, F>(self, len: usize, f: F) -> R
149 where
150 F: FnOnce(&mut [u8]) -> R,
151 {
152 let pkt = unwrap!(self.tx.available());
154 let r = f(&mut pkt[..len]);
155 self.tx.transmit(len);
156 r
157 }
158}
159
160pub trait StationManagement {
162 fn smi_read(&mut self, phy_addr: u8, reg: u8) -> u16;
164 fn smi_write(&mut self, phy_addr: u8, reg: u8, val: u16);
166}
167
168pub trait Phy {
170 fn phy_reset<S: StationManagement>(&mut self, sm: &mut S);
172 fn phy_init<S: StationManagement>(&mut self, sm: &mut S);
174 fn poll_link<S: StationManagement>(&mut self, sm: &mut S, cx: &mut Context) -> bool;
176}
177
178impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> {
179 pub fn station_management(&mut self) -> &mut impl StationManagement {
183 &mut self.station_management
184 }
185
186 pub fn phy(&self) -> &P {
188 &self.phy
189 }
190
191 pub fn phy_mut(&mut self) -> &mut P {
193 &mut self.phy
194 }
195}
196
197trait SealedInstance {
198 fn regs() -> crate::pac::eth::Eth;
199}
200
201#[allow(private_bounds)]
203pub trait Instance: SealedInstance + PeripheralType + RccPeripheral + Send + 'static {}
204
205impl SealedInstance for crate::peripherals::ETH {
206 fn regs() -> crate::pac::eth::Eth {
207 crate::pac::ETH
208 }
209}
210impl Instance for crate::peripherals::ETH {}
211
212pin_trait!(RXClkPin, Instance);
213pin_trait!(TXClkPin, Instance);
214pin_trait!(RefClkPin, Instance);
215pin_trait!(MDIOPin, Instance);
216pin_trait!(MDCPin, Instance);
217pin_trait!(RXDVPin, Instance);
218pin_trait!(CRSPin, Instance);
219pin_trait!(RXD0Pin, Instance);
220pin_trait!(RXD1Pin, Instance);
221pin_trait!(RXD2Pin, Instance);
222pin_trait!(RXD3Pin, Instance);
223pin_trait!(TXD0Pin, Instance);
224pin_trait!(TXD1Pin, Instance);
225pin_trait!(TXD2Pin, Instance);
226pin_trait!(TXD3Pin, Instance);
227pin_trait!(TXEnPin, Instance);