ove/async_net/
stm32f7_eth.rs1use ::core::ffi::c_void;
29use ::core::sync::atomic::{AtomicBool, Ordering};
30use ::core::task::Context;
31
32use embassy_net_driver::{Capabilities, Driver, HardwareAddress, LinkState, RxToken, TxToken};
33use embassy_sync::waitqueue::AtomicWaker;
34
35pub const MTU: usize = 1518;
37
38unsafe extern "C" {
39 fn ove_stm32f7_eth_async_init(mac: *const u8) -> ::core::ffi::c_int;
40 fn ove_stm32f7_eth_async_tx(frame: *const c_void, len: u32) -> ::core::ffi::c_int;
41 fn ove_stm32f7_eth_async_rx(
42 buf: *mut c_void,
43 buf_size: u32,
44 out_len: *mut u32,
45 ) -> ::core::ffi::c_int;
46 fn ove_stm32f7_eth_async_link_up() -> ::core::ffi::c_int;
47 fn ove_stm32f7_eth_async_set_notify(
48 cb: Option<unsafe extern "C" fn(*mut c_void)>,
49 user_data: *mut c_void,
50 );
51}
52
53unsafe extern "C" fn isr_notify(_ud: *mut c_void) {
57 RX_WAKER.wake();
58}
59
60static RX_WAKER: AtomicWaker = AtomicWaker::new();
61static INITED: AtomicBool = AtomicBool::new(false);
62
63pub fn wake_poll() {
70 RX_WAKER.wake();
71}
72
73pub struct Stm32f7EthDriver {
75 mac: [u8; 6],
76}
77
78impl Stm32f7EthDriver {
79 pub fn new(mac: [u8; 6]) -> Self {
82 let _ = unsafe { ove_stm32f7_eth_async_init(mac.as_ptr()) };
85 unsafe {
88 ove_stm32f7_eth_async_set_notify(Some(isr_notify), ::core::ptr::null_mut());
89 }
90 INITED.store(true, Ordering::Release);
91 Self { mac }
92 }
93}
94
95pub struct Stm32f7EthRx {
96 buf: [u8; MTU],
97 len: usize,
98}
99
100impl RxToken for Stm32f7EthRx {
101 fn consume<R, F>(mut self, f: F) -> R
102 where
103 F: FnOnce(&mut [u8]) -> R,
104 {
105 f(&mut self.buf[..self.len])
106 }
107}
108
109pub struct Stm32f7EthTx;
110
111impl TxToken for Stm32f7EthTx {
112 fn consume<R, F>(self, len: usize, f: F) -> R
113 where
114 F: FnOnce(&mut [u8]) -> R,
115 {
116 let mut buf = [0u8; MTU];
117 let n = len.min(MTU);
118 let result = f(&mut buf[..n]);
119 unsafe {
122 ove_stm32f7_eth_async_tx(buf.as_ptr() as *const c_void, n as u32);
123 }
124 result
125 }
126}
127
128impl Driver for Stm32f7EthDriver {
129 type RxToken<'a>
130 = Stm32f7EthRx
131 where
132 Self: 'a;
133 type TxToken<'a>
134 = Stm32f7EthTx
135 where
136 Self: 'a;
137
138 fn receive(&mut self, cx: &mut Context<'_>) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
139 let mut rx = Stm32f7EthRx {
140 buf: [0; MTU],
141 len: 0,
142 };
143 let mut out_len: u32 = 0;
144 let rc = unsafe {
145 ove_stm32f7_eth_async_rx(
146 rx.buf.as_mut_ptr() as *mut c_void,
147 MTU as u32,
148 &mut out_len as *mut u32,
149 )
150 };
151 if rc == 0 && out_len > 0 {
152 rx.len = out_len as usize;
153 Some((rx, Stm32f7EthTx))
154 } else {
155 RX_WAKER.register(cx.waker());
156 None
157 }
158 }
159
160 fn transmit(&mut self, _cx: &mut Context<'_>) -> Option<Self::TxToken<'_>> {
161 Some(Stm32f7EthTx)
162 }
163
164 fn link_state(&mut self, _cx: &mut Context<'_>) -> LinkState {
165 let up = unsafe { ove_stm32f7_eth_async_link_up() };
167 if up != 0 {
168 LinkState::Up
169 } else {
170 LinkState::Down
171 }
172 }
173
174 fn capabilities(&self) -> Capabilities {
175 let mut caps = Capabilities::default();
176 caps.max_transmission_unit = 1514;
177 caps
178 }
179
180 fn hardware_address(&self) -> HardwareAddress {
181 HardwareAddress::Ethernet(self.mac)
182 }
183}