aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGerhard de Clercq <[email protected]>2024-09-20 09:57:31 +0200
committerGerhard de Clercq <[email protected]>2024-09-20 09:57:31 +0200
commit5ea934d4ba6f0bc0e5e47b16f17dd8e881b528a3 (patch)
tree4be5ddca07a3ddf69546e26cdb9de1878425a093
parentd7780fcf83a8a35d7b09e5df7b62dd8218436715 (diff)
embassy_stm32/eth: support compliance testing
This change adds the possibility to perform compliance testing with STM32 systems by directly exposing SMI when needed. Users can then use this to configure PHY registers for test modes.
-rw-r--r--embassy-stm32/src/eth/mod.rs14
-rw-r--r--examples/stm32f4/src/bin/eth_compliance_test.rs77
2 files changed, 91 insertions, 0 deletions
diff --git a/embassy-stm32/src/eth/mod.rs b/embassy-stm32/src/eth/mod.rs
index bfe8a60d6..6442176da 100644
--- a/embassy-stm32/src/eth/mod.rs
+++ b/embassy-stm32/src/eth/mod.rs
@@ -177,6 +177,20 @@ pub unsafe trait PHY {
177 fn poll_link<S: StationManagement>(&mut self, sm: &mut S, cx: &mut Context) -> bool; 177 fn poll_link<S: StationManagement>(&mut self, sm: &mut S, cx: &mut Context) -> bool;
178} 178}
179 179
180impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
181 /// Directly expose the SMI interface used by the Ethernet driver.
182 ///
183 /// This can be used to for example configure special PHY registers for compliance testing.
184 ///
185 /// # Safety
186 ///
187 /// Revert any temporary PHY register changes such as to enable test modes before handing
188 /// the Ethernet device over to the networking stack otherwise things likely won't work.
189 pub unsafe fn station_management(&mut self) -> &mut impl StationManagement {
190 &mut self.station_management
191 }
192}
193
180trait SealedInstance { 194trait SealedInstance {
181 fn regs() -> crate::pac::eth::Eth; 195 fn regs() -> crate::pac::eth::Eth;
182} 196}
diff --git a/examples/stm32f4/src/bin/eth_compliance_test.rs b/examples/stm32f4/src/bin/eth_compliance_test.rs
new file mode 100644
index 000000000..5946fed79
--- /dev/null
+++ b/examples/stm32f4/src/bin/eth_compliance_test.rs
@@ -0,0 +1,77 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_stm32::eth::generic_smi::GenericSMI;
7use embassy_stm32::eth::{Ethernet, PacketQueue, StationManagement};
8use embassy_stm32::time::Hertz;
9use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config};
10use embassy_time::Timer;
11use static_cell::StaticCell;
12use {defmt_rtt as _, panic_probe as _};
13
14bind_interrupts!(struct Irqs {
15 ETH => eth::InterruptHandler;
16 HASH_RNG => rng::InterruptHandler<peripherals::RNG>;
17});
18
19#[embassy_executor::main]
20async fn main(_spawner: Spawner) -> ! {
21 let mut config = Config::default();
22 {
23 use embassy_stm32::rcc::*;
24 config.rcc.hse = Some(Hse {
25 freq: Hertz(8_000_000),
26 mode: HseMode::Bypass,
27 });
28 config.rcc.pll_src = PllSource::HSE;
29 config.rcc.pll = Some(Pll {
30 prediv: PllPreDiv::DIV4,
31 mul: PllMul::MUL180,
32 divp: Some(PllPDiv::DIV2), // 8mhz / 4 * 180 / 2 = 180Mhz.
33 divq: None,
34 divr: None,
35 });
36 config.rcc.ahb_pre = AHBPrescaler::DIV1;
37 config.rcc.apb1_pre = APBPrescaler::DIV4;
38 config.rcc.apb2_pre = APBPrescaler::DIV2;
39 config.rcc.sys = Sysclk::PLL1_P;
40 }
41 let p = embassy_stm32::init(config);
42
43 info!("Hello Compliance World!");
44
45 let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF];
46
47 const PHY_ADDR: u8 = 0;
48 static PACKETS: StaticCell<PacketQueue<4, 4>> = StaticCell::new();
49 let mut device = Ethernet::new(
50 PACKETS.init(PacketQueue::<4, 4>::new()),
51 p.ETH,
52 Irqs,
53 p.PA1,
54 p.PA2,
55 p.PC1,
56 p.PA7,
57 p.PC4,
58 p.PC5,
59 p.PG13,
60 p.PB13,
61 p.PG11,
62 GenericSMI::new(PHY_ADDR),
63 mac_addr,
64 );
65
66 let sm = unsafe { device.station_management() };
67
68 // Just an example. Exact register settings depend on the specific PHY and test.
69 sm.smi_write(PHY_ADDR, 0, 0x2100);
70 sm.smi_write(PHY_ADDR, 11, 0xA000);
71
72 // NB: Remember to reset the PHY after testing before starting the networking stack
73
74 loop {
75 Timer::after_secs(1).await;
76 }
77}