aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/eth/v2/mod.rs
diff options
context:
space:
mode:
authorSimon B. Gasse <[email protected]>2024-01-19 21:10:03 +0100
committerDario Nieuwenhuis <[email protected]>2024-02-01 01:33:34 +0100
commit42d8f3930a861dcc4540198bf2038151eb4e3e27 (patch)
treea188a1489792563413a9330d9fb74d7cb42dd01a /embassy-stm32/src/eth/v2/mod.rs
parente05f6505ae18696ad178119c747775b7e839ae8d (diff)
Implement MII interface
- Extend the eth/v2 module to support MII besides RMII. - Replace `Ethernet::new` with `Ethernet::new_mii` and `Ethernet::new_rmii`. - Update ethernet examples. - Add example for MII ethernet.
Diffstat (limited to 'embassy-stm32/src/eth/v2/mod.rs')
-rw-r--r--embassy-stm32/src/eth/v2/mod.rs136
1 files changed, 113 insertions, 23 deletions
diff --git a/embassy-stm32/src/eth/v2/mod.rs b/embassy-stm32/src/eth/v2/mod.rs
index 59745cba0..a176b01e5 100644
--- a/embassy-stm32/src/eth/v2/mod.rs
+++ b/embassy-stm32/src/eth/v2/mod.rs
@@ -39,12 +39,18 @@ pub struct Ethernet<'d, T: Instance, P: PHY> {
39 _peri: PeripheralRef<'d, T>, 39 _peri: PeripheralRef<'d, T>,
40 pub(crate) tx: TDesRing<'d>, 40 pub(crate) tx: TDesRing<'d>,
41 pub(crate) rx: RDesRing<'d>, 41 pub(crate) rx: RDesRing<'d>,
42 pins: [PeripheralRef<'d, AnyPin>; 9], 42 pins: Pins<'d>,
43 pub(crate) phy: P, 43 pub(crate) phy: P,
44 pub(crate) station_management: EthernetStationManagement<T>, 44 pub(crate) station_management: EthernetStationManagement<T>,
45 pub(crate) mac_addr: [u8; 6], 45 pub(crate) mac_addr: [u8; 6],
46} 46}
47 47
48/// Pins of ethernet driver.
49enum Pins<'d> {
50 Rmii([PeripheralRef<'d, AnyPin>; 9]),
51 Mii([PeripheralRef<'d, AnyPin>; 14]),
52}
53
48macro_rules! config_pins { 54macro_rules! config_pins {
49 ($($pin:ident),*) => { 55 ($($pin:ident),*) => {
50 critical_section::with(|_| { 56 critical_section::with(|_| {
@@ -57,11 +63,11 @@ macro_rules! config_pins {
57} 63}
58 64
59impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { 65impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
60 /// Create a new Ethernet driver. 66 /// Create a new RMII ethernet driver using 9 pins.
61 pub fn new<const TX: usize, const RX: usize>( 67 pub fn new_rmii<const TX: usize, const RX: usize>(
62 queue: &'d mut PacketQueue<TX, RX>, 68 queue: &'d mut PacketQueue<TX, RX>,
63 peri: impl Peripheral<P = T> + 'd, 69 peri: impl Peripheral<P = T> + 'd,
64 _irq: impl interrupt::typelevel::Binding<interrupt::typelevel::ETH, InterruptHandler> + 'd, 70 irq: impl interrupt::typelevel::Binding<interrupt::typelevel::ETH, InterruptHandler> + 'd,
65 ref_clk: impl Peripheral<P = impl RefClkPin<T>> + 'd, 71 ref_clk: impl Peripheral<P = impl RefClkPin<T>> + 'd,
66 mdio: impl Peripheral<P = impl MDIOPin<T>> + 'd, 72 mdio: impl Peripheral<P = impl MDIOPin<T>> + 'd,
67 mdc: impl Peripheral<P = impl MDCPin<T>> + 'd, 73 mdc: impl Peripheral<P = impl MDCPin<T>> + 'd,
@@ -74,8 +80,6 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
74 phy: P, 80 phy: P,
75 mac_addr: [u8; 6], 81 mac_addr: [u8; 6],
76 ) -> Self { 82 ) -> Self {
77 into_ref!(peri, ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en);
78
79 // Enable the necessary Clocks 83 // Enable the necessary Clocks
80 #[cfg(not(rcc_h5))] 84 #[cfg(not(rcc_h5))]
81 critical_section::with(|_| { 85 critical_section::with(|_| {
@@ -85,7 +89,6 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
85 w.set_eth1rxen(true); 89 w.set_eth1rxen(true);
86 }); 90 });
87 91
88 // RMII
89 crate::pac::SYSCFG.pmcr().modify(|w| w.set_epis(0b100)); 92 crate::pac::SYSCFG.pmcr().modify(|w| w.set_epis(0b100));
90 }); 93 });
91 94
@@ -99,14 +102,110 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
99 w.set_ethrxen(true); 102 w.set_ethrxen(true);
100 }); 103 });
101 104
102 // RMII
103 crate::pac::SYSCFG 105 crate::pac::SYSCFG
104 .pmcr() 106 .pmcr()
105 .modify(|w| w.set_eth_sel_phy(crate::pac::syscfg::vals::EthSelPhy::B_0X4)); 107 .modify(|w| w.set_eth_sel_phy(crate::pac::syscfg::vals::EthSelPhy::B_0X4));
106 }); 108 });
107 109
110 into_ref!(ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en);
108 config_pins!(ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en); 111 config_pins!(ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en);
109 112
113 let pins = Pins::Rmii([
114 ref_clk.map_into(),
115 mdio.map_into(),
116 mdc.map_into(),
117 crs.map_into(),
118 rx_d0.map_into(),
119 rx_d1.map_into(),
120 tx_d0.map_into(),
121 tx_d1.map_into(),
122 tx_en.map_into(),
123 ]);
124
125 Self::new_inner(queue, peri, irq, pins, phy, mac_addr)
126 }
127
128 /// Create a new MII ethernet driver using 14 pins.
129 pub fn new_mii<const TX: usize, const RX: usize>(
130 queue: &'d mut PacketQueue<TX, RX>,
131 peri: impl Peripheral<P = T> + 'd,
132 irq: impl interrupt::typelevel::Binding<interrupt::typelevel::ETH, InterruptHandler> + 'd,
133 rx_clk: impl Peripheral<P = impl RXClkPin<T>> + 'd,
134 tx_clk: impl Peripheral<P = impl TXClkPin<T>> + 'd,
135 mdio: impl Peripheral<P = impl MDIOPin<T>> + 'd,
136 mdc: impl Peripheral<P = impl MDCPin<T>> + 'd,
137 rxdv: impl Peripheral<P = impl RXDVPin<T>> + 'd,
138 rx_d0: impl Peripheral<P = impl RXD0Pin<T>> + 'd,
139 rx_d1: impl Peripheral<P = impl RXD1Pin<T>> + 'd,
140 rx_d2: impl Peripheral<P = impl RXD2Pin<T>> + 'd,
141 rx_d3: impl Peripheral<P = impl RXD3Pin<T>> + 'd,
142 tx_d0: impl Peripheral<P = impl TXD0Pin<T>> + 'd,
143 tx_d1: impl Peripheral<P = impl TXD1Pin<T>> + 'd,
144 tx_d2: impl Peripheral<P = impl TXD2Pin<T>> + 'd,
145 tx_d3: impl Peripheral<P = impl TXD3Pin<T>> + 'd,
146 tx_en: impl Peripheral<P = impl TXEnPin<T>> + 'd,
147 phy: P,
148 mac_addr: [u8; 6],
149 ) -> Self {
150 // Enable necessary clocks.
151 #[cfg(not(rcc_h5))]
152 critical_section::with(|_| {
153 crate::pac::RCC.ahb1enr().modify(|w| {
154 w.set_eth1macen(true);
155 w.set_eth1txen(true);
156 w.set_eth1rxen(true);
157 });
158
159 crate::pac::SYSCFG.pmcr().modify(|w| w.set_epis(0b000));
160 });
161
162 #[cfg(rcc_h5)]
163 critical_section::with(|_| {
164 crate::pac::RCC.apb3enr().modify(|w| w.set_sbsen(true));
165
166 crate::pac::RCC.ahb1enr().modify(|w| {
167 w.set_ethen(true);
168 w.set_ethtxen(true);
169 w.set_ethrxen(true);
170 });
171
172 // TODO: This is for RMII - what would MII need here?
173 crate::pac::SYSCFG
174 .pmcr()
175 .modify(|w| w.set_eth_sel_phy(crate::pac::syscfg::vals::EthSelPhy::B_0X4));
176 });
177
178 into_ref!(rx_clk, tx_clk, mdio, mdc, rxdv, rx_d0, rx_d1, rx_d2, rx_d3, tx_d0, tx_d1, tx_d2, tx_d3, tx_en);
179 config_pins!(rx_clk, tx_clk, mdio, mdc, rxdv, rx_d0, rx_d1, rx_d2, rx_d3, tx_d0, tx_d1, tx_d2, tx_d3, tx_en);
180
181 let pins = Pins::Mii([
182 rx_clk.map_into(),
183 tx_clk.map_into(),
184 mdio.map_into(),
185 mdc.map_into(),
186 rxdv.map_into(),
187 rx_d0.map_into(),
188 rx_d1.map_into(),
189 rx_d2.map_into(),
190 rx_d3.map_into(),
191 tx_d0.map_into(),
192 tx_d1.map_into(),
193 tx_d2.map_into(),
194 tx_d3.map_into(),
195 tx_en.map_into(),
196 ]);
197
198 Self::new_inner(queue, peri, irq, pins, phy, mac_addr)
199 }
200
201 fn new_inner<const TX: usize, const RX: usize>(
202 queue: &'d mut PacketQueue<TX, RX>,
203 peri: impl Peripheral<P = T> + 'd,
204 _irq: impl interrupt::typelevel::Binding<interrupt::typelevel::ETH, InterruptHandler> + 'd,
205 pins: Pins<'d>,
206 phy: P,
207 mac_addr: [u8; 6],
208 ) -> Self {
110 let dma = ETH.ethernet_dma(); 209 let dma = ETH.ethernet_dma();
111 let mac = ETH.ethernet_mac(); 210 let mac = ETH.ethernet_mac();
112 let mtl = ETH.ethernet_mtl(); 211 let mtl = ETH.ethernet_mtl();
@@ -182,24 +281,12 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
182 } 281 }
183 }; 282 };
184 283
185 let pins = [
186 ref_clk.map_into(),
187 mdio.map_into(),
188 mdc.map_into(),
189 crs.map_into(),
190 rx_d0.map_into(),
191 rx_d1.map_into(),
192 tx_d0.map_into(),
193 tx_d1.map_into(),
194 tx_en.map_into(),
195 ];
196
197 let mut this = Self { 284 let mut this = Self {
198 _peri: peri, 285 _peri: peri.into_ref(),
199 tx: TDesRing::new(&mut queue.tx_desc, &mut queue.tx_buf), 286 tx: TDesRing::new(&mut queue.tx_desc, &mut queue.tx_buf),
200 rx: RDesRing::new(&mut queue.rx_desc, &mut queue.rx_buf), 287 rx: RDesRing::new(&mut queue.rx_desc, &mut queue.rx_buf),
201 pins, 288 pins,
202 phy: phy, 289 phy,
203 station_management: EthernetStationManagement { 290 station_management: EthernetStationManagement {
204 peri: PhantomData, 291 peri: PhantomData,
205 clock_range: clock_range, 292 clock_range: clock_range,
@@ -302,7 +389,10 @@ impl<'d, T: Instance, P: PHY> Drop for Ethernet<'d, T, P> {
302 dma.dmacrx_cr().modify(|w| w.set_sr(false)); 389 dma.dmacrx_cr().modify(|w| w.set_sr(false));
303 390
304 critical_section::with(|_| { 391 critical_section::with(|_| {
305 for pin in self.pins.iter_mut() { 392 for pin in match self.pins {
393 Pins::Rmii(ref mut pins) => pins.iter_mut(),
394 Pins::Mii(ref mut pins) => pins.iter_mut(),
395 } {
306 pin.set_as_disconnected(); 396 pin.set_as_disconnected();
307 } 397 }
308 }) 398 })