1use core::future::Future;
2use core::task::{Context, Poll, Waker};
3use embassy_net_driver::{Capabilities, Driver, HardwareAddress};
4use paste::paste;
5
6use crate::pac;
7use crate::{Peripheral, PeripheralRef};
8
9#[doc(hidden)]
10#[repr(align(8))]
11pub struct Buffer([u8; pac::MSS_MAC_MAX_RX_BUF_SIZE as usize]);
12
13pub trait MacPeripheral: 'static + core::fmt::Debug + Peripheral {
14 #[doc(hidden)]
15 fn address(&self) -> *mut pac::mss_mac_instance;
16 #[doc(hidden)]
17 fn tx_buffer(&self) -> &'static mut Buffer;
18 #[doc(hidden)]
19 fn rx_buffer(&self, index: usize) -> &'static mut Buffer;
20}
21
22macro_rules! impl_mac {
29 ($n:expr) => {
30 paste! {
31 impl_mac!([<MAC $n>], [<MAC $n _TAKEN>], [<MAC_RX_BUFFER $n>], [<MAC_TX_BUFFER $n>], [<g_mac $n>]);
32 }
33 };
34
35 ($MAC:ident, $MAC_TAKEN:ident, $RX_BUFFER:ident, $TX_BUFFER:ident, $instance:ident) => {
37 #[derive(Debug)]
38 pub struct $MAC {
39 _private: (),
40 }
41 static mut $MAC_TAKEN: bool = false;
42 static mut $RX_BUFFER: [Buffer; pac::MSS_MAC_RX_RING_SIZE as usize] =
43 [const { Buffer([0; pac::MSS_MAC_MAX_RX_BUF_SIZE as usize]) };
44 pac::MSS_MAC_RX_RING_SIZE as usize];
45
46 static mut $TX_BUFFER: Buffer = Buffer([0; pac::MSS_MAC_MAX_TX_BUF_SIZE as usize]);
49
50 impl Peripheral for $MAC {
51 fn take() -> Option<Self> {
52 critical_section::with(|_| unsafe {
53 if $MAC_TAKEN {
54 None
55 } else {
56 $MAC_TAKEN = true;
57 Some(Self { _private: () })
58 }
59 })
60 }
61
62 unsafe fn steal() -> Self {
63 Self { _private: () }
64 }
65 }
66
67 impl MacPeripheral for $MAC {
68 fn address(&self) -> *mut pac::mss_mac_instance {
69 &raw mut pac::$instance
70 }
71
72 fn tx_buffer(&self) -> &'static mut Buffer {
73 #[allow(static_mut_refs)]
74 unsafe { &mut $TX_BUFFER }
75 }
76
77 fn rx_buffer(&self, index: usize) -> &'static mut Buffer {
78 unsafe { &mut $RX_BUFFER[index] }
79 }
80 }
81 };
82}
83
84macro_rules! impl_eth {
85 ($n:expr) => {
86 paste! {
87 impl_eth!([<ETH $n>], [<ETH $n _TAKEN>], [<MAC $n>]);
88 }
89 };
90
91 ($ETH:ident, $ETH_TAKEN:ident, $MAC:ident) => {
93 static mut $ETH: Option<EthernetDevice<$MAC>> = None;
94 static mut $ETH_TAKEN: bool = false;
95
96 impl PeripheralRef for EthernetDevice<$MAC> {
97 fn take() -> Option<&'static mut Self> {
98 critical_section::with(|_| unsafe {
99 if $ETH_TAKEN {
100 None
101 } else {
102 if let Some(mac) = $MAC::take() {
103 $ETH_TAKEN = true;
104 $ETH = Some(EthernetDevice::new(mac));
105 #[allow(static_mut_refs)]
106 Some($ETH.as_mut().unwrap())
107 } else {
108 None
109 }
110 }
111 })
112 }
113
114 unsafe fn steal() -> &'static mut Self {
115 unsafe {
116 $ETH = Some(EthernetDevice::new($MAC::steal()));
117 #[allow(static_mut_refs)]
118 $ETH.as_mut().unwrap()
119 }
120 }
121 }
122 };
123}
124
125#[cfg(feature = "beaglev-fire")]
126pub use beaglev_fire::*;
127#[cfg(feature = "beaglev-fire")]
128mod beaglev_fire {
129 use super::*;
130
131 impl_mac!(0); impl_eth!(0); pub(crate) fn default_mac_config() -> pac::mss_mac_cfg_t {
135 pac::mss_mac_cfg_t {
136 phy_addr: pac::PHY_RTL8211_MDIO_ADDR,
137 phy_type: pac::MSS_MAC_DEV_PHY_RTL8211,
138 pcs_phy_addr: pac::SGMII_MDIO_ADDR,
139 interface_type: pac::TBI,
140 phy_autonegotiate: Some(pac::MSS_MAC_RTL8211_phy_autonegotiate),
141 phy_mac_autonegotiate: Some(pac::MSS_MAC_RTL8211_mac_autonegotiate),
142 phy_get_link_status: Some(pac::MSS_MAC_RTL8211_phy_get_link_status),
143 phy_init: Some(pac::MSS_MAC_RTL8211_phy_init),
144 phy_set_link_speed: Some(pac::MSS_MAC_RTL8211_phy_set_link_speed),
145 phy_extended_read: Some(pac::NULL_mmd_read_extended_regs),
146 phy_extended_write: Some(pac::NULL_mmd_write_extended_regs),
147 queue_enable: [0; 4],
148 speed_mode: pac::__mss_mac_speed_mode_t_MSS_MAC_SPEED_AN,
149 speed_duplex_select: pac::MSS_MAC_ANEG_ALL_SPEEDS,
150 mac_addr: [0; 6],
151 phy_controller: core::ptr::null_mut(),
152 tx_edc_enable: 0,
153 rx_edc_enable: 0,
154 jumbo_frame_enable: 1,
155 jumbo_frame_default: pac::MSS_MAC_MAX_PACKET_SIZE,
156 length_field_check: 1,
157 append_CRC: 1,
158 fullduplex: 0,
159 loopback: 0,
160 rx_flow_ctrl: 1,
161 tx_flow_ctrl: 1,
162 ipg_multiplier: pac::MSS_MAC_IPG_DEFVAL,
163 ipg_divisor: pac::MSS_MAC_IPG_DEFVAL,
164 phyclk: pac::MSS_MAC_DEF_PHY_CLK,
165 max_frame_length: 0,
166 use_hi_address: 0,
167 use_local_ints: 0,
168 queue0_int_priority: 7,
169 queue1_int_priority: 7,
170 queue2_int_priority: 7,
171 queue3_int_priority: 7,
172 mmsl_int_priority: 7,
173 tsu_clock_select: 1,
174 amba_burst_length: pac::MSS_MAC_AMBA_BURST_16,
175 }
176 }
177}
178
179#[derive(Debug, Clone, Copy)]
183pub enum LinkSpeed {
184 Speed10MBPS,
185 Speed100MBPS,
186 Speed1000MBPS,
187}
188
189#[derive(Debug, Clone, Copy, PartialEq, Eq)]
190pub enum LinkState {
191 Down,
192 Up,
193}
194
195impl LinkState {
196 pub fn is_up(&self) -> bool {
197 *self == LinkState::Up
198 }
199}
200
201#[derive(Debug)]
202pub struct EthernetTx<M: MacPeripheral> {
203 ethernet: *mut EthernetDevice<M>,
204}
205
206impl<M: MacPeripheral> EthernetTx<M> {
207 pub fn send<R, F>(&mut self, len: usize, f: F) -> R
208 where
209 F: FnOnce(&mut [u8]) -> R,
210 {
211 let ethernet = unsafe { &mut *self.ethernet };
212 ethernet._send(len, f)
213 }
214}
215
216pub struct EthernetRx<M: MacPeripheral> {
217 ethernet: *mut EthernetDevice<M>,
218}
219
220impl<M: MacPeripheral> EthernetRx<M> {
221 pub async fn receive<R, F>(&mut self, f: F) -> R
222 where
223 F: FnOnce(&mut [u8]) -> R,
224 {
225 let ethernet = unsafe { &mut *self.ethernet };
226 ethernet._receive(f).await
227 }
228}
229
230#[derive(Debug)]
231pub enum RxError {
232 Split,
233}
234
235#[derive(Debug)]
236pub enum TxError {
237 Split,
238}
239
240pub struct EthernetDevice<M: MacPeripheral> {
241 mac: M,
242 rx_waker: Option<Waker>,
243 pending_rx: RingBuffer<(usize, usize), { pac::MSS_MAC_RX_RING_SIZE as usize }>,
245 rx_tokens_issued: usize,
246 tx_buffer_in_use: bool,
247 link_speed: LinkSpeed,
248 full_duplex: bool,
249 split: bool,
250}
251
252impl<M: MacPeripheral> EthernetDevice<M> {
253 fn new(mac: M) -> Self {
254 debug!(
255 "Creating EthernetDevice with rx ring size {}",
256 pac::MSS_MAC_RX_RING_SIZE
257 );
258 Self {
259 mac,
260 pending_rx: RingBuffer {
261 buffer: [(0, 0); pac::MSS_MAC_RX_RING_SIZE as usize],
262 head: 0,
263 tail: 0,
264 size: 0,
265 },
266 rx_tokens_issued: 0,
267 tx_buffer_in_use: false,
268 rx_waker: None,
269 link_speed: LinkSpeed::Speed10MBPS,
270 full_duplex: false,
271 split: false,
272 }
273 }
274
275 pub fn init(&self, mac_address: [u8; 6]) {
276 unsafe {
277 let mut config = default_mac_config();
278 config.mac_addr = mac_address;
279 pac::MSS_MAC_init(self.mac.address(), &mut config as *mut _);
280
281 pac::MSS_MAC_set_tx_callback(
282 self.mac.address(),
283 0,
284 Some(packet_tx_complete_handler::<M>),
285 );
286 pac::MSS_MAC_set_rx_callback(self.mac.address(), 0, Some(mac_rx_callback::<M>));
287
288 for i in 0..pac::MSS_MAC_RX_RING_SIZE as usize {
290 let enable_interrupts = if i == (pac::MSS_MAC_RX_RING_SIZE as usize - 1) {
291 -1 } else {
293 0 };
295
296 pac::MSS_MAC_receive_pkt(
297 self.mac.address(),
298 0,
299 self.mac.rx_buffer(i).0.as_mut_ptr(),
300 self as *const _ as *mut core::ffi::c_void,
301 enable_interrupts,
302 );
303 }
304
305 {
306 let mac_base = (*self.mac.address()).mac_base;
309 (*mac_base).NETWORK_CONTROL &= !pac::GEM_ENABLE_TRANSMIT;
311 (*mac_base).UPPER_TX_Q_BASE_ADDR =
312 (self.mac.tx_buffer().0.as_ptr() as u64 >> 32) as u32;
313 (*mac_base).NETWORK_CONTROL |= pac::GEM_ENABLE_TRANSMIT;
314 core::sync::atomic::fence(core::sync::atomic::Ordering::SeqCst);
315 }
316
317 pac::MSS_MAC_tx_enable(self.mac.address());
318
319 trace!("MAC config: {:#?}", config);
320 debug!("MAC initialized");
321 }
322 }
323
324 pub fn split(&mut self) -> (EthernetTx<M>, EthernetRx<M>) {
325 self.split = true;
326 (
327 EthernetTx {
328 ethernet: self as *mut _,
329 },
330 EthernetRx {
331 ethernet: self as *mut _,
332 },
333 )
334 }
335
336 pub fn link_speed(&self) -> LinkSpeed {
337 self.link_speed
338 }
339
340 pub fn full_duplex(&self) -> bool {
341 self.full_duplex
342 }
343
344 #[doc(hidden)]
345 pub fn debug_mac_queue(&self) {
346 debug!("MAC queue 0: {:#?}", unsafe {
347 (*self.mac.address()).queue[0]
348 });
349 }
350
351 pub fn send<R, F>(&mut self, len: usize, f: F) -> Result<R, TxError>
352 where
353 F: FnOnce(&mut [u8]) -> R,
354 {
355 if self.split {
356 Err(TxError::Split)
357 } else {
358 Ok(self._send(len, f))
359 }
360 }
361
362 fn _send<R, F>(&mut self, len: usize, f: F) -> R
363 where
364 F: FnOnce(&mut [u8]) -> R,
365 {
366 let mut lock_count = 0;
367 loop {
368 if !self.tx_buffer_in_use {
369 let got_lock = critical_section::with(|_| {
370 if !self.tx_buffer_in_use {
372 self.tx_buffer_in_use = true;
373 true
374 } else {
375 false
376 }
377 });
378 if got_lock {
379 break;
380 }
381 }
382 lock_count += 1;
383
384 if lock_count > 1000 {
386 self.tx_buffer_in_use = false;
387 warn!("Failed to get lock on ethernet TX buffer, resetting");
388 }
389 }
390 if len > self.mac.tx_buffer().0.len() {
391 panic!(
392 "Max ethernet TX packet size {} exceeded",
393 self.mac.tx_buffer().0.len()
394 );
395 }
396 let ret = f(&mut self.mac.tx_buffer().0[0..len]);
398 self.send_pkt(len);
399
400 ret
401 }
402
403 fn send_pkt(&mut self, len: usize) {
405 unsafe {
406 let tx_status = pac::MSS_MAC_send_pkt(
407 self.mac.address(),
408 0,
409 self.mac.tx_buffer().0.as_ptr(),
410 len as u32,
411 self as *const _ as *mut core::ffi::c_void,
412 );
413 if tx_status != 1 {
414 error!("Failed to send packet");
415 }
416 }
417 }
418 pub async fn receive<R, F>(&mut self, f: F) -> Result<R, RxError>
419 where
420 F: FnOnce(&mut [u8]) -> R,
421 {
422 if self.split {
423 Err(RxError::Split)
424 } else {
425 Ok(self._receive(f).await)
426 }
427 }
428
429 async fn _receive<R, F>(&mut self, f: F) -> R
430 where
431 F: FnOnce(&mut [u8]) -> R,
432 {
433 let future = RxFuture {
434 ethernet: self as *mut _,
435 };
436 let token = future.await;
437 embassy_net_driver::RxToken::consume(token, f)
438 }
439
440 pub fn link_state(&mut self) -> LinkState {
441 let mut test_speed = pac::__mss_mac_speed_t_MSS_MAC_1000MBPS;
442 let mut test_fullduplex = 0;
443 let test_linkup = unsafe {
444 pac::MSS_MAC_get_link_status(self.mac.address(), &mut test_speed, &mut test_fullduplex)
445 };
446
447 if test_linkup == 0 {
448 return LinkState::Down;
449 }
450 if test_speed == pac::__mss_mac_speed_t_MSS_MAC_1000MBPS {
451 self.link_speed = LinkSpeed::Speed1000MBPS;
452 } else if test_speed == pac::__mss_mac_speed_t_MSS_MAC_100MBPS {
453 self.link_speed = LinkSpeed::Speed100MBPS;
454 } else {
455 self.link_speed = LinkSpeed::Speed10MBPS;
456 }
457
458 self.full_duplex = test_fullduplex != 0;
459
460 LinkState::Up
461 }
462
463 pub fn mac_address(&self) -> [u8; 6] {
464 let mac = unsafe { *self.mac.address() };
465 mac.mac_addr
466 }
467}
468
469impl<M: MacPeripheral> Driver for EthernetDevice<M> {
470 type RxToken<'a> = RxToken<'a, M>;
471 type TxToken<'a> = TxToken<'a, M>;
472
473 fn receive(&mut self, cx: &mut Context<'_>) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
474 critical_section::with(|_| {
475 if !self.split && self.rx_tokens_issued < self.pending_rx.size {
476 self.rx_tokens_issued += 1;
477 Some((
478 RxToken {
479 phantom: core::marker::PhantomData,
480 ethernet: self as *mut _,
481 },
482 self.transmit(cx).unwrap(),
483 ))
484 } else {
485 if self.split {
486 warn!("RX split, not receiving");
487 }
488 self.rx_waker = Some(cx.waker().clone());
489 None
490 }
491 })
492 }
493
494 fn transmit(&mut self, _cx: &mut Context<'_>) -> Option<Self::TxToken<'_>> {
495 if self.split {
498 warn!("TX split, not transmitting");
499 None
500 } else {
501 Some(TxToken {
502 phantom: core::marker::PhantomData,
503 ethernet: self as *mut _,
504 })
505 }
506 }
507
508 fn link_state(&mut self, cx: &mut Context<'_>) -> embassy_net_driver::LinkState {
509 cx.waker().wake_by_ref();
510 match self.link_state() {
511 LinkState::Up => embassy_net_driver::LinkState::Up,
512 LinkState::Down => embassy_net_driver::LinkState::Down,
513 }
514 }
515
516 fn capabilities(&self) -> Capabilities {
517 let mut caps = Capabilities::default();
518 caps.max_transmission_unit = 9216; caps.max_burst_size = Some(pac::MSS_MAC_RX_RING_SIZE as usize);
520 caps
521 }
522
523 fn hardware_address(&self) -> HardwareAddress {
524 HardwareAddress::Ethernet(self.mac_address())
525 }
526}
527
528pub struct RxToken<'a, M: MacPeripheral> {
532 phantom: core::marker::PhantomData<&'a ()>,
533 ethernet: *mut EthernetDevice<M>,
534}
535
536impl<'a, M: MacPeripheral> embassy_net_driver::RxToken for RxToken<'a, M> {
537 fn consume<R, F>(self, f: F) -> R
538 where
539 F: FnOnce(&mut [u8]) -> R,
540 {
541 let ethernet = unsafe { &mut *self.ethernet };
542
543 let (buffer_number, len) = critical_section::with(|_| ethernet.pending_rx.pop().unwrap());
544 let rx_buf = &mut ethernet.mac.rx_buffer(buffer_number).0[0..len];
545 let ret = f(rx_buf);
546 unsafe {
547 pac::MSS_MAC_receive_pkt(
548 ethernet.mac.address(),
549 0,
550 rx_buf.as_mut_ptr(),
551 self.ethernet as *mut _,
552 1,
553 );
554 }
555 critical_section::with(|_| {
556 ethernet.rx_tokens_issued -= 1;
557 });
558 trace!("Consumed RX token");
559 ret
560 }
561}
562
563pub struct TxToken<'a, M: MacPeripheral> {
564 phantom: core::marker::PhantomData<&'a ()>,
565 ethernet: *mut EthernetDevice<M>,
566}
567
568impl<'a, M: MacPeripheral> embassy_net_driver::TxToken for TxToken<'a, M> {
569 fn consume<R, F>(self, len: usize, f: F) -> R
570 where
571 F: FnOnce(&mut [u8]) -> R,
572 {
573 let ethernet = unsafe { &mut *self.ethernet };
574 ethernet.send(len, f).unwrap()
575 }
576}
577
578pub struct RxFuture<M: MacPeripheral> {
581 ethernet: *mut EthernetDevice<M>,
582}
583
584impl<M: MacPeripheral> Future for RxFuture<M> {
585 type Output = RxToken<'static, M>;
586
587 fn poll(mut self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
588 critical_section::with(|_| {
589 let ethernet = unsafe { &mut *self.ethernet };
590 if ethernet.rx_tokens_issued < ethernet.pending_rx.size {
591 ethernet.rx_tokens_issued += 1;
592 Poll::Ready(RxToken {
593 phantom: core::marker::PhantomData,
594 ethernet: self.ethernet as *mut _,
595 })
596 } else {
597 ethernet.rx_waker = Some(cx.waker().clone());
598 Poll::Pending
599 }
600 })
601 }
602}
603
604extern "C" fn packet_tx_complete_handler<M: MacPeripheral>(
608 _mac: *mut core::ffi::c_void,
609 _queue: u32,
610 _desc: *mut pac::mss_mac_tx_desc,
611 user_data: *mut core::ffi::c_void,
612) {
613 trace!("MAC packet TX callback");
614 unsafe {
615 let ethernet = (user_data as *mut EthernetDevice<M>).as_mut().unwrap();
616 ethernet.tx_buffer_in_use = false;
617 }
618}
619
620extern "C" fn mac_rx_callback<M: MacPeripheral>(
621 _mac: *mut core::ffi::c_void,
622 _queue: u32,
623 rx_buf: *mut u8,
624 rx_size: u32,
625 _rx_desc: *mut pac::mss_mac_rx_desc,
626 user_data: *mut core::ffi::c_void,
627) {
628 trace!("MAC packet RX callback of size: {}", rx_size);
629 unsafe {
630 let ethernet = (user_data as *mut EthernetDevice<M>).as_mut().unwrap();
631 let buffer_number = (rx_buf as usize - (*ethernet).mac.rx_buffer(0).0.as_ptr() as usize)
632 / (pac::MSS_MAC_MAX_RX_BUF_SIZE as usize);
633 let succeeded = critical_section::with(|_| {
634 if let Some(waker) = (*ethernet).rx_waker.take() {
635 waker.wake_by_ref();
636 }
637 (*ethernet)
638 .pending_rx
639 .push((buffer_number, rx_size as usize))
640 });
641 if !succeeded {
642 warn!("Failed to push to pending rx");
643 pac::MSS_MAC_receive_pkt(ethernet.mac.address(), 0, rx_buf, user_data as *mut _, 1);
644 }
645 }
646}
647
648struct RingBuffer<T: core::fmt::Debug, const N: usize> {
651 buffer: [T; N],
652 head: usize,
653 tail: usize,
654 size: usize, }
656
657impl<T: core::fmt::Debug, const N: usize> core::fmt::Debug for RingBuffer<T, N> {
658 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
659 write!(f, "RingBuffer[")?;
660
661 write!(
673 f,
674 "] (size: {}, head: {}, tail: {})",
675 self.size, self.head, self.tail
676 )
677 }
678}
679
680impl<T: Default + Copy + core::fmt::Debug, const N: usize> RingBuffer<T, N> {
681 #[allow(dead_code)]
682 fn new() -> Self {
683 Self {
684 buffer: [T::default(); N],
685 head: 0,
686 tail: 0,
687 size: 0,
688 }
689 }
690
691 fn push(&mut self, item: T) -> bool {
693 if self.is_full() {
694 return false;
695 }
696 self.buffer[self.head] = item;
697 self.head = (self.head + 1) % N;
698 self.size += 1;
699 true
700 }
701
702 fn is_full(&self) -> bool {
703 self.size == N
704 }
705
706 fn is_empty(&self) -> bool {
707 self.size == 0
708 }
709
710 fn pop(&mut self) -> Option<T> {
711 if self.is_empty() {
712 None
713 } else {
714 let item = self.buffer[self.tail];
715 self.tail = (self.tail + 1) % N;
716 self.size -= 1;
717 Some(item)
718 }
719 }
720}